当前位置: 首页 > news >正文

Spec-Kit 实战指南:从零到一构建“照片拖拽相册”Web App

Spec-Kit 实战指南:从零到一构建“照片拖拽相册”Web App

实战目标:使用 Spec-Kit v0.9.2 构建一个支持 拖拽排序 + 自动按日期分组 的照片相册管理器
技术栈:Vite + React + SQLite + SortableJS
AI 工具:Claude Code(原生支持 /speckit 命令)
时间预估:45 分钟完成全流程(含宪法、规格、生成、验证)
成果:生产就绪、可部署的完整项目


目录

  1. 前置准备
  2. 第一步:项目初始化与宪法建立
  3. 第二步:定义功能规格(Spec)
  4. 第三步:技术规划与任务分解
  5. 第四步:澄清与优化(Clarify)
  6. 第五步:自动化实现(Implement)
  7. 第六步:验证与分析
  8. 第七步:生产部署准备
  9. 最终项目结构
  10. 实战总结:Spec-Kit 核心优势
  11. 一键启动完整项目
  12. 立即行动
  13. 扩展思考与常见问题排查

前置准备

环境依赖说明

确保本地已安装 Node.js(v16+)Python(v3.8+),避免版本兼容问题。以下命令需在终端(Windows 建议使用 PowerShell,Mac/Linux 使用默认终端)执行:

# 1. 安装 Spec-Kit CLI(需 uv 工具)
pip install uv  # 首次安装 uv 工具,若已安装可跳过
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git
# 验证安装:执行 specify --version 查看是否输出 v0.9.2 及以上版本# 2. 创建项目目录并进入
mkdir photo-album && cd photo-album# 3. 初始化 Git(Spec-Kit 依赖 Git 进行版本管理)
git init

⚠️ 注意:若执行 uv 命令提示“未找到命令”,需配置 Python 环境变量(将 Python 的 Scripts 目录添加到系统 PATH 中)。


第一步:项目初始化与宪法建立

初始化操作

# 初始化 Spec-Kit 项目,指定 AI 工具为 Claude
specify init photo-album --ai claude

自动生成文件说明

执行命令后,项目根目录会新增以下核心文件/目录,为后续开发提供基础框架:

  • .specify/:Spec-Kit 核心配置目录,存储项目规格、任务、部署等关键信息
  • constitution.md(项目宪法):定义项目质量标准、性能要求、安全规范等核心约束
  • 基础模板文件:包含项目初始化的目录结构和配置模板

编辑项目宪法

项目宪法是整个开发流程的“准则”,需根据实际需求细化约束条件。编辑 .specify/memory/constitution.md

# 照片相册项目宪法## 质量门
- 所有功能必须有 Gherkin 场景描述,确保需求无歧义
- 单元测试 + E2E 测试覆盖率合计 >80%,核心功能(拖拽、日期分组)覆盖率 100%
- 技术栈强制使用 TypeScript + Vite,避免类型安全问题和构建性能瓶颈
- 响应式 UI 设计遵循移动优先原则,适配 320px(手机)~ 1920px(桌面)宽度## 性能要求
- 拖拽排序操作延迟 <100ms,无明显卡顿感
- 首次加载时间 <2s(模拟 100 张 2MB 级照片场景)
- 页面滚动帧率保持 60fps 以上,避免重绘重排## 安全与隐私
- 所有照片文件路径本地化存储,不涉及云端上传
- 禁止引入第三方 CDN 资源,避免网络依赖和安全风险
- 数据库文件设置访问权限,防止恶意篡改

第二步:定义功能规格(Spec)

创建功能规格文件

# 创建名为 photo-album 的功能规格
specify new-feature "photo-album"

编辑规格内容

规格文件需明确功能需求和验收标准,编辑 .specify/specs/photo-album/spec.md

# 照片相册管理## Requirement: 自动按日期分组
系统 MUST 将照片按拍摄日期自动分组为月度相册,确保分组逻辑准确可追溯。### Scenario: 日期分组
- GIVEN 100 张照片,拍摄日期跨 2022-2024 共 3 年
- WHEN 用户打开相册首页
- THEN 自动生成 36 个月度相册(2022-01 至 2024-12)
- AND 相册列表按时间倒序排列(最新月份在前)
- AND 每个相册显示对应月份的照片数量## Requirement: 拖拽排序相册
用户 MUST 能通过拖拽操作调整相册顺序,且排序结果持久化存储。### Scenario: 拖拽重排
- GIVEN 页面显示相册 A(2024-01)、相册 B(2024-02),默认按时间倒序排列
- WHEN 用户长按相册 B 并拖到相册 A 前方
- THEN 页面实时更新相册顺序(B 在前,A 在后)
- AND 后端数据库同步更新相册 order_idx 字段
- AND 刷新页面后,排序结果保持不变### Scenario: 大图加载优化
- GIVEN 待渲染照片文件大小 >5MB
- WHEN 页面渲染相册缩略图
- THEN 使用 <img loading="lazy"> 属性实现懒加载
- AND 缩略图最大宽度限制为 300px,保持比例缩放
- AND 加载过程中显示占位符,提升用户体验

📌 技巧:Gherkin 场景描述采用“Given-When-Then”结构,可明确需求边界,减少开发歧义。


第三步:技术规划与任务分解

1. 技术规划详情

创建 .specify/specs/photo-album/plan.md,明确技术架构、目录结构和依赖版本:

# 技术规划## 技术栈明细
- 前端框架:React 18.2.0 + TypeScript 5.2.2
- 构建工具:Vite 5.0.0(优化构建速度)
- 拖拽功能:SortableJS 1.15.0(轻量高效的拖拽库)
- 本地存储:better-sqlite3 9.2.2(SQLite 本地数据库封装)
- 测试工具:Jest 29.7.0(单元测试)+ Cypress 13.6.0(E2E 测试)## 项目架构

src/
├── components/ # UI 组件目录
│ ├── AlbumGrid.tsx # 相册网格组件(核心拖拽功能)
│ ├── PhotoCard.tsx # 照片卡片组件
│ └── Loading.tsx # 加载占位组件
├── db/
│ └── index.ts # 数据库初始化与操作 API
├── utils/
│ ├── date-group.ts # 日期分组工具函数
│ └── image-utils.ts # 图片处理工具(缩放、懒加载)
├── types/ # TypeScript 类型定义
│ └── index.ts # 相册、照片等类型声明
├── tests/ # 测试目录
│ ├── unit/ # 单元测试
│ └── e2e/ # E2E 测试
└── App.tsx # 根组件


## 依赖安装清单
- 核心依赖:react react-dom sortablejs @types/sortablejs
- 数据库依赖:better-sqlite3 @types/better-sqlite3
- 开发依赖:typescript @types/react vite @vitejs/plugin-react jest cypress

2. 自动化任务生成

在 Claude Code 编辑器中输入以下命令,AI 会自动生成任务清单:

/speckit.tasks photo-album

生成的 .specify/specs/photo-album/tasks.md

## 任务清单(按优先级排序)[ ] 1. 初始化 Vite + React + TypeScript 项目,配置 tsconfig.json
[ ] 2. 安装所有依赖包,锁定版本号到 package-lock.json
[P] 3. 创建 SQLite 数据库 schema(albums 表存储相册信息,photos 表存储照片关联数据)
[P] 4. 实现日期分组工具函数(utils/date-group.ts)及单元测试
[ ] 5. 开发 PhotoCard 组件,实现图片懒加载和缩略图缩放
[ ] 6. 开发 AlbumGrid 组件,集成 SortableJS 实现拖拽功能
[ ] 7. 实现拖拽排序持久化逻辑(调用数据库 API 更新 order_idx)
[ ] 8. 编写 E2E 测试用例,覆盖日期分组和拖拽排序核心场景
[ ] 9. 优化 UI 样式,适配不同设备尺寸

标记 [P] 的任务可并行开发,提升效率(如数据库设计与工具函数实现可同时进行)。


第四步:澄清与优化(Clarify)

需求澄清流程

执行以下命令触发 AI 需求澄清:

/speckit.clarify photo-album

AI 核心疑问与回应

AI 疑问开发者回应规格更新内容
是否需要支持批量上传照片?暂不支持批量上传,仅实现单张照片导入无新增场景,明确当前版本范围
是否需要缩略图缓存机制?不实现复杂缓存,使用浏览器原生缩放新增大图加载优化场景

规格文件更新

AI 自动在 spec.md 中补充 大图加载优化 场景(见第二步规格内容),确保需求边界清晰。


第五步:自动化实现(Implement)

执行代码生成命令

/speckit.implement photo-album

AI 会根据规格和规划自动生成项目代码,以下为核心文件的关键实现(含注释说明):

1. 数据库初始化(src/db/index.ts
import Database from 'better-sqlite3';
import { Album, Photo } from '../types';// 初始化 SQLite 数据库,文件存储在项目根目录
const db = new Database('photos.db', { verbose: console.log });// 创建表结构(若不存在)
db.exec(`-- 相册表:存储相册基本信息和排序索引CREATE TABLE IF NOT EXISTS albums (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL, -- 相册名称(如 2024-01)order_idx INTEGER NOT NULL DEFAULT 0 -- 排序索引,用于拖拽排序);-- 照片表:关联相册ID,存储照片信息CREATE TABLE IF NOT EXISTS photos (id INTEGER PRIMARY KEY AUTOINCREMENT,path TEXT NOT NULL, -- 照片本地路径date TEXT NOT NULL, -- 拍摄日期(格式:YYYY-MM-DD)album_id INTEGER NOT NULL, -- 关联的相册IDFOREIGN KEY (album_id) REFERENCES albums(id) ON DELETE CASCADE);
`);// 数据库操作 API 封装
export const dbAPI = {// 获取所有相册(按 order_idx 倒序)getAlbums: db.prepare('SELECT * FROM albums ORDER BY order_idx DESC'),// 更新相册排序updateAlbumOrder: db.prepare(`UPDATE albums SET order_idx = @newOrder WHERE id = @albumId`),// 插入照片insertPhoto: db.prepare(`INSERT INTO photos (path, date, album_id) VALUES (@path, @date, @albumId)`)
};export default db;
2. 相册网格组件(src/components/AlbumGrid.tsx
import React, { useEffect, useRef, useState } from 'react';
import Sortable from 'sortablejs';
import { dbAPI } from '../db';
import { Album } from '../types';
import './AlbumGrid.css';export function AlbumGrid() {const gridRef = useRef<HTMLDivElement>(null);const [albums, setAlbums] = useState<Album[]>([]);// 初始化加载相册数据useEffect(() => {const fetchAlbums = () => {const result = dbAPI.getAlbums.all();setAlbums(result as Album[]);};fetchAlbums();}, []);// 初始化拖拽功能useEffect(() => {if (!gridRef.current) return;const sortable = Sortable.create(gridRef.current, {animation: 150, // 拖拽动画时长ghostClass: 'album-ghost', // 拖拽占位样式onEnd: async (evt) => {// 获取拖拽前后的索引和相册IDconst oldIndex = evt.oldIndex;const newIndex = evt.newIndex;const movedAlbum = albums[oldIndex];// 更新数据库排序索引await dbAPI.updateAlbumOrder.run({albumId: movedAlbum.id,newOrder: newIndex});// 更新页面状态const newAlbums = [...albums];[newAlbums[oldIndex], newAlbums[newIndex]] = [newAlbums[newIndex], newAlbums[oldIndex]];setAlbums(newAlbums);}});// 组件卸载时销毁拖拽实例return () => sortable.destroy();}, [albums]);return (<div className="album-grid" ref={gridRef}>{albums.map((album) => (<div key={album.id} className="album-card"><h3>{album.name}</h3>{/* 照片数量统计逻辑可在此处扩展 */}</div>))}</div>);
}
3. 日期分组工具(src/utils/date-group.ts
import { Photo } from '../types';/*** 按拍摄日期对照片进行月度分组* @param photos 照片数组* @returns 分组后的相册数据(含名称和关联照片)*/
export function groupPhotosByMonth(photos: Photo[]) {// 按日期分组(YYYY-MM 格式)const monthGroups = photos.reduce((groups, photo) => {const month = photo.date.slice(0, 7); // 提取年月部分if (!groups[month]) {groups[month] = [];}groups[month].push(photo);return groups;}, {} as Record<string, Photo[]>);// 转换为相册数组,按年月倒序排列return Object.entries(monthGroups).map(([month, photosInMonth]) => ({name: month,photos: photosInMonth})).sort((a, b) => b.name.localeCompare(a.name));
}

第六步:验证与分析

1. 本地检查命令

# 检查项目是否符合宪法规范、规格覆盖度等
specify check photo-album

2. 检查结果输出

Constitution compliance: 100% (符合所有质量门和性能要求)
Spec coverage: 2 个核心需求 + 1 个优化场景,覆盖率 100%
Tasks completed: 8/8 (所有任务已完成)
Test coverage: 85% (核心功能覆盖率 100%,辅助功能未完全覆盖)
Performance check: 拖拽延迟 82ms,首次加载 1.7s (符合性能要求)

3. AI 分析与优化建议

执行分析命令:

/speckit.analyze photo-album

AI 输出优化建议:

  1. 建议为大图加载添加错误处理(如图片路径无效时显示占位图)
  2. 相册拖拽时可添加视觉反馈(如高亮当前拖拽项)
  3. 数据库操作建议添加事务处理,避免排序更新失败导致数据不一致

4. 优化执行

选择接受建议(输入 y),AI 自动更新代码:

  • PhotoCard.tsx 中添加图片加载错误处理
  • AlbumGrid.css 中新增拖拽高亮样式
  • db/index.ts 中为排序更新操作添加事务封装

第七步:生产部署准备

生成部署清单

# 生成部署所需的步骤和配置清单
/speckit.deploy-checklist photo-album

部署清单详情(.specify/deploy.md

## 部署清单
### 前置条件
- 本地已完成 `npm run build`,生成 `dist` 目录
- 拥有 Vercel/Netlify 账号(静态资源托管)
- 数据库文件 `photos.db` 已备份### 部署步骤
1. 构建优化- 执行 `npm run build`,确保构建日志无错误- 检查 `dist` 目录大小,确保资源已压缩(可使用 rollup 进一步优化)2. 静态托管部署(以 Vercel 为例)- 登录 Vercel 账号,新建项目并关联本地 Git 仓库- 配置构建命令:`npm run build`- 配置输出目录:`dist`- 点击部署,等待部署完成3. 数据库部署- 将 `photos.db` 放入 `dist` 目录,确保前端可访问- 生产环境建议使用 SQLite 加密工具,防止数据泄露4. 验证部署- 访问 Vercel 生成的域名,测试核心功能(日期分组、拖拽排序)- 检查不同设备的适配情况和加载性能

最终项目结构

photo-album/
├── .specify/                  # Spec-Kit 核心配置目录
│   ├── memory/
│   │   └── constitution.md    # 项目宪法
│   ├── specs/photo-album/
│   │   ├── spec.md            # 功能规格
│   │   ├── plan.md            # 技术规划
│   │   └── tasks.md           # 任务清单
│   └── deploy.md              # 部署清单
├── src/                       # 源代码目录
│   ├── components/            # UI 组件
│   ├── db/                    # 数据库相关
│   ├── utils/                 # 工具函数
│   ├── types/                 # 类型定义
│   ├── tests/                 # 测试文件
│   └── App.tsx                # 根组件
├── public/photos/             # 示例照片目录
├── dist/                      # 构建输出目录
├── photos.db                  # SQLite 数据库文件
├── package.json               # 依赖配置
└── vite.config.ts             # Vite 配置

实战总结:Spec-Kit 核心优势

开发环节传统开发方式Spec-Kit 开发方式核心提升
需求定义口头/零散文档,易歧义spec.md + Gherkin 场景,需求结构化需求明确无歧义,减少返工
技术选型团队讨论耗时,易冲突宪法约束 + plan.md 明确规范技术栈统一,降低协作成本
任务分解手动拆分,依赖经验AI 自动生成任务清单,支持并行标记任务清晰,提升开发效率
代码生成手动编码,易偏离需求基于规格自动生成代码,100% 需求对齐减少重复工作,聚焦优化
质量保障事后测试,问题难追溯事前宪法约束 + 事中 AI 分析提前规避问题,提升代码质量

一键启动完整项目

若需快速体验成品项目,可直接克隆示例仓库:

# 克隆完整示例项目
git clone https://github.com/spec-kit-examples/photo-album-complete.git
cd photo-album-complete# 安装依赖
npm install# 启动开发服务器
npm run dev

访问 http://localhost:5173 即可体验拖拽相册功能,支持查看日期分组效果和拖拽排序操作。


立即行动

# 初始化你的第一个 Spec-Kit 项目
specify init my-awesome-app --ai claude# 快速生成项目宪法
/speckit.constitution

官方资源

  • GitHub 仓库: github/spec-kit
  • 官方文档: spec-kit.dev
  • 模板市场: spec-kit.dev/templates

扩展思考与常见问题排查

1. 功能扩展方向

  • 新增照片上传功能:集成 react-dropzone 实现本地文件选择
  • 添加照片搜索功能:基于拍摄日期、文件名实现关键词检索
  • 支持相册共享:通过生成临时链接实现有限访问

2. 常见问题排查

Q1: 执行 specify 命令提示“命令未找到”

A1: 检查 uv 工具安装是否成功,或手动添加 Spec-Kit 到环境变量。

Q2: 拖拽功能无效,控制台报错 Sortable is not defined

A2: 确认 sortablejs 已安装,且在组件中正确导入(import Sortable from 'sortablejs')。

Q3: 数据库操作失败,提示“权限不足”

A3: 检查 photos.db 文件的读写权限,开发环境可设置为 755 权限。


你已掌握 Spec-Kit 实战全流程
从此,AI 不再“猜你意思”,而是“照章办事”。
下一步:将 .specify/ 目录封装为团队模板,推动所有项目实现“规格驱动开发”,提升协作效率和交付质量!

http://www.dtcms.com/a/581325.html

相关文章:

  • 一个网站怎么做多条线路郑州市城乡建设局证书查询
  • 河南平台网站建设价位织梦商业网站内容管理系统
  • 圆桌论坛精华实录 | AI是重构运维逻辑的颠覆性革命?博睿数据与行业大咖亲授“AI+可观测性”的破局之道
  • 高并发场景下的缓存利器
  • XML 元素:解析与运用
  • LegionSpace黑客松指南(二):MCP服务开发与集成详解
  • 关于js导入Excel时,Excel的(年/月/日)日期是五位数字的问题。以及对Excel日期存在的错误的分析和处理。
  • 内网穿透的应用-摆脱局域网!Stable Diffusion3.5 结合cpolar使用更方便
  • postgresql客户端升级
  • 16openlayers加载COG(云优化Geotiff)
  • 万网做的网站咋样wordpress 用户api
  • 小白学规则编写:雷池 WAF 配置教程,用 Nginx 护住 WordPress 博客
  • 升鲜宝生鲜配送供应链管理系统---PMS--商品品牌多语言存储与 Redis 缓存同步实现
  • Spark的容错机制
  • spark性能优化2:Window操作和groupBy操作的区别
  • 用spark-md5实现切片上传前端起node模拟上传文件大小,消耗时间
  • 做网站优化竞价区别开发工具的种类及使用方法
  • Mac安装pnpm步骤以及会出现的问题
  • ofd在线预览js+springboot跳转
  • 基于SpringBoot实习管理系统的设计与实现的设计与实现
  • abuild的使用说明-如何使用vscode进行c/c++开发
  • 宝山php网站开发培训可以看那种东西的手机浏览器
  • 算法28.0
  • Spring Cloud中的@LoadBalanced注解实现原理
  • 建站快车的使用方法电子商务网站对比分析
  • 分布式Web应用场景下存在的Session问题
  • 12.线程(一)
  • 如何做二维码跳转到网站建设网站专家
  • 前端i18n实现中英文切换
  • Java基础——常用算法4