首页
归档
分类
标签
更多
留言板
说说
关于
Search
1
饥荒联机版控制台代码大全
1,024 阅读
2
编译安装带 Brotli 压缩的 Nginx
930 阅读
3
Obsidian多端快速同步插件
901 阅读
4
树莓派+EC20模块实现连接蜂窝网和短信收发
887 阅读
5
EC20通过gammu接收短信再转发优化
865 阅读
软件
CSS
Python
MySql
Java
typecho自定义
Vue
学习笔记
Linux
Shell脚本
Nginx
树莓派
邮件
拍照
热点
ec20
云盘
系统烧录
好玩
饥荒
硬件
工具
笔记
随心记
登录
Search
标签搜索
树莓派
Linux
Java
CSS
饥荒
小妙招
个人热点
nextcloud
云盘
DHT11
学习笔记
树莓派拍照
Nginx
MySql
ESP
娱乐
ec20模块
文件共享
git
图床
Mango
累计撰写
51
篇文章
累计收到
7
条评论
首页
栏目
软件
CSS
Python
MySql
Java
typecho自定义
Vue
学习笔记
Linux
Shell脚本
Nginx
树莓派
邮件
拍照
热点
ec20
云盘
系统烧录
好玩
饥荒
硬件
工具
笔记
随心记
页面
归档
分类
标签
留言板
说说
关于
搜索到
51
篇与
的结果
2025-05-06
饥荒联机管理控制台
饥荒联机版和队友联机网络状况一直一言难尽,在服务器中使用命令比较麻烦而且需要一定的技术水平,web界面的管理工具能够比较方便的管理服务器。
2025年05月06日
6 阅读
0 评论
2 点赞
2025-04-13
部署一个自己的全网广告拦截与反跟踪软件
AdGuard Home 是一款全网广告拦截与反跟踪软件。在您将其安装完毕后,它将保护您所有家用设备,同时您不再需要安装任何客户端软件。随着物联网与连接设备的兴起,掌控您自己的整个网络环境变得越来越重要。
2025年04月13日
2 阅读
0 评论
0 点赞
2025-02-16
微信小程序自定义Navbar自定义组件简单兼容写法
前引在小程序项目中经常有要自定义navbar的需求,网上有很多大佬分享的教程,但有的不太兼容,有的又写的比较麻烦,这里分享一种本人在用兼容性较好而且代码比较简单的一种写法。原理解释微信小程序navbar头部可以拆分为几部分构成:状态栏高度、胶囊高度、胶囊上下两侧外边距高度 。如下图所示:只要能取到各个部分的值,定位navbar和设置高度都会十分简单。获取状态栏高度const systemInfo = wx.getWindowInfo(); systemInfo.statusBarHeight胶囊按钮高度用胶囊按钮的bottom - topconst menuButtonInfo = wx.getMenuButtonBoundingClientRect(); menuButtonInfo.bottom - menuButtonInfo.top胶囊按钮的上下外边距menuButtonInfo.top - systemInfo.statusBarHeight完整代码ts代码Component({ data: { navHeight: 0, // 胶囊高度 即 navbar高度 navWidth: 0, // 显示宽度 navMarginY: 0, // 胶囊上下外边距 statusBarHeight: 0, // 状态栏高度 }, lifetimes: { attached() { const systemInfo = wx.getWindowInfo(); const menuButtonInfo = wx.getMenuButtonBoundingClientRect(); this.setData({ statusBarHeight: systemInfo.statusBarHeight, navHeight: menuButtonInfo.bottom - menuButtonInfo.top, navMarginY: menuButtonInfo.top - systemInfo.statusBarHeight, navWidth: systemInfo.screenWidth - menuButtonInfo.right + menuButtonInfo.left - 10, }) }, }, })wxml代码<view class="nav-box" style="padding-top: {{statusBarHeight}}px;"> <view style="height: {{navHeight}}px; margin: {{navMarginY}}px 0; " class="navbar"> <view>back</view> <view class="title">标题部分</view> </view> </view>wxss代码.navbar { position: relative; display: flex; align-items: center; background-color: coral; color: #ffffff; padding: 0 16rpx; box-sizing: border-box; } .navbar .title { position: absolute; top: 0; left: 0; height: 100%; width: 100%; display: flex; justify-content: center; align-items: center; font-size: 32rpx; }这只是一个介绍原理的简单示例,具体代码要根据业务需求来做出修改
2025年02月16日
355 阅读
0 评论
0 点赞
2024-12-24
Java使用SXSSFWorkbook导出Excel工具类
列 1col2 (列2)col3 前引在项目中经常有导出Excel的需求,为了方便就封装了一个导出Excel到前端的工具类,使用下来还比较好用使用JDK版本:1.8spring boot版本:2.6.15前端请求:axiosJava代码Excel所需Maven依赖 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.0.1</version> </dependency>完整代码如下:public class excelUtils { public static CellStyle headStyle(Workbook workbook) { // 创建单元格样式 CellStyle headerStyle = workbook.createCellStyle(); // 设置字体样式 Font headerFont = workbook.createFont(); headerFont.setBold(true); // 加粗 headerFont.setFontHeightInPoints((short) 12); // 字体大小 headerStyle.setFont(headerFont); // 可选:设置其他样式属性 headerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中 headerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中 return headerStyle; } public static CellStyle tableStyle(Workbook workbook) { CellStyle tableStyle = workbook.createCellStyle(); tableStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中 tableStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中 return tableStyle; } /** * @author Mango * * 获取对象的字段值 * @param object 对象 * @param key 字段名 * @return 字段值 */ public static String getFieldString(Object object, String key) { if(object instanceof Map){ return String.valueOf(((Map<?, ?>) object).get(key)); } Field field = null; String value = ""; try { field = object.getClass().getDeclaredField(key); field.setAccessible(true); String orgStr = String.valueOf(field.get(object)); if (orgStr != null) { value = orgStr; // 处理数组类型 if (orgStr.startsWith("[") && orgStr.endsWith("]")) { value = orgStr .replace("[", "") .replace("]", "") .replace("\"", ""); } } } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } return value; } /** * @author Mango * 导出Excel * @param response HttpServletResponse * @param srcList 数据源 * @param keys 数据源对应字段列表 * @param titles 表头 * @param excelName 文件名 */ public static void exportExcel(HttpServletResponse response, List<?> srcList, List<String> keys, List<String> titles, String excelName) { // 创建workbook // 使用 SXSSFWorkbook 比 XSSFWorkbook 内存占用少 SXSSFWorkbook workbook = new SXSSFWorkbook(); // 根据workbook创建sheet Sheet sheet = workbook.createSheet(excelName); //设置表头 Row titleRoe = sheet.createRow(0); // 设置表头样式 CellStyle headStyle = headStyle(workbook); // 向单元格中添加表头数据 for (int i = 0; i < titles.size(); i++) { Cell cell = titleRoe.createCell(i); cell.setCellValue(titles.get(i)); cell.setCellStyle(headStyle); } // 定义数据样式 CellStyle tableStyle = tableStyle(workbook); // 处理表格数据 for (int i = 0; i < srcList.size(); i++) { // 获取一组数据 Object object = srcList.get(i); // 生成行 Row rowData = sheet.createRow(i + 1); // 设置行高 rowData.setHeight((short) 400); // 向每一行中的单元格添加数据 // keys 为对象字段列表 for (int j = 0; j < keys.size(); j++) { String key = keys.get(j); Cell cell = rowData.createCell(j); cell.setCellStyle(tableStyle); String value = getFieldString(object, key); cell.setCellValue(value); } // 每100行就写一次磁盘,减少内存消耗 if (i % 100 == 0) { try { ((SXSSFSheet) sheet).flushRows(100); // 将缓存中的数据写入磁盘 } catch (IOException e) { throw new RuntimeException(e); } } } // 获取当前时间作为文件名 LocalDateTime localDateTime = LocalDateTime.now(); String fileName = excelName + localDateTime.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".xlsx"; // 设置响应头 try { response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); } catch (UnsupportedEncodingException e) { // 发生异常不处理中文文件名 response.setHeader("Content-Disposition", "attachment;filename=" + fileName); throw new RuntimeException(e); } response.setContentType("application/vnd.ms-excel;charset=utf-8"); response.setHeader("Accept-Ranges", "bytes"); // 返回数据 返回进度条 try (ByteArrayOutputStream fileOutputStream = new ByteArrayOutputStream(); ServletOutputStream out = response.getOutputStream()) { // 这里假设 workbook 是生成的 Excel 文件对象 workbook.write(fileOutputStream); // 获取文件的总大小,并设置响应头 byte[] fileBytes = fileOutputStream.toByteArray(); response.setHeader("Content-Length", String.valueOf(fileBytes.length)); // 分块传输文件内容 int chunkSize = 256; // 每次写入数据字节 int totalSize = fileBytes.length; int currentPosition = 0; while (currentPosition < totalSize) { int remaining = totalSize - currentPosition; int chunk = Math.min(chunkSize, remaining); // 写入一块数据 out.write(fileBytes, currentPosition, chunk); out.flush(); // 刷新输出流,确保数据传送给客户端 // 更新当前下载位置 currentPosition += chunk; } out.close(); workbook.close(); // 关闭工作簿 } catch (IOException e) { // 处理异常 response.reset(); response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); Map<String, String> map = new HashMap<>(); map.put("message", "下载文件失败: " + e.getMessage()); try { response.getWriter().println(JSON.toJSONString(map)); } catch (IOException ee) { ee.printStackTrace(); } e.printStackTrace(); } } }前端请求示例请求接口export const outExcel = async ( data: any, downloadProgress: Function, ) => { return await request({ url: "/test/outExcel", method: "post", data, responseType: "blob", onDownloadProgress: (event: any) => { downloadProgress(event); }, }); }注:这里的代码是已经封装过的统一封装的axiosresponseType: “blob” 指定文件为二进制onDownloadProgress利用回调函数返回下载进度下载示例const exportExcel = async () => { isProcessing.value = true; let response = null; try { response = await props.downloadMethod(props.searchForm, (event: any) => { progress.value = (event.loaded / event.total) * 100; if (progress.value > 0) { isProcessing.value = false; } }); } catch (e: any) { isProcessing.value = false; //出错时结束处理状态 isError.value = true; //下载失败 } if (response == null) return; // 没有返回数据 if (!response.status) { isError.value = true; //接口返回错误设置为下载失败 } const fileName = "教师参与情况" + formatDate(new Date(), "yy-MM-dd hh:mm:ss") + ".xlsx"; const blob = new Blob([response.data], { type: "application/vnd.ms-excel" }); // 创建一个链接来下载 Blob 对象 const downloadLink = document.createElement("a"); downloadLink.href = URL.createObjectURL(blob); downloadLink.download = decodeURI(fileName); downloadLink.style.display = "none"; document.body.appendChild(downloadLink); // 触发点击事件以下载文件 downloadLink.click(); // 清理创建的链接对象 document.body.removeChild(downloadLink); };将props.downloadMethod替换为下载接口props.searchFormt替换为筛选数据
2024年12月24日
779 阅读
2 评论
0 点赞
2024-11-22
keep-alive使用记录(返回界面不刷新)
前引keep-alive是vue自带的一个内置组件,可以实现缓存包裹在其中的动态切换组件。{% link Vue,Built-in Components,https://cn.vuejs.org/api/built-in-components#keepalive %}我这里是和路由结合全局使用全局添加keep-alive在界面切换的router-view处做修改 <router-view v-slot="{ Component }"> <keep-alive :include="cachedRoutes"> <component :is="Component" :key="$route.fullPath" /> </keep-alive> </router-view>cachedRoutes:为需要缓存界面路由name,可以根据使用情况设置,我这里写到了pinia中export const settingStore = defineStore("setting", { state: () => { return { cachedRoutes: Array<string>(), // 缓存的路由名称列表 }; }, getters: { getCachedRoutes(): string[] { return this.cachedRoutes; }, }, actions: { addRouteToCache(routeName: string) { if (!this.cachedRoutes.includes(routeName)) { this.cachedRoutes.push(routeName); } }, removeRouteFromCache(routeName: string) { const index = this.cachedRoutes.indexOf(routeName); if (index !== -1) { this.cachedRoutes.splice(index, 1); } }, }, });设置路由路由定义在需要缓存的界面路由mate中添加keepAlive: true { path: "/test/pageA", name: "pageA", meta: { title: "界面A", keepAlive: true }, component: () => import( "@/views/test/pageA/index.vue" as string ), }设置路由守卫,通过路由守卫向cachedRoutes 中添加需要缓存页面nameconst setRouteCache = (event: any) => { if (event.state) { const { name, meta } = currentRoute as any; if (meta.keepAlive) settingStore().removeRouteFromCache(name); } }; // 监听浏览器后退事件 window.addEventListener("popstate", setRouteCache); router.beforeEach(async (to: any, _from: any, next) => { // 设置浏览器标题 document.title = to.meta.title; window.history.state.action = to.name; currentRoute = _from; if (to.matched) { to.matched.forEach((record: any) => { if (record.name && record.components?.default) { const component = record.components.default; if (typeof component === "function") { // 处理异步组件 component().then((resolved: any) => { if (!resolved.default.name) { resolved.default.name = record.name; } }); } else if (!component.name) { // 处理普通组件 component.name = record.name; } } }); } if (to.meta.keepAlive) { const settingSate = settingStore(); settingSate.addRouteToCache(to.name); } next(); });其中下面这部分代码是设置页面name和路由的name绑定如果一致的可以去除 if (to.matched) { to.matched.forEach((record: any) => { if (record.name && record.components?.default) { const component = record.components.default; if (typeof component === "function") { // 处理异步组件 component().then((resolved: any) => { if (!resolved.default.name) { resolved.default.name = record.name; } }); } else if (!component.name) { // 处理普通组件 component.name = record.name; } } }); }
2024年11月22日
538 阅读
0 评论
0 点赞
2024-11-15
使用dpkg-deb对deb文件解压、重新打包
前引aic8800d80相关驱动在最新的linux内核中无法安装,在网上找了很多别人重新编译的驱动都无法正常使用,后来才了解到deb文件可以解压出源码文件,在针对错误进行修改后又可以重新打包。命令安装apt install dpkg解压deb文件dpkg-deb -x org.deb ./src/将deb文件解压到一个文件夹中修改源码文件为了后续重新打包最好不要改变源代码文件结构解压出包的控制信息dpkg-deb -e org.deb ./src/DEBIAN重新打包dpkg-deb -b ./src new.deb安装dpkg -i new.deb
2024年11月15日
578 阅读
0 评论
0 点赞
2024-10-09
树莓派安装AIC8800d80驱动
环境信息系统版本:6.6.51+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.6.51-1+rpt2 (2024-10-01) aarch64 GNU/LinuxUSB WIFI设备:TL-XDN7000H设备芯片:aic8800d80查看设备连接状态lsusb如果在usb设备列表中看到类似ID a69c:5721 aicsemi AIC Wlan的输出,是将设备识别为了存储模式,需要将存储模式修改为wlan模式切换模式(非必须)使用命令sudo usb_modeswitch -KQ -v a69c -p 5721将存储模式修改为wlan模式命令模式需要在每次启动都需要输入,比较麻烦,可以使用udev来管理设备sudo vim /etc/udev/rules.d/70-usb-modeswitch.rules粘贴以下内容ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="a69c", ATTR{idProduct}=="5721", RUN+="/usr/sbin/usb_modeswitch -v a69c -p 5721 -K"重新加载规则sudo udevadm control --reload-rules sudo udevadm trigger安装驱动我的TP-Link官方驱动在arm架构中安装失败,很可能是因为我的内核版本比较高,导致很多库不支持。这里找到了绿联的AIC8800D80驱动,和我使用的TL-XDN7000H芯片一致驱动下载地址:{% link 绿联,驱动下载,绿联WiFi6 USB无线网卡AIC8800D80驱动,https://www.lulian.cn/download/135.html %}驱动下载链接:绿联WiFi6 USB无线网卡AIC8800D80驱动文件中有详细安装教程,这里不再赘述我这里直接安装了里面的aic8800d80fdrvpackage_2024_0606.deb文件成功驱动TL-XDN7000H
2024年10月09日
677 阅读
0 评论
0 点赞
2024-09-05
NextCloud更新404解决办法
前引最近两个版本的NextCloud更新时更新器出现404导致无法更新之前的版本都正常解决办法:使用命令手动更新通过手动运行更新命令,更新nextcloud版本在nextcloud根目录中运行命令:sudo -u www-data php updater/updater.phar基本流程和在有界面中是一样在更新过程中避免用户访问造成错误,可以启动维护模式sudo -u www-data php occ maintenance:mode --on关闭维护模式sudo -u www-data php occ maintenance:mode --off下载失败解决办法由于国内网络等原因,可能会出现更新下载失败可以在本地将新的 nextcloud 下载后上传到服务器中,替换掉data/updater-*/downloads/(nextcloud安装目录)的文件,同时修改data/updater-*/下的文件 .step替换文件中 start 为 stop{"state":"stop","step":4}再重新运行更新命令即可
2024年09月05日
657 阅读
0 评论
0 点赞
2024-07-23
EC20通过gammu接收短信再转发优化
前引在接收到短信之后会将内容较大的短信内容拆分到不同文件中保存,在之前的自动转发脚本转发短信文本内容不全解决最近在阅读gammu官方文档的时候发现官方有个Processing message text in Python 的示例:Following script (if used as RunOnReceive handler) written in Python will concatenate all text from received message:#!/usr/bin/env python import os numparts = int(os.environ["DECODED_PARTS"]) text = "" # Are there any decoded parts? if numparts == 0: text = os.environ["SMS_1_TEXT"] # Get all text parts else: for i in range(1, numparts + 1): varname = "DECODED_%d_TEXT" % i if varname in os.environ: text = text + os.environ[varname] # Do something with the text print("Number {} have sent text: {}".format(os.environ["SMS_1_NUMBER"], text))这个python脚本能将在不同文件中的短信内容拼接,刚好能够实现我们的需求,将这个python代码转写为shell代码,和之前的短信转发代码组合后的新代码:#!/bin/bash numparts=${DECODED_PARTS} text="" if [ "$numparts" -eq 0 ]; then text=${SMS_1_TEXT} else for i in $(seq 1 $numparts); do varname="DECODED_${i}_TEXT" if [ ! -z "${!varname}" ]; then text="${text}${!varname}" fi done fi echo "${text}" |mutt -s "树莓派转发${SMS_1_NUMBER}短信" mstzf@foxmail.com就能够完美实现短信转发功能gammu官网链接:{% link RunOnReceive,Gammu,https://docs.gammu.org/smsd/run.html#index-7 %}ec20模块使用:{% link 树莓派+EC20模块实现连接蜂窝网和短信收发,TeohZY,https://blog.teohzy.com/post/raspi-ec20/index.html %}
2024年07月23日
865 阅读
0 评论
0 点赞
2024-07-14
为你的Typecho博客添加一个访问统计
前引在之前的静态Hexo 中借助的是第三方的统计平台,现在转到动态博客下,有了自己的数据库就没有必要再使用第三方的统计;于是就有了typecho访问统计插件TeohVistgithub地址:{% link github,TeohVisit,https://github.com/mstzf/TeohVisit.git %}插件实现的功能非常简单,就只是记录了访问数据,和在需要的界面提供数据安装将代码克隆到typecho插件目录,在管理后台找到 TeohVisit 之间开启使用即可git clone https://github.com/mstzf/TeohVisit.git使用具体使用需要修改主题源码,或者自定义独立界面模板插件提供了两种读取数据的方法getStat:返回所需要的单个值,具体值为:today,yesterday,month,totalgetAllStats:返回全部数据示例:if (TeohVisit_Plugin::isPluginEnabled()) { $stats = TeohVisit_Plugin::getAllStats(); $data = [ 'today_unique_visitors' => $stats['today']['unique_visitors'], 'today_views' => $stats['today']['views'], 'yesterday_unique_visitors' => $stats['yesterday']['unique_visitors'], 'yesterday_views' => $stats['yesterday']['views'], 'month_total_views' => $stats['month']['total_views'], 'total_total_views' => $stats['total']['total_views'] ]; }
2024年07月14日
814 阅读
0 评论
0 点赞
1
2
...
6