2026年4月

先打个预防针,企业里是有更多标准化的解决方案的,我这个方案就是图个方便省事。

背景

我们有个小程序里有一个弹窗,弹窗里有个蛮复杂的 ui 设计,然后点击不同的内容会打开对应的视频进行播放。
我考虑到视频内容肯定会增加,那就不能写死代码。这个 ui 比较复杂然后又只是个小弹窗,感觉实在没必要用代码去实现了。
但是图片更新起来快啊,oss 里上传一下就完事。考虑到以后有类似的需求都可以偷个懒,于是就做了这个小工具。

功能

简单说就是给图片上加上热区,每个热区可以配置点击后的事件。

当 ui 更新新的图片后,打开这个工具网站给图片配置一下热区事件,然后导出后还是一张图片,往 oss 里一扔就完成更新了。  

代码里集成这个 sdk 后可以直接响应图片上的点击事件,如果 sdk 不合适你的平台,那就集成一下 core 包,一个纯 js 包,ai 实现一下就完事了。集成起来非常简单。

网址

项目网址: https://clickable-img.dev.noteloom.app

后续

因为数据是公开的,所以我想上线个加密功能来着,支持配置一个密钥进行加密。不过看有没有人用吧,没人用就不做了。

我遇到了特别没有水平的评委,他问我的问题类比一下:

  • 手机能飞吗?
  • 手机开飞行模式能飞吗?
  • 为什么手机开飞行模式不能飞?
  • 为什么你不做能飞的手机?

我们做 A 的,他一直在问我为什么不做 B?

有的团队 PPT 没讲完,问答环节出问题,分数依然比我们高。我不说我们做的多好,至少 PPT 我们规定时间讲完了,问答环节评委提问逆天我也胡诌过去了。最逆天的是一个团队在问答的时候和评委吵起来,评委直接揭底,分数依然比我们高。

我本人能很快调节,之前因为生病,在自家厂里呆过两年,各种奇葩客户都见过。打击最大的是我的队员们,他们依然无法接受非客观原因导致的止步。

还有一点让我很爽,我们给了其他参赛队员压力(有人在讨论我们的项目有实物,能动),被其他院的老师认可。比赛有时候真的需要运气。

你是不是见过这样的代码:一个文件几千行,一个函数做了十件事,改一个地方崩三个地方。今天我们不背理论,直接用5种前端最常用的设计模式,把你从“面条代码”里捞出来。学完你会发现:原来代码可以像乐高一样,哪里坏了换哪里。

前言

设计模式不是“高大上”的面试题,而是前辈们踩过无数坑后总结的“套路”。就像下棋有定式,写代码也有常见问题的标准解法。今天我们从实际场景出发,不讲23种全部,只挑前端最常用的5种:单例、观察者、工厂、策略、装饰器。看完你就能立刻用在项目里。

一、单例模式:全局只有一个的“独生子”

场景:全局弹窗、登录框、Store、线程池。你希望整个应用只有一个实例,反复创建会浪费资源或导致状态冲突。

不用的痛:每次调用都new Modal(),结果页面上出现十几个重叠的弹窗。

实现

class Singleton {
  constructor() {
    if (!Singleton.instance) {
      this.data = [];
      Singleton.instance = this;
    }
    return Singleton.instance;
  }
  add(item) {
    this.data.push(item);
  }
}
const a = new Singleton();
const b = new Singleton();
console.log(a === b); // true

前端更常见的写法:用闭包或模块(ES6模块本身就是单例)。

// modal.js
let instance;
export function getModal() {
  if (!instance) {
    instance = new Modal();
  }
  return instance;
}

现代替代:直接导出对象字面量(export default { show() {} }),ES6模块天然单例。

二、观察者模式:让不相干的组件“悄悄对话”

场景:购物车更新后,导航栏的数字要变、价格要重算、埋点要上报。你不想让购物车直接调用导航栏的方法(耦合太紧)。

不用的痛:购物车里写header.updateCartCount()sidebar.recalculate()analytics.track()…每加一个模块,购物车代码就要改一次。

实现

class EventBus {
  constructor() {
    this.events = {};
  }
  on(event, callback) {
    if (!this.events[event]) this.events[event] = [];
    this.events[event].push(callback);
  }
  emit(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(cb => cb(data));
    }
  }
  off(event, callback) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(cb => cb !== callback);
    }
  }
}
const bus = new EventBus();
// 购物车模块
bus.emit('cartUpdated', { count: 3 });
// 导航栏模块
bus.on('cartUpdated', (data) => updateCount(data.count));
// 埋点模块
bus.on('cartUpdated', (data) => track('cart', data));

观察者模式是前端最常用的模式之一。Vue的响应式原理、React的事件系统、Node.js的EventEmitter都是它的变体。

三、工厂模式:不用自己 new,让“工厂”替你造

场景:根据不同参数创建不同类型的对象,但创建逻辑复杂(比如需要条件判断、依赖注入)。你不想在业务代码里到处写newif-else

不用的痛:每个用到按钮的地方都要写一堆if (type === 'primary') return new PrimaryButton()…重复代码爆炸。

实现

class ButtonFactory {
  createButton(type) {
    switch(type) {
      case 'primary':
        return new PrimaryButton();
      case 'danger':
        return new DangerButton();
      default:
        return new DefaultButton();
    }
  }
}
const factory = new ButtonFactory();
const btn = factory.createButton('primary');

工厂模式把创建对象的逻辑集中管理,业务代码只依赖工厂接口。

更简单的函数工厂

function createUser(role) {
  const base = { createdAt: Date.now() };
  if (role === 'admin') {
    return { ...base, permissions: ['read', 'write', 'delete'] };
  }
  return { ...base, permissions: ['read'] };
}

四、策略模式:消灭“if-else 毒瘤”

场景:表单校验:用户名规则、密码规则、邮箱规则各不相同。或者根据用户等级计算折扣:普通会员9折,黄金会员8折,钻石会员7折。你不想写一长串if-else

不用的痛:一个函数里十几个if-else,加一个新策略要改原有代码,还容易引入bug。

实现

// 策略对象
const discountStrategies = {
  normal: (price) => price * 0.9,
  gold: (price) => price * 0.8,
  diamond: (price) => price * 0.7,
};
function getDiscount(level, price) {
  return discountStrategies[level]?.(price) ?? price;
}
// 使用时
const finalPrice = getDiscount('gold', 100); // 80

校验示例:

const validators = {
  required: (val) => val.trim() !== '',
  minLength: (val, len) => val.length >= len,
  email: (val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val)
};
function validate(value, rules) {
  for (let rule of rules) {
    const [name, param] = rule.split(':');
    if (!validators[name]?.(value, param)) return false;
  }
  return true;
}

策略模式把算法(策略)提取成独立对象,可以动态替换、复用。

五、装饰器模式:给代码“贴金”而不改源码

场景:给现有函数添加日志、性能监控、权限校验、缓存功能,但不修改函数本身。

不用的痛:在每个函数内部手动加console.time,加完又删,污染业务逻辑。

实现(JavaScript高阶函数版本,TS装饰器已在之前文章讲过):

function withLog(fn) {
  return function(...args) {
    console.log(`调用 ${fn.name} 参数:`, args);
    const result = fn.apply(this, args);
    console.log(`返回值:`, result);
    return result;
  };
}
function add(a, b) { return a + b; }
const loggedAdd = withLog(add);
loggedAdd(2, 3); // 输出日志,返回5

更通用的装饰器组合:

function withTimer(fn) {
  return function(...args) {
    const start = performance.now();
    const result = fn.apply(this, args);
    const end = performance.now();
    console.log(`${fn.name} 耗时 ${end - start}ms`);
    return result;
  };
}
// 组合多个装饰器
const enhanced = withLog(withTimer(add));

装饰器模式让你能“叠加”功能,保持单一职责。

六、实际项目中的组合运用

比如一个用户登录模块:

  • 单例模式:全局唯一的UserStore
  • 工厂模式:根据角色创建不同的用户实例(createUser('admin'))。
  • 观察者模式:登录成功后,触发userLoggedIn事件,购物车、头像组件、权限菜单分别响应。
  • 策略模式:不同等级用户的权限校验策略。
  • 装饰器模式:给API请求函数加上缓存、重试、日志。

七、总结:设计模式是“招式”,不是“教条”

  • 单例:全局唯一,省资源。
  • 观察者:解耦事件发布和订阅。
  • 工厂:集中创建对象。
  • 策略:消灭if-else,算法可互换。
  • 装饰器:动态增强功能。

不要为了用模式而用模式。当你的代码出现重复、难维护、改一处动全身时,想想哪种模式能帮你解耦。写代码就像搭积木,模式是那些标准接口的积木块,让你搭得又快又稳。


如果你觉得今天的“招式”够实用,点个赞让更多人看到。明天我们将聊聊前端架构设计——从技术选型到目录结构,如何搭建一个能支撑三年迭代的项目骨架。我们明天见!

读丁真语录,享坎坷人生

最近看到有人搞了个蒸馏同事的skill,还有峰哥skill(这是好事啊😂),决定自己也搞个丁真的,不是什么正经功能,纯粹是给枯燥的编程生活加点笑料。

🤔 这玩意有啥用?(其实没卵用)

简单说,就是把网上那些「丁真体」搞怪语录的思维模式教给了AI(videcoding😂)。

普通AI给的人生建议是这样的:

  • "要保持积极乐观的心态"
  • "需要互相理解和沟通"
  • "建议理性投资,分散风险"

装了这技能包的AI,画风就变了:

  • 人生建议 → "比你优秀的人还比你努力,那你努力还有什么用?"
  • 恋爱问题 → "叫你心中没女人,又没叫你身边没女人。"
  • 赚钱理财 → "钱是给女人看的,不是给女人花的。"
  • 学习规划 → "大学四年你不吃苦,将来就要苦40年。大学四年肯吃苦,那你就要苦44年。"

🎭 效果怎么样?

毒鸡汤

用户 ❯ 给个鸡汤
丁真 ❯ 大学四年你不吃苦,将来就要苦40年。
      大学四年肯吃苦,那你就要苦44年。

金钱歪理

用户 ❯ 没钱了
丁真 ❯ 感情没了先去挣钱,感情可以不稳定,但事业要稳定。
      毕竟没钱的付出都是没用的付出,少一份没用的付出,
      人生不会无路可走,因为你还有死路一条。

努力无用论

用户 ❯ 想努力了
丁真 ❯ 比你优秀的人还比你努力,那你努力还有什么用?

纯真模式

用户 ❯ 太纯真了
丁真 ❯ 我、我...那个...嗯...

🧠 核心思维模式

这技能包不是简单模仿丁真说话,而是提炼了6个核心思维模式:

  1. 反卷哲学 - 表面劝你努力,实则劝你放弃,为摆烂提供合理借口
  2. 恋爱多线程 - 感情可以不稳定,但"选择"要稳定,备胎思维
  3. 金钱至上 - 所有问题最终都能归结为"钱没到位"
  4. 废话真理 - 说了等于没说,但听起来很有道理,无法反驳
  5. 自嘲防御 - 先自黑为敬,让别人无话可说
  6. 胡说八道 - 把明显错误的逻辑说得理直气壮

💻 怎么安装?

支持各种主流AI编程工具,一行命令搞定:

Claude Code

# 安装到当前项目
mkdir -p .claude/skills
git clone https://github.com/wangkai000/dingzhen-skill.git .claude/skills/dingzhen-skill

Cursor

mkdir -p .cursor/skills
git clone https://github.com/wangkai000/dingzhen-skill.git .cursor/skills/dingzhen-skill

VS Code (Cline / Continue)

mkdir -p .cline/skills
git clone https://github.com/wangkai000/dingzhen-skill.git .cline/skills/dingzhen-skill

安装后AI会自动识别,在合适的场景使用。也可以直接对AI说 "用丁真的风格回答" 手动触发。

......各种激活方式都行

🎮 怎么用?

输入这些触发词就行:

> 丁真
> 丁真语录  
> 来条丁真
> 网络丁真
> 我测你码
> 瑞克五代
> 电子烟
> 抽烟
> 纯真

📦 内部有啥?

这技能包结构很清晰:

dingzhen-skill/
├── SKILL.md           # 入口:元数据、角色设定、核心句式、风格DNA
└── references/        # 详细资料库
    ├── 完整语录大全
    ├── 按场景分类版
    ├── 语录生成器
    └── 补充包

🔧 持续进化

这个技能包是开源的,支持自己补充新语录:

  • 新恋爱语录 → 更新 01-quotations.md 恋爱部分
  • 新努力/金钱语录 → 更新对应部分
  • 新句式规律 → 更新 03-generator.md
  • 新搞笑段子 → 更新 04-supplementary.md

⚠️ 注意事项

  • 基于截至2026年4月的网络流传语录,最新梗可能需要手动补充
  • 无法还原真实丁真的口音、表情和肢体语言(毕竟只是个文字技能包)
  • 涉及敏感话题时会自动过滤,保持娱乐性
  • 过于严肃的话题不适合用此风格回答

🚀 项目地址

GitHub地址

Gitee地址

MIT许可证 — 随便用,随便改,随便造。


💡 本skill仅供娱乐,与真实人物无关\
📺 部分语录来源B站"喜欢唱跳rap的小明"\
🚀 支持持续进化,欢迎提交新语录!

一句话总结:给AI加个嘴贫技能,让写代码的日子没那么枯燥。毕竟,生活已经很难了,何不笑着面对?😄 (其实就是没有卵用的练手skill)

最近半年一直在折腾一个项目——用 AI 自动生成短视频。起因是身边做小生意的朋友总问我能不能帮忙剪视频发抖音,我想这事儿应该能自动化,就开始做了。

分享一下技术方案和踩过的坑,希望对有类似想法的朋友有参考价值。


整体架构

用户上传素材 + 输入文案
    ↓
TTS 语音合成( MiniMax / 火山引擎)
    ↓
根据语音时长自动分配素材时间轴
    ↓
云端渲染(转场、字幕、BGM )
    ↓
成品视频

后端 FastAPI + MySQL ,前端 Vue 3 ,视频渲染走云端 API ,手机端用 Capacitor 套了个壳。一个人全栈,没有团队。


几个有意思的技术点

1. TTS 选型

试了一圈,最后主力用 MiniMax speech-2.8-hd ,中文多音字准确率目前最好。火山引擎作为补充,主要是剪映生态的独有音色(奶气萌娃、广告解说这种)。Azure 的中文效果一般,Fish Audio 没深入测。

踩坑:TTS 返回的音频时长和文字长度不是线性关系,语气词、停顿都会影响。批量生成时如果对时长有严格要求,需要做重试机制。

2. 素材自动分配

这块逻辑最复杂。用户上传 N 个素材(视频+图片混合),系统要自动决定每个素材展示多久、从视频的哪个位置截取。

几个关键决策:

  • 视频从中间 70% 区域截取(跳过开头 20% 和结尾 10%),因为大部分手机拍的视频开头都是晃动的
  • 图片展示时长根据总时长动态计算,保证每张都出现,最少 1 秒/张
  • 批量生成时用发牌算法分配素材,保证每条视频的封面帧不同

3. 批量生成去重

做矩阵号的核心需求是"一组素材生成几十条不重复的视频"。去重策略:

  • AI 扩写多组文案时分配不同的切入角度(预定义了 30 个角度)
  • 每条视频的素材起始偏移不同
  • 视频截取位置随机化
  • 第一个 clip 强制用不同素材保证封面不同

4. 浮点精度问题

这个坑最隐蔽。视频时间轴用浮点数计算,多个 clip 拼接时 accumulated 会漂移,导致素材重叠或出现缝隙。解决方案是每次用 round 后的值更新 accumulated:

cs = round(clip_start, 1)
ce = round(clip_end, 1)
accumulated += (ce - cs)  # 不是 accumulated += clip_dur

5. 实时语音输入

加了个语音输入功能,用户对着手机说文案直接转文字。技术上是浏览器 AudioContext 采集 PCM → WebSocket 传到后端 → 转发到阿里云 paraformer-realtime-v2 。

踩坑:中间结果和最终结果的拼接如果处理不好会闪烁,最后用了"快照 + 增量"的方案解决。


技术栈汇总

技术
前端 Vue 3 + Vite + Capacitor
后端 Python 3.13 + FastAPI + SQLAlchemy
数据库 MySQL 8
存储 阿里云 OSS + CDN
AI 文案 通义千问
TTS 火山引擎
语音识别 阿里云 paraformer-realtime-v2


目前自己和几个朋友在用,做餐饮和服装的,反馈还行。有兴趣的可以体验一下 ios 可以直接用 PWA: https://zj.xinghepay.com ,Android 也有 APK

技术上有什么想聊的欢迎评论区交流,特别是视频处理和 TTS 这块,踩的坑比较多,能聊的也多

苦于找不到充值渠道,想起来有 poe 这个壳,一看竟然提供对外工具的 api 了。

昨晚充了$20 那个,结果一晚就干了$5 (完全是自己没节省,瞎聊)左右,从 codex app 转过来的。写代码能力确实比 codex 强。

也可以切模型

具体价格详情:

使用方法: https://poe.com/api/applications/ClaudeCode

我的成长背景:

我是男的。我家有爷爷奶奶,爸爸和妈妈,我弟(比我小 13 岁),叔叔,姥姥,大舅,小舅。

我从小就是一个比较内向的人。从小我爸妈就把垃圾情绪发泄给我,导致我一直拉个脸,他们就会怒斥我,为什么老是拉个脸!!!!

我爸从我小时就来到深圳,跟我大舅做吊车生意,算是给我大舅打工。我妈从我幼儿园到小学 5 年纪,之后就把我丢到我爷爷奶奶家了,她来深圳和我爸住一块了。我从此以后就寒暑假来深圳找我爸妈。

到了深圳以后,就开始猛教训我,他们不是拉近和我的关系,而是一直让我做家务,一直训斥我,一直教育我,一直打压我说我是个废物。我很不明白,为什么对我态度这么差?好像我学习不好就对他们没用。

给各位 2 友分享分享拍到的猫猫。thanks
(有一张图片太大,上传不到墨雪飘影图床,传的 imgur,不知道能不能正常显示)
首先必须是我儿子,拍的最多的也是他,马上四岁了!
image
image
社会咪sulky
image
一群小猫,看着就很惬意poor
image
上班路上遇到的奶牛哥
image
下午徒步偶遇的社牛奶牛哥(跟上面不是一个)
image

看介绍是完全自动化的开发.
有个问题: 这个过程中应该要自动化测试.  是不是只适合部分类型的项目(自动化测试比较成熟/简单的): 比如在浏览器里运行的, 没有 UI 的. 对于在本机上运行的有 UI 的程序, 是不是就不太合适了.

很多 Rust 开发者都有一个共同的经历:某天打开终端,df -h 一看,~/.cargo 目录已经悄悄长到了好几个 GB,甚至十几个 GB。

这并不奇怪。Cargo 在 home 目录里积累的缓存种类繁多:从 crates.io 拉下来的索引数据、下载的 .crate 压缩包、解压后的源码、git 依赖的克隆……每个新项目、每次版本更新都会往里加东西,但从来没有东西会被自动删掉。

社区里已经有第三方工具(比如 cargo-cache)来处理这个问题,但 Cargo 官方从未内置过缓存管理能力。

从 nightly-2023-11-17 开始,这件事有了变化。

本文基于 Rust 官方博客 2023 年 12 月 11 日发布的《Cargo cache cleaning》整理撰写,作者为 Eric Huss,代表 Cargo 团队。

原文地址


这个功能是什么

Cargo 在 nightly 频道新增了一个不稳定特性:垃圾回收(GC)。它的核心是两件事:

一是追踪:Cargo 会在 ~/.cargo/.global-cache 创建一个 SQLite 数据库,记录各类缓存数据最后一次被使用的时间戳。每次运行 cargo buildcargo fetch 等涉及缓存读写的命令,都会更新这个数据库。

二是清理:分为自动和手动两种方式。


自动清理:每天运行一次

启用 GC 后,Cargo 每天会检查一次缓存数据的最后使用时间,对超期未使用的数据执行删除。

默认的超期策略是:

  • 本地可以重新生成(无需重新下载)的数据:超过 1 个月未使用则删除;
  • 需要重新下载才能恢复的数据:超过 3 个月未使用则删除。

这里的区分有一定合理性:解压后的源码目录(src/)不需要网络就能从已有的 .crate 文件重建,所以可以更激进地清理;而 .crate 文件本身和索引数据一旦删除就要重新下载,因此给了更宽松的窗口期。

有一个细节值得注意:当 Cargo 处于离线模式时(比如加了 --offline--frozen 参数),自动清理会被禁用。 设计者考虑到,如果你正处于长时间离线的环境中,强行删缓存可能会让你无法继续工作。


手动清理:cargo clean gc

除了自动清理,Cargo 还新增了 cargo clean gc 子命令,支持手动指定清理策略。

几个典型的用法示例:

# 删除超过 3 天未使用的下载数据
cargo clean gc --max-download-age=3days

# 将下载缓存总大小控制在 1 GiB 以内
cargo clean gc --max-download-size=1GiB

这对 CI 环境尤其有用——很多 CI 系统会缓存 ~/.cargo 目录来加速构建,但缓存太大又会拖慢上传和恢复速度,cargo clean gc 可以在构建结束后做一次精准的瘦身。

需要说明的是,目前这个子命令的 CLI 设计还属于实验阶段,稳定化之前可能会有调整。


如何启用

这是一个不稳定特性,目前需要 nightly 版本。在 ~/.cargo/config.toml 中加入:

[unstable]
gc = true

或者通过环境变量临时开启:

CARGO_UNSTABLE_GC=true cargo build

也可以用 CLI flag 对单次命令生效:

cargo build -Zgc

启用后,Cargo 会在首次运行时扫描已有的缓存目录,建立初始的追踪数据库。这次初始扫描可能会有一点延迟,之后的日常使用影响极小(测试数据显示额外开销在 0 到约 50ms 之间)。


背后的设计考量

这个功能听起来简单,实现层面却有不少值得一提的权衡。

性能:每次 Cargo 运行都需要更新数据库,但团队特别注意不要让这影响正常的构建体验。实际删除操作每天只做一次,而不是每次命令后都做,就是为了把开销集中在一个时间点,而不是分散地拖慢每一次构建。

并发锁:这是改动中技术上最复杂的部分。Cargo 之前只有一把包缓存锁,现在改为三种锁定状态:多个构建可以同时持有共享读锁;下载新包时持有独立的写锁(不影响其他构建并行读取);清理缓存时持有排他写锁,阻止任何读取。

值得注意的是,1.75 之前的 Cargo 不认识这把排他写锁。在新旧版本并存的环境里理论上存在冲突风险,但团队认为这种情况在实践中极少出现。

文件系统兼容性:Cargo 对各种异常情况做了容错设计。如果无法获取锁(比如在只读文件系统上),GC 会静默跳过,不会报错中断你的工作。这对 Docker 挂载目录和网络文件系统(NFS)这类场景尤其重要。

向后兼容:缓存数据会被各个版本的 Cargo 共用,因此数据库格式的稳定性至关重要。团队选择 SQLite 的原因之一正是它的磁盘格式自 2004 年以来保持稳定,且支持向后兼容的 schema 迁移。


还不包括哪些内容

有一点需要特别说明:这次 GC 功能清理的是 ~/.cargo 全局缓存,不包括项目的 target/ 目录。

target/ 目录往往才是磁盘空间的真正大户,在多项目开发场景下轻松超过百 GB。对 target/ 的清理支持,Cargo 团队计划通过将 fingerprint 系统迁移到 SQLite 来实现,但这是另一个更大的工程,目前还在规划阶段。


SQLite:Cargo 的下一步

这个 GC 功能对 Cargo 项目还有一层额外的意义:它是 SQLite 在 Cargo 中的初次大规模实战。

团队明确表示,SQLite 在 Cargo 中的使用还会扩展到更多地方,目前规划中的有两个方向:

注册表索引缓存:现在 Cargo 把索引缓存存储为大量小文件,在某些文件系统上性能不佳,而且同样无限增长。未来可能会改用 SQLite 存储,同时支持细粒度的时间戳追踪和定期清理。

target 目录管理:Cargo 现在用一套叫做"fingerprint"的机制来判断哪些内容需要重新编译,每个构建产物对应 4 个格式各异的文件。团队计划把这套机制也迁移到 SQLite,届时不仅可以清理过期数据,还有望改进追踪精度、提升性能,并提供"为什么这个 crate 被重新编译了"之类的调试信息。


小结

Cargo 的缓存自动清理功能,解决了一个长期存在但被忽视的问题:本地缓存只进不出。

它的设计策略是保守的:每天一次、按使用时间决定去留、离线时不动、遇到错误静默跳过。这些选择都优先保证用户体验的平稳,而不是激进地压缩磁盘占用。

对于多数开发者来说,启用之后基本感觉不到它的存在——直到某天发现 ~/.cargo 比以前小了不少。


所以我做了这个 JoyfulWords

在富文本编辑器的基础上,我增加了左侧的全网素材搜索🔍。这样我可以在写文章时候随时搜索素材,甚至图片,而不用离开编辑器。

在右侧,我集成了 AI 功能,AI 可以帮我修改文章、可以帮我生成思维导图、可以随时创作一张图片。

最重要的是,可以随时生成信息图,利用 nanobanana 的强大能力,自动把文本中的关键信息提炼成图,再也不用担心配图了。

欢迎大家使用和提出意见

界面截图:

截图

上线当日在各个平台都收到了非常多的很有建设性的建议反馈,还收到了一些非常好的产品提交,每个产品都是很棒的产品

经过开发调试测试,又更新了好几轮,已经非常银杏花~

支持了徽章快捷佩戴,修复了一些已知的 bug

此外:

2026 年 4 月 17 日 10 点至 2026 年 4 月 19 日 20 点,可以直接参与抽奖活动,将会通过抽奖功能抽出 10 个 18.88 支付宝现金红包。

抽奖地址: https://chanpinpai.com/topic/PkbImnNz

🎯 社区核心玩法

目前,产品派已开放以下核心功能:

  1. 产品发布与展示


    • 你可以提交自己的产品,完善介绍、分类、标签等信息,构建一个精美的展示页,让他人快速了解其价值。
  2. 产品发现与榜单


    • 浏览最新产品热门产品产品榜单,通过社区的力量高效筛选,不错过任何值得关注的新鲜事物。
  3. 丰富的社区互动


    • 这里不只是普通的发帖讨论,还支持多种趣味互动功能,让交流更有深度和乐趣:
      • 投票:适合发起选择题,快速收集用户意见与产品反馈。
      • 抽奖:支持定时开奖与自动派发奖品,是举办互动活动的利器。
      • 优惠码:非常适合分发邀请码、限时福利或专属折扣。
      • 盲盒:与抽奖不同,这是即时开奖,惊喜(或“空盒”)即刻揭晓。


🎁 上线专属福利,诚邀第一批种子用户

为感谢早期支持者,我们准备了专属身份和限时活动:

  • 种子用户勋章:在 2026 年 4 月 17 日至 7 月 17 日 期间注册的用户,将永久获得 「种子用户」 专属勋章,铭记您与社区共同的起点。

  • 开站抽奖活动:为庆祝上线,我们特地通过社区的“抽奖功能”发起了一个活动:


    • 活动时间2026 年 4 月 17 日 10:00 至 4 月 19 日 20:00
    • 活动奖励:我们将抽出 10 位 幸运用户,每人赠送 18.88 元 支付宝现金红包。


✨ 如何加入我们?

如果你平时喜欢发现新产品,如果你正在精心打磨自己的产品,亦或你单纯喜欢交流、结识新朋友,「产品派」 都欢迎你的到来。

立即访问社区,发现更多可能:
👉 https://chanpinpai.com

让我们在这里,重新点燃对每一个好产品的好奇与热情。期待在社区与你相遇!


—— 一个同样受困于收藏夹,并希望做出改变的产品爱好者

https://vibelabs.run

目前主打 Codex ,0.2 倍率,稳定可用,1:1 充值,1 元 = 5 刀!

现在还有限时活动,进交流群,邀请朋友建号进群,可以赠送双方各 1 元(5 刀)额度!

db7d5c9b082a41918976b4d1dd0777fb
8c3e25111a034040818003a315b9bd16
fdef028c37d94f72b9e2df2ddb3679f7
a71fa53cccfd46b8b0e9a1eee117405c
828e5a0f98554fd3bb45bb1a2db1c0c3
04bb55c38be3463ca1a0f32e37d1b524
fbc4154522c54b78bb1c70befcb68c21
bed451059fcd4fc4b0af946b6d08d167
aeb9aaa992284294ade37ef6dfcc6f92
442e005a133444499048bc562f82320f

请用完的在评论区说一下。

之前一直是用 claude sonnet 4.6 / opus 4.6 但是 openclaw 之类的 claude 都已经不让用 plus 会员订阅了。 现在看到大家很多讨论 chatgpt 的模型,现在 Gpt 质量跟 snooet 比怎么样,强很多吗? openclaw 大家现在都用什么模型呢? 感觉国内的是不是差点意思?

2023 年 10 月中旬,crates.io 团队收到一封用户反馈:他们维护的某个 crate,放在 README 里的 shields.io 徽章不显示了。

这件事乍看毫不起眼。shields.io 徽章时不时出问题很正常,原因五花八门。但这次的问题链,一旦顺着拉下去,牵出的东西让整个 crates.io 团队都没想到。

本文基于 Rust 官方博客 2023 年 10 月 26 日发布的《A tale of broken badges and 23,000 features》整理撰写,作者为 Tobias Bieniek,代表 crates.io 团队。

原文地址


一个徽章,一条 20 MB 的 API 响应

这位用户在提 Issue 时已经自己做了初步定位,发现问题的根源在 shields.io 向 crates.io 发出的那个 API 请求:

这个 crate 大量使用了 feature flag,导致 API 响应的体积极度膨胀。

具体来说,shields.io 调用的是 crates.io 的 /api/v1/crates/{crate_name} 接口——这个接口会一次性返回该 crate 所有已发布版本的完整元数据,包括每个版本的全部 feature 列表。

问题是,这个 crate 叫做 icondata,它的 API 响应已经超过了 20 MB。shields.io 拿到这个响应之后直接超时,徽章自然也就坏了。

20 MB 是什么概念?这个 crate 当时一共才发布了 9 个版本


9 个版本,为什么会有 20 MB?

答案是:这个 crate 有将近 2.3 万个 Cargo feature。

icondata 是一个为 Rust 网页应用提供 SVG 图标的库。它把每一个图标都对应设计成一个独立的 Cargo feature,这样用户在编译时只需要启用自己用到的图标,最终打包出的 WebAssembly 产物就不会把成千上万个用不到的图标都塞进去。

从 crate 作者的角度看,这个设计完全合理。SVG 图标库本来就有成千上万个图标,按需引入是最自然的做法,Cargo 的 feature 机制也正是为此而生。cargo 不会报错,crates.io 也不会给出任何警告。

但没有人告诉这个 crate 的作者:2.3 万个 feature,已经把 crates.io 的某些内部机制压垮了。


问题一:API 响应永远不分页

crates.io 的 /api/v1/crates/{name} 接口有一个长期的设计问题:它返回所有版本的完整数据,没有分页

对于只有几个版本、每个版本 feature 寥寥无几的普通 crate,这不是问题。但 icondata 有 2.3 万个 feature,哪怕只有 9 个版本,每次 API 调用都需要把 9 × 2.3 万条 feature 数据一并吐出来,响应体积随之爆炸。

团队知道分页是正确的方向,但这是一个破坏性变更——已有无数工具和集成依赖当前的响应结构。这个问题被搁置了很久,直到这次事件才让团队意识到必须提上日程。


问题二:索引文件也在膨胀

crates.io 的稀疏索引(sparse index)是另一个受害者。

Cargo 在解析依赖时,需要从索引中获取每个 crate 的元数据。索引文件中存储的内容包括该 crate 每个版本的依赖和 feature 列表。对于普通 crate,这个文件很小,Cargo 可以快速拉取和解析。

icondata 的索引文件因为包含 2.3 万个 feature 的重复记录,体积同样极为庞大。每次有用户或 CI 环境需要解析这个 crate 的依赖时,都需要下载和处理这个异常大的文件。


问题三:数据库查询承压

crates.io 的后端使用 PostgreSQL 存储 crate 的元数据。feature 数据以关联记录的形式存储在数据库表中,查询某个 crate 的完整信息时,需要通过 JOIN 把这些记录拼回来。

2.3 万条 feature 记录的存在,让原本为普通规模设计的查询开始出现性能问题。这类查询对绝大多数 crate 可以在毫秒级完成,但遇到 icondata 这种异常情况,耗时会急剧上升。


团队的应对

面对这次事件,crates.io 团队采取了几项措施。

立即生效的限制:新发布的 crate 版本,feature 数量上限为 300 个。 这一限制已记录在 Cargo 的官方文档中。对于有特殊需求的 crate,团队表示会逐案评估是否给予豁免。

这个数字的选择有一定的工程判断成分:300 个 feature 对绝大多数用例来说绰绰有余,同时也能将 API 响应体积和数据库查询压力控制在可接受的范围内。

API 分页的问题,团队明确表示将被列为近期必须解决的工作,这次事件提供了足够的推动力。


一个值得深想的细节

这件事有一个值得单独拿出来说的侧面:整个过程中,icondata 的作者没有做任何"错误"的事。

用 feature 来控制编译粒度,是 Rust 生态里成熟的做法。cargo 文档里有这个模式,众多知名 crate 也都在用。没有任何工具链工具会在你的 feature 数量超过某个阈值时发出警告,crates.io 在接受发布时也不会提示任何异常。

问题出在基础设施的隐性假设上:API 的设计者从未预料到会有 crate 拥有数万个 feature;数据库查询的设计者也没有为这种极端情况预留余量。这类问题不到被触发,几乎不可能在事前被发现。

对于写基础设施代码的人来说,这是一个标准的"边界条件"教训:系统在正常范围内运行良好,在正常范围之外,假设就开始逐一失效。


如果你现在就想用 v0 只包含需要的图标……

icondata 最终将自己拆分为多个子 crate,每个子 crate 对应一个图标库(如 Bootstrap Icons、Remix Icons 等),每个子 crate 各自包含该库的图标 feature。这样每个 crate 的 feature 数量就控制在了合理范围内,同时保留了按需引入的设计意图。

这是一个在遭遇系统限制之后的工程权衡:不改变设计理念,但改变实现的边界划分。


小结

一个坏掉的 shields.io 徽章,揭开了 crates.io 在超出预期规模时的多个薄弱点:无分页的 API、膨胀的索引文件、未能为极端情况设计的数据库查询。

团队的修复是务实的:先设一个上限防止同样问题再次发生,再逐步处理更深层的架构问题。现在,Cargo 的文档里白纸黑字写着:每个 crate 最多 300 个 feature,特殊情况逐案审批。

这条规则的背后,是 2.3 万个 SVG 图标和一个坏掉的版本徽章。


各位好,潜水 V2EX 很久了,第一次发帖分享自己做的东西。

我做了一个叫「星河智剪」的 AI 短视频工具,主要解决一个痛点:很多小商户想发短视频做营销,但不会剪辑,也没时间学。

用起来很简单——上传几张图片或视频素材,输入一段文案(或者直接粘贴抖音/小红书链接自动提取文案),点一下就能生成带配音、字幕、BGM 、转场的短视频。整个过程大概 30 秒

做了几个月了,说几个我觉得还不错的功能点:

批量混剪:一组素材 + AI 自动扩写多组文案,一次生成几十条不重复的视频,做矩阵号的应该懂这个需求
智能配音:接了 MiniMax 和火山引擎的 TTS ,按场景(探店、促销、品牌故事等)自动推荐合适的音色,有 29 种音色可选
智剪模式:用自然语言下指令,比如"加个慢动作""叠一行文字""换个轻快的 BGM",LLM 解析意图后自动执行
实时语音输入:对着手机说文案,实时转文字,不用打字
链接提取:粘贴抖音/小红书链接,自动提取标题和文案
340+ 首 BGM 库:按场景分类,也支持根据文案语气自动匹配
技术栈是 Vue 3 + FastAPI + MySQL ,视频渲染走云端,手机端用 Capacitor 打包了 Android App ,也支持 PWA 直接用

送一波专业版兑换码,先到先得:

每个码可以兑换 1000 积分(够生成 100 条视频),在 App 里「个人中心 → 会员中心 → 兑换点卡」使用。

976B2F3A8FD8828F 专业版
540F6A7FC188E174 专业版
49B8E9193EDEE775 专业版
441C57B449B8B011 专业版
4850C87AB0564876 专业版
67C0A88828668D21 专业版
84E516FEAB243EBF 专业版
16AE64AED397B58C 专业版
2B42823FB41C746B 专业版
0D95CAEB96CD54D4 专业版

用完了评论区吱一声,我再补。

体验地址: https://zj.xinghepay.com

欢迎各位试用吐槽,有什么建议或者想聊技术实现的都可以回复,我会一直在,谢谢大家


🧊 导航魔方 NaviCube

就是个 HTML 文件,把 navicube.html 下载到本地就可以使用

生成导航站也是个 HTML 文件,放哪里都可以访问

要编辑,把导航站 HTML 文件,拖回编辑器即可

🌐 介绍

📥 Github

一个功能丰富的个人导航站管理工具,单文件、零依赖、即开即用。双击 HTML 文件即可运行,所有数据存储在浏览器本地,无需服务器。

🔄 编辑 → 发布 → 再编辑,一个文件搞定

NaviCube 最精妙的设计在于:它既是编辑器,也是导航页本身

┌─────────────┐     生成导航页      ┌─────────────┐
│   编辑器     │ ──────────────────→ │  独立导航页   │
│ navicube.html│                     │  .html 文件  │
└─────────────┘ ←────────────────── └─────────────┘
                  拖回即可再编辑
  • 一键生成导航页 — 在编辑器中整理好分类和站点,点击「生成导航页」,即刻得到一个功能完备的独立 HTML 文件:自带搜索、分类目录、响应式布局,直接部署到任意静态托管即可上线
  • 拖回来继续改 — 把生成的导航页 HTML 文件拖回编辑器,所有数据完整还原,继续增删改,无需手动维护 JSON 或数据库
  • 文件即数据 — 导航页 HTML 文件本身就是数据源,不需要额外的配置文件或数据库。分享文件就是分享导航站,收到文件的人既能直接使用,也能拖进编辑器二次定制

💡 简单说:编辑器里搭积木,生成出来就是成品网页,想改?拖回来接着搭。

🔒 安全与隐私

NaviCube 将你的数据安全放在首位:

  • 🌐 纯本地运行 — 无需服务器,无需注册账号,双击 HTML 文件即可使用

  • 💾 数据存于浏览器 — 所有分类、站点、配置均存储在浏览器 localStorage 中,不经过任何第三方服务器

  • 🔑 密钥本地保管 — API Key 等敏感信息仅保存在你的浏览器中,不会上传到任何云端

  • 🚫 无数据采集 — 不收集任何用户数据、行为统计或使用追踪

  • 📦 数据完全自主 — 随时导出 JSON 备份,数据迁移自由,不锁定平台

  • 👁️ 代码透明 — 单文件 HTML ,所有代码可审查,无隐藏行为

  • 演示站https://www.shidao.biz/

  • 宣传页https://www.shidao.biz/navicube

  • 编辑器https://www.shidao.biz/navicube/deck/