开发规范
开发规范
1. 代码风格
1.1 格式化(Prettier)
- 统一使用 Prettier 做代码格式化,避免手工调整风格。
- 配置文件:
.prettierrc.jsontabWidth: 4printWidth: 160semi: truesingleQuote: false(统一双引号)trailingComma: noneendOfLine: lf
- 命令:
npm run format(对src/执行写入式格式化)
1.2 代码规范检查(ESLint)
- 配置文件:
eslint.config.ts(flat config) - 启用规则集:
eslint-plugin-vue:flat/essential@vue/eslint-config-typescript:recommended@vue/eslint-config-prettier/skip-formatting:跳过与 Prettier 冲突的格式化规则
- 忽略目录:
dist/、dist-ssr/、coverage/ - 命令:
npm run lint(默认带--fix --cache)
1.3 类型检查(TypeScript / vue-tsc)
- 类型检查命令:
npm run type-check(vue-tsc --build) - 严格构建:
npm run build:strict(先类型检查,再构建) - 路径别名:
@/* -> src/*(见tsconfig.json/tsconfig.app.json)
1.4 开发/构建脚本(Vite)
npm run dev:本地开发npm run build:构建产物npm run preview:本地预览构建产物
1.5 换行、编码、尾空格(EditorConfig)
- 配置文件:
.editorconfig - 统一约束:
charset = utf-8trim_trailing_whitespace = trueend_of_line = lf
2. 命名与文件组织
2.1 命名规范
- 变量 / 函数:
camelCase - 类型:
PascalCase(UserInfo、PaginatedResult) - 组件:
PascalCase(UserCard.vue、LoginAgreement.vue) - 常量:
UPPER_SNAKE_CASE(仅对真正的常量使用)
2.2 文件与目录命名
- 页面目录(views):业务域用
kebab-case(如admin-merchant/、after-sales/) - 页面文件:
- 入口页统一
Index.vue - 详情页用
Detail.vue(如需要) - 表单页用
Form.vue(如需要)
- 入口页统一
- 组件文件:统一
PascalCase.vue - Hook / Composable 文件:
useXxx.ts(如useCrudPage.ts、useTenantPath.ts) - 导出聚合:目录
index.ts作为统一出口(如components/common/**/index.ts、stores/index.ts) - 禁止项:
- 文件名包含空格(例如
xxx copy.vue) - 文件名包含
copy、new等临时标记
- 文件名包含空格(例如
2.3 导入约定
- 路径优先用别名:
@/xxx,避免../../..。 - 类型导入:优先
import type { ... } from "..."。 - 环境变量读取:只从
import.meta.env读取。
3. Vue 组件开发规范
3.1 SFC 写法
- 默认使用:
<script setup lang="ts"> - 页面/组件命名:使用
defineOptions({ name: "Xxx" })(便于调试/KeepAlive/埋点) - Props / Emits:
- props 命名使用
camelCase(模板中可使用kebab-case) - 需要默认值的 props 必须给默认值
- props 命名使用
3.2 组件自动导入(Vort UI)
- 组件自动导入由
unplugin-vue-components+ 自定义解析器VortResolver实现(见vite.config.ts、src/components/vort/resolver.ts)。 - 允许两种写法(无需手动 import):
<vort-button />(kebab-case)<VortButton />(PascalCase)
- 类型声明文件:自动生成到
src/components.d.ts(不要手改,避免被覆盖)。
3.3 Teleport 挂载点
- 根组件
App.vue内提供#vort-teleport-container作为统一挂载点,弹层类组件应优先挂载到该容器,确保层级与 CSS 变量继承一致。
4. 路由规范(Vue Router)
4.1 路由组织
- 路由入口:
src/router/index.ts - 路由守卫:
src/router/guards.ts - 模块路由:
src/router/routes/**
4.2 多租户 URL 约定
- 多租户解析工具:
src/utils/business/tenant.ts - 关键原则:
- URL 是唯一上下文源:优先从 URL 解析
tenantId与adminType(token 解码后得到shop/vendor/...) - 需要租户的端必须在 URL 中同时包含
tenantId与adminType token,缺失视为旧链接并重定向 - 导航拼接租户前缀时使用
resolveTenantPath()/buildTenantPath(),不要手写字符串拼接
- URL 是唯一上下文源:优先从 URL 解析
4.3 路由守卫约定
- 白名单路由(无需登录):
/login - 未登录:无
accessToken时跳转/login - 动态菜单加载:首次进入需要按权限加载菜单并注入路由(由
menus相关 store/util 实现)
5. 状态管理规范(Pinia)
5.1 Store 组织
- store 入口:
src/stores/index.ts - 模块 store:
src/stores/modules/*.ts - 推荐写法:
defineStore("xxx", () => { ... })(Composition API store)
5.2 持久化与运行时上下文
- 使用
pinia-plugin-persistedstate。 - 仅持久化可跨标签共享的最小数据(当前约定:
accessToken、userInfo)。 - adminType 以 URL 为准:
- 不依赖 localStorage 的
adminType残留值 afterHydrate后从 URL 同步到 store
- 不依赖 localStorage 的
- 每标签页隔离的数据(例如店铺/供应商运行时信息)使用
sessionStorage,并以tenantId + adminType作为 key 维度隔离。
6. 请求与接口规范(Axios)
6.1 统一请求入口
- 统一封装:
src/api/request.ts - 再导出入口:
src/utils/request.ts(禁止绕开封装直接使用 axios)
6.2 环境变量与 baseURL
baseURL由环境变量拼接:VITE_BASE_URLVITE_REQUEST_URL_PREFIX(可被单次请求config.prefix覆盖)
6.3 环境变量清单(项目实际读取)
- 路由 base:
VITE_BASE_DIR(用于createWebHistory与 Vitebase) - 请求 base:
VITE_BASE_URL - 请求前缀:
VITE_REQUEST_URL_PREFIX - 默认登录账号(平台端):
VITE_DEFAULT_USER_NAMEVITE_DEFAULT_USER_PASSWORD
- 默认登录账号(商户端/门店端):
VITE_DEFAULT_STORE_NAMEVITE_DEFAULT_STORE_PASSWORD
6.3 请求头约定
satoken:从localStorage.accessToken读取X-ADMIN-TYPE:从 store 读取,URL 兜底X-ClIENT-TYPE:固定为admin- 多租户 header:
X-Shop-Id:商户端/门店端X-Vendor-Id:供应商端
6.4 FormData 上传
config.data为FormData时不手动设置Content-Type,避免 boundary 丢失。
6.5 响应结构与错误处理
- 统一响应结构(
src/types/api.d.ts):code: numbermessage: stringdata: T
- 成功条件:
code === 0 - 失败条件:
code > 0- 统一 reject,错误对象至少包含
code/message/data
- 统一 reject,错误对象至少包含
- 登录失效:
code === 401或 HTTP401/403:触发登出流程(userStore.logout())
- 禁止项:
- 页面中重复写
try/catch + toast逻辑(优先复用封装与统一提示) - 在业务层随意吞掉错误(除非明确标注“额外数据获取,不影响主流程”)
- 页面中重复写
7. 业务 Hook / 组合式函数规范
7.1 Hook 目录与职责
src/hooks/:面向页面/业务场景的 Hook(如useCrudPage、useDialogForm)src/composables/:更通用的组合式工具(如租户路径处理)
7.2 useCrudPage 约定(列表页统一模式)
useCrudPage负责:- 分页参数(
page/size)与列表加载 - 搜索提交与重置
- 表格排序
- 选中行与批量操作
- 分页参数(
- 失败提示使用
@/components/vort/message,避免各页自行实现重复提示逻辑。
8. 样式规范(Tailwind / SCSS / Less)
8.1 全局样式入口
src/assets/styles/index.css- Tailwind v4:
@import "tailwindcss"; - 动画库:
@import "tw-animate-css"; @theme inline/ CSS 变量作为主题映射基础
- Tailwind v4:
src/theme/index.scss- Vort 主题变量与全局覆盖(配合
variables.scss)
- Vort 主题变量与全局覆盖(配合
8.2 新增样式优先级
- 优先:Tailwind 工具类(与 CSS 变量配合)
- 需要全局一致时:写入
src/theme/index.scss - 仅影响当前组件时:
<style scoped>,跨组件覆盖使用:deep() - Less 使用场景:既有页面已使用
<style lang="less" scoped>,新增保持与页面一致即可
9. 注释与可维护性
9.1 注释风格
- 对外导出的函数/工具/复杂逻辑使用 JSDoc(含
@param、@returns、示例)。 - 注释目标:
- 解释“为什么这么做”(why),而不是重复代码本身(what)。
9.2 错误类型与 unknown
catch (error)后优先以unknown处理,再做最小必要的类型收窄/断言。- 避免把
any作为默认方案(除非在封装层做兼容兜底)。
10. 图片与截图(文档配图)
- 建议放置目录:
docs/文章文档/assets/ - 命名建议:
yyyyMMdd_模块_主题.png(例如20260128_登录_验证码流程.png)







