分类: 技术学习

  • 开源!极简的WP弹窗公告插件

    开源!极简的WP弹窗公告插件

    常关注我的博客的人知道,我在之前因为备案临时把博客切到了备用的cyou域名,然后发了一个弹窗公告通知“成年更新”。

    这个弹窗公告不是主题自带的,是我设定需求和风格+AI写出来的。

    弹窗整体是白色亚克力底+黑色文字,很简单。就一个按钮“已知晓”(欢迎二开,但是请不要加广告并以我名义分发!)

    效果图

    插件下载

    项目结构

    wp-plugin-announce

    • css
      • announce.css
    • js
      • announce.js
    • announce.php

    代码

    announce.php

    <?php
    /**
     * Plugin Name: Announce
     * Description: 一个显示浮动弹窗的插件
     * Version: 1.0
     * Author: Nibbles
     */
    
    if (!defined('ABSPATH')) {
        exit; // 防止直接访问
    }
    
    // 加载插件所需的脚本和样式
    function announce_enqueue_scripts() {
        wp_enqueue_style('announce-style', plugin_dir_url(__FILE__) . 'css/announce.css');
        wp_enqueue_script('announce-script', plugin_dir_url(__FILE__) . 'js/announce.js', array('jquery'), null, true);
    }
    add_action('wp_enqueue_scripts', 'announce_enqueue_scripts');
    
    // 在页面中插入弹窗的HTML结构
    function announce_display_popup() {
        ?>
        <div id="announce-popup" class="announce-popup">
            <div class="announce-content">
                <h2 id="announce-title"><?php echo esc_html(get_option('announce_title', '提示')); ?></h2>
                <p id="announce-message"><?php echo esc_html(get_option('announce_message', '这是一个重要的公告!')); ?></p>
                <button id="announce-close"><?php _e('已知晓', 'announce'); ?></button>
            </div>
        </div>
        <div id="announce-overlay" class="announce-overlay"></div>
        <?php
    }
    add_action('wp_footer', 'announce_display_popup');
    
    // 添加插件设置页面
    function announce_settings_page() {
        add_options_page(
            'Announce Settings',
            'Announce',
            'manage_options',
            'announce',
            'announce_settings_page_html'
        );
    }
    add_action('admin_menu', 'announce_settings_page');
    
    function announce_settings_page_html() {
        ?>
        <div class="wrap">
            <h1><?php _e('Announce 设置', 'announce'); ?></h1>
            <form method="post" action="options.php">
                <?php
                settings_fields('announce_settings');
                do_settings_sections('announce');
                submit_button();
                ?>
            </form>
        </div>
        <?php
    }
    
    // 注册设置选项
    function announce_register_settings() {
        register_setting('announce_settings', 'announce_title');
        register_setting('announce_settings', 'announce_message');
    
        add_settings_section(
            'announce_section',
            __('弹窗设置', 'announce'),
            null,
            'announce'
        );
    
        add_settings_field(
            'announce_title',
            __('弹窗标题', 'announce'),
            'announce_title_callback',
            'announce',
            'announce_section'
        );
    
        add_settings_field(
            'announce_message',
            __('弹窗内容', 'announce'),
            'announce_message_callback',
            'announce',
            'announce_section'
        );
    }
    add_action('admin_init', 'announce_register_settings');
    
    function announce_title_callback() {
        $announce_title = get_option('announce_title', '');
        echo '<input type="text" name="announce_title" value="' . esc_attr($announce_title) . '" />';
    }
    
    function announce_message_callback() {
        $announce_message = get_option('announce_message', '');
        echo '<textarea name="announce_message" rows="5" cols="50">' . esc_textarea($announce_message) . '</textarea>';
    }
    ?>
    

    css/announce.css

    /* 弹窗通用样式 */
    .announce-popup {
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        padding: 20px;
        border-radius: 10px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        z-index: 10001;
        display: none;
        text-align: center;
        max-width: 90%;
        max-height: 90%;
        overflow-y: auto;
        backdrop-filter: blur(10px); /* 添加背景模糊效果 */
        background-color: rgba(255, 255, 255, 0.8); /* 亚克力效果的白色背景 */
        color: black; /* 黑色文字 */
    }
    
    /* 按钮样式 */
    #announce-close {
        background-color: #007AFF;
        color: white;
        border: none;
        padding: 10px 20px;
        border-radius: 5px;
        cursor: pointer;
        margin-top: 20px;
    }
    
    #announce-close:hover {
        background-color: #005fcb;
    }
    
    /* 遮罩层样式 */
    .announce-overlay {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.5);
        z-index: 10000;
        display: none;
    }
    

    js/announce.js

    jQuery(document).ready(function($) {
        // 检查本地存储中的 acknowledge 记录
        if (!localStorage.getItem('announce_acknowledged')) {
            $('#announce-popup').fadeIn(); // 显示弹窗
            $('#announce-overlay').fadeIn(); // 显示遮罩层
        }
    
        // 处理 "已知晓" 按钮的点击事件
        $('#announce-close').on('click', function() {
            $('#announce-popup').fadeOut(); // 隐藏弹窗
            $('#announce-overlay').fadeOut(); // 隐藏遮罩层
            localStorage.setItem('announce_acknowledged', 'true'); // 设置 acknowledge 记录
        });
    });
    
  • VuePress —— 全流程建立博客的另一灾备方案

    VuePress —— 全流程建立博客的另一灾备方案

    Another disaster recovery plan for the blog: VuePress. I want to share VuePress programing experience.

    为什么要做这一方案?

    作为站长的我们首先要确保博客业务的连续性,还有文章等数据的备份。次之还有备份站运营成本上的考虑,其中本站采用的是知名的WordPress程序,在Docker容器中运行,虽然说容器本身迁移方便,但是如果这台VPS一时出问题了,那么还是要买且迁移到新的VPS来,对于维护成本来说还是有点高的。

    而且现在的Serverless开发平台(也就是vercel、netlify、zeabur)免费计划中跑VuePress静态站点绰绰有余,然后静态站前端代码从GitHub 仓库里抓取,每次我们对博客的修改,从本地git到仓库中,然后触发Serverless的重新构建机制,域名的话可以用*.eu.org,这样整套流程下来没有💴上的成本,且网站都在国外也不会因国内原因导致无法访问甚至封禁,本地也保存了网站的数据。

    写在建站前你必须要的

    1. 基本的电脑操作知识(知道怎么装软件,知道怎么复制粘贴,会用代码编辑器的基本功能即可)
    2. 有个合适的国外proxy,Watt Toolkit中也有免费的Github加速选项可以试试
    3. 有Github账号(新手注册登录即可)
    4. 合适的翻译工具,最好支持截图翻译
    5. 会写MarkDown文件
    6. 一个能随时回答你发的问题的AI,如kimi.ai

    具体实现流程

    1、NodeJS环境部署

    NodeJS的版本不建议太高,优先选择LTS(长期支持版本),博主选用的是v18.20.4(LTS x64)

    【挂proxy】官网下载:https://nodejs.org/dist/v18.20.4/node-v18.20.4-x64.msi
    中文镜像站:https://npmmirror.com/mirrors/node/v18.20.4/node-v18.20.4-x64.msi

    直接默认安装位置即可,NodeJS程序本身只有几十MB。在安装过程到 tools for native modules 步骤的时候,不要勾选,然后下一步直到安装完成即可,安装完后还需重启系统。

    检查版本,【Win+R快捷键输入cmd调出终端】

    node -v   #开头是node,不是nodejs!

    出现v18.20.4即安装成功。

    本篇我们采用npx安装,类似于npm,它们都是NodeJS里预置的软件包管理器。什么意思倒不用在意,只是知道它们是指令的开头即可。

    然后为了后续的访问速度还要换镜像源:https://nibbles.cyou/shift-source.html

    2、VuePress 安装

    博主选择的是带主题的vuepress-recohttps://theme-reco.vuejs.press/

    打开cmd

    创建一个文件夹(这路径上不能有中文)并让cmd执行路径指向此处:

    法一【Win11/10】:找到系统自带的“终端”软件,在设置中更改默认为cmd,然后直接在文件夹里右键,选择“在终端中打开”。若没有可以去Microsoft Store里下载“终端”这个软件。

    法二【更简单】:更改路径栏为cmd,则打开的cmd直接就指向这个路径了。

    npx命令安装并初始化

    文档里,revili可视化搭建部署起来还是会有点问题。所以直接用下面的一行命令(npx开头的)

    # 初始化,并选择 2.x
    npx @vuepress-reco/theme-cli init

    输入后待其下载完后会进入初始化选项

    第一问中:新的目录指的是在cmd指向的文件夹下再新建一个文件夹。(Y/n),若是的话需要先开大写锁定(键盘上的capslock)后打y,若不是就n。一般情况下空文件夹里创建此项目可以直接n。

    除了最后一个问题和第一个问题,其他均可后期更改 config.ts 里的配置改变。

    3、配置VuePress-reco主题

    准备工作与层级关系

    我喜欢用WebStorm来改配置,当然你使用VSCode也行,不过最好不要用“记事本”!

    为了让我们的网站在更改后能及时看到,可以先dev运行下。在编辑器里打开文件夹后,打开 package.json 即可看到运行的按钮:

    初次运行成功时候,看到下方的编辑器内置的终端窗口中会弹出两个链接:

    Local所指的是只能本地电脑访问的,
    Network所指的是指内网里的设备都可以访问的,但外网无法访问。

    改配置的时候,建议把浏览器窗口和编辑器窗口精简化,并排成两列的布局

    要更改的地方配置文件
    公告侧边弹窗config.ts 45行-98行bulletin
    首页模块及内容README.md Frontmatter
    首页顶部导航栏config.ts 33行-44行navbar
    网站logo和作者头像.vuepress/public 替换同名文件,logo.pnghead.png
    首页右上角固定的Github地址指向config.ts 第16行docsRepo

    这里只是一部分常用的需要改的地方

    ⭐ 配置文件更改时候最重要的是: 注意层级 !让我们解析一下config.ts的前半段:

    各种不同颜色的圈圈,同样的颜色代表此为成对出现的。

    值得一提的是,作者在原文档中部分的冒号为全角的冒号,他是打错了,但该配置的时候大家要认清并改过来哦! 半角就是英文输入法下输入的,全角是中文输入法下的。半角: ,全角比较紧凑要改!

    尽量各条语句之间开头对齐,用缩进清晰明了地展示层级关系。

    能改的仅有引号内的内容,若要删去或者添加需要按照格式整对注释或添加,有的参数不用的可以移到注释里。快速注释方法:【CTRL+/】

    参数名称一般对应着这东西到底是用来干嘛的,可以借助截图翻译软件通过单词意思来填上合适的内容。

    MarkDown中的Frontmatter

    Frontmatter即是MarkDown文件中被两行 --- 括起来的部分

    文档中关于Frontmatter首页设置:https://theme-reco.vuejs.press/docs/theme/frontmatter-home.html

    也是要按照格式一个个填,不过没有了引号和,结尾,但是一定要注意缩进。文档页面中最后有全部都应用上去的示例,可以先全部复制上,然后再删改。

    注意,Frontmatter是会被主题解析的,各部分参数会显示到指定位置。—框起来以外的位置就是README.md的正文了,也就是MdContent module显示在首页上的内容。

    4、Vite生成静态网页目录

    点击此按钮开始build静态文件,当终端出现绿色的done的字样即代表生成完毕。(VSCode类似)

    生成到了 .vuepress/dist 这个目录下面。

    注意,每次更改(比如加文章、改样式)都需要重新生成一遍!

    5、上传到Github

    为了我们后续部署到Serverless平台,所以此处我们先利用Git上传到Github上。

    Git官网下载:https://github.com/git-for-windows/git/releases/download/v2.46.0.windows.1/Git-2.46.0-64-bit.exe 安装过程直接一路下一步下去。

    Github上创建一个new repository:https://github.com/new ,并对此命名,然后Create repository确认创建。新创建的里面不会有什么东西,但给了git的代码教程:

    Git要加速使用系统proxy的话可以看:https://nibbles.cyou/shift-source.html

    如果你不太想输入很多命令的话(看着不多,其实后面git add的时候需要加很多文件),可以试下Github Desktop,安装后登录账号密码,然后把仓库拉取到本地并作为同步文件夹。

    之后把整个项目文件夹(不只是.vuepress)全部拖到同步文件夹中让客户端上传上去。在提交的时候需要自己写一点commit日志,比如如上的first commit。

    以后每次只要网页目录有变动,就及时使用git或Github Desktop上传。

    6、部署到zeabur

    zeabur:https://zeabur.com

    邮箱注册后会发送登陆链接到你的邮箱,从邮件中的链接进去即是后台。

    创建项目→新建服务→Github(从Github仓库部署)→选择刚创建的存网页的仓库

    然后趁机还没运行完毕,下拉找到设置→根目录,修改为/.vuepress/dist

    回到上面”重新部署“,等待片刻,当出现运行中并有绿点则代表部署成功。

    如果需要测试访问,可以直接使用一个zeabur.app的二级域名:下拉,网络→公开→生成域名→填入你喜欢的前缀,稍等下就可以使用 填的前缀.zeabur.app 来访问了。

    7、免费域名eu.org

    免费获取 EU.org 顶级域名丨岚天小窝

    https://blog.ltya.top/posts/eu-org.shtml

    更改为自己申请到的eu.org域名:下拉,网络→公开→自定义域名→到解析服务那里CNAME解析,如下

    稍等片刻,即可直接访问了~


    看到这里的你应该能手搓出一个VuePress的站点了吧~ 还有问题的话不妨问问AI哦。

    既然有了自己的站点,那就努力更新内容吧!

  • 换源代码汇总

    换源代码汇总

    引言

    博主最近在折腾一个静态博客,使用vuepress-reco驱动,中途有网络问题遇到了很多麻烦,这里特别写一篇文章提醒自己以后在环境搭建的过程中还要对包管理器全局换源。初始操作中不仅是换源,还有git传输网络自动走系统proxy的代码,我也一并放在本文中。

    代码

    博主所用的开发环境如下:

    >node -v
    v18.20.4
    
    >npm -v
    10.7.0
    
    >pnpm -v
    9.7.1
    
    >yarn -v
    1.22.22
    

    换源命令通用格式

    淘宝源域名已经变更了,不过填原来的域名也没啥影响,但建议尽快改为新域名!
    https://registry.npm.taobao.org => https://registry.npmmirror.com

    修改源:

    <npm|pnpm|yarn> config set registry https://registry.npm.taobao.org

    检查配置:

    <npm|pnpm|yarn> config get registry

    实际输入命令的时候<>不用加,选一个在括号里的就好

    Git跟随系统Proxy

    上传到GitHub的时候,都是timeout的报错,那么在不修改超时时间的情况下,一条命令把传输自动跟随系统的proxy:

    git config --global core.gitProxy "auto"
  • C语言初入门 —— 基础的杂记

    C语言初入门 —— 基础的杂记

    当你开始学其他语言,回头看Python。你会对Python之禅中“简单优于复杂”有所体会,Python太简洁了😂

    我目前是暑假自学状态,所以本笔记是融合了国际知名的《Harvard CS50x》和国内b站的《鹏哥C语言》。和以前学的Python有些结构重合的部分我就不再提了,文中有的会有些许疑问,我还在学习,若有记得不对的可以提出来哈~

    CS50x:写程序更关注于自己的想法,以及实现需要的函数、条件、循环、变量。

    C语言学习笔记

    //头文件:引入标准输入输出库stdio是缩写,不要拼成studio!
    #include <stdio.h>

    C语言中的变量要先声明变量类型

    main函数是程序的入口 ,C语言程序是从main函数的第一行开始执行。且一个项目中只能有一个main(),一个项目不代表一个文件。

    printf("填入占位符\n", 占位符要代表的)
     //%c,%f,%s,%d这类是占位符。当然也可以直接用。
    

    语言的char单字符数字类型,应当用单引号括住单字符,双引号可以用于字符串(或零字符的字符串)

    字符的本质就是ASCII编码。

    printf("%c\n",'a');
    printf("%c\n",97);//两者输出结果相同
    

    C语言字符串中个特殊的知识,就是在字符串的末尾隐藏放着一这个\0字符是字符串的结束标志。 所以打印函数或者计算字符串长度strlen()的函数会在遇到此字符后停止打印或计算。 观察方法:F10+调试-窗口-监视,填入字符串并展开即可看到。 没有\0字符的情况有可能使用了字符数组

    char arr[] = {'a','b','c','d','e','f'};
    printf("%s\n",arr);
    //但是输出就会没有终止,往往打印的时候后面会尾随乱码。为了避免这种情况,在字符数组后要自己手动添加\0
    char arr[] = {'a','b','c','d','e','f','\0'};

    strlen()string.h的库函数(需要include),统计的就是\0前的字符个数(不计\0本身) 函数本身返回的是size_t类型的,所以占位符最好换成%zd

    C语言中的switch也是代表选择结构的关键字之一

    C语言中还有do while循环

    转向语句:break语句、goto语句、continue语句、return语句

    行内注释用//,多行的要用/* */

    PythonC
    elifelse if
    or||
    and&&
    i+=1 / i-=1可用左边的形式,
    但若每次都加1则可表达为i++ / i–

    C语言的各种数据类型都有自己的长度,计算操作符数用sizeof(),其返回C语言规定是只能是无符号整数(0和正整数),为了统一各系统返回值类型,定义了 size_t 类型来表示,故没有规定具体的类型:unsigned intunsigned long long等。括号内如果放的是表达式,则不会真实地计算。

    signed和unsigned:sign能表示正负数,unsign即无符号

    char不确定是否有无符号,取决于编译器的实现。大部分的情况char == unsigned char

    int默认是signed,且打印的占位符为%d。(unsigned打印占位符为%u)

    数据类型——模具 ,C语言中变量需要声明数据类型,若有给初始值的过程即初始化。无初始化的话不能让你用。已有初始化后又给值那就叫赋值。

    float num = 3.14f;

    全局变量在花括号外,局部变量在花括号内,局部值优先。

    除号 / 两端都是整数,即为整数除法(且结果也为整数-只有整数部分丢弃小数部分)

    负数取模的规则是,结果的正负号由第一个运算数的正负号决定

    连续赋值,从右往左赋

    单目操作符(++,–等),之前讲的符号中两边都要跟东西的是双目操作符

    环境配置

    《鹏哥C语言》中是用VS2022来教学的,还有关于scanf()函数的配置问题,我写到Gitee Wiki中了。

    but,我要强推CS50x课程对教学用IDE的解决方案!
    (国外的讲师深知教学应该更重于idea和实现的代码,而非前期的繁杂的环境配置)

    课程中使用了远程VSCode作为编辑器,并且云端已经全部搭建好C语言的环境了,开箱即用!
    这样的CodeSpace可以通过Github登录授权后拥有:https://cs50.dev
    (至于速度的话,你都能流畅在YouTube上看课了,同样网络环境下打开这链接,速度还是快的)

    对于编译的操作还简化了很多,编译一个hello.c只需下面两条命令

    make hello
    ./hello

    (后面课程Arrays中介绍了make实际上是clang的自动执行脚本,笔记)

    同时侧边栏安装了一个图标是一个爱quack叫的吉祥物鸭子的插件,点开一看,是个免费的AIChat!
    不过,它的回答只能是英文的哦~ 基本上是能看懂滴

    如下,这只鸭子的回答真的很喜欢quack🦆,也有可以在线使用的地方:https://cs50.ai/chat

    还有安装Docker,也许后面的课程还会教项目的上线吧。

  • 【杂谈】真的需要系统地学那么多编程语言吗?

    我目前是个准大一,专业为计算机类(待分流)。

    你看,

    大学课程学的是C语言,打竞赛学的是C++,为了找工作学Java。

    这三门语言每一门的不论是系统课程还是成套书籍,真的很多很多,真的有必要投入很大时间到这个上面去系统学习每门语言吗?

    况且,

    AI时代的来临,AI可以开始教你写代码了,那哼哧哼哧学的传统系统课程是不是就没啥必要了呢?

    AI的教法直接是以你的目的需求为导向,而系统课程是全方位的考虑到各种需求的人群。

    所以,谁能指条明路呀?

  • Java上的HelloWorld,怎么这么多细节?

    Java上的HelloWorld,怎么这么多细节?

    课程链接见下(不是推广,只是优秀的课程应该被广泛传播。)

    本文就只列了一些课程重点和我踩过的一堆坑,新手学Java,我们相互学习交流。

    Java的跨平台性

    核心机制(JVM):

    1)JVM是一个虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指令管理数据、内存、寄存器,包含在JDK中。
    2)对于不同的平台,有不同的虚拟机。
    3)Java虚拟机机制屏蔽了底层运行平台的差别,实现了“一次编译,到处运行”(跨平台)。

    编译和运行流程:

    注意命令!javac是编译,java才是运行。*.java为源文件,*.class为字节码文件。

    若程序无错是无任何提示,默默地在同目录下生成字节码文件。但是有错会报错在cmd,无法编译。

    运行的本质是把字节码文件装载到JVM虚拟机内执行。

    修改后的源文件需要重新编译,才能在再执行中生效。(并非前端的所改即得)

    Hello World!

    public class Hello {
        public static void main(String[] args) {
          System.out.println("Hello World!");
      }
    }

    细节,注意!有的是真实踩过的坑,有的是老师的提醒。

    • print后面的字母是小写的L,即l。意为line“(行),在输出之后会自动添加一个换行符(\n。若不慎打成了printIn则会报错提示找不到这个方法。Java语言严格区分大小写
      有关打印到屏幕上的方法就System.out.println()System.out.print()
    • main(){}间的空格是为了编程规范,程序能跑,但适当的空格有利于协作者的阅读。
    • 但是Java应用程序的执行入口是main()方法。
      它有固定的书写格式public static void main(String[] args)(…)
    • 每条花括号内的语句的后面要以;分号结束,凡是括号都是成对出现的。
    • public class后的类名要和文件名保持一致(因为Java类 Hello 被声明为 public
    • 注意在编译时cmd窗口的代码页编码和代码编辑器中显示的文件编码是否相同(以下可展开)
    • 若输出内容包含中文,务必要设置中文编码GBKUTF-8
    如何查看cmd窗口的代码页编码?

    右键cmd窗口标题栏,属性→当前代码页

    不推荐更改代码页编码,其更改注册表比较繁琐。文件转编码其实更快。

    如何按指定编码保存?

    以VSCode编辑器为例,

    执行命令依次为

    javac Hello.java
    java Hello

    注意后面的指令不用带.class后缀,因为类的名字就是Hello

    其他Tips

    • 编译后,源文件中每一个类都会对应每一个字节码文件,对应依据就是同名
    • 【再提一下】如果源文件包含一个public类则文件名必须按该类名命名!
    • 一个源文件中最多只能有一个public类。其它类的个数不限。也可以将main方法写在非public类中,然后指定运行非public类,这样入口方法就是非public的main方法。main可以在不同类中。