Instruction file imported from pospynow/pindou (
.github/instructions/frontend.instructions.md). Copyright stays with the author.
前端开发规范
技术约束
- Vue 3 Composition API:所有组件使用
<script setup lang="ts">,禁止 Options API - Tailwind CSS:样式优先使用 Tailwind 类,复杂动画才写自定义 CSS
- Pinia:全局状态(当前颜色板、转换结果、加载状态)放 store,组件局部状态用
ref/reactive
手机适配规则
- 所有可交互元素最小高度
min-h-[44px],最小宽度min-w-[44px] - 字体
text-base(16px)起步,避免text-sm在输入区域(防止 iOS 自动缩放) - 布局默认单列 flex/grid,平板以上
md:前缀扩展 - 图片预览区域使用
aspect-square或aspect-[4/3]保持比例
图片上传组件规范
<!-- 支持拍照 + 相册的标准模板 -->
<input
type="file"
accept="image/jpeg,image/png,image/webp"
capture="environment"
@change="handleFileChange"
class="sr-only"
/>
- 拍照按钮和"从相册选择"分开提供(
capture属性存在时某些安卓只弹相机) - 选中后用
URL.createObjectURL()做本地预览,不要先上传 - 文件大小前端限制 ≤ 10MB,超出提示用户
Canvas 拼豆渲染
- 渲染逻辑封装在
src/composables/usePindouCanvas.ts - 每个格子:先填充颜色方块,可选绘制圆形(拼豆外观)和描边
- 支持导出:
canvas.toBlob()→ 触发下载或 Web Share API(手机分享)
// 格子渲染伪代码参考
function drawBead(ctx, x, y, size, color, style: 'square' | 'circle') {
ctx.fillStyle = color
if (style === 'circle') {
ctx.beginPath()
ctx.arc(x + size/2, y + size/2, size/2 - 1, 0, Math.PI * 2)
ctx.fill()
} else {
ctx.fillRect(x, y, size, size)
}
}
API 调用
- 统一在
src/api/convert.ts和src/api/palette.ts中封装 - 使用 axios,baseURL 通过
import.meta.env.VITE_API_BASE_URL注入 - 上传图片用
FormData,其余参数追加为表单字段
状态管理(Pinia)
stores/
├── useConvertStore.ts # 转换状态(result, loading, error)
├── usePaletteStore.ts # 颜色板列表和当前选择
└── useOptionStore.ts # 网格尺寸、拼豆大小等参数
TypeScript 类型
关键类型定义在 src/types/index.ts:
interface BeadColor { id: string; name: string; hex: string; rgb: [number, number, number] }
interface ColorPalette { id: string; name: string; beadSize: number; colors: BeadColor[] }
interface ConvertOptions { paletteId: string; gridWidth: number; gridHeight: number; beadSize: number; crop?: string }
interface ConvertResult { grid: string[][]; colorStats: Record<string, number>; previewUrl: string }