最新发布
-
编译安装带 Brotli 压缩的 Nginx 安装依赖 apt install dpkg-dev curl gnupg2 build-essential zlib1g-dev libpcre3 libpcre3-dev unzip cmake -y下载编译源码 添加nginx源码库 添加 Nginx 密钥: curl -L https://nginx.org/keys/nginx_signing.key | apt-key add -添加密钥后,使用以下命令添加 Nginx 存储库: vim /etc/apt/sources.list.d/nginx.list添加如下内容 deb http://nginx.org/packages/ubuntu/ focal nginx deb-src http://nginx.org/packages/ubuntu/ focal nginx更新存储库 apt update -y 下载nginx Brotli 源文件 目录文件最好保持一致,在后续编译配置文件修改部分需要文件路径正确 cd /usr/local/src apt source nginx安装编译nginx所需要的文件 apt build-dep nginx -y从github下载 Brotli 源代码: git clone --recursive https://github.com/google/ngx_brotli.git 修改编译配置文件 修改Nginx 源并编辑 debian 规则文件添加 Brotli模块 : cd /usr/local/src/nginx-*/ vim debian/rules添加位置不同位置可能有些许不同,这里需要注意模块路径,也就是github下载 Brotli 源代码存储路径,如果位置不对需要自行修改 1.26.1版本 image-20240703160843201图片 1.22.1版本 其他版本添加位置也可能会有不同 --add-module=/usr/local/src/ngx_brotli 编译文件 使用以下命令编译并构建具有 ngx_brotli 支持的 nginx 包: dpkg-buildpackage -b -uc -us在编译时如果出现以下报错: /usr/bin/ld: cannot find -lbrotlienc /usr/bin/ld: cannot find -lbrotlicommon collect2: error: ld returned 1 exit status make[2]: *** [objs/Makefile:383: objs/nginx] Error 1 make[2]: Leaving directory '/usr/local/src/nginx-1.26.1/debian/build-nginx' make[1]: *** [Makefile:10: build] Error 2 make[1]: Leaving directory '/usr/local/src/nginx-1.26.1/debian/build-nginx' make: *** [debian/rules:62: build-arch.nginx] Error 2 dpkg-buildpackage: error: debian/rules build subprocess returned exit status 2image-20240703162706876图片 只需要编译编译一下brotli子模块即可 cd /usr/local/src/ngx_brotli/deps/brotli mkdir out cd out cmake -DCMAKE_BUILD_TYPE=Release .. makebrotli子模块编译完成后再执行编译命令 cd /usr/local/src/nginx-* dpkg-buildpackage -b -uc -us 若没有新的报错出现,在/usr/local/src就有可安装的deb软件包 安装 Nginx 并启用 Brotli 支持 安装软件包 cd /usr/local/src/ dpkg -i *.deb若软件无法安装,出现如下报错 image-20240703163851175图片 新nginx和原有的冲突,现在安装的nginx再重新安装即可 apt remove nginx apt --fix-broken install 启用Brotli 安装所有软件包后,编辑 Nginx 主配置文件并启用 Brotli 支持: vim /etc/nginx/nginx.conf在 http{ 下面添加以下行 brotli on; brotli_comp_level 6; brotli_static on; brotli_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/x-icon image/vnd.microsoft.icon image/bmp image/svg+xml;重新启动 Nginx 服务: systemctl restart nginx 验证 Nginx 和 Brotli curl -H 'Accept-Encoding: br' -I http://localhost如果一切正常,您将看到 brotli 支持的结果“content-encoding:br”,如下所示: 禁用nginx更新 将 nginx 标记为保持: sudo apt-mark hold nginx查看所有被标记为“保持”的包: apt-mark showhold取消“保持”状态,允许更新: sudo apt-mark unhold nginx
-
Obsidian多端快速同步插件 Obsidain插件安装 插件名称:Self-Hosted LiveSync 插件安装:Obsidian设置关闭在第三方插件中关闭安全模式胡直接搜索插件名安装 插件配置:要实现多端能够实时同步功能需要一台能够公网访问的服务器,以及需要自行安装配置后台,需要一定的计算机相关基础,可根据自己需求酌情选择是否要继续使用该插件: 以下过程可在搭建好后台程序后再根据步骤配置 找到插件相关配置 image-20240610001933032图片 配置远程库链接、用户名、密码 image-20240610002315828图片 配置同步模式 image-20240610002817722图片 可更具需要选择,我这里使用这个插件主要就是喜欢其能实时同步的功能,这里就选择LiveSync 后台同步库搭建 安装 docker环境 这里提供了docke和docker-compose两种方式,再不同服务器上的安装方式大体都一样,这里就不再赘述,详细安装步骤可参考Docker官网。 Install Docker Engine on Debian | Docker Docs 配置CouchDB 插件的同步功能需要依赖NoSQL 文档数据库,需要为Docker内的CouchDB提供配置 在任意位置创建配置文件,但是需要记住这个文件路径,后续需要将文件路径映射到docker中,例如:/root/Obsidian/couchdb/下创建文件local.ini [couchdb] single_node=true [chttpd] require_valid_user = true [chttpd_auth] require_valid_user = true authentication_redirect = /_utils/session.html [httpd] WWW-Authenticate = Basic realm="couchdb" enable_cors = true [cors] origins = app://obsidian.md,capacitor://localhost,http://localhost credentials = true headers = accept, authorization, content-type, origin, referer methods = GET, PUT, POST, HEAD, DELETE max_age = 3600 启动Docker容器: 这里提供了两种方法,可更具需要自行选择 docker命令方式 docker run --rm -it -e COUCHDB_USER=<username> -e COUCHDB_PASSWORD=<password> -v /root/Obsidian/couchdb/db:/opt/couchdb/data -v /root/Obsidian/couchdb/local.ini:/opt/couchdb/etc/local.ini -p 5984:5984 couchdb COUCHDB_USER 后面的<username>改为希望设置的用户名; COUCHDB_PASSWORD 后面的<password>改为希望设置的用户密码; /root/Obsidian/couchdb/local.ini 改为前述配置文件的外部路径; /root/Obsidian/couchdb/db 改为希望存放数据库文件夹的路径; -p 5984:5984 冒号前面的5984是希望暴露在外的端口,与前述防火墙放通的端口一致即可。 这些都需要记住,在配置插件时需要用到 docker-compose方式 version: '3.1' services: couchdb: image: couchdb container_name: <DB_NAME> restart: unless-stopped ports: - "5984:5984" environment: COUCHDB_USER: "<username>" COUCHDB_PASSWORD: "<password>" volumes: - /root/Obsidian/couchdb/data:/opt/couchdb/data - /root/Obsidian/couchdb/local.ini:/opt/couchdb/etc/local.ini启动命令 docker-compose up关闭命令 docker-compose down参数解释和docker方式的一样
-
TeoTag:在typecho中使用和butterfly一样的外挂标签 {% label 声明: red %} 绝大部分的样式都是hexo butterfly的原生样式,本人只是将功能在typecho中做了相应的移植。 {% link Butterfly,Butterfly,https://butterfly.js.org/ %} 我只是站在了巨人的肩膀上 为什么会有TeoTag 在此之前,博客使用了Hexo框架和Butterfly主题,文章内有很多样式都使用了Butterfly主题的写作语法;这两天将博客迁移到了typecho下,导致文章的很多非MarkDown格式内容都没法和原来一样正常显示,重新修改起来也比较麻烦,就想着把之前在Butterfly下的格式全部般过来,便有了TeoTag这个插件。 {% link TeoTag,github,https://github.com/mstzf/TeoTags %} 现有功能 Note Tabs label timeline link hideToggle 语法和渲染结果 和Butterfly一样的用法 Butterfly Note {% note simple %} 默认 提示块标签 {% endnote %} {% note default simple %} default 提示块标签 {% endnote %} {% note primary simple %} primary 提示块标签 {% endnote %} {% note success simple %} success 提示块标签 {% endnote %} {% note info simple %} info 提示块标签 {% endnote %} {% note warning simple %} warning 提示块标签 {% endnote %} {% note danger simple %} danger 提示块标签 {% endnote %} {% note simple %} 默认 提示块标签 {% endnote %} {% note default simple %} default 提示块标签 {% endnote %} {% note primary simple %} primary 提示块标签 {% endnote %} {% note success simple %} success 提示块标签 {% endnote %} {% note info simple %} info 提示块标签 {% endnote %} {% note warning simple %} warning 提示块标签 {% endnote %} {% note danger simple %} danger 提示块标签 {% endnote %} Tabs {% tabs test1 %} <!-- tab --> **This is Tab 1.** <!-- endtab --> <!-- tab --> **This is Tab 2.** <!-- endtab --> <!-- tab --> **This is Tab 3.** <!-- endtab --> {% endtabs %}{% tabs test1 %} This is Tab 1. This is Tab 2. This is Tab 3. {% endtabs %} {% tabs test2, 3 %} <!-- tab --> **This is Tab 1.** <!-- endtab --> <!-- tab --> **This is Tab 2.** <!-- endtab --> <!-- tab --> **This is Tab 3.** <!-- endtab --> {% endtabs %}{% tabs test2, 3 %} This is Tab 1. This is Tab 2. This is Tab 3. {% endtabs %} {% tabs test3, -1 %} <!-- tab --> **This is Tab 1.** <!-- endtab --> <!-- tab --> **This is Tab 2.** <!-- endtab --> <!-- tab --> **This is Tab 3.** <!-- endtab --> {% endtabs %}{% tabs test3, -1 %} This is Tab 1. This is Tab 2. This is Tab 3. {% endtabs %} {% tabs test4 %} <!-- tab 第一个Tab --> **tab名字为第一个Tab** <!-- endtab --> <!-- tab @fab fa-apple-pay --> **只有图标 没有Tab名字** <!-- endtab --> <!-- tab 炸弹@fas fa-bomb --> **名字+icon** <!-- endtab --> {% endtabs %}{% tabs test4 %} tab名字为第一个Tab 只有图标 没有Tab名字 名字+icon {% endtabs %} label 臣亮言:{% label 先帝 %}创业未半,而{% label 中道崩殂 blue %}。今天下三分,{% label 益州疲敝 pink %},此诚{% label 危急存亡之秋 red %}也!然侍衞之臣,不懈于内;{% label 忠志之士 purple %},忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气;不宜妄自菲薄,引喻失义,以塞忠谏之路也。 宫中、府中,俱为一体;陟罚臧否,不宜异同。若有{% label 作奸 orange %}、{% label 犯科 green %},及为忠善者,宜付有司,论其刑赏,以昭陛下平明之治;不宜偏私,使内外异法也。臣亮言:{% label 先帝 %}创业未半,而{% label 中道崩殂 blue %}。今天下三分,{% label 益州疲敝 pink %},此诚{% label 危急存亡之秋 red %}也!然侍衞之臣,不懈于内;{% label 忠志之士 purple %},忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气;不宜妄自菲薄,引喻失义,以塞忠谏之路也。 宫中、府中,俱为一体;陟罚臧否,不宜异同。若有{% label 作奸 orange %}、{% label 犯科 green %},及为忠善者,宜付有司,论其刑赏,以昭陛下平明之治;不宜偏私,使内外异法也。 timeline {% timeline 2022 %} <!-- timeline 01-02 --> 这是测试页面 <!-- endtimeline --> {% endtimeline %}{% timeline 2022 %} 这是测试页面 {% endtimeline %} {% timeline 2022,pink %} <!-- timeline 01-02 --> 这是测试页面 <!-- endtimeline --> {% endtimeline %}{% timeline 2022,pink %} 这是测试页面 {% endtimeline %} 颜色可取: blue pink red purple orange green link 这部分使用的是 (张洪Heo - 分享设计与科技生活 (zhheo.com)) 的样式 {% link 获取网站的Favicon图标并显示在你的网页上,owen0o0,https://github.com/owen0o0/getFavicon %}{% link 获取网站的Favicon图标并显示在你的网页上,owen0o0,https://github.com/owen0o0/getFavicon %} {% link TeohZY,TeohZY,https://blog.teohzy.com %}{% link TeohZY,TeohZY,https://blog.teohzy.com %} hideToggle {% hideToggle 标题 %} 内容1 内容2 内容3 {% endhideToggle %}{% hideToggle 标题 %} 内容1 内容2 内容3 {% endhideToggle %}
-
树莓派+EC20模块实现连接蜂窝网和短信收发 软硬件 树莓派 ec20 wvdial gammu SIM卡 EC20模块 概述 EC20-CE是移远通信最近推出的LTE Cat 4无线通信模块,采用LTE 3GPP Release 11 技术,支持最大下行速率 150 Mbps和最大上行速率50 Mbps;同时在封装上兼容移远通信多网络制式LTE EC21系列、EC25系列和EG25-G 模块,实现了3G网络与4G网络之间的无缝切换。 EC20-CE采用镭雕工艺,镭雕工艺具有外观更漂亮、金属质感强、散热更好、信息不容易被抹除、更能适应自动化需求等优点。 EC20-CE内置多星座高精度定位GNSS(GPS/GLONASS/BDS/Galileo/QZSS)接收机;在简化产品设计的同时,还大大提升了定位速度及精度。 EC20-CE内置丰富的网络协议,集成多个工业标准接口,并支持多种驱动和软件功能(适用于Windows 7/8/8.1/10/11、Linux、Android等操作系统下的USB驱动等),极大地拓展了EC20-CE在M2M领域的应用范围,如CPE、路由器、数据卡、平板电脑、车载、智能安全以及工业级PDA等。 产品特性 更多详情可到官网查看 {%link LTE EC20-CE,QUECTEL,https://www.quectel.com.cn/product/lte-ec20-ce %} 产品手册 Quectel_Product_Brochure_CN_V7.8) 查看设备是否挂载成功 使用命令 sudo ls /dev |grep ttyUSB挂载成功会有如图输出 要是没有看到设备则检查设备是否稳定插入、更换USB口或者重启设备之后再重新使用命令查看 拨号上网 wvdial 安装 wvdial是一个方便使用的PPP拨号模块,它能调用调制调节器,并通过PPP上网,无需像手动拨号一样配置繁琐的文件 sudo apt update sudo apt install wvdial 配置 修改配置文件 sudo vim /etc/wvdial.conf 可以继续使用 [Dialer Defaults]也可以重新根据自己需要添加,我这里为了没有多余手机卡,也为了方便输入命令,就直接使用 电信/移动SIM卡使用以下配置 [Dialer Defaults] Init1 = ATZ Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 Modem Type = Analog Modem Modem = /dev/ttyUSB3 Baud = 115200 New PPPD = yes ISDN = 0 Phone = *99# Username = card Password = card联通卡使用以下配置 [Dialer Defaults] Init1 = ATZ Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 Init3 = at+cgdcont=1,"ip","uninet" Modem Type = Analog Modem Modem = /dev/ttyUSB3 Baud = 115200 New PPPD = yes ISDN = 0 Phone = *99# Password = card Username = card配置来源于 Quectel EC20 在 Linux 上的使用 在配置文件中大部分都不需要自己调整,只有Modem和Baud需要根据自己设备情况进行调整 Modem:根据情况选择合适的设备我的这个ttyUSB2和ttyUSB3都能正常使用 Baud:根据情况选择合适的波特率,对于ec20来说9600-115200都可以 启动wvdial sudo wvdial 查看网络设备 ifconfig 可以看到多了ppp0和wwan0两个设备 正常情况还无法访问网络,因为默认路由在其他网络设备中,需要重新配置路由 配置路由 查看路由 sudo route配置路由的方式有很多种,我这里的方法比较简单粗暴,需要具体配置的可自己查找方法 sudo route add default dev ppp0该命令会在路由表中添加一条新的默认路由 在每次重启后都会刷新路由,可以将命令加到/etc/rc.local中,每次开机都执行添加方法 sudo vim /etc/rc.local在exit 0前添加 su - root -c `route add default dev ppp0`通过systemctl来管理wvdial 开机自启wvdial的方法有很多种,并不一定要使用systemctl 最简单的就是和添加路由一样,在/etc/rc.local中添加启动命令 sudo vim /etc/rc.local # 添加 wvdial & 编写控制wvdial启动和检测wvdial运行脚本 新建sh脚本文件,可以放到你想存放的地方 我这里在root用户下/root/shell中 sudo mkdir /root/shell && cd shell # 名字可以任起 sudo vim onwvdial.shwvdial控制脚本内容 #!/bin/bash DEVICE_NAME="/dev/ttyUSB3" # 和wvdial配置设备一致 LOG_FILE="/var/log/wvdial_on.log" # 日志文件存储位置 PROCESS_NAME=(wvdial pppd) # 需检查占用软件 # 定义函数检查进程是否占用设备 check_device_usage() { local process_name=$1 local device=$2 local pids=$(pgrep -f "$process_name") if [ -z "$pids" ]; then return fi for pid in $pids; do echo "pid:$pid" local device_count=$(lsof -p "$pid" 2>/dev/null | grep -e "$device" | wc -l) if [ "$device_count" -gt 0 ]; then echo "占用设备:$device" kill $pid fi done return } function check_wvdial() { if pgrep -x "wvdial" >/dev/null; then return 0 # wvdial 进程在运行 else return 1 # wvdial 进程未运行 fi } for process in $PROCESS_NAME; do echo "进程名: $process" check_device_usage $process $DEVICE_NAME done wvdial >> "$LOG_FILE" 2>&1 & route add default dev ppp0 while true;do if ! check_wvdial;then echo "$(date +"%Y-%m-%d %H:%M:%S") - wvdial 进程未运行,正在重新启动..." >> "$LOG_FILE" wvdial >> "$LOG_FILE" 2>&1 & fi sleep 120 done该脚本包含功能: 停止wvdial启动前所需设备的占用 启动wvdial 添加ppp0默认路由 每120秒检测wvdial是否运行 记录启动、错误日志 设置可执行权限 sudo chmod u+x /root/shell/onwvdial.sh 编写systemctl控制文件 sudo vim /etc/systemd/system/wvdial_on.service配置文件内容如下: [Unit] Description=Safe Start Wvadil After=dev-ttyUSB3.device Requires=dev-ttyUSB3.device [Service] User=root Group=root ExecStart=/root/shell/onwvdial.sh # 路径根据自己配置修改 [Install] WantedBy=multi-user.target 启动服务 systemctl daemon-reload systemctl start wvdial_on.service systemctl enable wvdial_on.service设置自启动后就不需要在/etc/rc.local中添加修改路由和启动wvdial命令了 配置防火墙 如果在ec20模块连接4G网络后还需要使用wifi则需要配置防火墙,不需要则不用配置 sudo iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE sudo iptables -A FORWARD -i ppp0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT sudo iptables -A FORWARD -i wlan0 -o ppp0 -j ACCEPT 将防火墙规则写入文件 sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"顺序执行命令即可 收发短信 安装软件gammu sudo apt install gammu gammu-smsd 配置gammu 使用命令 sudo gammu-config配置可参考我的 或者直接修改/root/.gammurc,效果是一样的 如果没有/root/.gammurc文件就使用命令 [gammu] port = /dev/ttyUSB2 model = connection = at19200 synchronizetime = yes logfile = logformat = nothing use_locking = no gammuloc =修改 /etc/gammu-smsdrc [gammu] # Please configure this! port = /dev/ttyUSB2 connection = at19200 # Debugging #logformat = textall # SMSD configuration, see gammu-smsdrc(5) [smsd] service = files logfile = syslog RunOnReceive = /root/msmtp/sh/send-smsd.sh # 发送邮件脚本 # Increase for debugging information debug = yes #debuglevel = 0 # Paths where messages are stored inboxpath = /var/spool/gammu/inbox/ outboxpath = /var/spool/gammu/outbox/ sentsmspath = /var/spool/gammu/sent/ errorsmspath = /var/spool/gammu/error/ 编辑收到短信后自动发送邮件脚本 树莓派配置邮件这里不再赘述,可以自行搜索,或者参考我之前的一篇博客 {% link 树莓派开机自动发送邮件,TeohZY,https://blog.teohzy.com/posts/smpxjfsyj/ %} 编辑脚本 vim /root/msmtp/sh/send-smsd.sh文件路径根据自己需要修改 #!/bin/bash for i in `seq $SMS_MESSAGES` ; do if [ $i -eq 1 ]; then phone="$SMS_1_NUMBER" fi tmp="$(eval echo '$'SMS_${i}_TEXT)" message="$text$tmp" done echo "$message" |mutt -s "树莓派短信转发" xxx@163.com 重启gammu systemctl restart gammu-smsd.service 短信测试 向目标号码发送短信后邮箱能收到短信 通过终端向其他号码发送短信 gammu-smsd-inject TEXT 目标号码 -text '短信内容' -unicode如果收到短信说明配置成功 短信发送失败踩坑 查看端口占用 sudo lsof /dev/ttyUSB2如果有其他进程和gammu-sms占用设备,可以使用kill命令结束非必须进程 设备波特率和wvdial重复 检查wvdial配置和gammu配置,如果wvdial已经使用了ttyUSB3和波特率115200则gammu配置中就不要再使用相同设备和波特率,可以使用ttyUSB2和波特率at19200 ModemManager占用设备 查看设备后发现有进程ModemMnana在使用设备,可以停用ModemManager 需要考虑实际使用情况来判断,在确认ModemManager确实不是必要软件后再进行操作 sudo systemctl disable ModemManager.service sudo systemctl stop ModemManager.service
-
树莓派访客拍照C语言版 前引 不知道因为什么原因Picamera2包调用摄像头拍照,在一个程序中达到一定次数之后就会导致系统的内存泄漏,除了重启软件没有什么好的方法来解决,但作为一个监控性质的软件,经常发生这种错误还是比较无法接受的事情。 因此决定看看能不能直接使用C语言来完成监控人员到访和录像这一系列动作 代码 代码部分十分简单 #include <pigpio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/wait.h> #include <time.h> int pinNumber = 18; int getVideo(){ time_t timep; struct tm *p; char filePath[28]; time (&timep); p=gmtime(&timep); int hour = 8+p->tm_hour; sprintf(filePath,"%s%d%02d%02d%02d%02d%02d%s","/Disk/MyCloud/Stream/Safe/",1900+p->tm_year,1+p->tm_mon,p->tm_mday,(hour>=24)?(hour-24):hour,p->tm_min,p->tm_sec,".mp4"); char command[1000]; sprintf(command,"%s%s%s%s", "libcamera-vid -t 5000 --width 1280 --height 720 --codec libav -o ",filePath," && sudo chown www-data ",filePath); return system(command); } int main() { int value = 0; if (gpioInitialise() < 0) { printf("pigpio initialization failed\n"); return 1; } gpioSetMode(pinNumber, PI_INPUT); while(1){ value = gpioRead(pinNumber); if(value==1){ getVideo(); } time_sleep(1.0); } gpioTerminate(); return 0; }由于在之前 使用的GPIO库wiringPi.h已经暂停维护,在新版的树莓派系统中不在默认安装,这里使用了pigpio.h库 如果没有安装 sudo apt update sudo apt install pigpio 编译 gcc monitor.c -o monitor -lpigpio -lrt -lpthread 引脚编号 默认为BCM编号 主要拍照代码 system(command)实际是为了调用系统的libcamera-vid 即 sprintf(command,"%s%s%s%s", "libcamera-vid -t 5000 --codec libav -o ",filePath," && sudo chown www-data ",filePath);这部分代码为录一个5秒的视频并保存到filePath目录下,同时修改视频权限方便给Nextcloud修改查看 人体红外代码 int value = 0; if (gpioInitialise() < 0) { printf("pigpio initialization failed\n"); return 1; } gpioSetMode(pinNumber, PI_INPUT); while(1){ value = gpioRead(pinNumber); if(value==1){ getVideo(); } time_sleep(1.0); } gpioTerminate();当有人到访时输出高电平,检测到高电平时触发录像
-
堆叠轮播图(color ui原生小程序代码优化) {% note info simple %} 界面内容并非本人原创,只是适配了原生小程序代码 {% endnote %} 最近找了一些小程序的组件库,发现了Color UI界面和色彩搭配都比较符合我的需求,但是在进一步了解的时候发现这个项目已经停更了很长时间,有一部分功能已经无法正常使用。 感兴趣的可以到作者仓库看看 {% link coloruicss,github,https://github.com/weilanwl/coloruicss?tab=readme-ov-file %} 项目中的堆叠轮播图挺好看,但是没有原生小程序代码,故此进行了简单的适配 这里封装成了组件,组件属性根据自己需求修改 tower-swiper.json { "component": true, "usingComponents": {} }tower-swiper.wxml <view> <view class="tower-swiper" bindtouchmove="TowerMove" bindtouchstart="TowerStart" bindtouchend="TowerEnd"> <view class="tower-item {{item.zIndex==1?'none':''}}" wx:for="{{swiperList}}" wx:key="index" style="transform: scale(calc(0.5 + {{item.zIndex}} / 10));--index: {{item.zIndex}};margin-left: calc({{item.mLeft}} * 100rpx - 150rpx); z-index: {{item.zIndex}};"> <view class="swiper-item"> <image src="{{item.url}}" mode="aspectFill" wx:if="{{item.type=='image'}}"></image> <video src="{{item.url}}" autoplay loop muted data-show-play-btn="false" objectFit="cover" wx:if="{{item.type == 'video'}}"></video> </view> </view> </view> </view>tower-swiper.wxss .tower-swiper { height: 420rpx; position: relative; max-width: 750rpx; overflow: hidden; } .tower-swiper .tower-item { position: absolute; width: 300rpx; height: 380rpx; top: 0; bottom: 0; left: 50%; margin: auto; transition: all 0.2s ease-in 0s; opacity: 1; } .tower-swiper .tower-item .none { opacity: 0; } .tower-swiper .tower-item .swiper-item { width: 100%; height: 100%; border-radius: 6rpx; overflow: hidden; }tower-swiper.js Component({ /** * 组件的属性列表 */ properties: { swiperList:{ type:Array, value:[{ id: 0, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big84000.jpg' }, { id: 1, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big37006.jpg', }, { id: 2, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big39000.jpg' }, { id: 3, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg' }, { id: 4, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big25011.jpg' }, { id: 5, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big21016.jpg' }, { id: 6, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big99008.jpg' }] }, towerStart:{ type:Number, value:0 } }, /** * 组件的初始数据 */ data: { timer:null, towerStart: 0, direction: 'left' }, lifetimes:{ attached(){ this.TowerSwiper(); this.direction = 'left'; this.setData({ direction: "left" }) this.swiperOn() } }, /** * 组件的方法列表 */ methods: { swiperOn(){ const _this = this let timer = this.data.timer if(!timer){ timer = setInterval(()=>{ _this.TowerEnd() },1000) this.setData({ timer }) } }, // 初始化towerSwiper TowerSwiper() { let list = this.data.swiperList; for (let i = 0; i < list.length; i++) { list[i].zIndex = parseInt(list.length / 2) + 1 - Math.abs(i - parseInt(list.length / 2)) list[i].mLeft = i - parseInt(list.length / 2) } this.setData({ swiperList: list }) }, // towerSwiper触摸开始 TowerStart(e) { const pageWidth = wx.getSystemInfoSync().windowWidth this.setData({ towerStart: e.touches[0].pageX, direction: e.touches[0].pageX < pageWidth/2 ? 'right':'left' }) }, // towerSwiper计算方向 TowerMove(e) { this.setData({ direction: e.touches[0].pageX - this.data.towerStart > 0 ? 'right' : 'left' }) }, // towerSwiper计算滚动 TowerEnd() { let direction = this.data.direction; let list = this.data.swiperList; if (direction == 'right') { let mLeft = list[0].mLeft; let zIndex = list[0].zIndex; for (let i = 1; i < this.data.swiperList.length; i++) { list[i - 1].mLeft = list[i].mLeft list[i - 1].zIndex = list[i].zIndex } list[list.length - 1].mLeft = mLeft list[list.length - 1].zIndex = zIndex } else { let mLeft = list[list.length - 1].mLeft; let zIndex = list[list.length - 1].zIndex; for (let i = list.length - 1; i > 0; i--) { list[i].mLeft = list[i - 1].mLeft list[i].zIndex = list[i - 1].zIndex } list[0].mLeft = mLeft; list[0].zIndex = zIndex; } this.setData({ direction, swiperList: list }) }, } })
-
使用MySql触发器简化各表数据操作 触发器基本语法 生成一个触发器 CREATE TRIGGER 触发器名 触发事件(BEFORE|AFTER INSERT|UPDATE|DELETE) ON 表名 FOR EACH ROW 触发器激活后需要执行的语句一些注意事项 同一个数据库中不能创建同名触发器 在同一张表中不能出现触发条件相同的触发器 使用NEW和OLD来获取数据变化前后的记录值 如果激活后只有一条操作,可以直接写,如果需要复杂操作则需要使用BEGIN...END;语句包围 查看触发器 SHOW TRIGGERS ; 删除触发器 DROP TRIGGER 触发器名; 修改触发器 将已有触发器删除后再重新创建😂 一个简单的触发器示例 CREATE TRIGGER update_userinfo_trigger AFTER UPDATE ON user FOR EACH ROW BEGIN IF NEW.user_name <> OLD.user_name THEN UPDATE task_my SET user_name = NEW.user_name WHERE user_id = NEW.id; UPDATE table1 SET user_name = NEW.user_name WHERE user_id = NEW.id; UPDATE table2 SET user_name = NEW.user_name WHERE user_id = NEW.id; END IF; END;该触发器实现了,在更新user表中的name时,可以同时联动着将其他表中的name也更新掉,实现用户数据的统一
-
树莓派开启个人热点(二)解决网速慢问题 前言 为了在方便树莓派联网的同时让其他设备也能上网,就有了将树莓派作为软路由的想法,经过在网上各种搜索后不断折腾,最终也实现了这一目的。有同样需求的可参照下文 {% link 树莓派开启个人热点,Mstzf,https://blog.teohzy.com/post/startAP/index.html %} 一番配置下来确实成功开启了个人热点,但是网速和稳定性一直不是很理想 问题原因 hostapd配置文件网络协议没有设置正确 hostapd v2.9 和 树莓派4B都已经可以支持WIFI5,而我之前的配置还在使用上个世纪的iee802.11a协议 解决办法 修改以下hostapd配置文件即可 # vim /etc/hostapd/hostapd.conf将原配置文件删除,替换为新的 interface=wlan0 driver=nl80211 ssid=AP-Pi4 hw_mode=a channel=0 ieee80211n=1 ieee80211ac=1 ieee80211ax=1 ieee80211d=1 ieee80211h=1 country_code=CN auth_algs=1 wpa=2 wpa_passphrase=123456789 wpa_key_mgmt=WPA-PSK WPA-PSK-SHA256 rsn_pairwise=CCMP macaddr_acl=0 wmm_enabled=1 wmm_ac_bk_cwmin=4 wmm_ac_bk_cwmax=10 wmm_ac_bk_aifs=7 wmm_ac_bk_txop_limit=0 wmm_ac_bk_acm=0 wmm_ac_be_aifs=3 wmm_ac_be_cwmin=4 wmm_ac_be_cwmax=10 wmm_ac_be_txop_limit=0 wmm_ac_be_acm=0 wmm_ac_vi_aifs=2 wmm_ac_vi_cwmin=3 wmm_ac_vi_cwmax=4 wmm_ac_vi_txop_limit=94 wmm_ac_vi_acm=0 wmm_ac_vo_aifs=2 wmm_ac_vo_cwmin=2 wmm_ac_vo_cwmax=3 wmm_ac_vo_txop_limit=47 wmm_ac_vo_acm=0 he_su_beamformer=1 he_su_beamformee=1 he_mu_beamformer=1 he_bss_color=5 he_default_pe_duration=0 he_basic_mcs_nss_set=2 he_oper_centr_freq_seg0_idx=0 require_ht=1 he_su_beamformee=1 he_su_beamformer=1 he_bss_color=3 he_twt_required=1 vht_capab=[SHORT-GI-80][RX-STBC1][TX-STBC][SU-BEAMFORMER][SU-BEAMFORMEE]重启hostapd # sudo systemctl start hostapd
-
远程访问本地搭建的NextCloud(反向代理网页) 前言 在没有公网IP的情况下,很难从其他网络环境中直接访问到部署在本地的web服务,这时候就需要通过内网穿透的方式来实现。而对于内网穿透,有着很多的实现方式,最为常见的就是通过云服务器搭建和使用别人提供的服务 自建内网穿透服务 需要有自己的云服务器 服务端和客户端都需要下载frp,下载地址 => Releases · fatedier/frp (github.com) 服务端配置 编辑frps.ini文件 [common] # frp监听的端口,默认是7000,可以改成其他的 bind_port = 7000 # 授权码,需要与客户端一致,请改为更复杂的 token = aaaaaa # frp管理后台端口,请按自己需求更改 dashboard_port = 7500 # frp管理后台用户名和密码,请改成自己的 dashboard_user = Mango dashboard_pwd = 12345678 enable_prometheus = true # http 端口可更改 vhost_http_port = 8090 # https 端口可更改 vhost_https_port= 8081 #vhost_https_port = 8080 # frp日志配置 路径根据自己需求更改 log_file = /root/frp/.frps.log log_level = error log_max_days = 3 配置systemd守护进程便于管理 vim /etc/systemd/system/frps.service输入以下内容并保存 [Unit] Description=fraps service After=network.target syslog.target Wants=network.target [Service] Type=simple #启动服务的命令(此处写你的frps的实际安装目录) ExecStart=/root/frp/frps -c /root/frp/frps.ini [Install] WantedBy=multi-user.target启动frps并设置开机自启 systemctl daemon-reload systemctl start frps systemctl enable frps 配置nginx 如果没有nginx先安装 apt update apt install nginx编辑配置文件 vim /etc/nginx/sites-enabled/nextcloud # 也可以不新建nextcloud文件,直接配置默认文件 vim /etc/nginx/sites-enabled/defaultnginx代理frps配置文件参考 可配置SSL开启https server{ listen 80; listen 443 ssl; #对应你的域名 server_name xxx.xxx.cn; # https 域名证书相关配置 # ssl证书存储路径,根据个人存储路径设置,我的被存在了 /etc/nginx/ssl/ 文件夹下面 ssl_certificate /etc/nginx/ssl/xxx.mstzf.cn.pem; ssl_certificate_key /etc/nginx/ssl/xxx.mstzf.cn.key; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; location / { proxy_pass http://127.0.0.1:8090; # 映射的frp服务端frps.ini的 vhost_http_port端口 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_max_temp_file_size 0; proxy_redirect off; proxy_read_timeout 240s; client_max_body_size 0; } } }重启nginx服务 systemctl restart nginx 客户端配置 编辑frpc.ini文件 [common] # 远程服务器地址 # 替换为自己的域名 server_addr = 0.0.0.0 # 远程服务器监听端口 # 和服务端 bind_port 相同 server_port = 7000 # 连接密钥 # 必须和服务端配置相同 token = aaaaaa # 配置日志文件 # 日志级别:trace, debug, info, warn, error # 日志保存路径根据需求修改 log_file = /home/zh/frp/log/.log log_level = error log_max_days = 3 # 客户端管理配置 admin_addr = 127.0.0.1 admin_port = 7500 admin_user = Mango admin_pwd = 12345678 # 代理端口配置 模板 # [内容随意 如ssh] # type = 连接类型 如 tcp # local_ip = 127.0.0.1 # local_port = 22 本地需要代理的端口 # remote_port = 2222 将本地22端口代理为远程的2222端口 # 该配置下,可用远程 ip 的 2222 端口访问到本地的 22 端口服务 [ssh] type = tcp local_ip = 127.0.0.1 local_port = 22 remote_port = 2222 [rdp] type=tcp local_ip = 127.0.0.1 local_port=3389 remote_port=3389 [nx] type=tcp local_ip=127.0.0.1 local_port=4000 remote_port=4000 [web] type = http local_ip = 127.0.0.1 local_port = 80 #subdomain = root # 绑定的域名 和nginx配置下的 server_name 相同 custom_domains = xxx.mstzf.cn 为frpc配置systemd守护进程便于管理 编辑文件 vim /etc/systemd/system/frpc.service输入以下内容 [Unit] Description=Frp Client Service After=network.target [Service] Type=simple User=root Restart=on-failure RestartSec=5s # 根据frp所在位置设置 ExecStart=/home/zh/frp/frpc -c /home/zh/frp/frpc.ini LimitNOFILE=1048576 [Install] WantedBy=multi-user.target启动frpc并配置开机自启 systemctl daemon-reload systemctl start frpc systemctl enable frpc 使用第三方服务 我个人使用的是Sakura Frp,有能够满足基本需求的免费套餐,vip套餐也很划算,已经能够满足我的基本需求 {% link SakuraFrp,SakuraFrp,https://www.natfrp.com/ %} 注册账号 完善个人信息 如果有建站需求想要使用国内站点,需要完成实名认证和有备案域名,否则只能使用国外的站点来搭建 在客户端安装frp软件 这一部分官网中已经介绍得十分的详细,这里只有几个关键命令,具体可到官网查看 {% link frpc 基本使用指南,SakuraFrp 帮助文档,https://doc.natfrp.com/frpc/usage.html %} 确认系统架构 uname -m获取软件链接 {% link 软件下载,SakuraFrp,https://www.natfrp.com/tunnel/download %} 安装 cd /usr/local/bin wget -O frpc <下载地址> chmod 755 frpc 配置守护进程(systemd) 具体操作可去指导文档查看 {% link Systemd配置frpc服务,SakuraFrp帮助文档,https://doc.natfrp.com/frpc/service/systemd.html %} 添加工作目录 mkdir -p /usr/local/etc/natfrp编辑配置文件 vim /etc/systemd/system/frpc@.service输入配置内容 [Unit] Description=SakuraFrp Service After=network.target [Service] Type=idle #DynamicUser=yes Restart=on-failure RestartSec=60s ExecStart=/usr/local/bin/frpc -f %i WorkingDirectory=/usr/local/etc/natfrp [Install] WantedBy=multi-user.target重载systemd systemctl daemon-reload 新建隧道 对于远程访问网页的,需要选择可建站的节点;至于选择国内还是国外要先看自己的域名是否已经备过案,备案过的域名可以使用国内节点,国内节点在各方面都要优于国外。如果没有备案域名,就只能使用国外节点。 image-20231114121753361图片 image-20231114121907030图片 端口根据本地网页端口配置 在绑定域名和自动HTTPS中一定要输入自己需要使用的域名 配置DSN解析 动画图片 复制节点域名,到域名服务商处配置DNS解析,将自己的域名CNAME到复制的节点域名上 记录类型选择CNAME 记录值选择选择节点所绑定域名 配置SSL证书 {% link 配置frpc使用的SSL证书,SakuraFrp帮助文档,https://doc.natfrp.com/frpc/ssl.html %} 从服务商下载域名SSL证书选择Nginx,将证书重命名为 将其中 扩展名为pem的直接将扩展名修改为crt 并只保留域名和扩展名 即 如 nextcloud.mstzf.cn.key 的形式 将证书移动到之前配置的工作目录中 /usr/local/etc/natfrp 启动隧道 systemctl <start|stop> <Unit名称> # <Unit名称> 即下图 -f 之后 红色框部分
-
CSS实现水波纹扩散效果 主要CSS animation transform: scale() opacity nth-child() 效果展示 代码 <div> <style> .ripple { width: 200px; height: 200px; position: absolute; top: calc(50% - 100px); left: calc(50% - 100px); border-radius: 50%; background-color: blueviolet; } /* 根据需求自定义 */ .content{ position: absolute; z-index: 99; /* 与.ripple的top和left相同 */ top: calc(50% - 100px); left: calc(50% - 100px); width: 200px; height: 200px; border-radius: 50%; background-color: rgb(42, 42, 180); font-size: 20px; font-weight: bold; color: #FFF; text-align: center; line-height: 200px; } .ripple:nth-child(2){ animation: wave 1s linear infinite; } .ripple:nth-child(3){ animation: wave 2s linear infinite; } .ripple:nth-child(4){ animation: wave 3s linear infinite; } .ripple:nth-child(5){ animation: wave 4s linear infinite; } @keyframes wave { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(1.5); } } </style> <div class="box"> <div class="content">内容</div> <div class="ripple"></div> <div class="ripple"></div> <div class="ripple"></div> <div class="ripple"></div> <div class="ripple"></div> </div> </div>实现的逻辑就是通过animation动画重复将这些元素放大1.5倍,同时将元素变为完全透明,从而达到波纹扩散的效果