You need to sign in or sign up before continuing.
hookehuyr

docs: 添加 API 文档和组件速查表

- 新增 docs/api-docs/README.md(API 文档缓存说明)
- 新增 docs/api-docs/常用组件速查表.md(组件使用速查)
- 更新 .claude/settings.local.json(权限配置)

---

**详细信息**:
- **影响文件**: .claude/settings.local.json, docs/api-docs/README.md, docs/api-docs/常用组件速查表.md
- **技术栈**: 文档
- **测试状态**: N/A
- **备注**: 提供 Taro 和 NutUI 文档缓存方案及常用组件使用示例

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
......@@ -78,7 +78,12 @@
"Bash(__NEW_LINE_b32968d45b3e16a9__ python3 /tmp/update-imports.py)",
"Bash(/Users/huyirui/program/itomix/git/manulife-weapp/docs/reports/2026-02-09/components-cleanup-report.md <<'EOF'\n\n---\n\n## ✅ 执行结果(2026-02-09)\n\n### 已完成的清理和重组\n\n#### 阶段 1: 清理未使用组件 ✅\n- ✅ 删除 `qrCode.vue` \\(11KB\\)\n- ✅ 删除 `FilterTabs.example.vue`\n- ✅ 删除 `PlanPopup/` 目录(旧版本)\n\n#### 阶段 2: 组件目录重组 ✅\n\n**创建的分类目录**:\n1. `navigation/` - 导航组件\n2. `list/` - 列表组件\n3. `forms/` - 表单组件\n4. `cards/` - 卡片组件\n5. `documents/` - 文档相关组件\n6. `plan/` - 计划书相关组件\n7. `icons/` - 图标组件\n\n**组件迁移清单**:\n```\nnavigation/\n├── TabBar.vue\n└── NavHeader.vue\n\nlist/\n├── ListItemActions/\n├── LoadMoreList/\n├── SectionCard.vue\n└── SectionItem.vue\n\nforms/\n├── FilterTabs.vue\n└── SearchBar.vue\n\ncards/\n├── MaterialCard.vue\n└── ProductCard.vue\n\ndocuments/\n├── DocumentPreview/\n├── OfficeViewer.vue\n└── PdfPreview.vue\n\nplan/\n├── PlanFields/\n├── PlanFormContainer.vue\n├── PlanPopupNew.vue\n└── PlanTemplates/\n\nicons/\n└── IconFont.vue\n```\n\n**路径更新统计**:\n- 更新文件数:38 个\n- 更新类型:import 语句\n- 更新范围:src/pages/, src/components/\n- 验证结果:✅ 通过(0 errors, 30 warnings)\n\n### 📊 最终收益\n\n**代码质量**:\n- ✅ 删除 3 个未使用组件(约 11KB)\n- ✅ 组件按功能分类,结构清晰\n- ✅ 所有引用路径已更新\n- ✅ 代码检查通过(0 errors)\n\n**可维护性**:\n- ✅ 组件查找更快速\n- ✅ 功能边界更明确\n- ✅ 为未来组件扩展预留空间\n- ✅ 符合项目架构原则\n\n**文档更新**:\n- ✅ CHANGELOG.md 已更新\n- ✅ 本报告已创建\n\n---\n\n**执行时间**: 2026-02-09\n**执行状态**: ✅ 完成\n**下一步**: 可以继续优化组件内部实现,或清理其他未使用代码\nEOF)",
"Bash(tail:*)",
"Bash(pnpm build:weapp:*)"
"Bash(pnpm build:weapp:*)",
"Bash(pnpm view:*)",
"Bash(pnpm update:*)",
"Bash(open:*)",
"Bash(awk:*)",
"Bash(else)"
]
},
"enableAllProjectMcpServers": true,
......
# API 文档缓存
本目录用于缓存 Taro 和 NutUI 的核心文档,方便离线查询。
## 📚 在线文档
### Taro 官方文档
- **Taro 官网**: https://docs.taro.zone/
- **Taro Vue 3**: https://docs.taro.zone/docs/vue3
- **Taro 组件**: https://docs.taro.zone/docs/components
- **Taro API**: https://docs.taro.zone/docs/apis
- **Taro 最佳实践**: https://docs.taro.zone/docs/best-practices
### NutUI 官方文档
- **NutUI 官网**: https://nutui.jd.com/h5/#/
- **NutUI Taro 版本**: https://nutui.jd.com/taro/
- **NutUI 组件列表**: https://nutui.jd.com/taro/component.html
## 🔧 本地缓存方案
### 方案 1: 使用文档工具(推荐)
#### DevDocs
```bash
# 安装 DevDocs(macOS)
brew install devdocs
# 启动服务
devdocs
# 在浏览器访问
open http://localhost:9292
```
#### Zeal(Windows/Linux)
- 下载地址: https://zealuser.com/downloads/
### 方案 2: 离线文档网页
#### Taro PDF 文档
```bash
# 创建 docs/pdf 目录
mkdir -p pdf
# 下载 Taro Vue 3 PDF(如果官方提供)
# 从 https://docs.taro.zone/ 下载
```
#### 使用 wget 镜像整个站点
```bash
# 镜像 Taro 文档(仅用于学习)
wget \
--recursive \
--no-clobber \
--page-requisites \
--html-extension \
--convert-links \
--restrict-file-names=windows \
--domains docs.taro.zone \
--no-parent \
docs.taro.zone/docs/vue3
# 镜像 NutUI 文档
wget \
--recursive \
--no-clobber \
--page-requisites \
--html-extension \
--convert-links \
--restrict-file-names=windows \
--domains nutui.jd.com \
--no-parent \
nutui.jd.com/taro/
```
### 方案 3: 创建常用组件速查表
在项目中维护常用的组件使用示例,例如:
#### nut-button 常用用法
```vue
<!-- 基础按钮 -->
<nut-button type="primary">主要按钮</nut-button>
<!-- 次要按钮(描边) -->
<nut-button plain type="primary">次要按钮</nut-button>
<!-- 独占一行 -->
<nut-button type="primary" block>独占一行</nut-button>
<!-- 自定义样式 -->
<nut-button
type="primary"
color="#2563EB"
class="!h-[88rpx] !rounded-[16rpx] !text-[30rpx]"
>
自定义样式
</nut-button>
### 方案 4: 使用 VSCode 插件
推荐安装以下插件:
1. **Taro Snippets**
- 提供 Taro 代码片段
- 自动补全组件和 API
2. **Vue 3 Snippets**
- Vue 3 代码片段
3. **Inline HTML**
- 直接在编辑器中预览 HTML/CSS
## 📝 常用属性速查
### nut-button 常用属性
| 属性 | 说明 | 类型 | 默认值 |
|------|------|------|--------|
| type | 类型 | `'default' \| 'primary' \| 'info' \| 'success' \| 'warning' \| 'danger' \| 'light'` | `'default'` |
| size | 大小 | `'large' \| 'normal' \| 'small' \| 'mini'` | `'normal'` |
| plain | 是否为描边按钮 | `boolean` | `false` |
| block | 是否为块级按钮(独占一行) | `boolean` | `false` |
| color | 自定义颜色 | `string` | - |
| disabled | 是否禁用 | `boolean` | `false` |
| loading | 是否加载中 | `boolean` | `false` |
### nut-popup 常用属性
| 属性 | 说明 | 类型 | 默认值 |
|------|------|------|--------|
| visible | 是否显示 | `boolean` | `false` |
| position | 弹出位置 | `'top' \| 'right' \| 'bottom' \| 'left' \| 'center'` | `'center'` |
| round | 是否圆角 | `boolean` | `false` |
| close-on-click-overlay | 点击遮罩是否关闭 | `boolean` | `true` |
| safe-area-inset-bottom | 是否适配底部安全区 | `boolean` | `false` |
## 🚀 快速查询
### grep 搜索现有用法
```bash
# 搜索 nut-button 的用法
grep -r "nut-button" src/ --include="*.vue" -A 3 -B 1
# 搜索 nut-popup 的用法
grep -r "nut-popup" src/ --include="*.vue" -A 5 -B 1
# 搜索 TailwindCSS 类名
grep -r "!h-\[88rpx\]" src/ --include="*.vue"
# 搜索特定的样式模式
grep -r "flex-1.*gap-3" src/ --include="*.vue"
```
### 提取组件使用示例
从现有代码中提取常用模式:
```bash
# 查找所有按钮样式
grep -r "nut-button" src/components/plan/ -A 10
# 查找所有弹窗配置
grep -r "PlanPopupNew" src/ -A 5 -B 5
```
## 💡 最佳实践
1. **查文档优先**:遇到不熟悉的组件,先查官方文档
2. **搜索现有代码**:项目中可能有类似的用法
3. **记录常用模式**:将常用代码片段保存到文档
4. **使用类型提示**:TypeScript 可以提示可用的属性
## 📚 推荐学习资源
- [Taro 官方示例](https://docs.taro.zone/docs/tutorial)
- [NutUI 组件示例](https://nutui.jd.com/taro/demos.html)
- [Vue 3 官方文档](https://cn.vuejs.org/)
- [TailwindCSS 文档](https://tailwindcss.com/docs)
## 🔄 文档更新
记录文档更新时间,方便追踪:
- **Taro 版本**: 4.1.11
- **NutUI 版本**: 4.3.14
- **最后更新**: 2026-02-10
# 常用组件速查表
本文件记录项目中常用的组件使用模式,方便快速查找和复制。
## nut-button
### 基础用法
```vue
<!-- 主要按钮 -->
<nut-button type="primary">确定</nut-button>
<!-- 次要按钮(描边) -->
<nut-button plain type="primary">取消</nut-button>
<!-- 独占一行 -->
<nut-button type="primary" block>确定</nut-button>
<!-- 禁用状态 -->
<nut-button disabled>禁用</nut-button>
<!-- 加载中 -->
<nut-button loading>提交中...</nut-button>
```
### 自定义样式(项目常用)
```vue
<!-- 双按钮并排(取消 + 主要操作) -->
<div class="flex gap-3 w-full">
<nut-button
plain
type="primary"
class="flex-1 !h-[88rpx] !rounded-[16rpx] !text-[30rpx] !border-blue-600"
>
取消
</nut-button>
<nut-button
type="primary"
color="#2563EB"
class="flex-1 !h-[88rpx] !rounded-[16rpx] !text-[30rpx]"
>
确定
</nut-button>
</div>
<!-- 单按钮独占一行 -->
<nut-button
type="primary"
color="#2563EB"
block
class="!h-[88rpx] !rounded-[16rpx] !text-[30rpx]"
>
确定
</nut-button>
<!-- 灰色关闭按钮 -->
<nut-button
type="primary"
color="#9CA3AF"
block
class="!h-[88rpx] !rounded-[16rpx] !text-[30rpx]"
>
关闭
</nut-button>
```
## nut-popup
### 基础用法
```vue
<template>
<nut-popup
:visible="visible"
position="bottom"
round
@update:visible="handleVisibleChange"
>
<div>弹窗内容</div>
</nut-popup>
</template>
<script setup>
import { ref } from 'vue'
const visible = ref(false)
const handleVisibleChange = (value) => {
visible.value = value
}
</script>
```
### 项目常用配置
```vue
<nut-popup
:visible="visible"
position="bottom"
round
:style="{ height: '90%' }"
:close-on-click-overlay="true"
:safe-area-inset-bottom="true"
@update:visible="handleVisibleChange"
>
<div class="h-full flex flex-col bg-gray-50 overflow-hidden rounded-t-2xl">
<!-- Header -->
<div class="flex justify-between items-center px-5 py-4 bg-white border-b border-gray-100 flex-shrink-0">
<span class="text-lg font-bold text-gray-900">标题</span>
<div class="p-2 -mr-2" @click="handleClose">
<IconFont name="close" size="16" color="#9CA3AF" />
</div>
</div>
<!-- Scrollable Content -->
<div class="flex-1 overflow-y-auto p-4">
<div class="bg-white rounded-xl p-5 shadow-sm">
内容
</div>
</div>
<!-- Footer Buttons -->
<div class="p-4 bg-white border-t border-gray-100 flex gap-3 flex-shrink-0 pb-safe">
<nut-button
plain
type="primary"
class="flex-1 !h-[88rpx] !rounded-[16rpx] !text-[30rpx]"
@click="handleClose"
>
取消
</nut-button>
<nut-button
type="primary"
color="#2563EB"
class="flex-1 !h-[88rpx] !rounded-[16rpx] !text-[30rpx]"
@click="handleSubmit"
>
确定
</nut-button>
</div>
</div>
</nut-popup>
```
## nut-tabs
### 基础用法
```vue
<nut-tabs v-model="activeTab">
<nut-tab-pane title="标签1">内容1</nut-tab-pane>
<nut-tab-pane title="标签2">内容2</nut-tab-pane>
</nut-tabs>
```
### 自定义标题
```vue
<nut-tabs v-model="activeTab">
<template #titles>
<view class="filter-tabs-wrapper">
<view
v-for="item in tabsData"
:key="item.id"
:class="[
'filter-tab-item',
activeTab === item.id ? 'filter-tab-active' : 'filter-tab-inactive'
]"
@tap="onTabClick(item.id)"
>
<text class="filter-tab-text">{{ item.name }}</text>
</view>
</view>
</template>
</nut-tabs>
```
## nut-input / nut-textarea
### nut-input
```vue
<nut-input
v-model="value"
placeholder="请输入"
:clearable="true"
@input="handleInput"
/>
```
### nut-textarea
```vue
<!-- NutUI textarea (部分样式可能不支持深度选择器) -->
<nut-textarea
v-model="content"
placeholder="请输入内容"
:maxlength="200"
@input="handleInput"
/>
<!-- 原生 textarea (完全控制样式) -->
<textarea
v-model="content"
class="custom-textarea"
:maxlength="200"
@input="handleInput"
/>
```
```css
.custom-textarea {
width: 100%;
min-height: 200rpx;
padding: 24rpx;
border: 2rpx solid #E5E7EB;
border-radius: 16rpx;
font-size: 28rpx;
}
```
## nut-picker
### 基础用法
```vue
<template>
<nut-picker
:visible="showPicker"
:columns="columns"
:default-value="value"
@update:visible="showPicker = $event"
@confirm="handleConfirm"
@cancel="handleCancel"
/>
</template>
<script setup>
import { ref } from 'vue'
const showPicker = ref(false)
const value = ref(['选项1'])
const columns = ref([
{ text: '选项1', value: '1' },
{ text: '选项2', value: '2' },
])
const handleConfirm = ({ selectedOptions }) => {
console.log('选中:', selectedOptions)
}
</script>
```
## nut-toast / NutUI.showToast
### 轻提示
```javascript
import Taro from '@tarojs/taro'
// 成功提示
Taro.showToast({
title: '操作成功',
icon: 'success',
duration: 2000
})
// 失败提示
Taro.showToast({
title: '操作失败',
icon: 'error',
duration: 2000
})
// 加载提示
Taro.showLoading({
title: '加载中...',
mask: true
})
// 关闭加载
Taro.hideLoading()
// 纯文本提示
Taro.showToast({
title: '提示信息',
icon: 'none'
})
```
## nut-dialog
### 弹窗确认
```javascript
import Taro from '@tarojs/taro'
Taro.showModal({
title: '提示',
content: '确定要删除吗?',
success: (res) => {
if (res.confirm) {
console.log('用户点击确定')
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
```
## 图标组件
### IconFont 组件
```vue
<template>
<!-- 使用 IconFont 组件 -->
<IconFont name="close" size="16" color="#9CA3AF" />
<IconFont name="heart" size="20" color="#EF4444" />
<IconFont name="heart-fill" size="20" color="#EF4444" />
</template>
<script setup>
import IconFont from '@/components/icons/IconFont.vue'
</script>
```
### 动态切换图标
⚠️ **重要**: IconFont 动态切换时需要添加 `:key` 强制重新渲染
```vue
<template>
<IconFont :name="iconName" :key="iconName" size="20" />
</template>
<script setup>
import { ref } from 'vue'
import IconFont from '@/components/icons/IconFont.vue'
const iconName = ref('heart')
const toggleIcon = () => {
iconName.value = iconName.value === 'heart' ? 'heart-fill' : 'heart'
}
</script>
```
## 列表组件
### nut-cell
```vue
<nut-cell
title="单元格"
sub-title="副标题"
is-link
@click="handleClick"
/>
```
### nut-checkbox / nut-checkbox-group
```vue
<template>
<nut-checkbox-group v-model="checkedList">
<nut-checkbox label="选项1">选项1</nut-checkbox>
<nut-checkbox label="选项2">选项2</nut-checkbox>
</nut-checkbox-group>
</template>
<script setup>
import { ref } from 'vue'
const checkedList = ref(['选项1'])
</script>
```
## 表单组件
### 表单验证模式
```vue
<template>
<nut-form>
<nut-form-item label="姓名" required>
<nut-input
v-model="form.name"
placeholder="请输入姓名"
:clearable="true"
/>
</nut-form-item>
<nut-form-item label="手机号" required>
<nut-input
v-model="form.phone"
placeholder="请输入手机号"
type="tel"
:clearable="true"
/>
</nut-form-item>
<nut-button type="primary" @click="handleSubmit">提交</nut-button>
</nut-form>
</template>
<script setup>
import { reactive } from 'vue'
const form = reactive({
name: '',
phone: ''
})
const handleSubmit = () => {
// 验证
if (!form.name) {
Taro.showToast({ title: '请输入姓名', icon: 'none' })
return
}
if (!form.phone) {
Taro.showToast({ title: '请输入手机号', icon: 'none' })
return
}
// 提交逻辑
console.log('表单数据:', form)
}
</script>
```
## 常用 TailwindCSS 类
### 布局
```vue
<!-- Flexbox 布局 -->
<div class="flex items-center justify-between">...</div>
<div class="flex gap-3">...</div>
<div class="flex flex-col">...</div>
<!-- Grid 布局 -->
<div class="grid grid-cols-2 gap-4">...</div>
```
### 尺寸
```vue
<!-- 宽度 -->
<div class="w-full">全宽</div>
<div class="w-1/2">一半宽</div>
<div class="flex-1">自适应</div>
<!-- 高度 -->
<div class="h-[88rpx]">固定高度</div>
<div class="min-h-[100rpx]">最小高度</div>
```
### 间距
```vue
<!-- Padding -->
<div class="p-4">四周内边距</div>
<div class="px-4 py-2">水平+垂直内边距</div>
<!-- Margin -->
<div class="mb-4">下边距</div>
<div class="mx-auto">水平居中</div>
<!-- Gap (flex/grid 子元素间距) -->
<div class="gap-3">子元素间距</div>
```
### 文字
```vue
<!-- 大小 -->
<div class="text-[30rpx]">30rpx</div>
<div class="text-lg">大号</div>
<div class="text-sm">小号</div>
<!-- 颜色 -->
<div class="text-gray-900">深灰</div>
<div class="text-blue-600">蓝色</div>
<div class="text-red-500">红色</div>
<!-- 对齐 -->
<div class="text-left">左对齐</div>
<div class="text-center">居中</div>
<div class="text-right">右对齐</div>
```
### 圆角和边框
```vue
<!-- 圆角 -->
<div class="rounded-[16rpx]">16rpx 圆角</div>
<!-- 边框 -->
<div class="border border-gray-200">边框</div>
```
## 样式覆盖技巧
### 深度选择器
```vue
<style lang="less" scoped>
// 修改 NutUI 组件内部样式
:deep(.nut-button) {
border-radius: 16rpx !important;
}
:deep(.nut-tabs__titles) {
display: none;
}
</style>
```
### TailwindCSS + !important
```vue
<template>
<!-- 使用 ! 覆盖 TailwindCSS 样式 -->
<nut-button class="!h-[88rpx] !rounded-[16rpx] !text-[30rpx]">
按钮
</nut-button>
</template>
```
## 最后更新
- **更新时间**: 2026-02-10
- **维护者**: Claude Code
- **Taro 版本**: 4.1.11
- **NutUI 版本**: 4.3.14