Files
CheckInApp/docs/development.md
T
2026-01-03 19:34:20 +08:00

8.2 KiB

开发指南

开发环境设置

后端开发

# 克隆项目
git clone <repository>
cd CheckInApp

# 创建虚拟环境
python -m venv venv
source venv/bin/activate  # Linux/Mac
venv\Scripts\activate     # Windows

# 安装依赖
pip install -r backend/requirements.txt

# 安装开发依赖
pip install pytest pytest-asyncio black flake8

python3 run.py

前端开发

cd frontend

# 安装依赖
npm install

# 启动开发服务器
npm run dev

# 代码格式化
npm run lint
npm run format

项目结构

后端目录说明

backend/
├── main.py              # FastAPI 应用入口,CORS、路由注册
├── config.py            # Pydantic Settings 配置
├── dependencies.py      # 依赖注入(认证、权限)
├── exceptions.py        # 自定义异常类
│
├── models/              # SQLAlchemy 数据模型
│   ├── database.py      # 数据库连接、Session
│   ├── user.py
│   ├── check_in_task.py
│   ├── check_in_record.py
│   └── task_template.py
│
├── schemas/             # Pydantic 请求响应模型
│   ├── user.py
│   ├── task.py
│   ├── auth.py
│   └── response.py      # 标准化响应
│
├── api/                 # API 路由(按模块划分)
│   ├── auth.py          # 认证相关
│   ├── users.py         # 用户管理
│   ├── tasks.py         # 任务管理
│   ├── check_in.py      # 打卡功能
│   ├── admin.py         # 管理员功能
│   └── templates.py     # 模板管理
│
├── services/            # 业务逻辑层
│   ├── auth_service.py
│   ├── user_service.py
│   ├── task_service.py
│   ├── check_in_service.py
│   ├── scheduler_service.py
│   ├── template_service.py
│   └── registration_manager.py
│
└── workers/             # Selenium 自动化
    ├── token_refresher.py    # QQ 登录
    ├── check_in_worker.py    # 打卡执行
    └── email_notifier.py     # 邮件发送

前端目录说明

frontend/src/
├── main.js              # Vue 应用入口
├── App.vue              # 根组件
│
├── api/                 # API 封装
│   ├── client.js        # Axios 实例、拦截器
│   └── index.js         # API 模块(auth, user, task 等)
│
├── views/               # 页面组件
│   ├── LoginView.vue
│   ├── DashboardView.vue
│   ├── TasksView.vue
│   ├── RecordsView.vue
│   └── admin/           # 管理员页面
│
├── components/          # 可复用组件
│   ├── TaskCard.vue
│   ├── RecordTable.vue
│   └── ...
│
├── stores/              # Pinia 状态管理
│   ├── auth.js          # 认证状态
│   ├── user.js          # 用户信息
│   └── task.js          # 任务列表
│
├── router/              # Vue Router
│   └── index.js         # 路由配置、导航守卫
│
└── composables/         # 组合式函数
    ├── useAuth.js
    └── useTask.js

开发流程

添加新功能

1. 后端 API 开发

步骤:

  1. models/ 定义数据模型
  2. schemas/ 定义请求响应模型
  3. services/ 实现业务逻辑
  4. api/ 创建路由端点
  5. main.py 注册路由

示例: 添加一个新的"任务标签"功能

# models/task_tag.py
class TaskTag(Base):
    __tablename__ = "task_tags"
    id = Column(Integer, primary_key=True)
    task_id = Column(Integer, ForeignKey("check_in_tasks.id"))
    tag_name = Column(String(50))

# schemas/tag.py
class TaskTagCreate(BaseModel):
    tag_name: str

# services/tag_service.py
def create_tag(db: Session, task_id: int, tag_data: TaskTagCreate):
    tag = TaskTag(task_id=task_id, tag_name=tag_data.tag_name)
    db.add(tag)
    db.commit()
    return tag

# api/tags.py
@router.post("/tasks/{task_id}/tags")
def add_tag(task_id: int, tag: TaskTagCreate, db: Session = Depends(get_db)):
    return tag_service.create_tag(db, task_id, tag)

# main.py
from api import tags
app.include_router(tags.router, prefix="/api")

2. 前端开发

步骤:

  1. api/index.js 添加 API 调用
  2. stores/ 创建或更新状态
  3. 创建或更新 Vue 组件
  4. 配置路由(如需要)

示例: 添加标签管理页面

// api/index.js
export const tagApi = {
  addTag: (taskId, data) => client.post(`/tasks/${taskId}/tags`, data),
  getTags: (taskId) => client.get(`/tasks/${taskId}/tags`)
}

// stores/tag.js
export const useTagStore = defineStore('tag', {
  state: () => ({
    tags: []
  }),
  actions: {
    async fetchTags(taskId) {
      const { data } = await tagApi.getTags(taskId)
      this.tags = data
    }
  }
})

// components/TagManager.vue
<template>
  <div>
    <a-tag v-for="tag in tags" :key="tag.id">{{ tag.tag_name }}</a-tag>
    <a-button @click="addTag">添加标签</a-button>
  </div>
</template>

数据库迁移

# 修改模型后生成迁移脚本
# 手动创建脚本在 backend/scripts/migrate_*.py

# 执行迁移
python backend/scripts/migrate_xxx.py

测试

后端测试

# tests/test_task_service.py
import pytest
from backend.services import task_service

def test_create_task():
    task = task_service.create_task(db, user_id=1, task_data)
    assert task.name == "Test Task"
    assert task.is_active == True

# 运行测试
pytest backend/tests/

前端测试

// tests/TaskCard.spec.js
import { mount } from '@vue/test-utils'
import TaskCard from '@/components/TaskCard.vue'

test('displays task name', () => {
  const wrapper = mount(TaskCard, {
    props: { task: { name: 'Test Task' } }
  })
  expect(wrapper.text()).toContain('Test Task')
})

// 运行测试
npm run test

代码规范

后端规范

  • 使用 Black 格式化: black backend/
  • 遵循 PEP 8
  • 函数添加类型注解
  • API 路由使用 Pydantic 模型验证
  • 使用 dependency injection
# 好的示例
async def create_task(
    task_data: TaskCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
) -> TaskResponse:
    """创建新任务"""
    return task_service.create_task(db, current_user.id, task_data)

前端规范

  • 使用 ESLint + Prettier
  • 组件使用 Composition API
  • 使用 <script setup> 语法
  • Props 添加类型验证
  • 统一使用 Ant Design Vue 组件
<!-- 好的示例 -->
<script setup>
import { ref, computed } from 'vue'

const props = defineProps({
  task: {
    type: Object,
    required: true
  }
})

const isActive = computed(() => props.task.is_active)
</script>

调试技巧

后端调试

# 使用 logging
import logging
logger = logging.getLogger(__name__)
logger.info(f"Creating task for user {user_id}")

# 使用 pdb
import pdb; pdb.set_trace()

# 查看 SQL 查询
import logging
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

前端调试

// 使用 Vue Devtools
// Chrome 扩展安装

// console 输出
console.log('Task data:', task.value)

// 调试 API 请求
axios.interceptors.request.use(request => {
  console.log('Request:', request)
  return request
})

常见问题

CORS 错误

.env 添加前端地址:

CORS_ORIGINS=http://localhost:3000

数据库锁定

使用 connection pool:

engine = create_engine(
    DATABASE_URL,
    pool_pre_ping=True,
    pool_size=10
)

Selenium 超时

增加等待时间:

WebDriverWait(driver, 30).until(...)

Git 工作流

# 创建功能分支
git checkout -b feature/task-tags

# 提交代码
git add .
git commit -m "feat: add task tag functionality"

# 合并到主分支
git checkout main
git merge feature/task-tags

# 推送
git push origin main

性能优化

后端优化

  • 使用 SQLAlchemy 的 joinedload 避免 N+1 查询
  • 添加数据库索引
  • 使用异步任务处理耗时操作
  • 启用 gzip 压缩

前端优化

  • 使用虚拟滚动处理大列表
  • 路由懒加载
  • 图片懒加载
  • 使用 keep-alive 缓存组件