技术修罗场:当AI开始卷死同行

deepseek

最近比较忙,今天才嚼着外卖送的机械制式早餐吃了deepseek爆火的瓜。

这年头连算法推荐的快餐都在玩排列组合式创新。当看到"某AI被另一个AI卷失业"的标题,恍惚间以为打开了科技版《甄嬛传》:昨天还在给人类做PPT的AI,今天竟被新模型夺了宫斗冠军的宝座。

梁文峰那句"技术没有秘密"像极了奶茶店的公开配方表,谁都能看到奶盖和茶底的比例,但隔壁街模仿者做出来的永远是工业糖精味。
行业里每天诞生37个"中国版ChatGPT",可真正跑通代码那刻才会发现:开源框架是敞亮的橱窗,而核心数据才是后厨那锅熬了180天的老卤——闻着香,复制难。

这场AI马拉松里,参赛者们的起跑线早已被Ctrl+C/V抹平差距。但总有人在别人调参摸鱼时,默默给模型喂了300TB垂类数据;当同行用公开论文速成时,有人把服务器跑到冒烟只为优化0.01%的准确率。
就像手游里的氪金玩家,表面都是648抽卡,暗地里有人靠肝,有人真靠玄学。

看着GitHub上参数量以指数级膨胀的模型,我突然理解了科技圈的生存法则:这里没有永恒的神话,只有用算力铺就的护城河。
当某个凌晨三点,某位工程师第108次修正损失函数时,或许他正在铸造这个时代真正的技术货币——不是代码本身,而是烧在显卡里的那5000小时试错成本。

必应每日壁纸的API,基于PHP。

源码

<?php
date_default_timezone_set("UTC");//世界标准时间
#date_default_timezone_set("GMT");//格林尼治标准时间
#date_default_timezone_set("PRC");//北京时间
$requestUri = $_SERVER['REQUEST_URI'];
$decodedUrl = urldecode($requestUri);
$req_uri = explode('/',$decodedUrl);
$idx = $req_uri[2];
$region = $req_uri[3];
if (empty($req_uri[4])){
    $size = '1920x1080';
    $format = 'webp';
} else {
    $size = $req_uri[4];
    $format = empty($req_uri[5])?'jpg':$req_uri[5];
}
if ($region == 'CN'){
     $region = 'zh-CN';
} else if ($region == 'JP'){
     $region = 'ja-jp';
} else if ($region == 'US'){
     $region = 'en-US';
} else if ($region == 'CA'){
     $region = 'en-ca';
}
if ($size == 'PC'){
     $size = '1920x1080';
} else if ($size == '4K'){
     $size = 'UHD';
} else if ($size == 'mobile'){
     $size = '1080x1920';
}
$json_url = 'https://global.bing.com/HPImageArchive.aspx?format=js&idx='.$idx.'&n=1&setlang=en&mkt='.$region;
#zh-Hans;ja
#$data = file_get_contents($url);
$ch = curl_init($json_url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
$UserAgent = 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36 Edg/116.0.1938.62';
curl_setopt($ch, CURLOPT_USERAGENT, $UserAgent);
$data = curl_exec($ch);
curl_close($ch);
if (curl_error($ch)) {
    echo 'CURL请求失败'.$errorMessage;
    exit;
}
$json_data = json_decode($data,true);
$link = trim($json_data['images'][0]['urlbase']);
$image_url = 'https://global.bing.com'.$link.'_'.$size.'.'.$format;
header("Content-Type: image/jpeg");
header("location: $image_url");
#readfile($image_url);
exit;
?>

调用方法

# 日期
当天 0(默认)
昨天 1
前天 2
……
往前第七天:7
# 国家
服务器归属地:[默认]
中国:CN | zh-CN
日本:JP | ja-jp
美国:US | en-US
加拿大:CA | en-ca
其它:[请自行探索]
# 尺寸
1920x1080:[默认] | PC | 1920x1080
3840x2160:4K | UHD
1080x1920:mobile | 1080x1920
其它:[请自行探索]
# 图片格式
webp:[默认] | webp
jpg:[单独留空] | jpg
# 格式
最简格式:(国家根据服务器IP而定)
https://api.wheiss.com/bing_daily
简化格式:
https://api.wheiss.com/bing_daily/[日期]/[国家]
完全格式:
https://api.wheiss.com/bing_daily/[日期]/[国家]/[尺寸]/[图片格式]
# 举例
今天中国的必应电脑壁纸:
https://api.wheiss.com/bing_daily/0/CN
https://api.wheiss.com/bing_daily/0/zh-CN/1920x1080/webp
今天日本的必应手机壁纸:
https://api.wheiss.com/bing_daily/0/JP/mobile/webp
https://api.wheiss.com/bing_daily/0/ja-jp/1080x1920/webp
昨天加拿大的必应4K壁纸:
https://api.wheiss.com/bing_daily/1/CA/4K
https://api.wheiss.com/bing_daily/1/en-ca/UHD/jpg

转载自https://www.wheiss.com/original/bing-daily/

Windows安装pycharm教程。

下载安装文件

进入PyCharm官网,下载安装文件。

下载

安装PyCharm

由于安装过程都是中文的,这里就仅展示部分界面,打开安装包后下一步,在此页面按照下图勾选,其他选项根据需求自行勾选。

安装

安装完成后选择稍后重新启动,接下来我们打开软件进行 激活 以及 汉化

激活&汉化

在首次打开软件时会进行一些询问,按照下图勾选继续。

1

2

选择试用软件。

试用计划

选择试用后就可以关闭软件开始激活了。

激活

使用激活工具即可激活至2099年了,激活后即可正常使用。

激活

汉化

由于软件默认没有中文,需要安装插件来进行汉化,根据截图来操作即可。

安装中文语言包后点击 Restart IDE 重启即可生效。

汉化

关联Python

按照之前的Python安装教程后,PyCharm打开会自动关联Python环境,所以无需额外配置,自己有需求的可以尝试自定义环境。

vbs脚本下载。

众所周知的原因,此工具不提供下载,回复邮箱获取。

Windows安装Python教程。

下载Python安装文件

打开Python官网,下载安装文件。

需要指定版本可以点击All Releases,选择需要的版本下载。

下载

安装Python

双击下载的安装文件后按照下列截图勾选。

1

2

3

点击 install 安装Python。
等待进度条走完出现 Setup was successful 表示安装完成。

安装完成

验证安装

打开终端工具:通过快捷键 Win + r 输入 cmd 回车打开命令提示符。

验证安装

这个就是安装成功的提示,其中的 3.12.1 是你安装的版本,与教程不同属于正常现象。

当出现 >>> 代表安装成功了。

然后就可以安装自己喜欢的开发工具进行开发了,可以使用 VS Code Pycharm ,这些就是扩展操作了,后面有时间会写。

使用shell脚本自动备份文件到WebDAV,支持增量备份。

最近买的独服自己加了个2t的硬盘,装的pve开始玩,因为是小厂,最近在考虑备份的问题,如果是大厂就没这么多担忧了。

首先是网站以及docker,这个可以用面板来备份,pve虚拟机备份的话就不能用面板了。
看了下别人的方法,都不是很适合我,于是,开始琢磨手搓一个备份脚本。

可以备份多个目录的文件打包后传到alist挂载的网盘内,也可以是存储桶。
主要是相对网上大多数的方法而言,更加的简单灵活,但网站备份方面依赖面板的备份,当然也可以直接指定项目运行的目录,免去使用面板生成备份文件。

开始配置

首先在alist内挂载存储,可以是本地,也可以是网盘&存储桶,我现在用的是夸克网盘,因为虚拟机的快照过大,存储桶显然不是性价比最高的选择。
然后在alist设置→对象存储→生成id以及密钥→添加一个存储桶,设定名称以及选择你备份文件存储的网盘&存储桶(挂载网盘教程参考官方文档)。

image

然后复制粘贴代码保存到你想存储的目录下即可。

脚本模块示例:

/root/backup/
├── backup.sh          # 主脚本
├── config.conf        # 配置文件
├── logs/              # 日志目录
├── temp/              # 临时目录
└── snar/              # snar文件目录
    ├── dir1.snar     # 对应目录1的snar文件
    ├── dir2.snar     # 对应目录2的snar文件
    └── ...

备份流程:

  1. 读取配置文件
  2. 创建临时目录和日志目录
  3. 检查每个备份目录的变化
  4. 创建增量备份包
  5. 上传到WebDAV
  6. 清理临时文件
  7. 记录日志

WebDAV上传实现:

使用 curl 命令进行WebDAV操作
支持断点续传(未验证)
验证上传完整性

验证可行性

测试了小文件的上传,打包网站什么的自然没什么问题。
然后测试了把虚拟机备份上传到webdav,18G左右的快照,跑了一个多小时上传成功了,期间没有遇到大家说的webdav的断流
大文件应该也没什么问题了,开始贴代码。

测试日志

小型备份

image
大型备份

image

配置文件

# config.conf

# WebDAV配置
WEBDAV_URL="http://127.0.0.1:5244/dav"    # 此处根据实际情况修改,后缀/dav不要删除
WEBDAV_USER="username"
WEBDAV_PASS="password"

# 备份目录配置(空格分隔多个目录)
BACKUP_DIRS="/opt/1panel/backup/"

# 远程备份目录
REMOTE_BACKUP_DIR="/夸克/backup"    # 根据你的命名自行修改

# 其他配置
COMPRESS_LEVEL=6       # 压缩级别(1-9)
INCREMENTAL_BACKUP=false    # 是否启用增量备份

脚本代码

#backup.sh

#!/bin/bash

###################
# 常量定义
###################
SCRIPT_DIR="/root/tut_backup"
CONFIG_FILE="${SCRIPT_DIR}/config.conf"
LOG_DIR="${SCRIPT_DIR}/logs"
TEMP_DIR="${SCRIPT_DIR}/temp"
SNAR_DIR="${SCRIPT_DIR}/snar"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_PREFIX="backup_${DATE}"

# 全局变量,用于进度显示
CURRENT_FILE=""
CURRENT_PROGRESS=0
CURRENT_SPEED=0

###################
# 配置文件加载
###################
# 如果配置文件不存在,提示用户
if [ ! -f "$CONFIG_FILE" ]; then
    echo "请先配置 ${CONFIG_FILE} 文件"
    exit 1
fi

# 加载配置文件
source "$CONFIG_FILE"

###################
# 依赖检查
###################
check_dependencies() {
    local missing_deps=()

    # 检查必要的命令
    for cmd in bc curl tar; do
        if ! command -v "$cmd" >/dev/null 2>&1; then
            missing_deps+=("$cmd")
        fi
    done

    # 如果有缺失的依赖,提示用户安装
    if [ ${#missing_deps[@]} -ne 0 ]; then
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] 缺少必要的依赖,请手动安装: ${missing_deps[*]}"
        exit 1
    fi
}

###################
# 工具函数
###################
# 获取文件大小(字节)
get_file_size() {
    local file="$1"
    if [ -f "$file" ]; then
        stat --format="%s" "$file"
    else
        echo "0"
    fi
}

# 格式化大小
format_size() {
    local size=$1
    if [ -z "$size" ] || [ "$size" -eq 0 ]; then
        echo "0B"
        return
    fi

    if [ "$size" -ge 1073741824 ]; then
        echo "$(echo "scale=2; $size/1073741824" | bc)GB"
    elif [ "$size" -ge 1048576 ]; then
        echo "$(echo "scale=2; $size/1048576" | bc)MB"
    elif [ "$size" -ge 1024 ]; then
        echo "$(echo "scale=2; $size/1024" | bc)KB"
    else
        echo "${size}B"
    fi
}

# 控制台输出函数
console_log() {
    local level=$1
    local message=$2
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [${level}] ${message}"
}

# 计算传输速度
calculate_speed() {
    local bytes=$1
    local seconds=$2

    if [ "$seconds" -eq 0 ] || [ "$bytes" -eq 0 ]; then
        echo "0"
        return
    fi

    local speed=$((bytes / seconds))
    format_size "$speed"
}

# 进度条显示函数
show_progress() {
    local current=$1
    local total=$2
    local speed=$3
    local width=50

    # 防止除以零错误
    if [ "$total" -eq 0 ] || [ -z "$total" ]; then
        return
    fi

    local percentage=$((current * 100 / total))
    local filled=$((percentage * width / 100))
    local empty=$((width - filled))

    # 确保filled和empty不为负数
    [ "$filled" -lt 0 ] && filled=0
    [ "$empty" -lt 0 ] && empty=0

    # 格式化显示
    printf "\r[$(date '+%Y-%m-%d %H:%M:%S')] [PROGRESS] "
    printf "%-30s " "$(basename "$CURRENT_FILE")"
    printf "["
    printf "%${filled}s" "" | tr ' ' '#'
    printf "%${empty}s" "" | tr ' ' '-'
    printf "] "
    printf "%3d%% " "$percentage"
    if [ -n "$speed" ]; then
        printf "%10s/s" "$speed"
    fi

    # 如果完成了,换行
    if [ "$current" -ge "$total" ]; then
        printf "\n"
    fi
}

# 日志函数
log() {
    local level=$1
    local message=$2
    local log_file="${LOG_DIR}/backup_${DATE}.log"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

    echo "[${timestamp}] [${level}] ${message}" >> "$log_file"

    case "$level" in
        "BACKUP")
            if [ -n "$3" ]; then
                local file_size=$(get_file_size "$3")
                echo "└── 备份文件大小: $(format_size "$file_size")" >> "$log_file"
            fi
            ;;
        "UPLOAD")
            if [ -n "$3" ]; then
                local file_size=$(get_file_size "$3")
                echo "├── 文件大小: $(format_size "$file_size")" >> "$log_file"
                echo "├── 开始时间: $timestamp" >> "$log_file"
            fi
            ;;
        "UPLOAD_COMPLETE")
            local start_time=$3
            local file=$4
            local end_time=$(date +%s)
            local duration=$((end_time - start_time))
            local file_size=$(get_file_size "$file")

            if [ "$duration" -gt 0 ] && [ "$file_size" -gt 0 ]; then
                local speed=$((file_size / duration))
                local formatted_speed=$(format_size "$speed")

                echo "├── 结束时间: $timestamp" >> "$log_file"
                echo "├── 耗时: ${duration} 秒" >> "$log_file"
                echo "├── 平均速度: ${formatted_speed}/s" >> "$log_file"
                echo "└── 传输完成" >> "$log_file"
            else
                echo "├── 结束时间: $timestamp" >> "$log_file"
                echo "└── 传输完成" >> "$log_file"
            fi
            ;;
    esac
}

###################
# 错误处理函数
###################
handle_error() {
    local error_message=$1
    console_log "ERROR" "$error_message"
    log "ERROR" "$error_message"
    cleanup
    exit 1
}

###################
# 清理函数
###################
cleanup() {
    console_log "INFO" "开始清理临时文件..."
    log "INFO" "开始清理临时文件..."

    # 清理临时文件
    rm -rf "${TEMP_DIR:?}"/*

    # 如果需要清理过期的本地日志,可以设定保留天数
    # 例如,保留最近 7 天的日志
    # 如果不需要清理日志,可以注释或删除以下代码
    find "$LOG_DIR" -type f -name "*.log" -mtime +7 -delete
}

###################
# WebDAV 操作函数
###################
# WebDAV上传函数
upload_to_webdav() {
    local file="$1"
    local remote_path="$2"
    local start_time=$(date +%s)

    CURRENT_FILE="$file"
    console_log "INFO" "开始上传: ${file} 到 ${remote_path}"
    log "UPLOAD" "开始上传: ${file} 到 ${remote_path}" "$file"

    # 创建远程目录
    curl -s -X MKCOL -u "${WEBDAV_USER}:${WEBDAV_PASS}" \
         "${WEBDAV_URL}${REMOTE_BACKUP_DIR}/${DATE}" >/dev/null 2>&1

    # 使用临时文件存储进度信息
    local progress_file="${TEMP_DIR}/progress_$$"

    # 获取文件大小
    local file_size=$(get_file_size "$file")

    # 启动后台进程监控上传进度
    (
        local last_size=0
        local last_time=$start_time

        while [ -f "$progress_file" ]; do
            if [ -f "$progress_file" ]; then
                local current_time=$(date +%s)
                local transferred=$(tail -n 1 "$progress_file" 2>/dev/null | grep -o '[0-9]*' || echo "0")

                if [ -n "$transferred" ] && [ "$transferred" -gt 0 ]; then
                    local time_diff=$((current_time - last_time))
                    local size_diff=$((transferred - last_size))

                    if [ "$time_diff" -gt 0 ]; then
                        local current_speed=$(calculate_speed "$size_diff" "$time_diff")
                        show_progress "$transferred" "$file_size" "$current_speed"

                        last_size=$transferred
                        last_time=$current_time
                    fi
                fi
            fi
            sleep 1
        done
    ) &

    # 上传文件
    curl -# -T "$file" \
         -u "${WEBDAV_USER}:${WEBDAV_PASS}" \
         -H "Expect:" \
         "${WEBDAV_URL}${remote_path}" \
         2>"$progress_file" || \
         handle_error "文件上传失败: ${file}"

    # 清理进度文件
    rm -f "$progress_file"

    # 计算总体平均速度
    local end_time=$(date +%s)
    local total_time=$((end_time - start_time))
    local total_size=$(get_file_size "$file")
    local avg_speed=$(calculate_speed "$total_size" "$total_time")

    # 显示100%进度
    show_progress "$total_size" "$total_size" "$avg_speed"

    console_log "INFO" "上传完成: ${file} (平均速度: ${avg_speed}/s)"
    log "UPLOAD_COMPLETE" "上传完成: ${file}" "$start_time" "$file"
}

###################
# 备份函数
###################
create_backup() {
    local dir="$1"
    local dir_name=$(basename "$dir")
    local snar_file="${SNAR_DIR}/${dir_name}.snar"
    local backup_file="${TEMP_DIR}/${BACKUP_PREFIX}_${dir_name}.tar.gz"
    local start_time=$(date +%s)

    console_log "INFO" "开始备份目录: ${dir}"
    log "BACKUP" "开始备份目录: ${dir}"

    if [ "$INCREMENTAL_BACKUP" = "true" ] && [ -f "$snar_file" ]; then
        console_log "INFO" "创建增量备份: ${dir}"
        log "INFO" "创建增量备份: ${dir}"
        tar czf "$backup_file" -g "$snar_file" "$dir" 2>/dev/null || \
            handle_error "创建增量备份失败: ${dir}"
    else
        console_log "INFO" "创建完整备份: ${dir}"
        log "INFO" "创建完整备份: ${dir}"
        if [ "$INCREMENTAL_BACKUP" = "true" ]; then
            tar czf "$backup_file" -g "$snar_file" "$dir" 2>/dev/null || \
                handle_error "创建完整备份失败: ${dir}"
        else
            tar czf "$backup_file" "$dir" 2>/dev/null || \
                handle_error "创建完整备份失败: ${dir}"
        fi
    fi

    local end_time=$(date +%s)
    local duration=$((end_time - start_time))

    console_log "INFO" "备份完成: ${dir} (耗时: ${duration} 秒)"
    log "BACKUP" "备份完成: ${dir}" "$backup_file"
    log "INFO" "备份耗时: ${duration} 秒"

    return 0
}

###################
# 主函数
###################
main() {
    # 检查依赖
    check_dependencies

    # 创建必要的目录
    mkdir -p "$LOG_DIR" "$TEMP_DIR" "$SNAR_DIR"

    console_log "INFO" "开始备份任务..."
    log "INFO" "开始备份任务..."

    # 检查配置
    if [ -z "$BACKUP_DIRS" ]; then
        handle_error "未配置备份目录"
    fi

    # 处理每个备份目录
    for dir in $BACKUP_DIRS; do
        if [ ! -d "$dir" ]; then
            console_log "WARN" "目录不存在,跳过: ${dir}"
            log "WARN" "目录不存在,跳过: ${dir}"
            continue
        fi

        # 创建备份
        create_backup "$dir"

        # 上传到WebDAV
        local dir_name=$(basename "$dir")
        local backup_file="${TEMP_DIR}/${BACKUP_PREFIX}_${dir_name}.tar.gz"
        upload_to_webdav "$backup_file" "${REMOTE_BACKUP_DIR}/${DATE}/${dir_name}.tar.gz"
    done

    # 清理
    cleanup

    console_log "INFO" "备份任务完成"
    log "INFO" "备份任务完成"
}

# 执行主函数
main "$@"

手动执行的ssh日志示例:

# 首次运行时会检查并安装所需依赖。
root@tut:~/tut_backup# /root/backup/backup.sh
[2024-12-22 04:43:45] [WARN] 正在安装必要的依赖: bc
[2024-12-22 07:12:19] [INFO] 开始备份任务...
[2024-12-22 07:12:19] [INFO] 开始备份目录: /opt/1panel/backup/
[2024-12-22 07:12:19] [INFO] 创建增量备份: /opt/1panel/backup/
[2024-12-22 07:12:36] [INFO] 备份完成: /opt/1panel/backup/ (耗时: 17 秒)
[2024-12-22 07:12:36] [INFO] 开始上传: /root/backup/temp/backup_20241222_071219_backup.tar.gz 到 /夸克/backup/20241222_071219/backup.tar.gz
[2024-12-22 07:14:07] [PROGRESS] backup_20241222_071219_backup.tar.gz [##################################################] 100%     3.82MB/s
[2024-12-22 07:14:07] [INFO] 上传完成: /root/backup/temp/backup_20241222_071219_backup.tar.gz (平均速度: 3.82MB/s)
[2024-12-22 07:14:07] [INFO] 开始清理临时文件...
[2024-12-22 07:14:07] [INFO] 备份任务完成

Web新特性 Screen Wake Lock API

阻止屏幕黑屏休眠

今天上网冲浪时发现了Chrome和Safari浏览器都支持了名为Screen Wake Lock的API,可以设置Web网页打开的状态下,显示器屏幕不会自动休眠。

Screen Wake Lock API(屏幕唤醒锁API)允许网页应用程序防止设备屏幕自动变暗或锁定,适用于需要保持屏幕常亮的场景,例如阅读电子书、进行演示或跟随导航。

在特定网站内,可以有意想不到的效果,某项目介绍页面,进入演讲模式的时候,一定是不能息屏的。或者你有一些将教案的的需求应该也可以理解这个API的作用。

就可以使用这里的Screen Wake Lock API了。

语法与使用

要想屏幕保持唤起状态,很简单,一行代码的事情:

navigator.wakeLock.request('screen');

浏览器支持:目前大多数主流浏览器都已支持该API,但需要在安全环境(如HTTPS)下使用。这是传统方式的一个更好的替代方案。

但是,当页面最小化或者切换到非当前标签页时,Screen Wake Lock API 的锁定行为会被释放。这是因为浏览器的设计旨在保护用户的电池寿命和设备资源,当页面不再活跃时(比如被最小化或切换到后台),就会自动释放屏幕唤醒锁。

为了方便使用,当页面重新变为活动状态(例如用户切换回该标签页)时,可以通过事件监听器来重新请求 Screen Wake Lock。具体来说,可以监听 visibilitychange 事件,当页面变为可见时,重新申请屏幕唤醒锁。下面是一个简单的实现方法:

let wakeLock = null;

// 定义请求 Wake Lock 的函数
async function requestWakeLock() {
    try {
        wakeLock = await navigator.wakeLock.request('screen');
        console.log('屏幕唤醒锁已激活');

        // 监听 wake lock 被释放的情况,例如系统或用户动作
        wakeLock.addEventListener('release', () => {
            console.log('屏幕唤醒锁已释放');
        });
    } catch (err) {
        console.error(`错误: ${err.name}, ${err.message}`);
    }
}

// 监听页面的可见性变化
document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'visible') {
        // 当页面重新变为可见时,重新请求 Wake Lock
        requestWakeLock();
    } else if (wakeLock !== null) {
        // 页面不可见时,释放 wake lock
        wakeLock.release().then(() => {
            wakeLock = null;
            console.log('屏幕唤醒锁已手动释放');
        });
    }
});

// 初始请求 Wake Lock
requestWakeLock();

代码说明:

  1. requestWakeLock(): 定义了一个请求屏幕唤醒锁的函数,当请求成功时会保持屏幕常亮。

  2. visibilitychange 事件监听器: 当页面的可见性发生变化时触发。判断 document.visibilityState 是否为 'visible':
    · 如果页面重新变为可见状态,则再次调用 requestWakeLock() 重新申请屏幕唤醒锁。
    · 如果页面变为不可见且 Wake Lock 存在,则主动释放 Wake Lock。

  3. 自动释放处理: 通过监听 wakeLock 的 release 事件,可以知道 Wake Lock 何时被系统或其他原因释放。

这种方式可以在用户重新切回页面时自动重新申请唤醒锁,保持屏幕不熄灭。确保用户在使用你的应用时能持续保持屏幕的亮度,而不会因为页面切换而被中断。

要求 / 兼容性

此API要想生效,需要是https协议,或者是localhost本地环境。

目前Chrome和Safari浏览器均已经支持wake-lock特性,Firefox已经开启实验支持,按照历史经验,没多久就会正式支持了,此API全面使用指日可待。

QQ可用api接口整理。

查询好友纪念日

手机QQ内打开

https://h5.qzone.qq.com/friend/day/你的扣扣号/对方的扣扣号/friendDay?_wwv=90802&_nav_statusclr=

通过QQ号API获取用户高清QQ头像

接口示例末尾的可根据需要自行修改,100表示普通,640表示高清。

普通头像:

https://thirdqq.qlogo.cn/g?b=qq&nk=QQ号&s=100
https://q2.qlogo.cn/headimg_dl?dst_uin=QQ号&spec=100

高清头像:

https://qlogo1.store.qq.com/qzone/QQ号/QQ号/640

QQ线索

查看未添加QQ的共同好友信息,手机QQ内发送该链接打开。

https://ti.qq.com/friends/recall?uin=需要查询的QQ号

获取QQ群头像

https://p.qlogo.cn/gh/群号/群号/640/

快捷指令

另外我还为查询纪念日和QQ线索做了一个IOS的快捷指令。

QQ线索/纪念日查询

友情链接获取网站截图来判断网站是否可用

调用接口:

https://s0.wp.com/mshots/v1/$domain

HTML代码:

<div class="links">
    <img class="link_bg" src=""/>
    <a href="https://zhaowenlong.com/">links</a>
</div>

JS代码:

window.addEventListener('DOMContentLoaded', (event) => {
  const linkElements = document.querySelectorAll('.link');

  linkElements.forEach((linkElement) => {
    const anchorElement = linkElement.querySelector('a');

    if (anchorElement) {
      const href = anchorElement.getAttribute('href');
      const linkBgImage = linkElement.querySelector('.link_bg');

      if (linkBgImage) {
        linkBgImage.src = `https://s0.wp.com/mshots/v1/${encodeURIComponent(href)}`;
      }
    }
  });
});

添加适当的css即可正常显示了。

尝试使用 GPT-SoVITS 克隆喜欢的音色。

在GitHub上发现了 GPT-SoVITS 这个项目,它可以基于简短的语音进行训练,即可克隆出几乎一样的声音。

而且上手简单不需要你会编程基础,直接在webUI上即可完成声音的克隆。

需要搭建的环境作者也会在教程中说明,照做即可。

我自己测试直接从B站上下载了在追的番剧:凡人修仙传,提取了人物紫灵和主角韩立2分钟左右带背景音乐的音频进行训练,很轻松的就可以克隆出几乎一致的音色。

如果平时需要读稿子或者文案配音用该工具可以非常方便的生成想要的音频进行使用。

AI生成音频预览:

出于对原作者的尊重,我不会直接提供整合包的网盘链接。

有需要的可以联系作者 [花儿不哭](https://space.bilibili.com/5760446) 发私信获取,或者从 Github 下载。

使用VScode连接远程Linux服务器开发

我的环境:

本地环境:Windows11 专业版23H2
远程环境:Debian 11.1 64bit
VScode版本:VSCode-x64-1.85.2

注意:使用Linux低版本会不兼容,如CentOS7.6版本,降低你的vscode版本,或使用更新的Linux系统版本。

Remote-SSH安装和环境准备

首先安装VSCode,然后在扩展商店中搜索"Remote",安装搜索到的"Remote-SSH",安装完成后在vscode内添加新的Remote-SSH主机。

输入:

ssh root@ip //这里填写你的服务器ip

选择你的配置文件目录,然后打开你的配置文件。

Host 192.168.1.111  // 这里可以重命名
  HostName 192.168.1.111  // 这里是你的服务器ip
  User root

然后打开vscode尝试连接一下我们保存的服务器,这时会打开一个新的窗口,并且询问你连接的主机是什么系统,选择你服务器对应的系统,点击下一步,然后输入你的root帐户密码,然后会自动安装vscode服务器的server,安装成功后会自动连接,然后在该窗口新建一个终端。

// 使用组合键
Ctrl+Shift+`

生成PEM key

ssh-keygen -m PEM -t rsa -C "mykey" // 这里的备注可以写成其他的

这里会询问保存到哪里,直接下一步就可以。

// 示例
root@VM-12-7-debian:~# ssh-keygen -m PEM -t rsa -C "1c2g"
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:MqSZCxncAm4njJgO45inGJJuG6D4+JpyS9OyoIFXnWM 1c2g
The key's randomart image is:
+---[RSA 3072]----+
|.                |
|=+ .             |
|*=+.. .          |
|*+o+ * .         |
|Bo+ = E S        |
|O+ + o +         |
|O+= o            |
|+O++             |
|*==.             |
+----[SHA256]-----+
root@VM-12-7-debian:~# pwd  // 查看当前目录
/root
root@VM-12-7-debian:~# cd .ssh  // 进入.ssh目录
root@VM-12-7-debian:~/.ssh# ls  // 查看该目录下文件
authorized_keys  id_rsa  id_rsa.pub  // 这里会生成两个密钥,一个是公钥一个是私钥。

将公钥输出到authorized_keys

cat id_rsa.pub >> authorized_keys

至此,服务端的配置已经完成了。

本机配置

下载服务器生成的id_rsa私钥文件下载到本地,公钥之前我们已经部署在服务器上了,把私钥保存到你喜欢的地方,现在我们需要配置一下本地使用的是哪一个私钥。

// 修改你之前的配置文件,把密钥文件指定到你保存的目录下。
Host 2C4G
  HostName 192.168.1.111
  User root
  IdentityFile "C:\Users\bing\.ssh\keys\id_rsa" // 此处为你保存的密钥目录。

这样每次连接服务器就会用这个用户和私钥尝试去登陆服务器了。