Skip to content

03 简历四条主线逐条拆解(对齐、修正、话术) ​

这篇的用途:面试官通常会照着简历一条一条问。这篇把四条 bullet 逐条拆成四栏: ① 简历原文 → ② 代码事实核对(能不能说)→ ③ 你本人在这一条的贡献 → ④ 60 秒标准回答。 🚩 表示"这条简历与代码不符,必须按修正后的说法讲"。修正话术详见 10-压力面与简历修正话术.md。


总览:四条 bullet 的一句话自评 ​

简历 bullet代码事实核对修正后能不能讲面试价值
① 多源 AI 视频编排(6+ 供应商、统一 BullMQ、多段一致性/分镜合并/首尾帧桥接、10+ 生成方式)⚠️ 三处需要修正:多源动态路由已退化、首尾帧桥接在多数场景被降级、不是所有生成都走队列可以讲,但必须按修正后的表述⭐⭐⭐ 最容易挖深,也最容易翻车
② 任务全生命周期管理(状态机、崩溃恢复、积分冻结日志防重复扣减、引用计数保护)⚠️ 一处需要修正:"引用计数保护"实为"引用存在性 + 唯一约束 + 延迟删除";其余全部为真且是你主导的可以说得很硬⭐⭐⭐ 你的主场,主打这条
③ 全架构落地(React 19 + Vite + Zustand、Express 5 + DB、独立管理后台 + Recharts、TS 全栈类型安全)⚠️ 技术栈全部属实;但"类型安全"要降级表述(strict: false、后端 54 个 @ts-nocheck)可以说⭐⭐ 适合做"广度"展示,不适合深挖
④ 生产级基础设施(多环境配置、Docker Compose 一键部署、微信登录 + 微信支付)⚠️ 两处需要修正:compose 只起 PG/Redis(无 app 服务);微信支付只有 Native 扫码可以说,但要主动补全真实形态⭐⭐ 容易被运维老手问穿,先交底

一句话策略:主线押 ② 和 ①,③④ 讲事实不吹。


Bullet ① 多源 AI 视频编排 ​

①-1 简历原文 ​

集成阿里云 DashScope、豆包 Seedance 等 6+ 个视频服务供应商,统一 BullMQ 任务队列调度,支持多段视频一致性合并、分镜合并、首尾帧桥接,覆盖商品展示、翻拍改编等 10+ 种生成方式

①-2 代码事实核对 ​

表述事实结论
"6+ 个视频服务供应商"历史真实集成 6 个:腾讯云 VOD AIGC、火山 Ark(Seedance 2.0)、Seedance 2.0 代理网关、Seedance 2.5 网关、筷子科技丽帧、HappyHorse。当前新任务只走腾讯云 VOD 1 个(resolveProvider() 恒等返回 'tencent-vod')🚩 需改成"历史接入 6 家 / 当前生产使用 1 家 / 保留历史实现供在途任务轮询"
"统一 BullMQ 任务队列调度"9 条业务队列、单进程 8 个 worker 是真的;但 video-generate 队列只有恢复逻辑在用,主流链路是"路由直接调供应商 + 进轮询队列";另有 3 条链路完全不进队列(内存自管)🚩 需改成"统一的任务队列与轮询调度",不要暗示"全部生成都走队列"
"多段视频一致性合并"为真:尾帧→首帧锚 + 尾帧定格约束 + 音色锚 + 提示词承接块,四层✅ 可讲,但要补"腾讯通道会降级"
"分镜合并"为真:分镜方案生成 + 合并阶段用 enforceStoryboardShotConstraints(画面描述可让模型改写、文案硬锁用户原文)✅ 可讲
"首尾帧桥接"接口层为真,但腾讯 VOD 在有任意参考图/参考视频时会把 FirstFrame/LastFrame 强制降级为 Reference;爆款复刻链路显式关闭桥接🚩 必须按 05 分册 Q15 的说法讲:能力支持 ≠ 默认生效
"10+ 种生成方式"14 种独立生成方式 + 若干不计费能力✅ 可讲,能报出名字更好
"阿里云 DashScope"用于分镜理解(Qwen VL)、生图(Qwen-Image)、TTS/声音克隆——不是视频生成供应商✅ 表述无碍,但别把它算进"视频供应商"

①-3 你的贡献 ​

这一条不是单一作者:多段生产链路(productionWorker)与模型目录(modelCatalog)主要是同事写的(你 0 提交)。你本人的落点在:

  • 首尾帧 / 分镜头 / 快节奏方向(提交记录:首尾帧+分镜头画质升级、拆分镜头、feat: 快节奏);
  • 轮询队列的引入(feat: video poll to mq、feat: video poll skill)——这属于 bullet ②,但也是这条"统一调度"的基础;
  • 前端的对应功能页。

话术:"这一条里多段生产的分段续跑是同事主导的,我参与的是首尾帧、分镜头这块和轮询链路的改造;整条链路的设计我能完整讲清。"

①-4 60 秒标准回答 ​

视频生成这块我们历史接入过 6 个供应商:腾讯云 VOD AIGC、火山引擎的 Arc/Seedance 两个网关、筷子科技,还有快乐马。现在新任务统一走腾讯云 VOD——切换是为了把生成、超分、字幕擦除、换脸收敛到同一家的能力面上。 老实现一个都没删,因为轮询是拿数据库里存的 provider 字段去取实现的;发布时删掉实现,会让发布瞬间还在途的老任务全部轮询失败,那就是"钱付给了供应商、片子永远拿不到"。所以废弃通道的实现要保留到最后一个在途任务结束。 抽象是一个四方法的接口:createTask / queryStatus / poll / generateVideo,上层完全不用关心厂商差异。但我要承认,路由层已经退化了——resolveProvider 现在是个恒等函数,所以今天的抽象主要服务于"按历史任务号回捞实现",不是动态选源。 一致性方面,多段生成靠四层:上一段尾帧当下一段首帧锚、尾帧定格约束、从第一段抽 6 秒人声当全批音色锚、提示词里加承接块。不过实测上天通道在有参考图时会把首尾帧降级成参考图,所以多数场景实际主力是"参考图 + 提示词接续"——这一点我不想说成"我们靠首尾帧做到了完全连贯"。


Bullet ② 任务全生命周期管理(你的主场) ​

②-1 简历原文 ​

设计完整状态机(pending → processing → done/failed),实现崩溃恢复(启动自动扫描异常任务重新入队)、积分冻结日志防重复扣减、引用计数保护

②-2 代码事实核对 ​

表述事实结论
"完整状态机 pending → processing → done/failed"为真且更完整:task_status 是 PostgreSQL 原生枚举,含 pending / queued / processing / done / failed / cancelled;另有一维 phase(submitting / polling / concatenating)✅ 建议补上 queued/cancelled 和 phase ——显得更严谨
"崩溃恢复(启动自动扫描异常任务重新入队)"为真:启动 + 每 10 分钟双轨;按"有无外部任务号"分两条路;启动强制覆盖 active job、周期巡检跳过 active;9 条自管链路前置拦截✅ 强项,可以讲得非常细
"积分冻结日志防重复扣减"为真:credit_holds 表(该迁移是你写的,1/1 提交)+ 部分唯一索引 (task_id) WHERE status='held' 防重复冻结 + settle/refund 的 CAS 幂等✅ 强项
🚩 "引用计数保护"不准确。代码里 refCount 只出现在"参考图数量"里,没有计数式引用保护。真实实现是 oss_key_in_use()(跨 12+ 张业务表的存在性判定)+ DB 触发器 + 唯一约束 + 30 天延迟删除🚩 改口为"基于引用存在性判定 + 数据库触发器 + 唯一约束的文件生命周期保护"
(未写但很值的)并发收尾抢占、2 小时超时、对账巡检都在代码里✅ 建议加进简历或至少准备好讲

②-3 你的贡献(这条最实) ​

按 git log --author 精确核对:

  • taskRecovery.ts:14/33 提交(恢复逻辑的主要作者之一);
  • videoWorker.ts:10/19;
  • videoPollQueue.ts:你起的(feat: video poll to mq);
  • userCreditsStore.ts:11/45;
  • creditRecovery.ts:3/9;
  • backend/migrations/009_credit_holds.up.sql:1/1,完全是你写的;
  • rateLimiter.ts(用户名维度配额)、userResolver.ts、creditLock。

结论:这一条你可以放心地讲成"我负责的"。

②-4 60 秒标准回答 ​

任务生命周期这块我做三件事。 第一是状态机:状态是数据库原生枚举 pending/queued/processing/done/failed/cancelled,另外有一个 phase 字段区分"提交中"和"轮询中"。并发下的状态迁移我不用版本号乐观锁,用条件更新——把状态判断写进 WHERE,比如 UPDATE ... WHERE id=$1 AND status IN ('pending','queued','processing') RETURNING id,靠影响行数判断我有没有抢到这次迁移。这里的并发冲突不是"两个人改同一个字段",而是"多个巡检/Worker 同时想终结同一个任务",条件更新恰好是这个语义。 第二是崩溃恢复:启动时跑一次、之后每 10 分钟跑一次。扫所有非终态任务,按"有没有拿到供应商任务号"分两条路:没有就走 5 分钟新鲜度保护后重新入队;有就去问供应商真实状态——done 补收尾、failed 标失败退款、not_found 清空任务号重投、processing 就只投一条立即轮询的 job,交给专用轮询队列续跑。 这里最关键的一个设计是:启动时和周期巡检时对"活跃 job"的处理是相反的——重启后 Redis 里所有 active job 都是上一进程留下的僵尸(锁还没过期但已没人处理),必须无条件覆盖重排;而周期巡检时 active 意味着当前进程正在跑它,必须跳过,否则会破坏它的 lock 上下文。 第三是积分冻结:credit_holds 表上有一条部分唯一索引 (task_id) WHERE status='held',含义是在 held 状态下同一任务只能有一条记录——一个索引同时表达了幂等和状态机不变式。写入用 ON CONFLICT ... WHERE status='held' DO NOTHING 抢,抢不到就整个事务回滚。结算和退款都是 WHERE status='held' 的 CAS。 至于简历里的"引用计数保护",我要更正一下——它不是计数,是引用存在性判定:我们有一个 PG 函数跨十几张业务表判断文件是否还被引用,配合数据库触发器(入库自动撤销删除、出库前先判引用)和唯一约束,再加上 30 天延迟删除。选存在性判定而不是计数,是因为计数的失败模式是静默漂移,漏一次就是永久错误。


Bullet ③ 全架构落地 ​

③-1 简历原文 ​

前端 React 19 + Vite + Zustand,后端 Express5 + Mysql,管理后台独立 React 项目(Recharts 数据可视化),TypeScript 全栈统一类型安全

③-2 代码事实核对 ​

表述事实结论
"React 19 + Vite + Zustand"全部属实且版本更新:React 19.2.4 / Vite 8.0.16 / Zustand 5.0.12,另有 react-router 7、TanStack Query 5、Tailwind 3✅ 可以说,建议补上 Query 与 router
🚩 "Mysql"是 PostgreSQL 17(pg 驱动、JSONB、TIMESTAMPTZ、部分唯一索引、plpgsql 触发器)。MySQL 只存在于 2026-04-23~05-13 约三周的历史里(当时还只是 flag 门控的账号侧)🚩 必须改,见 10 分册话术
"Express 5"✅ 属实(5.2)✅
"管理后台独立 React 项目(Recharts)"✅ 属实:独立 Vite 应用、28 页、三种布局(Admin/分销/商务)、Recharts 三张图,是仓库里唯一 strict: true 且构建时跑 tsc -b 的包✅ 可以讲,最后那句是加分点
🚩 "TypeScript 全栈统一类型安全""统一类型"成立,"类型安全"要降级:根与 backend 的 tsconfig 都是 strict: false(只有 admin 开 strict);后端有 54 个文件首行 @ts-nocheck;类型共享实际是"前后端共用 9 份 JSON 规则 + 手工镜像联合类型 + 测试读前端源码做断言",没有跨包编译期约束🚩 改成"全栈统一 TypeScript,类型强度分层:新写的 service 是强类型,老路由层还有 @ts-nocheck 没收干净"

③-3 你的贡献 ​

  • 前端 App.tsx 拆分成 page + feature hook 架构(提交:refactor/front: App.tsx 拆分为独立 Page + feature hook 架构)——这是你起的头;
  • 管理后台的仪表盘(提交:feat: 仪表盘);
  • 积分板块、历史记录积分展示、邀请码、分销。

同时要能讲代价:App.tsx 拆掉了,但巨型代码转移到了 hook 层(useAssistantChat.ts 5228 行、CanvasWorkspace.tsx 5121 行)。这个自省比"我拆了 App.tsx"更有价值。

③-4 60 秒标准回答 ​

前端是 React 19.2 + Vite 8 + Zustand 5,路由用 react-router 7(约 57 条路由),服务端状态用 TanStack Query——分工是 Zustand 管客户端/UI 状态,Query 管服务端资源。管理后台是独立的 React 应用,独立子域部署,用 Recharts 做仪表盘可视化。 我做的其中一件事是把巨型 App.tsx 拆成 page + feature hook 架构(原来单文件上万行)。拆完我要诚实说一条代价:巨型代码从组件层转移到了 hook 层,现在最大的 hook 有 5000 多行。所以"拆分"只是第一步,真正要做到的是按业务域切开数据依赖,这个我们还没完成。 类型这块,"统一 TypeScript"是成立的,但"类型安全"要分层说:只管理后台开了 strict 并且把 tsc 挂在构建上;主站和后端是 strict: false,后端还有 54 个文件带 @ts-nocheck。前后端的类型共享目前是"共用 9 份 JSON 规则文件 + 手工镜像类型 + 测试读前端源码断言",没有编译期约束——正确的做法是抽一个 contracts 包让 tsc 把关。 数据库是 PostgreSQL 17(简历上写 MySQL 是历史遗留,我在项目早期确实用过一段 MySQL,但五月中旬就整体切到 PG 了,因为要用部分唯一索引和 JSONB 深扫)。


Bullet ④ 生产级基础设施 ​

④-1 简历原文 ​

多环境配置(本地磁盘 vs 阿里云 OSS)、Docker Compose 一键部署、微信登录+微信支付接入

④-2 代码事实核对 ​

表述事实结论
"多环境配置(本地磁盘 vs 阿里云 OSS)"为真但要说全:存储适配器实际只有两个后端(OSS + 本地磁盘);config 收口 181 个环境变量(后端共引用的唯一 env 键是 291 个,.env.example 只文档化 127 个 → 约 57% 未文档化),零必填校验✅ 可讲,但要主动交底"漏配会静默降级到本地磁盘"这个危险点
🚩 "Docker Compose 一键部署"compose 里只有 PostgreSQL 17 + Redis 7 两个基础设施容器,没有 app service、没有 Dockerfile。真实部署是:pm2 跑 tsx index.ts + nginx 反代 + 一个约 196 行的自研发布脚本(7 步、带 HEAD 断言和探活)🚩 改成"基础设施容器化(PG/Redis 用 compose 管)+ 应用侧 pm2 + nginx + 自研零静默失败发布脚本"
"微信登录"为真:微信开放平台扫码登录(snsapi_login),state 存 Redis 防重放,user_oauth_accounts 唯一约束绑定;另有短信验证码登录✅ 可讲(wechatOAuth.ts 是你写的)
"微信支付接入"为真但范围要收窄:只接了 V3 Native 扫码(无 JSAPI/H5/小程序/APP);另有支付宝当面付预下单。wxpayClient.ts 是你手写的(签名 + RSA 验签 + AES-GCM 解密)✅ 可讲,主动补上"只有 Native"
(未写但真实的欠账)无备份、CI 停摆、无告警通道都在代码/配置里🚩 建议主动交底,见 08、10 分册

④-3 你的贡献 ​

  • wxpayClient.ts(2/2 提交)、wechatOAuth.ts(1/1)——微信支付客户端与扫码登录是你写的;
  • OSS 生命周期(临时追踪 + 删除队列);
  • 发布脚本的健壮性改进相关。

④-4 60 秒标准回答 ​

基础设施这块我讲真实形态,避免夸大。 配置:所有环境变量收口在一个 config 模块里(181 个),用 IIFE 做派生值——比如某个通道的 enabled 由"必填项是否齐备"推导,避免出现"开关打开了但密钥没填"的半配置态。存储是有本地磁盘和 OSS 两套适配器,用环境变量切换。 部署:应用没有容器化——PostgreSQL 和 Redis 用 Docker Compose 起,应用侧是 pm2 跑 tsx + nginx 反代,发布走一个自研脚本:先做 git 拉取前体检,然后带 HEAD 断言(这是核心闸门,之前吃过"git pull 失败但后面照跑,结果更新了但没生效"的亏),再按改动 diff 决定要不要跑迁移和构建,然后按 pm_cwd 推断该重启哪个 pm2 进程——这里也踩过坑,早先硬编码进程名,在测试目录跑脚本会重启生产、而测试根本没重启,探活还是绿的。最后探活 20 次 × 3 秒,期望拿到 401 才算成功。 支付:微信走 V3 Native 扫码,我是自己手写的 HTTP 客户端,需要实现请求签名(WECHATPAY2-SHA256-RSA2048)、回调 RSA 验签、以及 AES-256-GCM 解密(密文末 16 字节取 auth tag)。有个坑是回调路由必须用 express.raw 且在全局 JSON parser 之前注册,否则 body 被消费掉,验签和解密全部失败。另外还接了支付宝当面付。 我要主动说三个欠账:① 数据库没有自动备份和 PITR,而它是资金账本,这是最大风险,现在只能靠改结构前手动 pg_dump;② CI 只有一个后端单测 job,而且因为账户欠费从八月初起实际没跑;③ 没有告警通道,线上问题靠人肉 grep pm2 日志。


附:建议的简历修改版(可直接替换) ​

鲨堂(陕西)文化传媒有限公司——全栈工程师 2026.04—至今 从 0 到 1 参与电商 AI 视频生成平台 shatangAI 的全栈研发,产品已上线 https://shatang.top

  1. 多源 AI 视频编排:接入过 6 家视频服务供应商(腾讯云 VOD AIGC、火山 Ark/Seedance 网关、筷子科技等),统一 Provider 抽象与 BullMQ 队列调度;实现多段生成的四层一致性保障(尾帧→首帧锚、尾帧定格、音色锚、提示词承接)与段级指纹复用,覆盖商品展示、爆款翻拍等 14 种生成方式
  2. 任务全生命周期管理:设计状态机(pending/queued/processing/done/failed/cancelled + phase 细分),实现启动 + 周期性双轨崩溃恢复(按外部任务号分支处理、启动强制覆盖僵尸 job)、2 小时轮询超时、并发收尾 Redis 抢占;积分采用"余额 + 流水 + 冻结"三表模型,用部分唯一索引杜绝重复扣减,并以小时级对账巡检兜底(余额漂移 / 多退 / 悬挂 / 负余额)
  3. 全架构落地:前端 React 19 + Vite + Zustand + TanStack Query,后端 Express 5 + PostgreSQL 17 + Redis;管理后台为独立 React 项目(Recharts 可视化,唯一开启 strict 并构建时校验类型);主导前端从单文件 App.tsx 拆分为 page + feature hook 架构
  4. 生产级基础设施:多环境配置收口(本地磁盘 / 阿里云 OSS 双存储适配器)、OSS 文件生命周期(临时追踪 7 天 + 软删延迟 30 天 + 引用存在性保护)、PostgreSQL/Redis 容器化 + pm2/nginx 部署 + 自研零静默失败发布脚本、微信扫码登录与微信支付(V3 Native,手写签名/验签/解密)

改动说明(面试被问起可以这么解释):

  • "6+" → "接入过 6 家",因为现在只有一家在跑;
  • "Mysql" → "PostgreSQL 17",这是硬事实;
  • "引用计数保护" → "引用存在性保护",因为计数式实现不存在;
  • "Docker Compose 一键部署" → 拆成"容器化 + pm2/nginx + 发布脚本",更准确且显得你懂部署;
  • 补上"部分唯一索引 / 对账巡检 / 并发收尾抢占 / 零静默失败发布"——这四个是真正的加分项,原来没写。

持续学习,持续构建。