07 · 从 0 到 1 设计一个系统:实战方法论
前面六章给了你一套思维和一箱工具;这一章把它们拧成一条照着做就能产出架构方案的流水线,并带你用一个真实例子从头走一遍。
开场:别一上来就画框
新手接到帮我设计个 X 这样的任务,最常见的反应是:抓起笔,在白板中央画一个框,写上服务器,再画个数据库,然后……就卡住了。
资深的人不一样。他们接到需求后的前几分钟,一个框都不画,只问问题:谁用?用来干嘛?多少人用?要多快?能不能丢数据?钱从哪来?因为他们知道一件事:
架构不是画出来的,是从约束里逼出来的。你没搞清楚约束,画什么都是瞎画。
这一章给你一套 8 步流程。它不是什么神秘公式,而是把前六章学的东西排了个先后顺序:先有需求与约束(02),再估规模,再定边界,再设计数据(05),再画图(03),再深入组件(04),再找瓶颈(06),最后回头审视取舍。
这套流程同时适用于两个场景:真刀真枪设计一个新系统,以及系统设计面试。两者的底层动作其实一模一样,区别只是面试压缩在 45 分钟里,且面试官在乎的是你思考的过程而非最终那张图。
一、八步流程总览
先看全景,再逐个拆解。注意:这八步不是一条直线走完就完事,而是一个会反复回头的循环。
┌─────────────────────────────────────────────┐
│ │
▼ │
① 澄清需求与范围 ──▶ ② 估算规模 ──▶ ③ 定义用例/API 边界 │
│ │
▼ │
⑤ 画高层架构 ◀────────────────── ④ 设计数据模型 │
│ │
▼ │
⑥ 逐个深入关键组件 ──▶ ⑦ 找瓶颈,针对性扩展 │
│ │
▼ │
⑧ 回顾取舍 / 列风险 / 列未决问题 ──┘
发现问题就回到任意一步重来| 步骤 | 你在干什么 | 对应前面哪一章 |
|---|---|---|
| ① 澄清需求与范围 | 先问问题,把模糊变明确,圈定 MVP 边界 | 02 |
| ② 估算规模 | 信封背面算一笔:用户量、QPS、数据量、读写比 | 本章新增 |
| ③ 定义核心用例 / API 边界 | 系统对外暴露哪些动作?入口长什么样? | 02 |
| ④ 设计数据模型 | 核心实体、关系、各自放进哪种存储 | 05 |
| ⑤ 画高层架构 | 先 Context 再 Container,先粗后细 | 03 |
| ⑥ 逐个深入关键组件 | 挑灵魂部件往里钻,套合适的模式 | 04 |
| ⑦ 找瓶颈,针对性扩展 | 涨 100 倍,第一个死哪?怎么破? | 06 |
| ⑧ 回顾取舍与风险 | 我放弃了什么?哪里还没想清楚? | 06 + 08 |
下面逐步讲方法,讲完立刻用一个完整例子把这八步走一遍。
步骤 ①:澄清需求与范围:先问问题,别急着画图
这是最被低估、却最能拉开差距的一步。做个像 Twitter 的东西这种模糊需求背后,藏着十几个没说出口的假设,你的任务是把它们逼出来。
要问的问题分三类:
- 功能边界:这个 MVP 到底要做什么、不做什么?比如要不要支持私信、要不要搜索。把不做的明确划出去,比列要做的更重要。
- 用户与规模:谁用?有多少人?增长多快?这步的答案会直接喂给步骤 ②。
- 质量与约束:要多快?能不能短暂不可用?数据能不能丢?有没有合规/成本红线?这些问题对应 06 质量属性 里那张清单。
关键心法:你的目标不是满足所有需求,而是确认哪些需求其实不重要。范围每砍掉一块,架构就简单一个量级。新手什么都想做,高手拼命做减法。
面试里,这一步还有个隐藏作用:面试官故意把题目出得很模糊,就是想看你会不会问。上来就闷头画图的人,基本已经挂了一半。
步骤 ②:估算规模:信封背面估算
back-of-the-envelope estimation:字面意思是在信封背面随手一算。不追求精确,只求数量级对不对。
为什么必须算?因为 1 万用户和 1 亿用户是两个完全不同的系统。前者一台机器一个数据库就够,后者每一层都要考虑分片、缓存、多活。不估规模就设计,等于不知道要盖平房还是摩天楼就开始浇地基。
估算只需要几个常识级的锚点数字记在脑子里:
┌──────────────────────────────────────────────────┐
│ 几个值得背下来的锚点数字 │
│ │
│ • 一天 ≈ 86,400 秒,约等于 10^5 秒(估算时就用它) │
│ • 1 千万日活,如果每人每天来 10 次 │
│ → 1 亿次/天 ÷ 10^5 秒 ≈ 1,000 QPS(平均) │
│ • 峰值通常是平均值的 2~5 倍 → 按 ~3,000 QPS 备容 │
│ • 读写比:社交/内容类常是读多写少,10:1 起步 │
│ • 一条文本记录 ~ 数百字节;一张图 ~ 数百 KB ~ 几 MB │
└──────────────────────────────────────────────────┘先看一个完整算例,感受一下手感,正式例子在后面:
假设做一个发帖应用,1000 万日活,人均每天发 1 条、刷 50 条。
- 写 QPS:1000 万条/天 ÷ 10^5 秒 = 100 写/秒,这是平均值;峰值 ×3 ≈ 300。
- 读 QPS:1000 万 × 50 = 5 亿次/天 ÷ 10^5 = 5000 读/秒,峰值 ≈ 15000。
- 读写比:5000 : 100 = 50 : 1——典型的读多写少,这一条立刻告诉你:缓存和读扩展是重点,写不是瓶颈。
- 存储量:一条帖子算 1 KB,1000 万/天 × 365 ≈ 3.6 TB/年,这里只算纯文本。如果带图,每帖均摊 500 KB,就是 1.8 PB/年。量级差了 500 倍,存储方案完全不同。
这几个除法已经把架构重心定出来了:这是个读密集系统,要在读路径上堆缓存;文本可以塞数据库,图必须走对象存储 + CDN。这些结论全是算出来的,不是拍脑袋的。
💡 估算的价值不在数字精确,而在它逼你想清楚这个系统到底会被什么压垮。读爆?写爆?存储爆?带宽爆?答案不同,后面七步全跟着变。
步骤 ③:定义核心用例 / API 边界
把系统当成一个黑盒,先想清楚外界能对它做哪些动作。这就是 API 边界:不写具体协议,只列动作清单。
比如一个发帖应用,核心动作可能就五六个:发帖、删帖、看某人主页、刷信息流、关注/取关。先列出来,然后挑出 1~2 个主航道,也就是用户最高频、最能体现系统特点的动作。对发帖应用来说,主航道通常就是 刷信息流。
为什么先定边界?因为边界一旦清楚,内部怎么实现就有了靶子。你不会再纠结要不要加这个模块,而是会问这个模块服务于哪个用例。服务不了任何用例的模块,就是过度设计(_TEMPLATE.md 里反复强调:没有为什么的部件就是过度设计)。
面试中,这一步还帮你收敛战场。你可以主动说:这个系统能做的事很多,但今天我重点设计刷信息流这条路,其它先放一放。这是成熟度的体现。
步骤 ④:设计数据模型,承接 05
05 数据与状态 的核心观点是:系统真正的难点不是逻辑,是数据。所以一旦用例清楚了,立刻设计数据,而不是先设计服务。
这一步做两件事:
- 画概念模型:核心实体是什么?它们之间什么关系?先用最朴素的方框和连线画出用户、帖子、关注关系、点赞这些概念,不用急着写建表语句。
- 给每类数据选存储形态:回忆 05 的关键句:不同数据的访问形态不同,就该放进不同类型的存储。
照搬 AI 对话产品模板第 7 节 那张表的思路,你应该能给每类数据填出这样一行:
| 数据 | 访问形态 | 适合的存储类型 |
|---|---|---|
| 用户 / 关注关系 | 要事务、要按关系查 | 关系型 |
| 帖子内容 | 写多、按 ID 取、结构简单 | 文档型 / 追加日志 |
| 信息流,即每人看到的列表 | 海量、要快、可重算 | 内存级缓存 |
| 图片 / 视频 | 大、不可变、按 URL 取 | 对象存储 + CDN |
新手通病是把所有东西一股脑塞进一个关系型数据库,然后用
LIKE做搜索、用大表存历史。数据建模这一步做对了,后面架构基本就顺了;做错了,后面再多缓存也救不回来。
步骤 ⑤:画高层架构,先 Context 再 Container
现在,也只有现在,才到了画框的时候。但要按 03 C4 模型 的顺序来:
- 先画 Context,也就是系统上下文:把你的系统当成一个黑盒,只画它和外部世界的关系,比如用户、第三方支付、邮件服务。这一步确认系统的边界在哪、和谁打交道。
- 再画 Container,也就是容器:把黑盒切开一层,画出几大块:客户端、API 网关、几个核心服务、几种存储。这一层就够画第一版架构图了,别急着往下钻到代码级。
铁律是先粗后细。第一张图就该是五六个框加箭头的粗线条,丑一点没关系,能讲清楚数据怎么流就行。把每个框内部画清楚,是后面步骤 ⑥ 的事。一上来就画二十个框的人,往往是在用画图的勤奋掩盖没想清楚的偷懒。
步骤 ⑥:逐个深入关键组件
第一张粗图画完,挑出 1~2 个灵魂部件往里钻。不是每个框都要深挖,只挖那个决定系统成败的。还记得 AI 对话产品 那句吗:灵魂部件是推理服务,其余一切都在保护和喂养这块 GPU。每个系统都有自己的那块 GPU。
深入时,就是 04 十大核心架构模式 派上用场的地方:这个组件要解耦?也许用事件驱动;读写形态差太大?也许上 CQRS;要扛突发流量?中间加消息队列削峰。模式不是用来炫技的,是用来回答这个组件遇到的具体问题的。
怎么判断哪个是灵魂部件?回到步骤 ②:被规模压垮的那个,就是它。读爆了,灵魂部件就是信息流的读路径;写爆了,就是写入与扇出;算力爆了,比如 AI 产品,就是推理服务。
步骤 ⑦:找瓶颈,针对性扩展
问自己那个经典问题:用户从现在涨 100 倍,第一个撑不住的地方在哪?然后是第二个、第三个。
这一步直接复用步骤 ② 的估算结果。既然算出来是 50:1 的读多写少,那第一个瓶颈八成在读路径:数据库读到冒烟,破解手段是缓存、读副本、把信息流预计算好。每个瓶颈都对应着一类成熟的破解套路,这正是每个模板第 9 节规模化与瓶颈在讲的东西。
关键是不要泛泛地说加缓存、上分片。要针对你这个系统算出来的具体瓶颈说。瓶颈在读就别去优化写,瓶颈在带宽就别去抠 CPU。对着不疼的地方猛敲,是新手最常见的浪费。
步骤 ⑧:回顾取舍、列出风险与未决问题
最后一步,也是最显功力的一步:回过头审视自己刚做的所有决定,把代价摆到台面上。
- 取舍:我选了 A,放弃了 B,代价是什么?比如预计算信息流换来了读的飞快,代价是写的时候要扇出,且数据会短暂不一致。
- 风险:哪个假设如果错了,整个设计就崩?比如我假设读写比是 50:1,要是来个明星用户被千万人关注,扇出就爆了。
- 未决问题:哪些我现在还没想清楚,需要标记出来留待以后?
这一步为什么重要?因为没有完美架构,只有清楚自己在拿什么换什么的架构。能主动说出自己方案的弱点,恰恰证明你真的想清楚了。而这些取舍与理由,正是下一章 08 ADR 要你郑重记下来的东西。今天说出口的每一句取舍理由,都该变成一条架构决策记录。
面试里,主动暴露弱点是加分项而非减分项;工作中,这一步则是你三个月后回来 review 时,救你命的那份当时我是怎么想的。
二、完整实战:从 0 设计一个短链接服务
光说方法太干,我们挑一个麻雀虽小、五脏俱全的系统,把八步从头走一遍。
为什么选短链接?它把长 URL 变成
s.xx/aB3xY这样的短链,需求极简、人人都懂,却逼着你触碰几乎每一个核心架构议题:海量读、唯一 ID、缓存、读写比悬殊、存储选型、热点……是小系统讲透大道理的最佳标本。重要提醒:下面展示的是一个人的思考过程,不是标准答案。你完全可以在某一步做不同的选择,只要你说得清为什么。
① 澄清需求与范围
接到做个短链接服务这个需求,我先问问题,并自己拍板一组假设:
- 要做:把长链接缩短成短链;访问短链时跳转到原链接;短链可设过期时间。
- 不做:MVP 砍掉自定义短链别名、点击统计分析、用户账号体系。先把核心跑通,这些都是后话。
- 质量约束:
- 跳转必须极快,用户点了要立刻跳,延迟超过几百毫秒就难受。
- 跳转服务几乎不能挂,否则全网这家的短链都会失效,属于灾难级故障。
- 短链一旦生成,对应关系不能变、不能丢。
- 短链要短,越短越好,这是产品价值本身。
注意我做的最重要的动作是划掉了三个功能。范围一收窄,系统瞬间清爽。
② 估算规模:信封背面
假设每天新建 1000 万条短链,读写比 100:1。短链就是为了被疯狂点击的,典型读极多写极少。
写 QPS = 1000 万 / 天 ÷ 10^5 秒 ≈ 100 次/秒 峰值 ×3 ≈ 300
读 QPS = 100 × 写 = ~10,000 次/秒 峰值 ≈ 30,000
存储量(5 年):
1000 万/天 × 365 × 5 ≈ 180 亿条
每条 ~ 500 字节(短码 + 原链 + 元数据)
→ 180 亿 × 500 B ≈ 9 TB算出三个决定性结论:
- 读 QPS 是写的 100 倍,这是个极端读密集系统,架构重心 100% 在读路径,缓存是命根子。
- 5 年才 9 TB,数据量不算夸张,单一存储 + 缓存能扛,暂时不用一上来就分库分表。
- 要支撑 180 亿条,短码至少要够长以避免撞码。用
0-9a-zA-Z共 62 个字符,62^7 ≈ 3.5 万亿,7 位短码绰绰有余。这个结论直接定义了核心算法。
看,短码该用几位这种核心设计,是从估算里算出来的,不是猜的。这就是步骤 ② 的威力。
③ 定义核心用例 / API 边界
黑盒对外就两个动作:
创建:给一个长链接,返回一个短码,低频,约 100 QPS。跳转:给一个短码,返回对应的长链接并跳转,超高频,约 10000 QPS。
主航道一目了然:
跳转。它的流量是创建的 100 倍,整个系统的成败就看它快不快、稳不稳。接下来所有设计,都优先伺候这条主航道。
④ 设计数据模型
概念模型简单到极致——核心就一个实体:
┌────────────────────────────────┐
│ 短链映射 (ShortLink) │
│ ────────────────── │
│ 短码 (主键, 7 位) │
│ 原始长链接 │
│ 创建时间 │
│ 过期时间 │
└────────────────────────────────┘选存储形态时,回到 05 的原则:看访问形态。
| 数据 | 访问形态 | 适合的存储 |
|---|---|---|
| 短码 → 长链 的映射 | 按短码精确查,海量,几乎不改 | KV 存储,天生适合按 key 取 value |
| 同一份映射的热点部分 | 极高频读、可容忍偶尔回源 | 内存级缓存 |
关键判断:这是个纯 key-value 查找问题,拿短码换长链,根本不需要关系型数据库的关联查询和复杂事务。硬上关系型,是把简单问题复杂化。选 KV 存储,是让数据形态决定存储类型的教科书示范。
⑤ 画高层架构:先 Context,再 Container
Context,把系统当黑盒:
┌──────────┐ 点短链 / 提交长链 ┌─────────────────┐
│ 用户/浏览器 │ ───────────────────▶ │ 短链接服务(黑盒)│
└──────────┘ ◀─────────────────── └─────────────────┘
302 跳转 / 返回短码Container,切开一层:这就是第一版架构图,粗线条、够用就好:
用户
│
│ ① 创建(少) ② 跳转(极多)
▼
┌─────────────────────────────────────────────┐
│ 接入层 / API 网关 │
│ (限流、路由、防刷) │
└───────┬──────────────────────────┬──────────┘
│ 创建 │ 跳转
▼ ▼
┌───────────────┐ ┌───────────────────┐
│ 创建服务 │ │ 跳转服务 │
│ 生成唯一短码 │ │ 查短码→拿长链→302 │
└───────┬───────┘ └────────┬──────────┘
│ 写 │ 先读缓存
│ ▼
│ ┌──────────────────┐ 命中?直接返回
│ │ 内存级缓存 │────────────────▶
│ └────────┬─────────┘
│ 写 │ 未命中,回源
▼ ▼
┌─────────────────────────────────────────────┐
│ KV 存储(短码 → 长链) │
└─────────────────────────────────────────────┘注意我刻意把
创建和跳转拆成两条路、两个服务,因为步骤 ② 告诉我它俩流量差 100 倍,读写形态完全不同。让它们各自独立扩展,跳转服务可以疯狂加机器,创建服务一两台就够。这其实就是 04 里读写分离 / CQRS 思想的朴素体现。
⑥ 逐个深入关键组件
灵魂部件有两个,各钻一下:
a. 跳转服务:主航道,关乎快和稳
读路径必须极致地快,所以套多级缓存:请求先打内存缓存,命中就直接返回,覆盖绝大多数热点短链;未命中才回源 KV 存储,取到后回填缓存。因为短码 → 长链的映射几乎永不变化,缓存可以放得又久又狠,命中率天然极高。这正是步骤 ② 那个 100:1 读写比送给我们的红利。
b. 创建服务:关乎短码怎么来、会不会撞
核心难题是怎么生成一个全局唯一、又短、又不易被猜的 7 位码。这是个经典岔路口,留到下一节专门掰扯。
为什么只深挖这两个?因为 API 网关、KV 存储都是成熟构件,按部就班配置即可,而短码生成和读缓存才是这个系统独有的、做错了会致命的地方。把精力压在刀刃上。
⑦ 找瓶颈,针对性扩展
跳转量再涨 100 倍,到百万 QPS 时会死在哪?逐个排查:
- 第一个瓶颈是跳转读流量打爆后端。破解方式是把本就很高的缓存命中率继续往用户侧推,把热点短链直接缓存到 CDN / 边缘节点,让大多数跳转根本到不了源站。这是读密集系统的标准答案。
- 第二个瓶颈是数据涨到几百 TB 后,单 KV 撑不住。破解方式是按短码分片。短码是随机的,天然均匀,分片极其简单。这又是步骤 ④ 选对了 KV、步骤 ② 让短码够随机的连锁红利。
- 第三个瓶颈是创建服务的发号成为单点。破解方式是不要每次都去问一个中心要号,因为它会成瓶颈;改成给每台创建机预先批发一段号段,本地慢慢发,发完再批发下一段。
看出规律没?几乎每个瓶颈的破解,都在兑现前面某一步埋下的伏笔。前面想得越清楚,这里越省力,这就是为什么不能跳步。
⑧ 回顾取舍、列风险与未决问题
把这一版方案的代价和软肋摆出来。这一步不是走过场,是整个设计最诚实的部分:
关键取舍:
| 我选了 | 放弃了 | 因为 |
|---|---|---|
| KV 存储 | 关系型的关联查询能力 | 这就是个 key-value 查找,用不上关联 |
| 重度缓存 + CDN | 一定的实时性,改了链接后缓存可能还是旧的 | 映射几乎不变,这个代价几乎为零 |
| 创建/跳转拆两条路 | 一点架构简洁性,两个服务而非一个 | 读写比 100:1,值得为各自独立扩展付这点复杂度 |
| 预批发号段发号 | 短码的严格连续/可预测 | 换来无单点、可水平扩展;短码本就不该可预测,这也是安全要求 |
风险与未决问题:
- 热点短链:某条链接突然被亿级点击时,缓存能扛大部分,但缓存失效的瞬间可能压垮源站,也就是缓存击穿。未决:要不要给热点 key 加单独的保护?
- 短码耗尽/撞码:7 位算过够用 5 年,但增长若远超预期,需提前预案升到 8 位。未决:监控短码空间使用率,设报警阈值。
- 删除/过期的回收:过期短码要不要回收复用?复用会引入旧链接被指向新目标的安全风险。未决:倾向不复用,但要确认存储成本能否承受。
这三条未决问题不是设计的失败,恰恰是设计成熟的标志。一个号称没有任何未决问题的方案,只说明作者还没想到那么深。把它们记下来,下一章你会知道,这些正是该写进 ADR 的内容。
三、贯穿全程的一条主线:架构是迭代出来的
如果这一章你只能记住一句话,那就是这句:
没有人能一次把架构画对。好架构是先画个粗的,再在压力下一轮轮长出来的。
回头看那个流程图为什么是个带回环的循环,因为真实过程从来不是 ①→②→…→⑧ 一条直线走到底:
- 你在步骤 ⑦ 发现读会爆,回到 ④ 改数据模型,比如加一层缓存表。
- 你在步骤 ⑧ 发现某个假设站不住,回到 ① 重新和需求方确认范围。
- 上线三个月后来了真实流量,你整个重走一遍,这次的估算换成了真实监控数据。
第一版:粗 第二版:细 第 N 版:实战打磨
┌────────┐ 发现瓶颈 ┌────────┐ 真实流量 ┌────────┐
│ 五六个框 │ ───────▶ │ 加缓存 │ ─────────▶ │ 分片/CDN │ ─▶ …
│ 能讲通即可│ │ 拆服务 │ │ 多活/降级│
└────────┘ └────────┘ └────────┘
▲ │
└──────────── 永远在长大 ──────────────────┘这也正是整个仓库三条阅读原则里那句架构是会长大的,见 根 README。别拿成熟期的图去套 MVP。你的短链服务第一版可能就是一个服务 + 一个 KV + 一层缓存,等真红了再长出 CDN、分片、号段。过度设计和想不到一样有害。
📌 真实案例:拿模板验证你的推演
本章用八步从 0 设计了短链接服务。现在去验证:打开本仓库 短链接服务模板,对照它的第 8 节关键决策和第 9 节瓶颈,看你推演时做的取舍和它一不一样。不一样不要紧,能说清各自为什么,你就在用架构师的方式思考了。
任何一个 模板 都能这么用:盖住后半,自己先用八步推演,再对照。
本章小结
- 架构不是画出来的,是从约束里逼出来的。接到需求先问问题、先估规模,别急着画框。
- 八步流程照着做就能产出方案:① 澄清需求范围 → ② 信封背面估规模 → ③ 定用例/API 边界 → ④ 设计数据模型 → ⑤ 先 Context 再 Container 画图 → ⑥ 深挖灵魂部件 → ⑦ 找瓶颈针对性扩展 → ⑧ 回顾取舍与风险。每一步都对应前六章的某个工具。
- 信封背面估算是被低估的超能力:几个除法就能定出系统重心。读爆、写爆、存储爆,答案不同,后面所有设计都跟着走。
- 先粗后细:第一张图就该是丑陋的五六个框,够讲清数据流就行。深挖只挖灵魂部件,精力压在刀刃上。
- 第八步最显功力:能主动说出自己方案放弃了什么、哪里还没想清楚,才证明你真想透了。
- 架构是迭代出来的:流程是个会反复回头的循环,而不是一条直线。别想一次画对,也别拿成熟期的架构套 MVP。
🎯 随堂检验
- A步骤 ⑤ 画高层架构
- B步骤 ② 信封背面估规模——还没算 QPS、读写比、存储量就定了组件
- C步骤 ⑧ 回顾取舍与风险
现在,轮到你了
动手练习:打开
../templates/,任选一个系统,比如电商、社交信息流、实时通讯、视频流媒体。先盖住第 4~9 节,自己拿这八步从头推演一遍,尤其别跳过步骤 ②,亲手算一笔它的 QPS 和存储量。推演完,再翻开模板对照:你的灵魂部件找对了吗?你估出的瓶颈,和它第 9 节说的一致吗?它在第 8 节做的取舍,和你做的一样吗?不一样不要紧,能说清各自为什么,你就已经在用架构师的方式思考了。
推演的时候,你一定会做出一连串我选 A 不选 B 的决定。这些决定此刻在你脑子里清清楚楚,但三个月后会忘得一干二净,到时候连你自己都会问:当初为什么这么定?
怎么把这些宝贵的为什么留住,让架构能随业务一起健康长大?这就是下一章的主题。
相关链接
- 上一章:06 · 质量属性与取舍 —— 第 ⑦⑧ 步找瓶颈、列取舍的判断依据都在这
- 下一章:08 · 架构决策记录(ADR)与演进 —— 把第 ⑧ 步说出口的为什么郑重记下来
- 配套:02 · 架构师的思考框架(步骤 ①③)、03 · 读懂与画好架构图(步骤 ⑤)、05 · 数据与状态(步骤 ④)
- 实战对照:
../templates/全部模板的第 3、4、8、9 节,正是这八步的产物;AI 对话产品模板 是一个走完整流程的好范例
💬 评论