Files
happy-life-star/docs/superpowers/specs/2026-04-07-mini-program-script-markdown-design.md
T
peanut 42d7bb3cb5 docs: 添加小程序剧本卡片 Markdown 渲染设计文档
设计内容:
- 扩展 Markdown 组件支持三级标题和粗体
- ScriptView.vue 卡片摘要使用 Markdown 渲染
- 新增 ScriptDetailView.vue 剧本详情页
- 点击卡片跳转查看详情

解决 issues: 小程序"创造未来"页面剧本内容以纯文本显示,
            无法正确渲染 Markdown 格式(标题、列表、粗体等)
2026-04-07 21:18:53 +08:00

290 lines
9.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.
---
author: Peanut
created_at: 2026-04-07
purpose: 定义小程序"创造未来"页面剧本卡片的 Markdown 渲染方案
---
# 小程序剧本卡片 Markdown 渲染设计
## 问题背景
小程序"创造未来"页面(ScriptView.vue)中,剧本卡片当前以纯文本形式显示内容:
- 摘要区域:`<text class="script-summary">{{ getScriptSummary(script) }}</text>`
- 完整内容:存储在 `script.plotJson.fullContent`
但后端返回的剧本数据是 **Markdown 格式**
```markdown
### 人物小传
花生米曾有过光芒闪耀的"破土而出"时刻...
### 戏剧驱动力
- 主人公当下最想要的一件具体的东西是:成为武林高手。
- 为了得到它,他必须承受或放弃的是:原本正常的生活节奏...
#### 第一场:抉择
- **时间**:日
- **地点**:花生米家中
- **人物**:花生米
花生米(自言自语):"成为武林高手,这听起来多带劲啊..."
```
当前纯文本显示导致:
- 标题与普通文本无法区分
- 列表项没有项目符号
- 粗体等格式丢失
- 阅读体验差
## 设计方案
### 架构概述
```
┌─────────────────────────────────────────────────────────────┐
│ ScriptView.vue │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 剧本卡片 (script-card) │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ 标题 / persona │ │ │
│ │ ├─────────────────────────────────────────────┤ │ │
│ │ │ 摘要区域 (Markdown 渲染 - 前 200 字符) │ │ │
│ │ │ ### 人物小传 │ │ │
│ │ │ 花生米曾有过光芒闪耀的... │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ [路径映射 →] (点击跳转详情页) │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
▼ 点击卡片
┌─────────────────────────────────────────────────────────────┐
│ ScriptDetailView.vue (新增) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 返回 剧本标题 │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ │ │
│ │ 完整 Markdown 内容渲染 │ │
│ │ ### 人物小传 │ │
│ │ 花生米曾有过... │ │
│ │ ### 戏剧驱动力 │ │
│ │ - 主人公当下最想要... │ │
│ │ #### 第一场:抉择 │ │
│ │ - **时间**:日 │ │
│ │ ... │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
### 组件复用
**已有组件**[`mini-program/src/components/Markdown.vue`](mini-program/src/components/Markdown.vue)
当前支持的 Markdown 格式:
- ✅ 分割线 `---`
- ✅ 四级标题 `#### `
- ✅ 列表项 `* ` / `- `
- ✅ 普通段落
**需要扩展支持**
- ❌ 三级标题 `### `
- ❌ 粗体 `**text**`
### 文件结构
```
mini-program/src/
├── components/
│ └── Markdown.vue # 扩展现有组件
├── pages/main/
│ ├── ScriptView.vue # 修改:卡片摘要使用 Markdown
│ └── ScriptDetailView.vue # 新增:剧本详情页
└── services/
└── epicScript.js # 现有服务,无需修改
```
## 实施细节
### 1. Markdown 组件扩展
**文件**`mini-program/src/components/Markdown.vue`
**新增解析规则**
```javascript
// 三级标题 ###
const h3Match = trimmed.match(/^###\s+(.+)/)
if (h3Match) {
blocks.push({ type: 'h3', content: h3Match[1] })
continue
}
// 粗体 **text** (在段落内容中处理)
// 由于小程序不支持富文本内的 HTML,粗体需要特殊处理
// 方案:将包含粗体的段落拆分为多个文本段
```
**模板新增**
```vue
<!-- 三级标题 -->
<text v-else-if="block.type === 'h3'" class="markdown-h3">{{ block.content }}</text>
```
**样式**
```css
.markdown-h3 {
display: block;
font-size: 30rpx;
font-weight: 600;
color: rgba(243, 232, 255, 0.95);
margin: 20rpx 0 12rpx 0;
line-height: 1.4;
}
```
### 2. ScriptView.vue 修改
**修改点 1**:导入 Markdown 组件
```javascript
import Markdown from '../../components/Markdown.vue'
```
**修改点 2**:摘要区域使用 Markdown 渲染
```vue
<!-- 原代码 -->
<text class="script-summary" lines="3">{{ getScriptSummary(script) }}</text>
<!-- 修改后 -->
<view class="script-summary">
<Markdown :content="getScriptSummary(script)" />
</view>
```
**修改点 3**:添加点击跳转
```vue
<view class="script-card" @click="viewScriptDetail(script)">
<!-- 卡片内容 -->
</view>
```
**修改点 4**:跳转方法
```javascript
const viewScriptDetail = (script) => {
uni.navigateTo({
url: `/pages/main/ScriptDetailView?id=${script.id}`
})
}
```
### 3. ScriptDetailView.vue 新建
**文件**`mini-program/src/pages/main/ScriptDetailView.vue`
**核心结构**
```vue
<template>
<view class="detail-view">
<view class="detail-header">
<text class="detail-title">{{ script.title }}</text>
<text class="detail-theme">{{ script.theme }}</text>
</view>
<scroll-view class="detail-content" scroll-y>
<Markdown :content="fullContent" />
</scroll-view>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useAppStore } from '../../stores/app.js'
import Markdown from '../../components/Markdown.vue'
const store = useAppStore()
const script = ref(null)
const fullContent = ref('')
onMounted(async () => {
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
const scriptId = currentPage.options.id
// 从 store 获取剧本详情
const targetScript = store.scripts.find(s => s.id === scriptId)
script.value = targetScript
// 获取完整内容
if (targetScript?.plotJson?.fullContent) {
fullContent.value = targetScript.plotJson.fullContent
}
})
</script>
```
### 4. 摘要提取逻辑
**当前逻辑**
```javascript
const getScriptSummary = (script) => {
const text = script.summary || script.content || ''
return text.replace(/\s+/g, ' ').trim()
}
```
**修改后**
```javascript
const getScriptSummary = (script) => {
// 优先使用 summary 字段
if (script.summary) {
return script.summary
}
// 从 fullContent 提取前 200 字符
const fullContent = script.plotJson?.fullContent || ''
if (fullContent) {
// 提取内容,去掉 Markdown 符号
return fullContent
.split('\n')
.filter(line => line.trim())
.slice(0, 5) // 取前 5 行
.join('\n')
.slice(0, 200) + '...'
}
return '暂无摘要'
}
```
## 验收标准
- [x] Markdown 组件支持三级标题 `###`
- [x] Markdown 组件支持粗体 `**text**`(如无法完美支持,降级为普通文本)
- [x] ScriptView.vue 卡片摘要使用 Markdown 渲染
- [x] 点击卡片可跳转到详情页查看完整内容
- [x] 详情页正确渲染完整 Markdown 格式
- [x] 样式与现有设计保持一致
## 注意事项
### 1. 粗体支持限制
微信小程序的 `<text>` 组件不支持富文本内的局部样式。
**解决方案**
- 方案 A:使用正则将 `**text**` 拆分为多个 `<text>` 组件(复杂)
- 方案 B:降级处理,粗体标记移除但保留文字(简单)
**推荐**:先实现方案 B,如效果不佳再考虑方案 A。
### 2. 长内容加载
剧本完整内容可能较长(2000+ 字符),详情页使用 `<scroll-view>` 确保可滚动浏览。
### 3. 数据获取
- 剧本数据已通过 `store.fetchScripts()` 加载到 store
- 详情页从 store 根据 ID 获取,无需额外 API 调用
## 参考文档
- [uni-app 页面跳转](https://uniapp.dcloud.net.cn/api/router.html)
- [uni-app scroll-view](https://uniapp.dcloud.net.cn/component/scroll-view.html)
- 已有 Markdown 组件:`mini-program/src/components/Markdown.vue`