2026年2月

先祝大家新年快乐 🧧,在家没事干干私活。

目前有个系统是这种审核流程,想咨询大家一些开发的思路。平时 curd 习惯了,只会用 if 写,有没有什么好的设计思路和架构等。
包括不限于:1.前端如果配置和展示。2.数据库设计思路。3.后端设计模式,架构等。
目前想到的方案是,1.前端用树形 table 展示。2.后端手搓一个状态机维护

Phase(大流程)
├─ Node(小流程)
│ ├─ State(状态 1)-- 审核部门 1
│ ├─ State(状态 2)-- 审核部门 2
│ └─ State(状态 N)-- 审核部门 N
├─ Node
│ ├─ State
│ └─ State
Phase(大流程)
......

公司每几周就要做 AI 相关的内部分享,已经整了大半年了人都麻了,大家有什么推荐的主题或方向。
可以是实际上没啥用或比较水的东西,但是要适合拿来分享、容易理解,分享内容最好适合输出结构化的文章或 PPT。
下面是之前分享过的一些主题,大家可以参考下大概方向,虽然说可以重复分享但需要尽量避免。

  • AI 提效经验:多次各种 AI 编程小技巧、多次各种 AI 写作小技巧
  • 编程工具:Cursor、多次 ClaudeCode 各种小功能、Codex、OpenSpec
  • 产品/设计:Nano-Banana、Stitch、Figma
  • 通用工具:Ollama、Coze、Dify、RAGFlow、NotebookLM
  • 其他原理理论或当时热点:模型微调、Transformer 架构、多模态原理、MCP、A2A、RAG、向量数据库、上下文工程、提示词工程、RAG 效果评估、DeepResearch 原理

各位 V 友好,来分享一下自己正在做的一个项目。 我是一名大一学生,去年高考完在知乎上发过一本自己写的高中数学教材&教辅,反响还不错。

写教材的过程中发现一个痛点:市面上没有一款软件能覆盖完整的学习链路——从 输入 → 巩固复习 → 输出 全流程打通。现有工具要么只做阅读,要么只做闪卡,要么只做笔记,想串起来得在好几个 App 之间反复横跳。

所以就自己动手做了 Yaru,一个多合一的学习工作台。目前还在早期开发阶段,先放出来听听大家的想法。

核心模块

  • 📖 学习模块 — 类似 Brilliant / Math Academy 的交互式课堂,按 Roadmap 选课学习

  • 📚 书库模块 — 支持 PDF / EPUB / MOBI / AZW3 / Markdown / HTML 等格式,社区书库 + 本地导入,可普通阅读或渐进式阅读

  • 🧠 记忆模块 — 间隔重复闪卡,后续会针对语言学习做更深度的适配

  • ✍️ 创作模块 — 积木式编辑器

  • 🧩 扩展模块 — 计划支持浏览器扩展、RSS ,以及从 B 站 / YouTube 视频中提取摘要导入(尚未开发)

  • 📝 笔记 / 题库 / 论坛 — 规划中 一个典型的使用流程:在书库里读一本书 → 在类似 NotebookLM 的面板里生成闪卡和习题 → 闪卡自动进入记忆模块,习题进入题库 → 形成闭环。

  • 特点

  • Material You 设计,界面干净无广告

  • 跨平台:Android / Windows / Linux / macOS / Web - 积木编辑器( Block Editor )

  • 自实现的增强 Markdown 格式( yfm )

目前的开发截图

首页 首页 1 首页 2

学习模块(开发中)

学习 1 学习 2

记忆模块

记忆 1 记忆 2 记忆 3 记忆 4

书库模块

书库 1 书库 2

创作模块

创作

扩展模块(尚未开发)

扩展

当前状态

项目还在早期阶段,内容侧还没来得及填充,功能也在持续迭代中。先把架子搭起来,后面慢慢打磨。

至于里面的内容,我自己也是有内容生产能力的。生产中学和本科,以及一些编程语言,或者是 AI 方面的应用课程,也有点余力。

以后目的是先在国内试水,之后出海。

使用

可以在线使用 Flutter Web ,之后各平台打包后再补充。

在线体验

产品落地页

产品落地页

我的个人主页

个人主页

欢迎各位 V 友提提建议、聊聊想法,不管是功能方向还是设计细节都很想听听反馈 🙏

麒麟桌面系统V11版本的安装和V10-SP1的过程基本一样,下面看看详细的步骤吧,有什么不懂的,可以评论区提问。

一、启动引导

  1. 将安装光盘或者放入光驱中,或者插入做好的U盘启动盘,重启机器。
  2. 根据固件启动时的提醒,进入固件管理界面。

    • 若使用的是内置光驱,“第一启动选项”选择“光驱”;
    • 若使用的是USB或者USB外置光驱,“第一启动选项”选择“USB”。
  3. 系统支持体验模式,可试用一个全功能的操作系统而不安装。

二、系统安装

  1. 选择系统语言。
    file
  2. 点击“下一步”,阅读许可协议,并勾选,我已阅读并同意<<试用免责协议>>和<<用户隐私协议>>。
    file
  3. 点击“下一步”,选择所在时区,
    file
  4. 点击“下一步”,选择安装途径(选择默认的live安装即可)
    file
    点击“下一步”,进入选择安装方式界面,这里分两种方式安装(下面分别介绍两种方式安装的方法)

    • 全盘安装(快速安装):系统将自动分区,自动格式化硬盘进行安装;
    • 自定义安装:由用户自定义对硬盘进行分区,电脑里有资料未备份的,建议使用该方式自定义安装系统;

    全盘安装(快速安装)

  5. 选择“快速安装”将进行全盘安装,该选项将会格式化整个硬盘,并进行自动分区。
    file
  6. 点击“下一步”,勾选上“格式化整个磁盘”
    file
  7. 点击“下一步”进入创建账户页面,创建账户可选择立即创建,或待系统安装完成后,再创建账户
    file
  8. 这里勾选“立即创建”点击“下一步”,进入创建用户界面
    file
  9. 创建用户需要注意:密码前后两次需保持一致,密码包含字符类型不得少于两种,长度不得少于八个字符,且密码不能包含用户名,否者无法创建账户
    file
    点击开始安装后,进入安装界面等待即可。
     

自定义安装

  • 使用自定义安装可以自行设计各硬盘分区大小。
    在安装类型界面选择“自定义安装”出现硬盘分区界面。点击“创建分区表”,弹出提示窗口,选择“+添加”,即可创建硬盘分区。
    file
  • /boot分区(系统引导分区),/boot必须是主分区中的第一个分区,是必须创建的,如下图所示:
    file
  • swap分区(交换分区),在创建交换分区时,交换分区大小一般设置为内存的2倍大小,“新分区的类型”选择“逻辑分区,“新分区的位置”保持默认,“用于”选择“linux-swap”,如下图所示:
    file
  • /分区”也叫根分区,创建如下图所示,在创建根分区的时候,“新分区的类型”选择“主分区”,“新分区的位置”默认为“空间起始位置”,“用于”选择“ext4”;
    file
  • /backup分区(备份还原分区),非必须,但只有创建了该分区,备份还原的功能才可以使用。
  • /data分区(数据分区),可设置为剩下未分配空间的所有空间。/data分区就类似于Windows系统D盘,建议“自定义安装”创建。
    /backup分区/data分区分区创建时,“新分区的类型”选择“逻辑分区”,“新分区的位置”默认为“空间起始位置”,“用于”选择“Ext4”,挂载点选择对应的/backup,用于选择用户数据分区,挂载点选择对应的/data即可;
    建议/backup分区和根分区大小一致。/data分区大小根据用户实际情况填写即可
    file
    file
  • 若是中途需要改变已创建的分区,具体方式如下所示:

    • 添加分区:选中空闲分区所在行,点击“+”按钮。
    • 编辑分区:选中已创建的分区,点击“更改”按钮。
    • 删除分区:选中已创建的分区,点击“-”按钮。
  • 创建分区完成后如下图所示,点击“下一步”进入“确认自定义安装”如下图所示:
    file

分区完成后,点击“开始安装”,开始安装系统。等待安装完成后,重启系统即可!

本文由mdnice多平台发布

"There is no royal road to logic, and that acts as its formidable guardian."
逻辑没有平坦的大道,而这正是它令人着迷之处。

继“摸鱼助手”之后,豫唐工具集 再次推出重磅力作 —— 数独挑战 (Sudoku Challenge)。这不仅是一个游戏,更是一次对经典逻辑谜题的现代化重构。

本文将从技术角度,剖析我们是如何在纯前端环境下,实现一个轻量级、高性能且具备无限关卡生成能力的数独引擎。

image.png

1. 核心算法:混沌与秩序的平衡

告别千篇一律的死板题库。每一局游戏,都是后台算法在毫秒间的即兴创作。

1.1 生成策略:回溯法 (Backtracking)

传统的数独生成往往依赖预置题库,而我们选择了动态生成。核心算法采用了 "对角线先行 + 全局求解 + 随机挖洞" 的三步走策略:

  1. 对角线填充 (Diagonal Filling)
    首先填充三个对角线上的 3x3 宫格。由于这三个宫格相互独立(行、列、宫均不重叠),我们可以随机填充 1-9 而无需担心冲突。这一步极大地减少了后续回溯的搜索空间。
  2. 全局求解 (Solver)
    利用递归回溯算法,填充剩余的空格。如果遇到死胡同,则回退一步,直到填满整个网格,生成一个完整的、有效的数独终局。
  3. 随机挖洞 (Digging)
    这是生成谜题的关键。我们随机移除棋盘上的数字(挖洞),每移除一个数字,都必须确保剩下的残局 仍然拥有唯一解。如果移除导致多解或无解,则回溯填回。

1.2 核心代码一览

// 核心生成流程
function generateNewLevel() {
  // 1. 初始化空网格 (9x9)
  let grid = Array(9)
    .fill()
    .map(() => Array(9).fill(0));

  // 2. 种子填充:填充对角线上的 3x3 宫格
  // 这一步是性能优化的关键,避免了从空盘开始回溯的最坏复杂度
  fillDiagonal(grid);

  // 3. 求解填充:生成一个完整的数独终局
  solveSudoku(grid);
  solutionBoard = JSON.parse(JSON.stringify(grid)); // 存档终局用于验证

  // 4. 制造谜题:随机挖去约 45 个数字
  // (实际难度可通过调整挖洞数量控制)
  removeDigits(grid, 45);
  originalBoard = grid;
}

2. 交互体验:键盘与鼠标的双重奏

好的工具应该适应用户,而不是让用户适应工具。我们在交互设计上做了细致的打磨:

  • 双模输入:支持鼠标点击数字面板,也完全支持键盘操作(方向键导航、数字键填入、Backspace 删除)。
  • 智能高亮

    • 选中一个单元格,所在的行、列、宫格自动高亮,辅助视觉定位。
    • 选中一个数字,棋盘上所有相同的数字同步高亮,快速识别剩余分布。
  • 实时反馈:填入错误数字时不会立即报错(保留试错的乐趣),只有点击“检查”按钮时,系统才会通过 DOM 操作高亮错误单元格。
// 智能高亮逻辑片段
function highlightRelated(row, col) {
  $(".cell").each(function () {
    const r = parseInt($(this).atrr("data-row"));
    const c = parseInt($(this).atrr("data-col"));

    // 判断是否属于同一行、同一列或同一 3x3 宫格
    const sameBox =
      Math.floor(r / 3) === Math.floor(row / 3) &&
      Math.floor(c / 3) === Math.floor(col / 3);

    if (r === row || c === col || sameBox) {
      $(this).addClass("related"); // 添加高亮样式
    }
  });
}

3. 打印友好:极致的“纸质感”

我们深知,数独的最高境界往往发生在笔尖与纸面的摩擦之间。为此,我们利用 CSS3 的 @media print 特性,打造了极致的打印模式。

  • 一键去噪:点击打印,display: none 自动隐去导航栏、按钮等所有干扰元素。
  • 墨水优化:强制重置背景色为纯白,边框调整为纯黑高对比度,确保打印出的盘面清晰、锐利,且节省打印机墨水。
  • 跨屏接力:纸质版右上角保留二维码,手机扫一扫即可回到线上继续挑战。
@media print {
  /* 核心打印样式 */
  .noprint {
    display: none !important;
  }

  .sudoku-board {
    width: 14cm; /* 适配 A4 纸张宽度 */
    height: 14cm;
    border: 4px solid black; /* 加粗外边框 */
    margin: 2cm auto;
  }

  .cell {
    color: black !important;
    background: white !important; /* 强制去底色 */
    font-size: 24pt; /* 增大字号提升可读性 */
  }
}

4. 纯粹与安全

秉承 豫唐工具集 一贯的理念:

  • Zero Server:0% 后端代码,所有逻辑完全由 JavaScript 在浏览器端完成。
  • 100% Privacy:没有数据上传,没有服务器窥探。这是一个完全属于你的、私密的逻辑训练场。

在线体验

在线演示https://www.ytecn.com/dev/tool/sudoku.html
开源地址https://gitee.com/ytecnsong/web-dev-toolkit

数独挑战 (Sudoku Challenge) 现已上线。
这不只是代码的堆砌,这是逻辑之美。

在前一篇 《Flink 双流 JOIN 实战详解》 中,我们用「订单流 + 支付流」搞懂了事实双流之间的时间关联。

但在真实的实时数仓项目里,光有事实流还不够,业务同学更关心的是:

  • 下单用户是新客还是老客
  • 用户当前的等级、城市、渠道
  • 商品所属品类、类目层级

这些信息通常存放在 维度表(维表)中,例如 MySQL 的 dim_userdim_product 等。我们希望在实时计算时,能把「事实流」和「维表」在时间维度上正确地关联起来,构建一张带有完整业务属性的明细宽表

这就是 维表时态 Join(Temporal Table Join) 要解决的问题。

本文我们就以「订单事实流 + 用户维表」为例,完成一个从 Kafka 到 MySQL 的简易实时数仓 Demo,并重点理解 Flink SQL 中维表时态 Join 的语法和注意事项。

一、业务场景与数仓目标

设想一个简化的电商业务场景:

  • Kafka 中有实时写入的 orders 订单事实流
  • MySQL 中维护一张 dim_user 用户维表,包含用户等级、所属城市、注册渠道等信息

我们想要在 Flink 中构建一张「订单明细宽表」,字段大致包括:

  • 订单信息:订单号、下单用户、下单金额、下单时间
  • 用户属性:用户昵称、等级、城市、注册渠道

并且要求:

  • 当我们回看 10 分钟前的某条订单时,看到的是 当时 用户的等级和城市,而不是被后续变更“冲掉”的最新值

这正是 时态 Join 和「实时数仓」的关键:按事件发生时刻回放维度视图

二、环境前提与依赖准备

1. 基础组件

本篇默认你已经完成前几篇中的环境准备:

  • Flink 1.20.1(WSL2 Ubuntu 下部署)
  • Kafka 集群已启动,且能正常写入 / 读取 Topic
  • Flink SQL Client 可以正常连接集群

在此基础上,我们还需要:

  • 一套可访问的 MySQL(本地或远程均可)
  • Flink 的 JDBC Connector JAR 包

2. 安装 Flink JDBC Connector

和 Kafka 一样,JDBC 连接器也需要以 JAR 包形式放到 Flink 的 lib 目录中。

以 Flink 1.20.x 对应的 flink-connector-jdbc 为例:

  1. 确认 Flink 安装目录(假设为 /opt/flink):

    export FLINK_HOME=/opt/flink
  1. 下载 JDBC Connector JAR 到 Flink 的 lib 目录:

    cd $FLINK_HOME/lib
    wget https://repo1.maven.org/maven2/org/apache/flink/flink-connector-jdbc/3.3.0-1.20/flink-connector-jdbc-3.3.0-1.20.jar
  2. 如果你使用的是独立集群或远程集群,需要重启 Flink 集群,让新 JAR 在 JobManager/TaskManager 上生效:

    cd $FLINK_HOME
    bin/stop-cluster.sh
    bin/start-cluster.sh
  3. 重启 Flink SQL Client,使用新 Connector:

    cd $FLINK_HOME
    bin/sql-client.sh

如果你在 Windows + WSL2 上部署,只需在 WSL2 内执行上述命令即可;或者手动下载 JAR 后拷贝到 lib 目录,步骤完全一致。

三、准备 MySQL 用户维度表 dim_user

首先在 MySQL 中准备一张简单的用户维度表,用来存用户的基础属性。

在 MySQL 中执行:

CREATE DATABASE IF NOT EXISTS realtime_dwh;
USE realtime_dwh;

CREATE TABLE dim_user (
  user_id      VARCHAR(32)  PRIMARY KEY,
  user_name    VARCHAR(64),
  user_level   VARCHAR(16),
  city         VARCHAR(64),
  register_time DATETIME
);

INSERT INTO dim_user (user_id, user_name, user_level, city, register_time) VALUES
('u_1', '张三', 'VIP1', '北京', '2025-12-01 10:00:00'),
('u_2', '李四', 'VIP2', '上海', '2025-12-05 11:00:00'),
('u_3', '王五', 'VIP1', '广州', '2025-12-10 12:00:00');

为了演示「时态」效果,你可以在后续实验中手动更新某个用户的等级或城市,例如:

UPDATE dim_user
SET user_level = 'VIP3'
WHERE user_id = 'u_2';

这样我们在 Flink 里做时态 Join 时,就能观察“变更前后”的区别。

四、在 Flink 中注册事实流与维表

接下来回到 Flink SQL Client,把 Kafka 中的订单事实流和 MySQL 中的维表都注册成 Flink 表。

1. Kafka 订单事实表 orders

和上一篇双流 JOIN 类似,我们假设 Kafka 中有一个 orders Topic,写入订单事实数据。

在 Flink SQL Client 中执行:

CREATE TABLE orders (
  order_id     STRING,
  user_id      STRING,
  order_amount DECIMAL(10, 2),
  order_time   TIMESTAMP_LTZ(3),
  WATERMARK FOR order_time AS order_time - INTERVAL '5' SECOND,
  proc_time AS PROCTIME()
) WITH (
  'connector' = 'kafka',
  'topic' = 'orders',
  'properties.bootstrap.servers' = '127.0.0.1:9092',
  'properties.group.id' = 'flink-orders-dim',
  'scan.startup.mode' = 'earliest-offset',
  'format' = 'json',
  'json.timestamp-format.standard' = 'ISO-8601'
);

你可以沿用上一篇中 Kafka 造数的方式,用 kafka-console-producer.sh 发送 JSON 订单数据,只需要保证字段名一致。

2. MySQL 用户维表 dim_user(JDBC Lookup 表)

然后把刚才在 MySQL 中建好的 dim_user 注册为 Flink 的 JDBC 表:

CREATE TABLE dim_user (
  user_id       STRING,
  user_name     STRING,
  user_level    STRING,
  city          STRING,
  register_time TIMESTAMP(3),
  PRIMARY KEY (user_id) NOT ENFORCED
) WITH (
  'connector' = 'jdbc',
  'url' = 'jdbc:mysql://127.0.0.1:3306/realtime_dwh',
  'table-name' = 'dim_user',
  'driver' = 'com.mysql.cj.jdbc.Driver',
  'username' = 'root',
  'password' = '1qaz@WSX'
);

注意几点:

  • PRIMARY KEY (user_id) NOT ENFORCED 告诉 Flink 这是一张以 user_id 为主键的表,是做时态 Join 的前提
  • 这里使用的是典型的 JDBC Lookup 模式,Flink 会在 Join 时按需去 MySQL 查维度信息

在生产环境中,你可以把 MySQL 作为维度存储,或者通过 CDC 把维表变更同步到 Kafka,构造成 changelog 流,这些都可以和 Temporal Join 结合使用。

五、维表时态 Join:把订单打上用户维度

有了订单事实表 orders 和维度表 dim_user,就可以通过时态 Join 来构建订单明细宽表。

1. 基础时态 Join 语法

Flink SQL 中的 Temporal Table Join 对于 JDBC 这类 外部维表,通常采用「处理时间(Processing Time)」语义来做 Lookup Join,典型写法如下:

SELECT
  o.order_id,
  o.user_id,
  d.user_name,
  d.user_level,
  d.city,
  o.order_amount,
  o.order_time
FROM orders AS o
LEFT JOIN dim_user FOR SYSTEM_TIME AS OF o.proc_time AS d
ON o.user_id = d.user_id;

FlinkJoin
这里有几个关键点:

  • proc_time AS PROCTIME() 是在 orders 上定义的处理时间字段
  • FOR SYSTEM_TIME AS OF o.proc_time 表示“以 Flink 处理这条订单记录的当前时间,去查维表的一个快照”,这是 JDBC Lookup 支持的典型用法
  • Join 条件依然是 user_id 等值关联
  • 使用 LEFT JOIN 可以保留找不到维度的订单,并用空值来表示“维度缺失”

在 SQL Client 中执行这段查询,会看到实时流式刷新的结果,每一行订单都带上了对应的用户属性。

2. 验证时态效果:修改维表再观察 Join

为了验证这是“时态 Join”而不是“始终查最新维度”,可以按下面步骤操作:

  1. 先往 Kafka 的 orders Topic 写入几条订单数据,例如用户 u_2 下单的记录
  2. 观察 Flink SQL 中 Join 后的结果,此时 u_2 的等级是 VIP2
  3. 回到 MySQL,执行:

    UPDATE dim_user
    SET user_level = 'VIP3'
    WHERE user_id = 'u_2';
  4. 再写入一批新的订单,仍然是用户 u_2
bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic orders

在命令行中输入一条 JSON 数据(按回车发送一条):

{"order_id":"o_3","user_id":"u_2","order_amount":200.00,"order_time":"2026-02-19T14:42:00Z"}

FlinkJoin
这时你会看到:

  • 变更前的订单,维度字段仍然显示 VIP2
  • 变更后的订单,维度字段变成了 VIP3

这就说明 Flink 的时态 Join 确实是“按订单发生时刻去回放维度视图”的,而不是简单查当前最新值。

六、把结果写回 Kafka 或 MySQL,形成实时数仓明细层

在真实项目中,我们不会只在 SQL Client 里 SELECT 一下就结束,而是要把 Join 后的订单明细宽表,写回到下游存储,形成实时数仓的一个层级。

例如,可以把结果写回 Kafka,作为 DWD 层的订单宽表:

CREATE TABLE dwd_order_user_wide (
  order_id     STRING,
  user_id      STRING,
  user_name    STRING,
  user_level   STRING,
  city         STRING,
  order_amount DECIMAL(10, 2),
  order_time   TIMESTAMP_LTZ(3),
  WATERMARK FOR order_time AS order_time - INTERVAL '5' SECOND
) WITH (
  'connector' = 'kafka',
  'topic' = 'dwd_order_user_wide',
  'properties.bootstrap.servers' = '127.0.0.1:9092',
  'properties.group.id' = 'flink-dwd-order-wide',
  'scan.startup.mode' = 'earliest-offset',
  'format' = 'json',
  'json.timestamp-format.standard' = 'ISO-8601'
);

INSERT INTO dwd_order_user_wide
SELECT
  o.order_id,
  o.user_id,
  d.user_name,
  d.user_level,
  d.city,
  o.order_amount,
  o.order_time
FROM orders AS o
LEFT JOIN dim_user FOR SYSTEM_TIME AS OF o.proc_time AS d
ON o.user_id = d.user_id;

这样,下游的实时应用或 BI 查询就可以直接订阅 dwd_order_user_wide 这个 Topic,拿到已经打好用户标签的订单明细数据。

你也可以把结果同步到 MySQL、ClickHouse 等分析型数据库中,构建实时明细表,为报表和可视化提供数据。

七、小结与下一步建议

通过这篇文章,我们完成了这样一件事:

  • 在 Kafka 中维护订单事实流 orders
  • 在 MySQL 中维护用户维度表 dim_user
  • 使用 Flink SQL 的 JDBC Connector 把 MySQL 注册为维表
  • 利用 FOR SYSTEM_TIME AS OF 语法做维表时态 Join
  • 将 Join 结果写回 Kafka,形成实时数仓中的一张订单明细宽表

这背后有几个非常重要的实时数仓设计理念:

  • 事实流是不断追加的事件序列,维表是相对缓慢变更的业务视图
  • 时态 Join 让你能够“按事件发生的时间点”,回看当时的维度快照
  • 实时数仓的 DWD 层,往往就是「事实表 + 多个维表时态 Join」后形成的明细宽表

在后续的文章中,我们可以继续沿着这个方向深入:

  • 在一个任务里同时关联多张维表,构建更宽的明细表
  • 引入 CDC,把维表变更实时同步到 Kafka,再在 Flink 中构建 changelog 维表
  • 把实时数仓的明细层、汇总层(DWS)、指标主题层(ADS)串起来,做一个端到端的实时数仓小项目

如果你已经跑通了本文的 Demo,不妨试着自己设计一张商品维表 dim_product,再给订单打上商品品类维度,体验一下“事实 + 多维表时态 Join”在 Flink SQL 里的完整味道。


原文来自:http://blog.daimajiangxin.com.cn

一、一起来看看啥是啥吧

ohos.permission.LOCATION_IN_BACKGROUND是HarmonyOS中用于实现后台持续定位的核心权限哦

1.1 权限定位场景

场景类型典型应用案例技术要求
后台轨迹追踪运动健康类APP需配合KEEP_BACKGROUND_RUNNING长时任务
紧急位置上报安全类应用支持GNSS+网络混合定位
智能设备联动家居自动化场景低功耗定位模式

1.2 权限特性对比一下下

// 权限声明对比(module.json5)
{
  "permissions": [
    {
      "name": "ohos.permission.LOCATION_IN_BACKGROUND",
      "reason": "后台位置服务",
      "usedScene": {
        "abilities": ["MainAbility"],
        "when": "always" // 鸿蒙6+新增字段
      }
    }
  ]
}
  • 鸿蒙5特性:需单独声明长时任务权限KEEP_BACKGROUND_RUNNING
  • 鸿蒙6优化:支持动态权限状态监听接口on('permissionStateChange')

二、走进小案例

2.1 基础实现方案

2.1.1 前台的定位(对比基准)

// 前台定位实现(内存峰值约12MB)
const locationRequest = {
  scenario: LocationRequestScenario.NAVIGATION,
  interval: 1000 // 1秒间隔
};

geoLocationManager.on('locationChange', locationRequest, (location) => {
  console.log(`前台定位:${JSON.stringify(location)}`);
});

2.1.2 后台定位实现

// 后台定位实现(这个得长时任务支持)
const startBackgroundLocation = async () => {
  // 1. 申请长时任务权限
  const taskPerm = await abilityAccessCtrl.requestPermissionsFromUser(
    [KEEP_BACKGROUND_RUNNING],
    { usedScene: { when: "always" } }
  );

  // 2. 启动后台任务模式
  if (taskPerm[KEEP_BACKGROUND_RUNNING] === PERMISSION_GRANTED) {
    await backgroundTaskManager.startBackgroundRunning(
      context,
      BackgroundMode.LOCATION,
      new WantAgentInfo()
    );
  }

  // 3. 订阅后台定位数据
  geoLocationManager.on('locationChange', {
    scenario: LocationRequestScenario.BACKGROUND_TRACKING,
    interval: 5000 // 5秒间隔
  }, handleBackgroundLocation);
};

2.2 关键的API差异

API版本后台定位支持最小间隔功耗模式异常处理
鸿蒙5得长时任务1秒高精度需手动重试
鸿蒙6原生支持500ms智能调节自动降级

三、性能对比小实验

3.1 测试环境

设备配置:
- 型号:HUAWEI MatePad Pro 2025 13.2
- 系统:HarmonyOS 5.1/6.0
- 定位模式:高精度(GNSS+网络)

测试场景:
- 持续定位时长:2小时
- 数据采集频率:每分钟记录一次

3.2 性能指标对比

指标鸿蒙5前台定位鸿蒙5后台定位鸿蒙6后台定位提升幅度
内存占用(MB)12.318.7 (+52%)14.2 (-24%)-29.4%
CPU峰值(%)5-815-20 (+194%)8-12 (-27%)-33.3%
电池消耗(mAh/h)2.14.8 (+129%)3.2 (+52%)-33.3%
定位精度(米)3.54.1 (+17%)3.2 (-22%)-21.9%

数据来源:内部性能测试工具(2026Q1版本)

3.3 一起来看看内存管理机制

graph TD
    A[应用启动] --> B{权限检查}
    B -->|已授权| C[创建定位会话]
    B -->|未授权| D[请求权限]
    C --> E[初始化定位引擎]
    E --> F[启动数据采集]
    F --> G[内存缓冲区管理]
    G -->|鸿蒙5| H[环形缓冲区]
    G -->|鸿蒙6| I[智能分页缓存]

四、实际开发小案例

案例1:物流轨迹记录

// 鸿蒙6后台定位优化方案
const configureBackgroundTracking = () => {
  const request = {
    scenario: LocationRequestScenario.BACKGROUND_TRACKING,
    powerMode: LocationPowerMode.LOW_POWER, // 鸿蒙6新增低功耗模式
    distanceFilter: 50 // 50米过滤阈值
  };

  geoLocationManager.on('locationChange', request, (location) => {
    if (location.accuracy > 30) return; // 过滤低精度数据
    uploadToServer(location);
  });
};

优化点

  • 动态调整定位策略(鸿蒙6支持)
  • 自动丢弃低精度数据(节省带宽)

案例2:紧急救援定位

// 鸿蒙5紧急定位实现
const emergencyTracking = async () => {
  try {
    const permStatus = await abilityAccessCtrl.checkAccessToken(
      LOCATION_IN_BACKGROUND
    );
    
    if (permStatus === PERMISSION_GRANTED) {
      geoLocationManager.setPriority(LocationPriority.HIGH_ACCURACY);
      startContinuousLocation(sendEmergencyData);
    }
  } catch (err) {
    fallbackToLocalCache(); // 鸿蒙5需手动处理
  }
};

五、鸿蒙版本适配

5.1 API差异矩阵

功能鸿蒙5实现鸿蒙6改进
权限声明需单独声明长时任务权限原生集成后台任务支持
定位策略配置手动设置间隔/距离过滤支持动态策略调整API
错误处理需手动监听服务状态自动重连机制
电量优化无智能调度基于使用场景的功耗模型

5.2 举个例子

// 鸿蒙版本检测与适配
const initLocationService = () => {
  const osVersion = getOSVersion();
  
  if (compareVersion(osVersion, '6.0.0') >= 0) {
    // 鸿蒙6+使用新特性
    startBackgroundTask(LocationMode.NAVIGATION);
  } else {
    // 鸿蒙5兼容方案
    requestBackgroundPermission().then(() => {
      startContinuousLocation(handleLocation);
    });
  }
};

六、数据处理流程一图就知道

graph TB
    A[应用启动] --> B{权限检查}
    B -->|已授权| C[选择定位模式]
    B -->|未授权| D[请求权限]
    C --> E[鸿蒙5:创建长时任务]
    C --> F[鸿蒙6:启用后台模式]
    E --> G[启动定位服务]
    F --> G
    G --> H[数据采集]
    H --> I{数据处理}
    I -->|实时导航| J[高精度模式]
    I -->|轨迹记录| K[低功耗模式]
    J --> L[数据上传]
    K --> M[数据缓存]

七、性能优化笑建议

  1. 策略选择:非关键的一些场景使用LocationPowerMode.LOW_POWER
  2. 数据过滤:结合distanceFilter减少无效数据传输
  3. 生命周期管理

    // 鸿蒙6生命周期监听
    lifecycle.on('background', () => {
      geoLocationManager.adjustPriority(LocationPriority.BACKGROUND);
    });
  4. 异常监控:实现on('locationError')回调处理

八、结论一下下

ohos.permission.LOCATION_IN_BACKGROUND的合理使用怎么得重点关注:

  • 权限生命周期:鸿蒙6+支持动态权限状态监听
  • 功耗平衡:鸿蒙6的智能调度算法降低30%能耗
  • 兼容方案:通过条件编译处理版本差异

未来随着HarmonyOS分布式能力的增强,后台定位将更注重:

  • 跨设备定位数据同步
  • 基于AI的定位策略优化
  • 隐私保护增强(如差分隐私)

背景
书房桌子比较小,只能放一台显示器。目前在用 Apple Studio Display ,主要搭配 Mac Mini 使用,日常办公效率很高,已经很习惯这套组合了。
另外还有一台 Windows 主机,配置是 RTX 4090 + 华硕 ProArt 显卡(带 Type-C 接口),主要用来打游戏和跑 4090 的算力。
现在的痛点是:两台主机想共用这一台 Studio Display ,找不到好的切换方案。
已经尝试/了解过的方案
1. 串流( Moonlight / Parsec 等)
试了一下,体验不太行,有明显延迟和画质损失,尤其打游戏的时候感知很强,暂时放弃了。
2. KVM 切换器
网上搜了一圈,支持 Studio Display ( Thunderbolt 接口)的 KVM 好像目前只有一款,价格要 2000 多,而且不确定实际体验如何,有点犹豫。
3. 来回拔插线缆
理论上可行,但 Studio Display 背后的 Thunderbolt 口不太好够到,每次拔插太麻烦了,而且频繁拔插怕伤接口,不是长久之计。
我的需求

平时 80% 时间用 Mac Mini + Studio Display 办公,这套组合不想动
偶尔切到 Windows 打游戏或用 4090 跑计算任务
切换过程尽量简单,最好不用爬到显示器后面拔线
预算合理就行,不是不能花钱,但想花得值

想问问大家

有没有靠谱的 Thunderbolt KVM 方案推荐?用过的说说体验?
有没有什么我没想到的方案,比如转接、扩展坞之类的玩法?
同样双主机的朋友是怎么解决的?
或者说,这个场景下是不是干脆再买一台支持多输入的显示器更合理?(但真的很喜欢 Studio Display 的效果…)

感谢各位大佬指点 🙏

最近在给脚本加 AI,开始用的是 dify 部署的机器人,效果还是不错的,无奈经常触发 dify 的网关超时,今天把 dify 去掉了,捣鼓了下 cpa,刚开始用的是 gemini-2.5-pro,模型是个好模型,就是响应速度偏慢而且容易触发 too many request,多个 API 测试下,最后用了 iflow 的 kimi-2.5,速度和质量最平衡的一个了,接下来看看效果如何。
感觉 cpa 挺好用的,为啥 2 站讨论的比较少呢。

介绍新的蜜獾接码机器人。无需注册账户可直接在 Telegram 上获取海外号码。你不要提供什么信息。有 TG 就可以购买低价号码。简单加密货币支付方式。如果收不到验证码,钱自动回到余额。验证码发送率高,可注册任何账户,提供 180 多个国家的号码。

一些例子:

Telegram — $0.28 起
Google — $0.04 起
VK — $0.05 起
Tinder — $0.02 起
OpenAI — $0.03 起

打开机器人并获取需要的号码: https://t.me/sms_otp_mihuanjiema_bot

不知道用 mac 的各位 2 友们有没有深入使用过系统自带的 Pages 应用
在很久之前我就很讨厌阅读和编写 word 文档, 收到 word 文档后我都会转成 pdf 后再读. 但总会有编写设计文档之类的工作, 就很痛苦.
前段时间尝试了一下这个一直躺在我应用列表但从未打开过的 Pages 应用, 发现意外的好用. 这里分享几个技巧:

  • 使用 pages 打开别人的 word 文档后, 第一件事是⌘+a, 把字体替换为SF Pro, 是的, 微软的那套字体我是真喜欢不起来, 换字体后行间距也大概率变得更有可读性了.
  • 活用 pages 应用内提供的文件格式转换功能: image

纯分享, 各位请畅所欲言~

我发现直接在一个对话中问 DeepSeek 影响拖延的因素 DeepSeek 给的回答里没有不安全感,但是我最近发现不安全感好像会影响我的拖延。然后我在另外一个对话中问 DeepSeek 不安全感是否会影响拖延,DeepSeek 说影响很大。

这就很不舒服了。我怀疑很可能是为了降低成本都对 LLM 的输出进行了限制。为了让 LLM 回答得更细致,比如能否通过先让 LLM 列一个大纲,然后再通过一个个追问让 LLM 展开各个主题呢?或者有没有更好的方法?

上面的我问了一下 DeepSeek ,它说我说的方法就是最推荐的了。这是我的测试结果: https://chat.deepseek.com/share/5ntx7ogg8n05tw6gon 。这回里面有安全感了。然后我又追问了一下 DeepSeek 有没有相关的网站,它提到了 STORM 。我用 procrastination 试了一下实在是太慢了,另外不知道用多了会不会要钱。有没有缓存输出结果的网站?做一个成本不高吧?

你可能会问为什么不直接去看书。拖延的书我也看过一些,我感觉不同的书各有侧重,还有很多重复的地方。总之就是体验不怎么好。

今日速览

  1. Sonnet 4.6:Claude 最强模型,性能接近 Opus,价格更亲民。
  2. Moda:AI 设计神器,生成可编辑的幻灯片、海报,告别模板束缚。
  3. Omnia:让品牌在 AI 搜索中脱颖而出,监控曝光、分析对手。
  4. Flixier:AI 视频编辑一体化,在时间轴上直接生成、扩展片段。
  5. ClawMetry:OpenClaw AI 代理的实时监控仪表板,一键安装免配置。
  6. Empirical Health:网页版心脏健康管理,查看血液报告、评估风险更方便。
  7. Travel Animator:动态地图标注旅行地点,个性化路线一目了然。
  8. Calendarly:日历变锁屏壁纸,日程自动更新,拿起手机就能看。
  9. Design Rails:对话 AI 创意总监,几分钟打造完整品牌识别方案。
  10. SPECTRE:智能编码工作流程,帮 AI 助手产出高质量代码。


1. Sonnet 4.6

Claude 家族的最新力作,这次升级让它在编码、设计、长文本推理等领域全面爆发,智能水平直逼顶级模型,但价格更接地气,适合日常任务。

  • 性能大幅提升,接近 Opus 级别
  • 支持 100 万 token 的上下文窗口
  • 计算机使用技能显著增强
  • 覆盖编码、知识工作、代理规划等多场景

热度:🔺543

Sonnet 4.6

访问官网 Product Hunt 详情


2. Moda

终于来了!这款 AI 设计工具能生成美观且符合品牌的内容,从幻灯片到广告一应俱全,关键是所有设计都能在分层画布里随意编辑,告别死板模板。

  • 生成可完全编辑的 AI 设计
  • 支持幻灯片、海报、广告等多种格式
  • 强大分层画布,灵活调整元素
  • 确保品牌一致性,提升视觉冲击力

热度:🔺481

Moda

访问官网 Product Hunt 详情


3. Omnia

想知道 AI 怎么看待你的品牌吗?Omnia 帮你透视 AI 推荐逻辑,监控曝光、分析对手,还能生成提升搜索可见性的内容,让品牌在 AI 时代站稳脚跟。

  • 分析 AI 如何推荐你的品牌
  • 监控品牌曝光和竞争对手动态
  • 发现真实 AI 提示,优化内容策略
  • 提升在 AI 搜索中的引用率和可见性

热度:🔺282

Omnia

访问官网 Product Hunt 详情


4. Flixier Generate AI Video in Timeline

大多数 AI 视频工具只负责生成,Flixier 却把 AI 塞进编辑时间轴,让你在一个地方搞定生成、扩展、连接视频片段,裁剪润色一气呵成,不用到处导出重建。

  • 在时间轴上直接生成和扩展视频镜头
  • 连接剪辑,无缝拼接片段
  • 支持裁剪、润色等编辑功能
  • 一体化工作流,无需导出或切换工具

热度:🔺185

Flixier Generate AI Video in Timeline

访问官网 Product Hunt 详情


5. ClawMetry for OpenClaw

专为 OpenClaw AI 代理打造的免费开源监控仪表板,就像 Grafana 的 AI 版,一键安装就能实时追踪令牌费用、子代理活动,数据通过动态可视化清晰呈现。

  • 免费开源,专注于 AI 代理可观测性
  • 一键安装(pip install clawmetry),无需配置
  • 实时监控令牌成本、子代理活动、会话历史
  • 支持 macOS、Linux、Windows 甚至 Raspberry Pi

热度:🔺164

ClawMetry for OpenClaw

访问官网 Product Hunt 详情


6. Empirical Health for web

之前只能在手机 app 上管理心脏健康?现在网页版来了!在大屏幕上查看血液检测报告(超过 100 个生物标志物)、评估心脏病风险、联系医生,一切变得更轻松。

  • 网页端直接访问,无需下载 app
  • 查看详细血液检测结果和生物标志物
  • 评估心脏病发作风险评分
  • 支持发送消息给医生、安排实验室复查

热度:🔺142

Empirical Health for web

访问官网 Product Hunt 详情


7. Travel Animator

旅行时总想记录每个停靠点?Travel Animator 让你在动态地图上标注地点,从六种样式、七种颜色中自由选择,标签模式可调,旅程路线瞬间清晰又个性。

  • 在动态地图上标注旅行地点
  • 六种设计样式和七种颜色可选
  • 支持“当前”、“已访问”、“始终显示”标签模式
  • 随时编辑或删除标签,个性化讲述旅程

热度:🔺130

Travel Animator

访问官网 Product Hunt 详情


8. Calendarly

厌倦了在锁屏上找日程?Calendarly 把你的日历变成动态壁纸,自动更新一天安排,拿起手机就能看,无需小部件或打开 app,设计模板还能随心定制。

  • 将日历实时显示为锁屏壁纸
  • 自动更新日程,无需手动操作
  • 精美模板可选,全面定制布局和风格
  • 完全保护隐私,所有功能在设备上运行

热度:🔺124

Calendarly

访问官网 Product Hunt 详情


9. Design Rails

想快速打造品牌识别?和 AI 创意总监聊几句,几分钟内拿到完整的 logo、配色、字体方案,文件直接丢进项目,让工具从第一天就生成品牌一致的界面。

  • 对话式 AI 创意总监,快速生成品牌方案
  • 包含 logo、配色、字体、声音语调、UI 风格
  • 提供代理准备文件,开箱即用
  • 兼容 Claude、Lovable 等工具,确保品牌一致性

热度:🔺123

Design Rails

访问官网 Product Hunt 详情


10. SPECTRE

给 AI 编码助手套上智能工作流程,通过 /范围、/计划、/执行 等步骤,引导它产出高质量代码,适合产品开发者提升效率。

  • 智能编码工作流程,涵盖规划到评估
  • 通过逐步开发方式提升代码质量
  • 支持 /范围、/计划、/执行、/清理、/测试、/重基、/评估 步骤
  • 帮助 AI 编码代理生成可靠成果

热度:🔺111

SPECTRE

访问官网 Product Hunt 详情