/frontend-dev
前端开发规范,包含 Vue 3 编码规范、UI 风格约束、TypeScript 规范等
$ npx -y skills add doccker/cc-use-exp --skill frontend-dev --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/frontend-dev
Context preview
The summary Claude sees to decide when to auto-load this skill.
前端开发规范,包含 Vue 3 编码规范、UI 风格约束、TypeScript 规范等
SKILL.md
frontend-dev.SKILL.mdname: frontend-dev
description: 前端开发规范,包含 Vue 3 编码规范、UI 风格约束、TypeScript 规范等
version: v3.0
paths:
- "**/*.vue"
- "**/*.tsx"
- "**/*.jsx"
- "**/*.ts"
- "**/*.js"
- "**/*.css"
- "**/*.scss"
- "**/*.less"
- "**/package.json"
- "**/vite.config.*"
前端开发规范
> 参考来源: Vue 官方风格指南、Element Plus 最佳实践
---
UI 风格约束
严格禁止(常见 AI 风格)
- ❌ 蓝紫色霓虹渐变、发光描边、玻璃拟态
- ❌ 大面积渐变、过多装饰性几何图形
- ❌ 赛博风、暗黑科技风、AI 风格 UI
- ❌ UI 文案中使用 emoji
后台系统(默认风格)
| 要素 | 要求 | |------|------| | 主题 | 使用组件库默认主题 | | 配色 | 黑白灰为主 + 1 个主色点缀 | | 动效 | 克制,仅保留必要交互反馈 |
---
技术栈
| 层级 | Vue(首选) | React(备选) | |------|------------|--------------| | 框架 | Vue 3 + TypeScript | React 18 + TypeScript | | 构建 | Vite | Vite | | 路由 | Vue Router 4 | React Router 6 | | 状态 | Pinia | Zustand | | UI 库 | Element Plus | Ant Design |
---
Vue 编码规范
组件基础
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import type { User } from '@/types'
// Props & Emits
const props = defineProps<{ userId: number }>()
const emit = defineEmits<{ (e: 'update', value: string): void }>()
// 响应式状态
const loading = ref(false)
const user = ref<User | null>(null)
// 计算属性
const displayName = computed(() => user.value?.name ?? '未知用户')
// 生命周期
onMounted(async () => { await fetchUser() })
// 方法
async function fetchUser() {
loading.value = true
try {
user.value = await api.getUser(props.userId)
} finally {
loading.value = false
}
}
</script>
<template>
<div class="user-card">
<h3>{{ displayName }}</h3>
</div>
</template>
<style scoped>
.user-card { padding: 16px; }
</style>命名约定
| 类型 | 约定 | 示例 | |------|------|------| | 组件文件 | PascalCase.vue | `UserCard.vue` | | Composables | useXxx.ts | `useAuth.ts` | | Store | useXxxStore.ts | `useUserStore.ts` |
---
状态管理(Pinia)
// stores/user.ts
export const useUserStore = defineStore('user', () => {
const user = ref<User | null>(null)
const token = ref<string>('')
const isLoggedIn = computed(() => !!token.value)
async function login(username: string, password: string) {
const res = await api.login(username, password)
token.value = res.token
user.value = res.user
}
return { user, token, isLoggedIn, login }
})---
交互状态处理
**必须处理的状态**: loading、empty、error、disabled、submitting
<template>
<el-skeleton v-if="loading" :rows="5" animated />
<el-result v-else-if="error" icon="error" :title="error">
<template #extra>
<el-button @click="fetchData">重试</el-button>
</template>
</el-result>
<el-empty v-else-if="list.length === 0" description="暂无数据" />
<template v-else>
<!-- 正常内容 -->
</template>
</template>---
TypeScript 规范
// types/user.ts
export interface User {
id: number
username: string
role: 'admin' | 'user'
}
export interface ApiResponse<T = unknown> {
code: number
message: string
data: T
}---
API 调用类型安全
| 规则 | 说明 | |------|------| | ✅ API 工具函数支持泛型 | `get<T>(url): Promise<T>` 而非返回 `unknown` | | ✅ 调用处指定泛型或断言 | `get<UserInfo>(url)` 或 `data as typeof ref.value` | | ❌ 禁止 `as any` 绕过 | 掩盖类型问题,后续维护踩坑 |
// ❌ get() 返回 unknown,赋值报 TS2322
const data = await get('/contact/config')
contact.value = data
// ❌ as any 绕过
contact.value = data as any
// ✅ 泛型约束(推荐)
const data = await get<ContactConfig>('/contact/config')
contact.value = data
// ✅ 类型断言(最小改动)
contact.value = data as typeof contact.value---
性能优化
| 场景 | 方案 | |------|------| | 大列表 | 虚拟滚动 | | 路由 | 懒加载 `() => import()` | | 计算 | 使用 `computed` 缓存 | | 大数据 | 使用 `shallowRef` |
// 路由懒加载
const routes = [
{ path: '/dashboard', component: () => import('@/views/Dashboard.vue') }
]
// 请求防抖
import { useDebounceFn } from '@vueuse/core'
const debouncedSearch = useDebounceFn((keyword) => api.search(keyword), 300)---
目录结构
src/
├── assets/
│ └── styles/ # 全局/共享样式
├── api/ # API 请求
├── components/ # 通用组件
├── composables/ # 组合式函数
├── router/ # 路由配置
├── stores/ # Pinia stores
├── types/ # TypeScript 类型
├── utils/ # 工具函数
├── views/ # 页面组件
├── App.vue
└── main.ts
---
样式管理规范
| 规则 | 说明 | |------|------| | ❌ 禁止在 `.vue` 中写大段样式 | `<style>` 块不超过 20 行 | | ❌ 禁止在 `.tsx` 中写大段内联样式 | 样式对象/CSS-in-JS 不超过 20 行 | | ✅ 共享样式抽到 `src/assets/styles/` | 按模块拆分文件 | | ✅ 组件内只保留极简样式 | Vue: scoped 微调;React: className 引用 |
src/assets/styles/
├── variables.scss # 变量(颜色、间距、字号)
├── common.scss # 通用样式
└── [module].scss # 按模块拆分
---
请求体完整性规范
| 规则 | 说明 | |------|------| | ❌ 禁止 UI 可选字段未传入 API | 用户选择/输入的字段必须全部传入请求体 | | ✅ 提交函数与表单字段一一对应 | 用 TypeScript interface 约束请求体 |
// ❌ UI 有支付方式选择器,但请求体没传 payMethod
const payMethod = ref<'wechat' | 'points' | 'mixed'>('wechat')
async function createOrder() {
await api.createOrder({
items: orderItems.value,
addressId: selectedAddress.value.id,
// payMethod 忘记传了!支付方式选择 UI 形同虚设
})
}
// ✅ 请求体与 UI 表单字段对应
interface CreateOrderRequest {
items: OrderItem[]
addressId: number
payMethod: 'wechat' | 'points' | 'mixed' // 类型约束确保不遗漏
}
async function createOrder() {
const request: CreateOrderRequest = {
items: orderItems.value,
addressId: selectedAddress.value.id,
payMethod: payMethod.value, // TypeScript 会提示缺少字段
}
await api.createOrder(request)
}---
API 错误处理规范
| 规则 | 说明 | |------|------| | ❌ 禁止静默忽略非成功响应 | `res.code !== 200` 时必须提示用户 | | ✅ 统一错误提示 | 非成功响应统一 `message.error` 提示 | | ✅ 网络异常也要处理 | `try/catch` 捕获请求异常 |
// ❌ 只处理成功,非 200 静默忽略
const res = await api.getList(params)
if (res.code === 200) {
list.value = res.data
}
// ✅ 成功 + 失败都处理
try {
const res = await api.getList(params)
if (res.code === 200) {
list.value = res.data
} else {
message.error(res.message || '加载失败')
}
} catch (e) {
message.error('网络异常,请稍后重试')
}---
类型复用规范
| 规则 | 说明 | |------|------| | ❌ 禁止多个文件重复定义相同接口 | `PageRespo
Read more
name: frontend-dev description: 前端开发规范,包含 Vue 3 编码规范、UI 风格约束、TypeScript 规范等 version: v3.0 paths: - "**/*.vue" - "**/*.tsx" - "**/*.jsx" - "**/*.ts" - "**/*.js" - "**/*.css" - "**/*.scss" - "**/*.less" - "**/package.json" - "**/vite.config.*"
前端开发规范
> 参考来源: Vue 官方风格指南、Element Plus 最佳实践
---
UI 风格约束
严格禁止(常见 AI 风格)
- ❌ 蓝紫色霓虹渐变、发光描边、玻璃拟态
- ❌ 大面积渐变、过多装饰性几何图形
- ❌ 赛博风、暗黑科技风、AI 风格 UI
- ❌ UI 文案中使用 emoji
后台系统(默认风格)
| 要素 | 要求 | |------|------| | 主题 | 使用组件库默认主题 | | 配色 | 黑白灰为主 + 1 个主色点缀 | | 动效 | 克制,仅保留必要交互反馈 |
---
技术栈
| 层级 | Vue(首选) | React(备选) | |------|------------|--------------| | 框架 | Vue 3 + TypeScript | React 18 + TypeScript | | 构建 | Vite | Vite | | 路由 | Vue Router 4 | React Router 6 | | 状态 | Pinia | Zustand | | UI 库 | Element Plus | Ant Design |
---
Vue 编码规范
组件基础
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import type { User } from '@/types'
// Props & Emits
const props = defineProps<{ userId: number }>()
const emit = defineEmits<{ (e: 'update', value: string): void }>()
// 响应式状态
const loading = ref(false)
const user = ref<User | null>(null)
// 计算属性
const displayName = computed(() => user.value?.name ?? '未知用户')
// 生命周期
onMounted(async () => { await fetchUser() })
// 方法
async function fetchUser() {
loading.value = true
try {
user.value = await api.getUser(props.userId)
} finally {
loading.value = false
}
}
</script>
<template>
<div class="user-card">
<h3>{{ displayName }}</h3>
</div>
</template>
<style scoped>
.user-card { padding: 16px; }
</style>命名约定
| 类型 | 约定 | 示例 | |------|------|------| | 组件文件 | PascalCase.vue | `UserCard.vue` | | Composables | useXxx.ts | `useAuth.ts` | | Store | useXxxStore.ts | `useUserStore.ts` |
---
状态管理(Pinia)
// stores/user.ts
export const useUserStore = defineStore('user', () => {
const user = ref<User | null>(null)
const token = ref<string>('')
const isLoggedIn = computed(() => !!token.value)
async function login(username: string, password: string) {
const res = await api.login(username, password)
token.value = res.token
user.value = res.user
}
return { user, token, isLoggedIn, login }
})---
交互状态处理
**必须处理的状态**: loading、empty、error、disabled、submitting
<template>
<el-skeleton v-if="loading" :rows="5" animated />
<el-result v-else-if="error" icon="error" :title="error">
<template #extra>
<el-button @click="fetchData">重试</el-button>
</template>
</el-result>
<el-empty v-else-if="list.length === 0" description="暂无数据" />
<template v-else>
<!-- 正常内容 -->
</template>
</template>---
TypeScript 规范
// types/user.ts
export interface User {
id: number
username: string
role: 'admin' | 'user'
}
export interface ApiResponse<T = unknown> {
code: number
message: string
data: T
}---
API 调用类型安全
| 规则 | 说明 | |------|------| | ✅ API 工具函数支持泛型 | `get<T>(url): Promise<T>` 而非返回 `unknown` | | ✅ 调用处指定泛型或断言 | `get<UserInfo>(url)` 或 `data as typeof ref.value` | | ❌ 禁止 `as any` 绕过 | 掩盖类型问题,后续维护踩坑 |
// ❌ get() 返回 unknown,赋值报 TS2322
const data = await get('/contact/config')
contact.value = data
// ❌ as any 绕过
contact.value = data as any
// ✅ 泛型约束(推荐)
const data = await get<ContactConfig>('/contact/config')
contact.value = data
// ✅ 类型断言(最小改动)
contact.value = data as typeof contact.value---
性能优化
| 场景 | 方案 | |------|------| | 大列表 | 虚拟滚动 | | 路由 | 懒加载 `() => import()` | | 计算 | 使用 `computed` 缓存 | | 大数据 | 使用 `shallowRef` |
// 路由懒加载
const routes = [
{ path: '/dashboard', component: () => import('@/views/Dashboard.vue') }
]
// 请求防抖
import { useDebounceFn } from '@vueuse/core'
const debouncedSearch = useDebounceFn((keyword) => api.search(keyword), 300)---
目录结构
src/ ├── assets/ │ └── styles/ # 全局/共享样式 ├── api/ # API 请求 ├── components/ # 通用组件 ├── composables/ # 组合式函数 ├── router/ # 路由配置 ├── stores/ # Pinia stores ├── types/ # TypeScript 类型 ├── utils/ # 工具函数 ├── views/ # 页面组件 ├── App.vue └── main.ts
---
样式管理规范
| 规则 | 说明 | |------|------| | ❌ 禁止在 `.vue` 中写大段样式 | `<style>` 块不超过 20 行 | | ❌ 禁止在 `.tsx` 中写大段内联样式 | 样式对象/CSS-in-JS 不超过 20 行 | | ✅ 共享样式抽到 `src/assets/styles/` | 按模块拆分文件 | | ✅ 组件内只保留极简样式 | Vue: scoped 微调;React: className 引用 |
src/assets/styles/ ├── variables.scss # 变量(颜色、间距、字号) ├── common.scss # 通用样式 └── [module].scss # 按模块拆分
---
请求体完整性规范
| 规则 | 说明 | |------|------| | ❌ 禁止 UI 可选字段未传入 API | 用户选择/输入的字段必须全部传入请求体 | | ✅ 提交函数与表单字段一一对应 | 用 TypeScript interface 约束请求体 |
// ❌ UI 有支付方式选择器,但请求体没传 payMethod
const payMethod = ref<'wechat' | 'points' | 'mixed'>('wechat')
async function createOrder() {
await api.createOrder({
items: orderItems.value,
addressId: selectedAddress.value.id,
// payMethod 忘记传了!支付方式选择 UI 形同虚设
})
}
// ✅ 请求体与 UI 表单字段对应
interface CreateOrderRequest {
items: OrderItem[]
addressId: number
payMethod: 'wechat' | 'points' | 'mixed' // 类型约束确保不遗漏
}
async function createOrder() {
const request: CreateOrderRequest = {
items: orderItems.value,
addressId: selectedAddress.value.id,
payMethod: payMethod.value, // TypeScript 会提示缺少字段
}
await api.createOrder(request)
}---
API 错误处理规范
| 规则 | 说明 | |------|------| | ❌ 禁止静默忽略非成功响应 | `res.code !== 200` 时必须提示用户 | | ✅ 统一错误提示 | 非成功响应统一 `message.error` 提示 | | ✅ 网络异常也要处理 | `try/catch` 捕获请求异常 |
// ❌ 只处理成功,非 200 静默忽略
const res = await api.getList(params)
if (res.code === 200) {
list.value = res.data
}
// ✅ 成功 + 失败都处理
try {
const res = await api.getList(params)
if (res.code === 200) {
list.value = res.data
} else {
message.error(res.message || '加载失败')
}
} catch (e) {
message.error('网络异常,请稍后重试')
}---
类型复用规范
| 规则 | 说明 | |------|------| | ❌ 禁止多个文件重复定义相同接口 | `PageRespo
保留你熟悉的 CLI/IDE,让 Claude Code、Gemini CLI、Codex、Cursor、GitHub Copilot 开箱即用 按费力度从低到高,用最少操作获得最大帮助 不是提示词集合,而是一套可维护的 AI 协作配置系统。
Repo: doccker/cc-use-exp
Other skills on cc-use-exp.
- /api-design-safety
当设计或修改 REST API 响应结构、处理 API 返回值,或生成 Excel/CSV/PDF/对账文件等下游产物时触发。防止 API 设计缺陷导致的字段错位、类型歧义,以及生成产物时关键字段缺失但静默成功的问题。
Open skill - /api-proxy-safety
网关/代理/WAF/CDN 中间件的安全关键词匹配实现规范,防止纯子串匹配误判正常响应内容中的技术术语(如 Cloudflare、502、error)
Open skill - /async-task-pattern
当 API/任务可能执行超过 10 秒(批量数据处理、远程 API 批量调用、全表扫描、跨租户聚合)时触发。防止同步接口被网关 30s 超时切断、用户重复点击触发并发、状态缓存内存泄漏等问题。提供异步任务状态机标准模板。
Open skill - /bash-style
当用户操作 .sh、Dockerfile、Makefile、.yml、.yaml 文件,或在 Markdown 中编写 bash 代码块时触发。提供 Bash 编写规范。
Open skill - /code-quality-principles
当编写新模块、设计接口、重构代码或代码审查时触发。提供经典模块化六原则检查清单(大小适中/调用深度/扇入扇出/边界清晰/作用域内聚/可预测性),适用于 PR/Review/新模块设计场景。
Open skill - /external-system-debugging
涉及浏览器、编辑器、CDN/WAF、IM 平台、操作系统剪贴板、第三方 SaaS 等"外部黑盒系统"的代码编写或 bug 调试时触发。强制先抓真实环境数据再推理,避免连续 2 轮"凭代码推理"的修复 no-op。关键词:粘贴/复制异常、跨平台显示不一致、第三方 API 怪结果、CDN/WAF 拦截、本地复现失败、HTML→MD 转换丢属性。
Open skill

