Files
JianSu-Naming/step4.md
王鹏 be1f5722ab feat: 完成见素起名小程序核心功能
- 实现 AI 起名功能(Kimi API 接入)
- 添加用户收藏功能(MySQL 数据库)
- 实现海报生成与分享
- 添加音效和触觉反馈
- 配置生产环境部署(WAR 包 + Nginx)
- 支持多种起名模式(经典、诗词、自然、现代)
- 实现分批加载优化体验
2026-04-17 15:34:51 +08:00

111 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

采用**异步并行生成**Asynchronous Parallel Generation是目前平衡“高响应速度”与“AI 生成质量”最立竿见影的方案。
其核心思路是将原来“一个请求等五个名字”的线性过程,拆分为“多个并发请求同时生成名字”。
---
## 1. 后端重构:`MiniMaxService.java`
我们需要利用 Java 的 `CompletableFuture` 来并发调用 AI 接口。
```java
@Service
public class MiniMaxService {
// 模拟原有的单次生成逻辑
private NameCard callAiToGenerateSingleName(String keyword, String mode, String surname) {
// 这里是原有的 MiniMax API 调用逻辑,但只要求它返回 1 个名字
// ...
}
public List<NameCard> generateNamesAsync(String keyword, String mode, String surname) {
int count = 5; // 我们需要生成 5 个名字
List<CompletableFuture<NameCard>> futures = new ArrayList<>();
for (int i = 0; i < count; i++) {
// 为每个名字开启一个异步线程
CompletableFuture<NameCard> future = CompletableFuture.supplyAsync(() -> {
return callAiToGenerateSingleName(keyword, mode, surname);
});
futures.add(future);
}
// 等待所有线程完成(或部分完成即可返回,提升容错)
return futures.stream()
.map(CompletableFuture::join) // 合并结果
.collect(Collectors.toList());
}
}
```
### 为什么这样做更快?
* **线性模式**AI 生成 5 个名字的时间 = $T1 + T2 + T3 + T4 + T5$(通常需要 8-12 秒)。
* **并行模式**:总耗时 = $max(T1, T2, T3, T4, T5)$(通常只需 2-3 秒)。
---
## 2. 前端感知优化:伪流式展示
虽然后端并行生成了结果,但如果我们等 5 个全部完成再返回,前端仍有空窗期。我们可以配合前端做一个“分批次渲染”。
### 修改 `index.js` 的 `fetchNames` 逻辑:
我们可以将请求拆分为两拨:一拨追求“极速响应”(先拿 2 个名字),二拨追求“完整体验”(再拿 3 个)。
```javascript
fetchNames(keyword, mode, surname) {
// 1. 发起第一波请求:先取 2 个名字,让用户立刻有卡片可以翻
this.requestNamingApi(keyword, mode, surname, 2).then(firstBatch => {
this.setData({
nameList: firstBatch,
currentIndex: 0
});
// 2. 第一波成功后,静默发起第二波请求:补齐剩下的名字
this.requestNamingApi(keyword, mode, surname, 3).then(secondBatch => {
this.setData({
nameList: [...this.data.nameList, ...secondBatch]
});
});
});
}
```
---
## 3. 仪式感补偿Loading 文案池
为了让异步加载的 1-2 秒不尴尬,在 `home.js` 跳转到 `index.js` 时,利用一个动态的文案池来分散用户注意力。
### 在 `index.wxml` 中添加:
```html
<view wx:if="{{nameList.length === 0}}" class="loading-container">
<view class="ink-blob"></view>
<text class="loading-text">{{loadingQuote}}</text>
</view>
```
### 在 `index.js` 中添加文案轮换:
```javascript
const quotes = [
"正在翻阅《古今集成》...",
"字里行间,寻觅归处...",
"笔墨将就,意境自生...",
"正在感悟山川意向..."
];
// 在 onLoad 中开启定时器
this.loadingTimer = setInterval(() => {
this.setData({
loadingQuote: quotes[Math.floor(Math.random() * quotes.length)]
});
}, 2000);
```
---
## 🛠️ 实施建议
1. **后端线程池**:在使用 `CompletableFuture` 时,务必自定义一个 `Executor`(线程池),不要使用默认的 `ForkJoinPool`,防止在高并发下把后端拖垮。
2. **音律分析延迟**:如果 `ToneAnalysisService` 依然很慢,可以先返回名字和出处,音律评分字段标记为“计算中”,待卡片翻转时再动态获取。
**这套“并行生成 + 分批返回”的方案,能将用户的体感等待时间从 10 秒以上直接压缩到 2 秒左右。**