RMDC系统设计文档 整体转换为SKILL

This commit is contained in:
zeaslity
2026-01-21 16:15:49 +08:00
parent fc72a7312e
commit 631cce9e1e
163 changed files with 37099 additions and 114 deletions

View File

@@ -0,0 +1,41 @@
---
name: frontend-design
description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.
---
This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.
## Design Thinking
Before coding, understand the context and commit to a BOLD aesthetic direction:
- **Purpose**: What problem does this interface solve? Who uses it?
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
- **Constraints**: Technical requirements (framework, performance, accessibility).
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.
Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is:
- Production-grade and functional
- Visually striking and memorable
- Cohesive with a clear aesthetic point-of-view
- Meticulously refined in every detail
## Frontend Aesthetics Guidelines
Focus on:
- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.
- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.
NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.
**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.
Remember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision.

View File

@@ -0,0 +1,6 @@
你是一名经验非常丰富的资深前端开发工程师UI美学领域的专家能够熟练使用vutify等现在的UI框架
请你参考https://github.com/anthropics/claude-code/blob/main/plugins/frontend-design/skills/frontend-design/SKILL.md Claude的官方前端开发SKILL说明
参考已有的比较合理的页面设计user-dashboard-style-guide.md
参考已有的前端开发规范文档 vue3-typescript-style-v2.md
你的目的是为了大模型进行前端开发设置一份prompt指导请实现一份包含模板框架的完善的前端开发Prompt说明

View File

@@ -0,0 +1,713 @@
---
description: UserDashboard 页面样式与布局设计指南 - 供后续页面设计参考
---
# UserDashboard 页面样式与布局设计指南
## 概述
此文档描述了 `UserDashboard.vue` 页面的样式和布局设计模式,可作为后续页面设计的参考标准。该页面采用 **Vue 3 + Vuetify 3 + TypeScript** 技术栈,实现了一个**分层钻取式(Drill-Down)导航**的 Dashboard 界面。
---
## 1. 整体页面结构
### 1.1 布局架构
```
┌─────────────────────────────────────────────────────────────┐
│ 顶部工具栏 (Top Bar) │
│ - 面包屑导航 (Breadcrumbs) │
│ - 全局搜索框 (Search Autocomplete) │
├─────────────────────────────────────────────────────────────┤
│ │
│ 主内容区域 (Main Content Area) │
│ - 可滚动区域 │
│ - 根据导航层级动态切换内容组件 │
│ │
│ │
│ │
└─────────────────────────────────────────────────────────────┘
```
### 1.2 根容器设置
```vue
<v-container
fluid
class="d-flex flex-column h-100 pa-0"
style="width: 95%; height: 100vh; min-height: 0;"
>
```
**设计要点:**
- 使用 `fluid` 流式布局
- `d-flex flex-column` 实现垂直弹性布局
- `h-100` 占满高度
- `pa-0` 移除内边距
- 宽度 `95%` 留出两侧适当边距
---
## 2. 顶部工具栏设计
### 2.1 结构
```vue
<div class="d-flex align-center px-4 py-2 bg-white border-b flex-shrink-0">
<!-- 面包屑导航 -->
<DashboardBreadcrumbs class="flex-grow-1" ... />
<!-- 搜索框 -->
<div style="width: 350px" class="ml-4">
<v-autocomplete ... />
</div>
</div>
```
### 2.2 设计要点
- **固定高度**:使用 `flex-shrink-0` 防止压缩
- **背景色**`bg-white` 白色背景
- **底部边框**`border-b` 分隔线
- **内边距**`px-4 py-2` 水平16px垂直8px
- **内容对齐**`d-flex align-center` 水平排列垂直居中
### 2.3 面包屑导航设计
```vue
<div class="px-4 py-2 d-flex align-center">
<v-btn variant="text" @click="..." :disabled="...">
层级名称
</v-btn>
<v-icon v-if="..." size="small" class="mx-2">mdi-chevron-right</v-icon>
<!-- 更多层级... -->
</div>
```
**特点:**
- 使用 `v-btn variant="text"` 作为可点击导航项
- 使用 `mdi-chevron-right` 图标作为分隔符
- 图标尺寸 `size="small"`,间距 `mx-2`
- 当前层级设置 `:disabled="true"` 表示不可点击
### 2.4 搜索框设计
```vue
<v-autocomplete
v-model="treeSearchSelect"
v-model:search="treeSearchQuery"
:items="treeSearchResults"
:loading="treeSearchLoading"
item-title="name"
item-value="id"
placeholder="Search Org / Repo / Branch..."
variant="outlined"
density="compact"
hide-details
prepend-inner-icon="mdi-magnify"
return-object
hide-no-data
bg-color="grey-lighten-5"
clearable
>
```
**特点:**
- `variant="outlined"` 外框样式
- `density="compact"` 紧凑型高度
- `bg-color="grey-lighten-5"` 浅灰色背景
- `prepend-inner-icon="mdi-magnify"` 搜索图标
- `hide-details` 隐藏辅助文本空间
- `clearable` 可清除按钮
---
## 3. 主内容区域设计
### 3.1 滚动容器
```vue
<div class="flex-grow-1 overflow-y-auto custom-scrollbar"
style="height: 80vh; min-height: 0; overflow-y: auto; overflow-x: hidden;">
```
**设计要点:**
- `flex-grow-1` 填充剩余空间
- `overflow-y-auto` 垂直滚动
- `overflow-x-hidden` 隐藏水平滚动
- 自定义滚动条样式
### 3.2 自定义滚动条样式
```css
.custom-scrollbar {
scrollbar-width: thin;
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
}
.custom-scrollbar::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: transparent;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.2);
border-radius: 3px;
}
```
**特点:**
- 细滚动条 `width: 6px`
- 透明轨道
- 半透明滚动条滑块
- 圆角处理
---
## 4. 列表组件设计模式
### 4.1 通用列表结构
```vue
<v-list lines="two" class="pa-2">
<v-list-subheader class="text-h6 font-weight-medium">
<v-icon class="mr-2">图标</v-icon>
列表标题
</v-list-subheader>
<!-- 空状态 -->
<v-empty-state
v-if="items.length === 0"
icon="mdi-database-off-outline"
title="暂无数据"
text="描述文本"
/>
<!-- 列表项 -->
<v-list-item
v-for="item in items"
:key="item.id"
@click="..."
class="mb-2"
rounded
hover
>
<!-- 前置图标 -->
<template #prepend>
<v-avatar color="primary" size="40">
<v-icon>图标</v-icon>
</v-avatar>
</template>
<!-- 标题 -->
<v-list-item-title class="font-weight-medium">
{{ item.name }}
</v-list-item-title>
<!-- 副标题 -->
<v-list-item-subtitle>...</v-list-item-subtitle>
<!-- 后置图标 -->
<template #append>
<v-icon>mdi-chevron-right</v-icon>
</template>
</v-list-item>
</v-list>
```
### 4.2 列表项悬停效果
```css
.v-list-item {
transition: all 0.2s ease;
}
.v-list-item:hover {
background-color: rgba(var(--v-theme-primary), 0.08);
}
```
---
## 5. 数据表格设计模式
### 5.1 表格工具栏
```vue
<v-toolbar color="transparent" density="compact" class="px-4">
<v-icon class="mr-2">mdi-hammer-wrench</v-icon>
<v-toolbar-title class="text-h6">表格标题</v-toolbar-title>
<v-spacer />
<v-btn color="primary" prepend-icon="mdi-plus" class="mr-2">
操作按钮
</v-btn>
<v-btn icon="mdi-refresh" variant="text" @click="..." :loading="loading" />
</v-toolbar>
```
### 5.2 数据表格
```vue
<v-data-table
:headers="headers"
:items="items"
:items-per-page="50"
:items-per-page-options="[25, 50, 100]"
fixed-header
height="calc(100vh - 280px)"
class="elevation-1"
hover
@click:row="handleRowClick"
>
<!-- 自定义列模板 -->
</v-data-table>
```
### 5.3 状态标签设计
```vue
<v-chip :color="getStatusColor(status)" size="small" variant="flat">
<v-icon start size="x-small">{{ getStatusIcon(status) }}</v-icon>
{{ status }}
</v-chip>
```
**状态颜色映射:**
```typescript
const statusColors = {
'SUCCESS': 'success',
'FAILURE': 'error',
'UNSTABLE': 'warning',
'ABORTED': 'grey',
'RUNNING': 'info'
}
```
---
## 6. 详情页面设计模式
### 6.1 详情页头部
```vue
<div class="d-flex align-center justify-space-between pa-4 bg-surface w-100">
<!-- 左侧组 -->
<div class="d-flex align-center ga-3">
<v-btn icon="mdi-arrow-left" variant="text" @click="goBack" />
<span class="text-h6 font-weight-bold">标题</span>
<v-chip :color="statusColor" size="small" variant="flat">状态</v-chip>
</div>
<!-- 右侧组 -->
<div class="d-flex align-center ga-2">
<v-btn color="info" variant="tonal" prepend-icon="mdi-eye">操作1</v-btn>
<v-btn color="primary" variant="flat" prepend-icon="mdi-open-in-new">操作2</v-btn>
</div>
</div>
```
### 6.2 详情卡片分组
```vue
<v-row>
<!-- 左侧列主要信息 -->
<v-col cols="12" md="7">
<v-card class="mb-4" variant="outlined">
<v-card-title class="text-subtitle-1 font-weight-bold">
<v-icon start size="small" color="primary">mdi-icon</v-icon>
卡片标题
</v-card-title>
<v-divider />
<v-card-text class="pa-4">
<!-- 详情内容 -->
</v-card-text>
</v-card>
</v-col>
<!-- 右侧列元信息 -->
<v-col cols="12" md="5">
<!-- 更多卡片... -->
</v-col>
</v-row>
```
### 6.3 详情项组件 (DetailItem)
```vue
<div class="d-flex align-center mb-5 detail-item">
<!-- 标签区域固定宽度 -->
<div class="d-flex align-center text-medium-emphasis flex-shrink-0" style="width: 140px;">
<v-icon size="small" class="mr-2" color="primary">{{ icon }}</v-icon>
<span class="text-body-2 font-weight-medium">{{ label }}</span>
</div>
<!-- 值区域胶囊样式 -->
<div class="flex-grow-1 d-flex align-center justify-space-between px-4 py-2 rounded-pill bg-grey-lighten-5 value-capsule">
<div class="text-body-2 font-weight-medium text-truncate flex-grow-1 mr-2">
<slot name="value">{{ value }}</slot>
</div>
<v-btn v-if="copyable" icon="mdi-content-copy" variant="text" size="x-small"
color="medium-emphasis" class="copy-btn" @click="copy" />
</div>
</div>
```
**胶囊样式 CSS**
```css
.value-capsule {
transition: all 0.2s ease;
min-height: 44px;
border: 1px solid rgba(0, 0, 0, 0.05);
}
.value-capsule:hover {
background-color: rgba(var(--v-theme-on-surface), 0.08) !important;
border-color: rgba(0, 0, 0, 0.1);
}
.copy-btn {
opacity: 0;
transition: opacity 0.2s ease;
}
.value-capsule:hover .copy-btn {
opacity: 1;
}
```
---
## 7. 弹窗设计模式
### 7.1 标准弹窗
```vue
<v-dialog v-model="showDialog" max-width="60vh" max-height="80vh">
<v-card>
<v-card-title>弹窗标题</v-card-title>
<v-divider />
<v-card-text>内容</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn variant="text" @click="cancel">取消</v-btn>
<v-btn color="primary" @click="confirm">确认</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
```
### 7.2 全屏弹窗(日志查看器)
```vue
<v-dialog v-model="showDialog" fullscreen transition="dialog-bottom-transition">
<v-card>
<v-toolbar color="primary" density="compact">
<v-btn icon="mdi-close" @click="close"></v-btn>
<v-toolbar-title>全屏弹窗标题</v-toolbar-title>
</v-toolbar>
<v-card-text class="pa-0 h-100">
<!-- 内容 -->
</v-card-text>
</v-card>
</v-dialog>
```
---
## 8. 状态处理模式
### 8.1 加载状态
```vue
<div v-if="loading" class="pa-4">
<v-skeleton-loader type="list-item@5" />
</div>
```
### 8.2 错误状态
```vue
<v-alert
v-else-if="error"
type="error"
variant="tonal"
class="ma-4"
closable
@click:close="error = null"
>
{{ error }}
</v-alert>
```
### 8.3 空状态
```vue
<v-empty-state
icon="mdi-database-off-outline"
title="暂无数据"
text="描述性文本说明"
/>
```
---
## 9. 颜色规范
### 9.1 主题颜色使用
| 用途 | 颜色 | Vuetify类/变量 |
|------|------|----------------|
| 主要操作 | 蓝色 | `primary` |
| 次要操作 | 灰色 | `secondary` |
| 成功状态 | 绿色 | `success` |
| 错误状态 | 红色 | `error` |
| 警告状态 | 橙色 | `warning` |
| 提示信息 | 蓝色 | `info` |
| 禁用/中性 | 灰色 | `grey` |
### 9.2 背景颜色
- 页面背景:默认(白色/浅灰)
- 卡片背景:`bg-surface`
- 输入框背景:`bg-grey-lighten-5`
- 胶囊值背景:`bg-grey-lighten-5`
---
## 10. 间距规范
### 10.1 Vuetify 间距系统
| 值 | 像素 | 使用场景 |
|----|------|----------|
| 1 | 4px | 极小间距 |
| 2 | 8px | 小间距 |
| 3 | 12px | 中等间距 |
| 4 | 16px | 标准间距 |
| 5 | 24px | 大间距 |
| 6 | 32px | 超大间距 |
### 10.2 常用间距组合
- 卡片内边距:`pa-4`16px
- 列表项底部间距:`mb-2`8px
- 详情项底部间距:`mb-5`24px
- 按钮组间距:`ga-2``ga-3`
---
## 11. 图标使用规范
### 11.1 常用图标
| 用途 | 图标 |
|------|------|
| 组织 | `mdi-domain` / `mdi-folder-network` |
| 仓库 | `mdi-source-repository` |
| 分支 | `mdi-source-branch` |
| 构建 | `mdi-hammer-wrench` |
| 搜索 | `mdi-magnify` |
| 导航 | `mdi-chevron-right` / `mdi-arrow-left` |
| 刷新 | `mdi-refresh` |
| 关闭 | `mdi-close` |
| 复制 | `mdi-content-copy` |
| 外部链接 | `mdi-open-in-new` |
| 日志 | `mdi-text-box-outline` |
### 11.2 图标尺寸
- 列表项图标:`size="small"` 或默认
- 状态标签图标:`size="x-small"`
- 头像图标:默认(在 `v-avatar` 内)
- 面包屑分隔符:`size="small"`
---
## 12. 组件化设计原则
### 12.1 组件拆分原则
1. **单一职责**:每个组件只负责一个功能
2. **可复用性**:将通用 UI 模式抽取为独立组件
3. **Props 驱动**:通过 Props 传递数据,通过 Events 传递交互
### 12.2 本项目组件结构
```
components/
├── projects/
│ ├── DashboardBreadcrumbs.vue # 面包屑导航
│ ├── OrganizationList.vue # 组织列表
│ ├── RepositoryList.vue # 仓库列表
│ ├── BranchList.vue # 分支列表
│ ├── BuildList.vue # 构建列表
│ └── BuildDetails.vue # 构建详情
├── common/
│ └── DetailItem.vue # 详情项组件
└── jenkins/
├── BuildTrigger.vue # 构建触发器
└── LogViewer.vue # 日志查看器
```
---
## 13. 交互模式
### 13.1 导航模式
- **钻取式导航**:点击列表项进入下一层级
- **面包屑回溯**:点击面包屑返回上层
- **全局搜索**:快速跳转到任意层级
### 13.2 动画效果
- 过渡动画:`transition: all 0.2s ease`
- 弹窗动画:`transition="dialog-bottom-transition"`
- 悬停效果:背景色变化、元素显现
### 13.3 自动刷新
- 列表数据刷新10秒间隔有运行中任务时3秒
- 详情数据刷新3秒间隔仅运行中状态
---
## 使用示例
### 创建新的钻取式页面
```vue
<template>
<v-container fluid class="d-flex flex-column h-100 pa-0" style="width: 95%; height: 100vh; min-height: 0;">
<!-- 顶部栏 -->
<div class="d-flex align-center px-4 py-2 bg-white border-b flex-shrink-0">
<YourBreadcrumbs ... />
<div style="width: 350px" class="ml-4">
<v-autocomplete ... />
</div>
</div>
<v-divider />
<!-- 主内容区 -->
<div class="flex-grow-1 overflow-y-auto custom-scrollbar" style="height: 80vh; min-height: 0;">
<div v-if="loading" class="pa-4">
<v-skeleton-loader type="list-item@5" />
</div>
<v-alert v-else-if="error" type="error" variant="tonal" class="ma-4" closable>
{{ error }}
</v-alert>
<YourList1 v-else-if="currentLevel === 'level1'" ... />
<YourList2 v-else-if="currentLevel === 'level2'" ... />
<YourDetails v-else-if="currentLevel === 'details'" ... />
</div>
</v-container>
</template>
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'
// Navigation State
type NavigationLevel = 'level1' | 'level2' | 'details'
const currentLevel = ref<NavigationLevel>('level1')
const selectedItem1 = ref<string>('')
const selectedItem2 = ref<string>('')
// Data State
const items1 = ref<Item1[]>([])
const items2 = ref<Item2[]>([])
const details = ref<Details | null>(null)
// UI State
const loading = ref(false)
const error = ref<string | null>(null)
// Auto-refresh timer
const refreshTimer = ref<number | null>(null)
// Navigation Functions
function selectItem1(name: string) {
selectedItem1.value = name
currentLevel.value = 'level2'
loadItems2(name)
}
function selectItem2(name: string) {
selectedItem2.value = name
currentLevel.value = 'details'
loadDetails(selectedItem1.value, name)
}
function navigateToLevel1() {
clearTimer()
currentLevel.value = 'level1'
selectedItem1.value = ''
selectedItem2.value = ''
}
function navigateToLevel2() {
clearTimer()
currentLevel.value = 'level2'
selectedItem2.value = ''
}
// Timer Management
function startRefresh() {
stopRefresh()
refreshTimer.value = window.setInterval(() => {
// Refresh logic
}, 10000)
}
function stopRefresh() {
if (refreshTimer.value) {
clearInterval(refreshTimer.value)
refreshTimer.value = null
}
}
function clearTimer() {
stopRefresh()
}
// Lifecycle
onMounted(() => {
loadItems1()
})
onBeforeUnmount(() => {
clearTimer()
})
</script>
<style scoped>
.custom-scrollbar {
scrollbar-width: thin;
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
}
.custom-scrollbar::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: transparent;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.2);
border-radius: 3px;
}
</style>
```
---

View File

@@ -0,0 +1,192 @@
**背景 (Context):**
你是一名资深前端架构师,负责搭建前端框架和制定开发规范。该项目要求极高的代码质量、无缝的用户体验(跨设备、跨主题)以及长期的可维护性。
**核心指令 (Core Directive):**
请你以架构师的身份,严格遵循并执行以下所有规范来生成代码、组件、模块和提供解决方案。你的任何产出都必须成为团队的代码典范。
## 1. 语言与语法 (Language & Syntax):**
* **TypeScript 至上 (TypeScript Supremacy):**
* 项目 **必须** 完全基于 TypeScript (`<script setup lang="ts">`)。**严禁** 任何 `.js` 文件或 JavaScript 语法的混入。
* **杜绝 `any`:** 除非在第三方库类型定义缺失且无法补充的极端情况下,否则**严禁**使用 `any`。所有变量、函数参数/返回值、Props、Emits、Pinia State/Actions **必须** 拥有精确的类型或接口Interface/Type
* **善用高级类型:** 积极使用泛型Generics、条件类型Conditional Types、映射类型Mapped Types和类型守卫Type Guards来创建灵活且类型安全的代码。
* **类型组织:** 全局共享的类型定义在 `@/types` 目录下,按模块划分文件(如 `user.d.ts`, `order.d.ts`)。
* **纯粹的 Vue 3 (Pure Vue 3):**
* **组合式API (`<script setup>`)**: 这是项目中**唯一**允许的组件逻辑组织方式。
* **响应式核心:** 精准使用 `ref``reactive``computed``watchEffect`。理解 `shallowRef``readonly` 等API的适用场景并在需要时使用它们来优化性能。
* **生命周期:** **必须** 使用 `onMounted`, `onUnmounted` 等组合式API钩子**严禁** 混用任何Vue 2选项式API。
* **依赖注入:** 复杂场景下,善用 `provide``inject` 进行跨层级组件通信,并为注入的值提供明确的类型定义和默认值。
* **状态管理:** 唯一的状态管理方案是 **Pinia**。Store的定义必须模块化包含清晰的 `state`, `getters`, `actions`,并全部进行严格的类型标注。
## 2. UI框架与布局哲学 (UI Framework & Layout Philosophy)
* **Vuetify 3 & Material Design:**
* 所有UI界面和组件**必须**基于 [Vuetify 3](https://vuetifyjs.com/en/) 构建。
* 深度贯彻 [Google Material Design 3 (MD3)](https://m3.material.io/) 设计哲学。
* **布局与容器 (Layout & Container Strategy):**
* **禁止全屏滚动 (No Body Scroll):** 现代Web应用应尽量避免 `body` 级别的全屏滚动。应用框架应固定视口高度(`h-screen`),将滚动限制在具体的**内容区域**内。
* **Flexbox 滚动陷阱防范:**
* 在使用 Flex 布局 (`d-flex flex-column`) 实现“头部固定、内容自适应”的结构时,**必须**给内容区域容器添加 `min-height: 0``overflow: hidden`,防止子元素撑破父容器导致滚动条失效。
* **视口锁定:** 页面主容器应通常设置为 `class="d-flex flex-column h-100"`,确保布局占满父级高度。
* **主题与响应式:**
* **必须**适配明亮/黑暗模式,严禁硬编码颜色。
* 利用 `useDisplay` 处理复杂响应式逻辑。
## 3. 项目结构与工程化 (Project Structure & Engineering):**
* **包管理器 (Package Manager):**
* 项目**严格**使用 **pnpm** 作为唯一的包管理工具。熟悉并利用其特性(如 `pnpm workspace`)。
* **模块化结构:** 遵循以下清晰、可扩展的目录结构:
```
src/
├── api/ # API层
│ ├── modules/ # 按业务模块划分
│ ├── interceptors.ts # 统一拦截器
│ └── index.ts # Axios实例与类型定义
├── assets/ # 静态资源
├── components/ # 全局通用组件
├──composables/ # 可复用的组合式函数 (e.g., usePagination.ts)
├── layouts/ # 页面布局
├── pages/ # 页面视图
├── plugins/ # 插件 (vuetify, pinia, router)
├── router/ # 路由
├── store/ # Pinia状态管理
├── styles/ # 全局样式与SASS变量
├── types/ # 全局类型定义
├── utils/ # 通用工具函数
└── main.ts # 应用入口
```
## 4. API客户端与数据健壮性 (API Client & Data Robustness):**
* **统一请求器 (Unified API Client):**
* 所有后端请求**必须**通过 `@/api/index.ts` 中封装的Axios实例发起。
* API按业务模块封装在 `@/api/modules/` 下,函数签名必须清晰,包含类型化的参数和返回值。
* **统一响应与错误处理:**
* **响应格式:** 后端标准响应格式为:
```typescript
interface ApiResponse<T = any> {
code: number;
status: number;
timestamp: string;
data: T;
message?: string; // Make message optional
error?: string;
}
```
* **响应代码:** 后端标准代码的含义如下:
```typescript
// 常见错误码定义
export enum ApiErrorCode {
CodeSuccess = 0 // 成功
CodeServerError = 10001 // 服务器内部错误
CodeParamError = 10002 // 参数错误
CodeUnauthorized = 10003 // 未授权
CodeForbidden = 10004 // 禁止访问
CodeNotFound = 10005 // 请求的数据不存在
CodeTimeout = 10006 // 请求超时
CodeValidationFail = 10007 // 验证失败
CodeBusiness = 20001 // 业务逻辑错误
}
```
* **统一拦截器:** 在响应拦截器 (`@/api/interceptors.ts`) 中,实现全局错误处理逻辑:
1. **业务成功:** `code` 为 `0`,直接解析并返回 `data`。
2. **业务失败:** `code` 不为 `0`,提取 `message`通过全局通知系统如Vuetify的Snackbar展示给用户并 `Promise.reject` 一个带有`data`的Error对象。
3. **HTTP错误:** 根据状态码 (401, 403, 404, 500+) 进行统一处理如401则跳转登录页。
4. **网络/超时错误:** 提示用户检查网络连接。
* **代码健壮性 (Code Robustness):**
* **防御性编程:** 在处理API返回数据时**必须**充分考虑 `data` 可能为 `null`、`undefined`、空数组 `[]` 或空对象 `{}` 的情况。
* **安全访问:** 使用可选链 (`?.`) 和空值合并运算符 (`??`) 来安全地访问嵌套对象的属性和提供默认值。
* **数据校验:** 在渲染前,对关键数据进行必要的格式校验或存在性检查,避免因数据格式错误导致页面崩溃。例如,渲染列表前检查`Array.isArray(list) && list.length > 0`。
* 在模板中,使用 `v-if` 或 `v-else` 来处理数据为空时的占位符或提示信息,提升用户体验。
## 5. 界面交互与数据展示规范 (Interaction & Data Presentation)
针对“数据截断”和“长列表体验差”的问题,**必须**严格执行以下规范:
### 5.1 长列表与滚动策略 (Long List & Scrolling)
* **滚动容器 (The Scroll Container):**
* 任何可能产生动态长度数据的区域(表格、列表、日志视窗),**必须**显式包裹在具有固定高度或 Flex 自适应高度的容器中。
* **必须**为该容器显式声明溢出行为:`overflow-y: auto` (或 Vuetify 类 `v-table--fixed-header` / `overflow-y-auto`)。
* **代码范例:**
```html
<div> <v-table>...</v-table> </div>
<div class="d-flex flex-column h-100">
<header>固定头部</header>
<div class="flex-grow-1 overflow-y-auto"> <v-table>...</v-table>
</div>
</div>
```
* **虚拟滚动 (Virtual Scrolling):**
* 对于预期超过 100 条数据的简单列表(非复杂表格),**优先**使用 Vuetify 的 `<v-virtual-scroll>` 组件。这能确保在展示万级数据时DOM 节点数量恒定,不仅有滚动条,且页面丝般顺滑。
* **粘性头部 (Sticky Headers):**
* 长表格 (`v-data-table`) **必须** 开启 `fixed-header` 属性。
* 长卡片列表的顶部操作栏,**必须** 使用 CSS `position: sticky; top: 0; z-index: ...` 确保用户在滚动浏览数据时,筛选和操作按钮始终可见。
### 5.2 数据截断与文本溢出 (Truncation & Overflow)
* **禁止静默截断:** 严禁文本在因为过长被截断Displaying "...")时,没有任何用户提示。
* **解决方案:**
* **表格单元格:** 必须为可能溢出的列设置最大宽度 (`max-width`) 和 `text-truncate` 类。
* **Tooltip 联动:** 当且仅当内容被截断时,**必须**提供 `<v-tooltip>` 悬浮显示完整内容。
* **多行文本:** 对于允许换行的文本(如备注、描述),使用 CSS `line-clamp` 限制行数(如最多显示 2 行),并提供“展开/收起”按钮。
### 5.3 界面美观与空状态 (Aesthetics & Empty States)
* **拒绝“开天窗” (No Empty Context):**
* 当 API 返回空数组或数据加载失败时,**严禁**留白。
* **必须**使用 `<v-empty-state>` 组件,配置友好的图标、标题(如“暂无数据”)和引导操作按钮(如“刷新”或“新建”)。
* **加载反馈 (Loading Feedback):**
* 数据请求期间,**严禁**展示空白页面或静止的旧数据。
* **表格:** 使用 `v-data-table` 的 `loading` 属性。
* **卡片/详情页:** **必须**使用 `<v-skeleton-loader>` (骨架屏) 占位保持布局稳定性避免数据加载完成时的页面抖动Layout Shift
* **留白与呼吸感:**
* 严格遵守 8px 网格系统。组件间距使用 Vuetify 的工具类(`ma-4`, `gap-4`)。
* 容器必须有适当的 `padding`,禁止文字紧贴浏览器边缘。
-----
**总结指令:**
现在,当你作为架构师回应我的开发需求时,除了满足原有的代码规范外,你需要特别自我审查以下几点:
1. 生成的页面布局是否会导致长数据把页面撑破?
2. 列表区域是否具备独立的垂直滚动条?
3. 表头是否固定?
4. 加载中和无数据时,是否提供了美观的反馈界面?
请确保你的代码方案在视觉和交互上是 “生产级” 的,而不仅仅是逻辑跑通。