uniapp对接RFID硬件:原生插件封装与盘存优化实战
1. 从扫码到RFID为什么uniapp项目需要换一套识别思路做过uniapp扫码功能的同学都知道uni.scanCode这个API用起来有多顺手——一行代码调起摄像头二维码、条形码统统搞定。但当你接到一个“用RFID识别资产标签”的需求时打开uniapp官方文档翻一遍会发现根本没有对应的API。这不是文档没写全而是RFID和扫码在技术链路上压根就是两回事。扫码的本质是光学识别摄像头拍一张图像算法解析图像中的编码信息。而RFID的本质是射频识别读写器发射特定频率的电磁波标签通过感应电流获取能量后回传数据。两者从物理层就不一样所以uniapp不可能用一个统一的JS API把两者都封装了。那在uniapp项目里到底怎么接RFID核心思路就一条RFID硬件厂商通常会提供Android原生SDK一个.jar或.aar包我们需要把它包装成uniapp能调用的原生插件然后在vue页面里通过uni.requireNativePlugin来调用。整个链路涉及Android原生开发、uniapp原生插件规范、广播接收、权限处理等多个环节这也是为什么很多前端同学一听到“RFID”就觉得头大。这篇文章适合两类人看一类是已经有一定uniapp开发经验需要对接RFID硬件的开发者另一类是想了解uniapp原生插件机制为后续对接其他硬件如身份证读卡器、指纹模块做技术储备的同学。我会从硬件选型、原生插件封装、广播数据解析、权限适配到打包上架把整条链路拆开讲清楚尽量让没有Android原生开发经验的前端也能跟着走通。提示本文涉及的RFID方案基于Android平台因为uniapp在iOS上对接RFID硬件的限制较多iOS对NFC的开放程度有限且不同厂商SDK差异大所以如果你的项目必须支持iOS建议先和硬件厂商确认是否有iOS端的SDK和MFi认证。2. RFID硬件选型与Android SDK的对接准备2.1 RFID模块的常见形态与通信方式市面上的RFID模块大致分三种形态一体式手持终端比如带RFID功能的PDA、外接式读写器通过蓝牙或USB连接手机、嵌入式模块集成到设备主板上的模组。在uniapp项目里最常见的是前两种。一体式手持终端通常厂商已经预装了Android系统并且提供了对应的SDK你只需要在uniapp项目里调用即可。外接式读写器则分蓝牙和USB两种连接方式蓝牙的需要处理蓝牙配对和数据传输USB的则需要处理USB权限和串口通信。从通信协议上看RFID读写器和Android设备之间通常走的是串口UART或USB HID协议。厂商的SDK一般会把这些底层通信封装好对外暴露几个关键方法初始化、开始盘存、停止盘存、读取标签数据、设置功率等。2.2 拿到SDK之后先做什么拿到厂商提供的SDK通常是一个.zip包里面有.jar/.aar文件、demo工程、API文档不要急着往uniapp项目里塞。正确的做法是先用Android Studio跑通厂商的demo。这一步至关重要因为你需要确认硬件本身是好的、SDK版本和你的Android设备兼容、权限配置正确。很多后续在uniapp里遇到的问题其实在原生demo阶段就能暴露出来。阅读API文档找出核心类和方法。重点关注初始化方法通常需要传入Context、盘存回调接口标签数据通过回调返回、电源控制方法打开/关闭射频、参数设置方法功率、盘存模式等。确认SDK依赖的Android版本和权限。RFID SDK通常需要android.permission.INTERNET、android.permission.ACCESS_NETWORK_STATE如果是蓝牙读写器还需要BLUETOOTH、BLUETOOTH_ADMINAndroid 12以上需要BLUETOOTH_SCAN、BLUETOOTH_CONNECTUSB读写器需要android.hardware.usb.host权限。2.3 uniapp原生插件的基本结构uniapp的原生插件分两种本地插件和云端插件。本地插件放在项目的nativeplugins目录下云端插件则需要在DCloud插件市场购买或下载。对于RFID这种定制化程度高的场景通常需要自己写本地插件。一个标准的Android原生插件目录结构是这样的nativeplugins/ YourRFIDPlugin/ android/ libs/ # 放厂商的.jar/.aar文件 src/ main/ java/ com/ yourcompany/ rfid/ RFIDModule.java # 插件主类 RFIDWXModule.java # 如果需要微信小程序端支持 AndroidManifest.xml build.gradle package.json # 插件配置文件其中RFIDModule.java是核心它需要继承UniModule类并用UniJSMethod(uiThread true)注解暴露给JS调用的方法。package.json里需要声明插件的id、名称、版本、Android依赖等信息。注意厂商的.jar/.aar文件可能和uniapp的默认依赖有冲突比如都引用了同一个版本的okhttp这时候需要在build.gradle里用exclude排除冲突的模块否则打包时会报Duplicate class错误。3. 把厂商SDK包装成uniapp原生插件的完整过程3.1 创建插件工程与配置package.json在HBuilderX里右键项目根目录选择“新建 - 原生插件”会生成一个插件模板。然后修改package.json{ name: YourRFIDPlugin, id: YourRFIDPlugin, version: 1.0.0, description: RFID读写器原生插件, _dp_type: nativeplugin, _dp_nativeplugin: { android: { plugins: [ { type: module, name: YourRFIDPlugin, class: com.yourcompany.rfid.RFIDModule } ], integrateType: aar, dependencies: [ com.android.support:appcompat-v7:28.0.0 ], abis: [ armeabi-v7a, arm64-v8a ], permissions: [ android.permission.INTERNET, android.permission.BLUETOOTH, android.permission.BLUETOOTH_ADMIN ] } } }这里有几个关键点integrateType指定为aar表示以aar形式集成abis指定支持的CPU架构RFID SDK通常包含.so文件需要根据厂商提供的架构来配置permissions里声明的权限会在打包时自动写入AndroidManifest。3.2 编写RFIDModule主类RFIDModule需要继承UniModule核心方法包括初始化、开始盘存、停止盘存、释放资源。下面是一个简化版的代码框架package com.yourcompany.rfid; import android.content.Context; import android.util.Log; import com.alibaba.fastjson.JSONObject; import com.taobao.weex.annotation.JSMethod; import com.taobao.weex.bridge.JSCallback; import com.taobao.weex.common.WXModule; import io.dcloud.feature.uniapp.annotation.UniJSMethod; import io.dcloud.feature.uniapp.bridge.UniJSCallback; import io.dcloud.feature.uniapp.common.UniModule; public class RFIDModule extends UniModule { private RFIDReader rfidReader; private UniJSCallback inventoryCallback; private boolean isInventorying false; UniJSMethod(uiThread true) public void init(JSONObject options, UniJSCallback callback) { try { Context context mUniSDKInstance.getContext(); rfidReader new RFIDReader(context); boolean success rfidReader.init(); JSONObject result new JSONObject(); result.put(success, success); callback.invoke(result); } catch (Exception e) { JSONObject error new JSONObject(); error.put(success, false); error.put(message, e.getMessage()); callback.invoke(error); } } UniJSMethod(uiThread true) public void startInventory(JSONObject options, UniJSCallback callback) { if (rfidReader null) { JSONObject error new JSONObject(); error.put(success, false); error.put(message, 请先调用init初始化); callback.invoke(error); return; } inventoryCallback callback; isInventorying true; rfidReader.startInventory(new RFIDReader.InventoryListener() { Override public void onTagRead(String epc, String rssi) { if (inventoryCallback ! null isInventorying) { JSONObject tag new JSONObject(); tag.put(epc, epc); tag.put(rssi, rssi); tag.put(timestamp, System.currentTimeMillis()); inventoryCallback.invokeAndKeepAlive(tag); } } }); } UniJSMethod(uiThread true) public void stopInventory(UniJSCallback callback) { isInventorying false; if (rfidReader ! null) { rfidReader.stopInventory(); } JSONObject result new JSONObject(); result.put(success, true); callback.invoke(result); } UniJSMethod(uiThread true) public void release(UniJSCallback callback) { isInventorying false; if (rfidReader ! null) { rfidReader.release(); rfidReader null; } JSONObject result new JSONObject(); result.put(success, true); callback.invoke(result); } }这里用到了invokeAndKeepAlive这是uniapp原生插件里实现持续回调的关键方法。普通的callback.invoke()只能回调一次而invokeAndKeepAlive可以多次回调适合盘存过程中不断返回标签数据的场景。3.3 处理广播接收与数据解析很多RFID读写器尤其是外接式蓝牙/USB读写器是通过**广播Broadcast**的方式把标签数据发给Android系统的。厂商SDK内部通常会注册一个BroadcastReceiver收到广播后解析出EPC、RSSI等数据再通过回调接口抛给上层。如果你发现厂商SDK没有提供回调接口而是直接发广播那就需要自己在插件里注册广播接收器private BroadcastReceiver rfidReceiver new BroadcastReceiver() { Override public void onReceive(Context context, Intent intent) { String action intent.getAction(); if (com.yourcompany.rfid.ACTION_TAG_READ.equals(action)) { String epc intent.getStringExtra(epc); String rssi intent.getStringExtra(rssi); if (inventoryCallback ! null isInventorying) { JSONObject tag new JSONObject(); tag.put(epc, epc); tag.put(rssi, rssi); inventoryCallback.invokeAndKeepAlive(tag); } } } };注册广播的代码放在init方法里IntentFilter filter new IntentFilter(); filter.addAction(com.yourcompany.rfid.ACTION_TAG_READ); mUniSDKInstance.getContext().registerReceiver(rfidReceiver, filter);注意Android 8.0以上对隐式广播做了限制如果厂商SDK用的是自定义action的广播需要确认是否在AndroidManifest里静态注册了或者是否需要在代码里动态注册。动态注册的广播在组件销毁时一定要记得unregisterReceiver否则会内存泄漏。3.4 在uniapp页面里调用插件插件写好后在vue页面里这样调用const rfidModule uni.requireNativePlugin(YourRFIDPlugin); export default { data() { return { tags: [], isScanning: false }; }, methods: { initRFID() { rfidModule.init({}, (res) { if (res.success) { uni.showToast({ title: 初始化成功 }); } else { uni.showToast({ title: 初始化失败 res.message, icon: none }); } }); }, startScan() { this.isScanning true; this.tags []; rfidModule.startInventory({}, (res) { // 这个回调会被多次触发每次返回一个标签 if (res.epc) { const exist this.tags.find(t t.epc res.epc); if (!exist) { this.tags.push({ epc: res.epc, rssi: res.rssi, timestamp: res.timestamp }); } } }); }, stopScan() { this.isScanning false; rfidModule.stopInventory((res) { console.log(停止盘存, res); }); } }, onUnload() { if (this.isScanning) { rfidModule.stopInventory(() {}); } rfidModule.release(() {}); } };这里有个细节startInventory的回调是持续触发的每次读到标签都会调一次。所以在页面里要做去重处理否则同一个标签会被重复添加。去重的逻辑可以基于EPC因为EPC是标签的唯一标识。4. 盘存数据去重、信号强度过滤与实时渲染优化4.1 为什么盘存数据需要去重和过滤RFID盘存的一个特点是同一个标签在盘存周期内会被多次读到。读写器每秒可能盘存几十次每次都会返回标签数据。如果不做处理页面上会瞬间涌入大量重复数据导致渲染卡顿甚至崩溃。去重只是第一步更关键的是信号强度RSSI过滤。RSSI值反映的是标签距离读写器的远近通常是一个负值比如-30dBm到-80dBm。RSSI越接近0说明信号越强标签越近。在实际项目中我们通常只关心一定距离内的标签所以可以设置一个RSSI阈值比如只保留RSSI大于-60dBm的标签。4.2 去重与过滤的具体实现在vue页面里可以用一个Map来存储已读到的标签key是EPCvalue是标签对象。每次收到新数据时先查Map里是否已存在如果存在则更新RSSI和最后读取时间如果不存在则新增。data() { return { tagMap: {}, // 用对象模拟Map tagList: [], // 用于渲染的数组 rssiThreshold: -60 }; }, methods: { handleTag(tag) { if (tag.rssi this.rssiThreshold) { return; // 信号太弱忽略 } if (this.tagMap[tag.epc]) { // 已存在更新RSSI和时间 this.tagMap[tag.epc].rssi tag.rssi; this.tagMap[tag.epc].lastSeen Date.now(); } else { // 新增 this.tagMap[tag.epc] { epc: tag.epc, rssi: tag.rssi, firstSeen: Date.now(), lastSeen: Date.now() }; } this.syncTagList(); }, syncTagList() { // 把Map转成数组按RSSI从强到弱排序 this.tagList Object.values(this.tagMap).sort((a, b) b.rssi - a.rssi); } }4.3 实时渲染的性能优化如果标签数量很多比如上百个每次更新都触发this.tagList ...会导致整个列表重新渲染性能很差。优化的思路有几种节流更新不要每次收到标签都更新UI而是用一个定时器比如每500毫秒把最新的数据同步到tagList。虚拟列表如果标签数量超过几百个用uniapp的scroll-view配合虚拟列表方案只渲染可视区域内的标签。分页展示如果业务上不需要同时展示所有标签可以分页显示每页20个。节流更新的实现data() { return { pendingUpdate: false }; }, methods: { handleTag(tag) { // ...去重逻辑... if (!this.pendingUpdate) { this.pendingUpdate true; setTimeout(() { this.syncTagList(); this.pendingUpdate false; }, 500); } } }提示RSSI值波动比较大同一个标签在不同时刻读到的RSSI可能相差10dBm以上。如果业务对距离判断要求高建议对RSSI做滑动平均滤波比如取最近5次的平均值这样距离判断会更稳定。5. Android权限适配与打包上架的踩坑记录5.1 动态权限申请的时机RFID插件涉及的权限分两类普通权限在AndroidManifest里声明即可和危险权限需要运行时动态申请。蓝牙相关的权限在Android 12以上属于危险权限必须动态申请。在uniapp里可以用plus.android.requestPermissions来申请权限const permissions [android.permission.BLUETOOTH_SCAN, android.permission.BLUETOOTH_CONNECT]; plus.android.requestPermissions(permissions, (result) { if (result.granted.length permissions.length) { // 权限全部授予 this.initRFID(); } else { uni.showToast({ title: 请授予蓝牙权限, icon: none }); } }, (error) { console.error(权限申请失败, error); });这里有个坑权限申请是异步的而且用户可能拒绝。所以初始化RFID的逻辑必须放在权限申请成功的回调里不能直接放在onLoad里。5.2 打包时的常见错误与解决打包uniapp原生插件时最常见的错误是依赖冲突和so文件缺失。依赖冲突的典型报错是Duplicate class com.xxx.xxx found in modules。解决方法是找到冲突的依赖在build.gradle里用exclude排除implementation(com.yourcompany:rfid-sdk:1.0.0) { exclude group: com.squareup.okhttp3, module: okhttp }so文件缺失的报错是java.lang.UnsatisfiedLinkError: dlopen failed: library libxxx.so not found。解决方法是确认abis配置里包含了厂商SDK支持的架构并且so文件确实被打包进了apk。可以用解压工具打开apk检查lib/目录下是否有对应的so文件。5.3 上架安卓应用市场的注意事项上架国内安卓应用市场时有几个和RFID相关的点需要特别注意权限说明如果应用申请了蓝牙权限需要在隐私政策里说明用途比如“用于连接RFID读写器设备”。隐私合规RFID读取的标签数据如果涉及用户信息需要在隐私政策里说明数据的收集、使用和存储方式。targetSdkVersion国内应用市场对targetSdkVersion有要求通常要求不低于30。如果厂商SDK的targetSdkVersion较低可能需要在build.gradle里覆盖配置。注意有些应用市场会检测应用是否真的使用了申请的权限。如果申请了蓝牙权限但实际没有蓝牙功能可能会被驳回。所以不要为了“以防万一”而申请不必要的权限。6. 从单次盘存到批量管理业务层的扩展思路6.1 标签数据的本地缓存与同步在实际项目中RFID盘存往往不是一次性的而是需要把盘存结果保存下来后续做资产盘点、出入库管理等。这时候就需要考虑数据的本地缓存和同步。本地缓存可以用uni.setStorageSync把标签列表存到本地key可以用盘存任务的ID。同步则需要在有网络的时候把数据上传到服务器。这里要注意的是盘存数据可能很大比如一次盘存几千个标签直接上传可能会超时建议分批上传每批100条。6.2 盘存任务的断点续传如果盘存过程中应用被切到后台或者崩溃了重新打开后应该能恢复之前的盘存状态。实现思路是每次盘存到新标签时除了更新内存里的数据还要把数据持久化到本地存储。应用启动时先检查是否有未完成的盘存任务如果有则恢复。// 保存盘存状态 saveInventoryState() { const state { taskId: this.taskId, tags: Object.values(this.tagMap), startTime: this.startTime, isScanning: this.isScanning }; uni.setStorageSync(inventory_state_ this.taskId, state); }, // 恢复盘存状态 restoreInventoryState(taskId) { const state uni.getStorageSync(inventory_state_ taskId); if (state) { this.taskId state.taskId; this.tagMap {}; state.tags.forEach(tag { this.tagMap[tag.epc] tag; }); this.syncTagList(); } }6.3 多读写器场景下的数据合并有些项目需要同时连接多个RFID读写器比如一个仓库有多个门禁读写器这时候需要把多个读写器的数据合并到一起。合并的关键是标签去重和位置标记。每个读写器有一个唯一ID标签数据里带上读写器ID这样就能知道某个标签是被哪个读写器读到的。在插件层面可以支持同时初始化多个读写器实例每个实例有独立的回调。在业务层面用一个全局的Map来合并数据key是EPCvalue里包含一个readers数组记录哪些读写器读到了这个标签。7. 一些实测有效的调试技巧与经验总结调试RFID插件最头疼的问题是看不到原生层的日志。HBuilderX的控制台只能看到JS层的日志原生层的Logcat日志需要单独查看。我的做法是用Android Studio的Logcat工具过滤tag为RFIDModule的日志。在插件的关键节点打日志比如初始化、开始盘存、收到标签、停止盘存。如果插件崩溃了Logcat里会有FATAL EXCEPTION的堆栈信息根据堆栈定位问题。另一个经验是先用厂商demo验证硬件再写插件。我遇到过好几次插件写好了但读不到标签排查半天发现是硬件本身的问题比如天线没接好、标签损坏、功率设置太低。如果先用demo验证硬件是好的就能排除硬件因素专注排查插件代码。还有一个坑是盘存功率的设置。功率太高会导致读取范围过大读到不需要的标签功率太低又读不到远处的标签。通常厂商SDK会提供设置功率的方法建议在初始化时根据实际场景调整。比如资产盘点场景功率可以设高一些门禁场景功率设低一些避免读到门外的标签。最后说一个关于标签数据格式的问题。不同厂商的RFID标签EPC编码格式可能不一样。有的用十六进制字符串有的用Base64有的直接是字节数组。在插件里最好统一转成十六进制字符串再传给JS层这样业务层处理起来比较方便。如果厂商SDK返回的是字节数组可以用bytesToHexString方法转换private String bytesToHexString(byte[] bytes) { StringBuilder sb new StringBuilder(); for (byte b : bytes) { String hex Integer.toHexString(b 0xFF); if (hex.length() 1) { sb.append(0); } sb.append(hex); } return sb.toString().toUpperCase(); }这些细节看起来不起眼但在实际项目里往往就是这些地方卡住你半天。希望这篇内容能帮你在uniapp对接RFID的路上少走一些弯路。

相关新闻

YOLOv11架构升级与部署实践:从C3k2到C2PSA的完整指南

YOLOv11架构升级与部署实践:从C3k2到C2PSA的完整指南

YOLOv11发布已经有一段时间了,ultralytics团队这次把整个训练、推理、验证、导出的链路又打磨了一遍。如果你和我一样,之前一直用YOLOv8跑业务,第一次切到v11大概率会有这种感觉:API几乎没变,但很多默认行为和网络细节…

2026/9/19 17:14:44 阅读更多 →
汽车企业数智化战略规划:从业务架构到数据平台落地

汽车企业数智化战略规划:从业务架构到数据平台落地

简介:这份汽车企业数智化战略规划PPT,面向汽车企业战略管理者、数字化转型负责人与咨询顾问,聚焦传统汽车产业在互联网时代的转型升级。资源为一个pptx文件,约二十二点六八MB,共一百四十五页。方案围绕“互联网1354”顶…

2026/9/19 17:14:44 阅读更多 →
Hugo Page.ReadingTime 方法详解:估算阅读时间的计算原理与多语言定制

Hugo Page.ReadingTime 方法详解:估算阅读时间的计算原理与多语言定制

Hugo Page.ReadingTime 方法详解:估算阅读时间的计算原理与多语言定制 【免费下载链接】hugo The world’s fastest framework for building websites. 项目地址: https://gitcode.com/gh_mirrors/hu/hugo 导读 Page.ReadingTime 是 Hugo 模板中用于估算页面…

2026/9/19 17:13:44 阅读更多 →

最新新闻

AssetRipper 提取 Unity 资源教程:从 .assets 到可导入文件的完整流程

AssetRipper 提取 Unity 资源教程:从 .assets 到可导入文件的完整流程

AssetRipper 提取 Unity 资源教程:从 .assets 到可导入文件的完整流程 【免费下载链接】AssetRipper GUI application to analyze game files 项目地址: https://gitcode.com/GitHub_Trending/as/AssetRipper 假设你手上有一个 Unity 游戏包,想把…

2026/9/20 20:28:59 阅读更多 →
机器学习前的数学补课要多久?《数学要素》25 章配齐 121 个代码本

机器学习前的数学补课要多久?《数学要素》25 章配齐 121 个代码本

机器学习前的数学补课要多久?《数学要素》25 章配齐 121 个代码本 【免费下载链接】Book3_Elements-of-Mathematics Book_3_《数学要素》 | 鸢尾花书:从加减乘除到机器学习;上架;欢迎继续纠错,纠错多的同学还会有赠书&…

2026/9/20 20:28:59 阅读更多 →
ant-design-vue Tour 引导组件完全指南:从 API 到源码原理的深度实践

ant-design-vue Tour 引导组件完全指南:从 API 到源码原理的深度实践

前端UI组件设计系统 【免费下载链接】ant-design-vue 🌈 An enterprise-class UI components based on Ant Design and Vue. 🐜 项目地址: https://gitcode.com/gh_mirrors/an/ant-design-vue 点击查看 免费下载 Tour(引导&#…

2026/9/20 20:28:59 阅读更多 →
FreeRTOS 测试框架实操手册:3 步跑通第一条队列用例

FreeRTOS 测试框架实操手册:3 步跑通第一条队列用例

FreeRTOS 测试框架实操手册:3 步跑通第一条队列用例 【免费下载链接】FreeRTOS Classic FreeRTOS distribution. Started as Git clone of FreeRTOS SourceForge SVN repo. Submodules the kernel. 项目地址: https://gitcode.com/GitHub_Trending/fr/FreeRTOS …

2026/9/20 20:28:59 阅读更多 →
Blackbird:一条命令扫遍 600+ 平台,OSINT 社交平台搜索与用户名反查工具

Blackbird:一条命令扫遍 600+ 平台,OSINT 社交平台搜索与用户名反查工具

Blackbird:一条命令扫遍 600 平台,OSINT 社交平台搜索与用户名反查工具 【免费下载链接】blackbird An OSINT tool to search for accounts by username and email in social networks. 项目地址: https://gitcode.com/GitHub_Trending/bl/blackbird …

2026/9/20 20:28:59 阅读更多 →
Faker 入门与进阶实战指南:用 Python 生成高质量假数据的完整方案

Faker 入门与进阶实战指南:用 Python 生成高质量假数据的完整方案

Faker 入门与进阶实战指南:用 Python 生成高质量假数据的完整方案 【免费下载链接】faker Faker is a Python package that generates fake data for you. 项目地址: https://gitcode.com/gh_mirrors/fak/faker Faker 是 Python 生态中一款生成假数据的工具包…

2026/9/20 20:27:58 阅读更多 →

日新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/19 23:01:36 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/19 17:50:38 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →