一、类型系统的重要性
-
类型安全保障
- 在编译时捕获错误,减少运行时异常
- 确保数据结构一致性,从数据库到 UI 的全链路类型检查
- 提供代码自动完成和智能提示,提高开发效率
-
类型定义分层
- 数据库层(SQL):定义物理数据结构和关系
- Supabase 类型层(supabase.ts):自动生成的数据库类型映射
- 业务类型层(types/):扩展数据库类型,添加业务逻辑
- API 接口层:定义请求和响应类型
- UI 组件层:定义表单和视图相关类型
二、核心文件和目录作用
-
数据库定义(用户管理.sql)
- 表结构定义(departments, roles, profiles 等)
- 视图创建(view_user_details, view_user_roles)
- 触发器和函数(update_modified_column, handle_new_user)
- 行级安全策略(RLS)设置
-
Supabase 类型(supabase.ts)
- 自动生成的数据库结构完整映射
- 提供 Tables, TablesInsert, TablesUpdate 等辅助类型
- 定义表与表之间的关系(Relationships)
- 通过
npx supabase gen types
命令更新
-
业务类型目录(types/)
- index.ts:集中导出所有类型
- system/:系统模块类型(profile, department, role 等)
- common/:通用类型(API 响应、分页、错误类型等)
- 业务模块/:其他业务模块的类型定义
-
API 服务层(api/)
- 封装与 Supabase 的通信
- 实现 CRUD 操作和复杂查询
- 处理错误和响应格式化
- 使用 types/ 定义的类型作为参数和返回值
-
状态管理(stores/)
- 使用 Pinia 管理全局状态
- 调用 API 方法获取和修改数据
- 维护 UI 状态(加载、错误等)
- 提供计算属性和操作方法
-
视图层(views/)
- 使用组件渲染 UI
- 通过 stores/ 获取和操作数据
- 处理用户交互和表单提交
- 使用类型保证模板和数据一致性
三、完整数据流程
1. 开发流程
-
数据库设计与更新
- 编写 SQL 创建或修改表结构
- 在 Supabase 中执行 SQL 或使用迁移工具
-
类型生成与扩展
- 运行
npx supabase gen types
更新 supabase.ts - 更新业务类型定义,扩展数据库类型
- 运行
-
API 服务实现
- 基于最新类型定义,实现或更新 API 方法
- 使用 Supabase 客户端执行查询和操作
-
状态管理更新
- 更新 Pinia store,使用新的类型和 API 方法
- 实现业务逻辑和状态管理
-
UI 组件开发
- 基于类型和状态创建或更新组件
- 实现用户交互和数据展示
2. 数据操作流程
创建数据流程:
- 用户在表单中输入数据
- 提交表单触发组件中的方法
- 组件调用 store 中的 action
- Store action 调用 API 服务方法
- API 服务使用 Supabase 客户端发送请求
- Supabase 执行数据库操作
- 响应沿原路径返回
- UI 更新展示结果
查询数据流程:
- 组件挂载或交互触发查询
- 组件调用 store 中的 action
- Store action 调用 API 服务方法
- API 服务构建查询并执行
- Supabase 返回查询结果
- API 服务格式化响应
- Store 更新状态
- 组件重新渲染展示数据
四、数据流程图
┌────────────────┐ ┌─────────────────┐ ┌──────────────────┐
│ │ │ │ │ │
│ 用户管理.sql │ │ supabase.ts │ │ types/*.ts │
│ (数据库定义) │─────▶│(自动生成类型映射)│─────▶│ (业务类型扩展) │
│ │ │ │ │ │
└────────────────┘ └─────────────────┘ └──────────┬───────┘
│
▼
┌────────────────┐ ┌─────────────────┐ ┌──────────────────┐
│ │ │ │ │ │
│ views/*.vue │◀─────│ stores/*.ts │◀─────│ api/*.ts │
│ (视图组件) │ │ (状态管理) │ │ (API服务) │
│ │ │ │ │ │
└───────┬────────┘ └────────┬────────┘ └──────────┬───────┘
│ │ │
└─────────────────────────▼───────────────────────────┘
│
▼
┌─────────────────┐
│ │
│ Supabase API │
│ │
└────────┬────────┘
│
▼
┌─────────────────┐
│ │
│ 数据库 │
│ │
└─────────────────┘
五、实际数据流示例
查询用户列表
1. views/system/ProfileList.vue:
- onMounted(() => profileStore.fetchProfiles(query))
2. stores/system/profile.ts:
- async fetchProfiles(query) { profiles.value = await getProfiles(query) }
3. api/system/profileService.ts:
- async getProfiles(query: ProfileQuery): Promise<Profile[]> {
const { data } = await supabase.from('profiles').select('*')
return data
}
4. Supabase 执行 SQL 查询:
- SELECT * FROM profiles WHERE ...
5. 数据返回至 Store:
- profiles.value = 查询结果
6. 组件重新渲染:
- <template><div v-for="profile in profileStore.profiles">...</div></template>
创建新用户
1. views/system/ProfileForm.vue:
- async handleSubmit() { await profileStore.saveProfile(formData) }
2. stores/system/profile.ts:
- async saveProfile(data) { return await createProfile(data) }
3. api/system/profileService.ts:
- async createProfile(data: CreateProfileRequest): Promise<Profile> {
const { data: profile } = await supabase.from('profiles').insert(data).select()
return profile
}
4. Supabase 执行 SQL 插入:
- INSERT INTO profiles (...) VALUES (...)
5. 数据返回至组件:
- router.push('/profiles') 跳转到列表页
六、核心优势总结
-
类型安全保障
- 编译时捕获错误,减少运行时异常
- IDE 提供智能提示和自动完成
- 类型即文档,减少注释需求
-
代码组织清晰
- 关注点分离,职责明确
- 逻辑复用,避免重复代码
- 模块化结构便于团队协作
-
业务逻辑扩展
- 基于数据库类型扩展业务类型
- 添加非数据库字段和计算属性
- 处理复杂数据结构如树形组织
-
全链路类型保障
- 从数据库到 UI 的一致性保证
- API 请求和响应类型明确
- 状态和组件的类型匹配
-
适应变更的能力
- 数据库变更时简单更新类型
- 类型错误提前暴露潜在问题
- 重构时可靠的类型检查支持
这种全链路类型驱动的开发模式是 Vue 3 + TypeScript + Supabase 项目的最佳实践,让应用更加健壮、可维护且易于扩展。
项目结构
---
description:
globs:
alwaysApply: true
---
project-root/
├── public/ # 静态资源
│ ├── favicon.ico # 网站图标
│ └── logo.png # 公司logo
├── src/ # 源代码
│ ├── assets/ # 资源文件
│ │ ├── images/ # 图片资源
│ │ └── styles/ # 样式文件
│ │ ├── variables.scss # SCSS变量
│ │ └── global.scss # 全局样式
│ ├── layouts/ # 布局组件
│ │ ├── MainLayout.vue # 主布局容器
│ │ └── BlankLayout.vue # 空白布局(登录页用)
│ ├── views/ # 页面视图(每个功能一个页面)
│ │ ├── Dashboard.vue # 首页/仪表盘
│ │ ├── indicators/ # 指标管理模块
│ │ │ └── IndicatorManage.vue # 指标管理(包含增删改查)
│ │ ├── accidents/ # 事故管理模块
│ │ │ └── AccidentManage.vue # 事故管理(包含增删改查)
│ │ ├── reports/ # 报表模块
│ │ │ └── ReportManage.vue # 报表管理(包含创建、查看)
│ │ └── system/ # 系统管理模块
│ │ ├── UserManage.vue # 用户管理
│ │ ├── RoleManage.vue # 角色管理
│ │ └── SystemSetting.vue # 系统设置
│ ├── services/ # 服务层(统一处理数据交互)
│ │ ├── supabase/ # Supabase服务
│ │ │ ├── client.ts # Supabase客户端配置
│ │ │ ├── auth.ts # 认证服务
│ │ │ └── storage.ts # 文件存储服务
│ │ ├── indicators/ # 指标服务
│ │ │ └── index.ts # 指标数据操作
│ │ ├── accidents/ # 事故服务
│ │ │ └── index.ts # 事故数据操作
│ │ ├── reports/ # 报表服务
│ │ │ └── index.ts # 报表数据操作
│ │ ├── system/ # 系统服务
│ │ │ ├── users.ts # 用户数据操作
│ │ │ └── roles.ts # 角色数据操作
│ │ └── hr/ # HR系统集成
│ │ └── index.ts # HR数据集成服务
│ ├── stores/ # Pinia状态管理
│ │ ├── index.ts # 状态管理入口
│ │ ├── indicators/ # 指标状态
│ │ │ └── index.ts # 指标状态管理
│ │ ├── accidents/ # 事故状态
│ │ │ └── index.ts # 事故状态管理
│ │ ├── reports/ # 报表状态
│ │ │ └── index.ts # 报表状态管理
│ │ └── system/ # 系统状态
│ │ ├── auth.ts # 认证状态
│ │ ├── users.ts # 用户状态
│ │ └── roles.ts # 角色状态
│ ├── utils/ # 工具函数
│ │ ├── formatters.ts # 格式化工具
│ │ └── calculations.ts # CCPS计算工具
│ ├── types/ # TypeScript类型
│ │ ├── index.ts # 类型导出入口
│ │ ├── database.ts # 数据库表类型(Supabase生成)
│ │ ├── enums.ts # 枚举类型定义
│ │ └── interfaces/ # 接口类型定义
│ │ ├── common.ts # 通用接口
│ │ ├── indicator.ts # 指标接口
│ │ ├── accident.ts # 事故接口
│ │ ├── report.ts # 报表接口
│ │ └── user.ts # 用户接口
│ ├── router/ # 路由配置
│ │ ├── index.ts # 路由入口
│ │ └── routes.ts # 路由定义
│ ├── App.vue # 根组件
│ └── main.ts # 入口文件
├── doc/ # 文档
│ ├── 技术方案.md # 技术方案文档
│ └── 项目构建历史.md # 项目构建历史
├── vite.config.ts # Vite配置
├── package.json # 项目依赖
└── README.md # 项目说明