Files
medical-mall/docs/admin/STYLE_SPECIFICATION.md
2026-02-02 20:07:37 +08:00

956 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Uni-App-X 样式规范 - CRMEB 风格指南
## 📚 概述
本文档定义了 mall 项目中所有页面的样式规范,参考 CRMEB 设计系统,使用 uni-app-x 的 `.uvue` 组件和 UTS 语言实现。
---
## 1. 颜色规范
### 1.1 基础色板
```typescript
// 在 uni.scss 中定义,所有 .uvue 文件都可使用
// 主要色系
$primary-color: #1890ff // 蓝色 - 主交互色
$success-color: #52c41a // 绿色 - 成功状态
$warning-color: #faad14 // 黄色 - 警告状态
$error-color: #ff4d4f // 红色 - 错误状态
$info-color: #1890ff // 信息色
$disabled-color: #bfbfbf // 禁用色
// 文字色系
$text-primary: #000000 // 主文本(标题、重点内容)
$text-secondary: #666666 // 次文本(辅助信息)
$text-tertiary: #999999 // 三级文本(弱化信息)
$text-disabled: #bfbfbf // 禁用文本
// 背景色系
$background-primary: #ffffff // 主背景(卡片、模态框)
$background-secondary: #fafafa // 次背景
$background-tertiary: #f5f5f5 // 页面背景
// 边框色系
$border-color: #d9d9d9 // 默认边框色
$border-light: #f0f0f0 // 浅边框(弱化分割)
$border-dark: #bfbfbf // 深边框(强调分割)
```
### 1.2 使用示例
```uvue
<template>
<view class="card">
<text class="title">主标题</text>
<text class="subtitle">副标题</text>
</view>
</template>
<style scoped lang="scss">
.card {
background: $background-primary;
border: 1px solid $border-color;
color: $text-primary;
}
.title {
color: $text-primary;
}
.subtitle {
color: $text-secondary;
}
</style>
```
---
## 2. 间距规范
### 2.1 间距系统
所有间距margin、padding**必须使用** `$space-*` 变量,基准为 **4px**
```typescript
$space-0: 0 // 无间距
$space-xs: 4px // 极小 - 图标之间
$space-sm: 8px // 小 - 小组件间距
$space: 12px // 基础 - 标准间距
$space-md: 16px // 中 - 块级元素间距
$space-lg: 24px // 大 - 大块间距
$space-xl: 32px // 极大 - 页面级间距
$space-2xl: 48px // 双倍极大
```
### 2.2 间距使用规则
```scss
// ✅ 正确用法
// 单个方向
.button {
margin-bottom: $space; // 12px
padding: $space-md; // 16px
margin-right: $space-sm; // 8px
}
// 组合方向
.header {
padding: $space-lg $space-md; // 24px 16px
margin: $space 0; // 12px 0
}
// ❌ 错误用法 - 不要这样做!
.button {
margin-bottom: 12px; // 不要使用硬编码值
padding: 5px; // 不要使用任意值
margin-right: 15px; // 必须使用变量
}
```
### 2.3 常见间距场景
```scss
// 页面顶层间距
.page {
padding: $space-lg; // 24px - 页面内边距
}
// 卡片间距
.card {
padding: $space-md; // 16px
margin-bottom: $space-lg; // 24px
}
// 表单项目间距
.form-item {
margin-bottom: $form-item-margin-bottom; // 16px
}
// 列表项目间距
.list-item {
padding: $space-md;
border-bottom: 1px solid $border-light;
&:not(:last-child) {
margin-bottom: 0; // 用 border 替代
}
}
// 按钮组间距
.button-group {
display: flex;
gap: $space-sm; // 8px
}
// 文字间距
.paragraph {
line-height: $line-height-lg; // 1.8
margin-bottom: $space; // 12px
}
```
---
## 3. 圆角规范
### 3.1 圆角系统
```typescript
$radius-0: 0 // 无圆角 - 锐角边缘
$radius-xs: 2px // 极小 - 微调
$radius-sm: 4px // 小 - 细微圆角
$radius: 6px // 默认 - 标准圆角(最常用)
$radius-lg: 8px // 大 - 明显圆角
$radius-xl: 12px // 极大 - 大圆角
$radius-2xl: 16px // 双倍极大
$radius-full: 9999px // 完全圆形(胶囊形)
```
### 3.2 圆角使用规则
```scss
// ✅ 正确用法
.card {
border-radius: $radius; // 6px - 卡片默认值
}
.badge {
border-radius: $radius-full; // 9999px - 圆形徽章
}
.button {
border-radius: $radius-sm; // 4px - 按钮圆角
}
.tag {
border-radius: $radius-sm; // 4px
}
.input {
border-radius: $radius-xs; // 2px - 输入框微调
}
// ❌ 不要这样做
.card {
border-radius: 8px; // 不要硬编码
border-radius: 50%; // 不要使用百分比
}
```
### 3.3 场景应用
```scss
// 页面卡片
.page-card {
background: $background-primary;
border-radius: $radius;
box-shadow: $shadow;
}
// 按钮
.btn {
border-radius: $radius-sm;
padding: $space-sm $space-md;
}
// 输入框
.input {
border-radius: $radius-xs;
border: 1px solid $border-color;
padding: $space-sm $space-sm;
}
// 头像(圆形)
.avatar {
border-radius: $radius-full;
width: 40px;
height: 40px;
}
// 标签
.tag {
display: inline-block;
padding: $space-xs $space-sm;
border-radius: $radius-sm;
background: $background-secondary;
}
```
---
## 4. 阴影规范
### 4.1 阴影系统
```typescript
$shadow-none: none // 无阴影
$shadow-xs: 0 1px 2px 0 rgba(0,0,0, 0.05)
$shadow-sm: 0 1px 2px 0 rgba(0,0,0, 0.06)
$shadow: 0 4px 6px -1px rgba(0,0,0, 0.1), 0 2px 4px -1px rgba(0,0,0, 0.06) // 默认
$shadow-md: 0 10px 15px -3px rgba(0,0,0, 0.1), 0 4px 6px -2px rgba(0,0,0, 0.05)
$shadow-lg: 0 20px 25px -5px rgba(0,0,0, 0.1), 0 10px 10px -5px rgba(0,0,0, 0.04)
$shadow-xl: 0 25px 50px -12px rgba(0,0,0, 0.25) // 强调
```
### 4.2 阴影使用规则
```scss
// ✅ 正确用法
// 卡片 - 使用标准阴影
.card {
background: $background-primary;
border-radius: $radius;
box-shadow: $shadow; // 标准阴影
padding: $space-md;
}
// 浮动元素 - 使用较强阴影
.floating-btn {
box-shadow: $shadow-lg; // 强调阴影
}
// 模态框 - 使用最强阴影
.modal {
box-shadow: $shadow-xl;
}
// 弱化分割线
.divider {
box-shadow: $shadow-xs; // 极弱阴影
height: 1px;
}
// ❌ 不要这样做
.card {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); // 不要硬编码
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.3); // 不要使用任意值
}
```
### 4.3 场景应用
| 场景 | 阴影 | 说明 |
| ---------- | ---------- | -------- |
| 页面背景 | none | 无需阴影 |
| 卡片 | $shadow | 标准卡片 |
| 列表项 | $shadow-xs | 弱化分割 |
| 下拉菜单 | $shadow-lg | 浮动显示 |
| 模态框背景 | $shadow-xl | 强调焦点 |
| 悬停状态 | $shadow-md | 交互反馈 |
| 输入框 | $shadow-xs | 焦点提示 |
---
## 5. 字体规范
### 5.1 字体大小系统
```typescript
$font-size-xs: 12px // 极小 - 说明文字
$font-size-sm: 13px // 小 - 辅助信息
$font-size: 14px // 默认 - 正文(最常用)
$font-size-md: 16px // 中 - 卡片标题
$font-size-lg: 18px // 大 - 页面二级标题
$font-size-xl: 20px // 极大 - 页面一级标题
$font-size-2xl: 24px // 双倍极大
$font-size-3xl: 30px // 三倍极大 - 页面主标题
```
### 5.2 行高和字重
```typescript
// 行高
$line-height-xs: 1.2 // 紧凑 - 标题
$line-height-sm: 1.4 // 小
$line-height: 1.6 // 默认 - 正文
$line-height-lg: 1.8 // 大
$line-height-xl: 2 // 特大 - 宽松
// 字重
$font-weight-normal: 400 // 常规
$font-weight-medium: 500 // 中等(用于强调)
$font-weight-semibold: 600 // 半粗体(用于标题)
$font-weight-bold: 700 // 粗体(强调标题)
```
### 5.3 排版规范
```scss
// ✅ 正确用法
// 页面主标题
.page-title {
font-size: $font-size-lg;
font-weight: $font-weight-bold;
color: $text-primary;
margin-bottom: $space-md;
}
// 卡片标题
.card-title {
font-size: $font-size-md;
font-weight: $font-weight-semibold;
color: $text-primary;
}
// 正文
.content {
font-size: $font-size;
line-height: $line-height;
color: $text-secondary;
}
// 说明文字
.description {
font-size: $font-size-sm;
color: $text-tertiary;
line-height: $line-height-sm;
}
// ❌ 不要这样做
.title {
font-size: 18px; // 不要硬编码
font-weight: bold; // 不要使用 bold
line-height: 1.5; // 不要硬编码
}
```
### 5.4 排版场景
```scss
// 标题层级
h1 {
font-size: $font-size-3xl;
font-weight: $font-weight-bold;
}
h2 {
font-size: $font-size-xl;
font-weight: $font-weight-bold;
}
h3 {
font-size: $font-size-lg;
font-weight: $font-weight-semibold;
}
h4 {
font-size: $font-size-md;
font-weight: $font-weight-medium;
}
// 段落
p {
font-size: $font-size;
line-height: $line-height;
margin-bottom: $space-md;
}
// 列表项
li {
font-size: $font-size;
line-height: $line-height;
margin-bottom: $space-sm;
}
// 表格
td {
font-size: $font-size;
line-height: $line-height;
padding: $space-sm;
}
```
---
## 6. 动画和过渡
### 6.1 过渡系统
```typescript
$transition-duration-fast: 0.1s
$transition-duration: 0.3s // 默认
$transition-duration-slow: 0.5s
$transition-timing-linear: linear // 匀速
$transition-timing: cubic-bezier(0.645, 0.045, 0.355, 1) // 标准缓动(推荐)
$transition-timing-ease-in: cubic-bezier(0.4, 0, 1, 1)
$transition-timing-ease-out: cubic-bezier(0, 0, 0.2, 1)
$transition-timing-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1)
```
### 6.2 过渡使用
```scss
// ✅ 正确用法
// 悬停效果
.button {
background: $primary-color;
transition: all $transition-duration $transition-timing;
&:active {
opacity: 0.8;
}
}
// 展开/折叠
.collapse {
transition: height $transition-duration $transition-timing;
}
// 淡入淡出
.fade-enter-active,
.fade-leave-active {
transition: opacity $transition-duration $transition-timing;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
```
---
## 7. 响应式设计
### 7.1 断点系统
```typescript
$breakpoint-xs: 320px // 极小屏幕
$breakpoint-sm: 576px // 小屏(平板)
$breakpoint-md: 768px // 中屏(平板)
$breakpoint-lg: 992px // 大屏(笔记本)
$breakpoint-xl: 1200px // 特大屏(桌面)
$breakpoint-2xl: 1600px // 超大屏
```
### 7.2 媒体查询使用
```scss
// 手机优先设计
.page {
padding: $space; // 手机12px
@media (min-width: $breakpoint-sm) {
padding: $space-md; // 平板16px
}
@media (min-width: $breakpoint-lg) {
padding: $space-lg; // 桌面24px
}
}
// 栅格布局
.grid {
display: grid;
grid-template-columns: 1fr; // 手机1列
@media (min-width: $breakpoint-sm) {
grid-template-columns: repeat(2, 1fr); // 平板2列
}
@media (min-width: $breakpoint-lg) {
grid-template-columns: repeat(3, 1fr); // 桌面3列
}
}
```
---
## 8. Z-index 管理
### 8.1 Z-index 系统
```typescript
$z-index-hide: -1
$z-index-base: 0
// 导航
$z-index-navbar: 100
$z-index-sidebar: 99
$z-index-sticky: 50
// 浮层
$z-index-dropdown: 1000
$z-index-popover: 1010
$z-index-tooltip: 1020
$z-index-modal-backdrop: 1040
$z-index-modal: 1050
$z-index-popconfirm: 1060
$z-index-notification: 1070
```
### 8.2 使用规则
```scss
.navbar {
z-index: $z-index-navbar; // 导航栏始终在最上
}
.modal-backdrop {
z-index: $z-index-modal-backdrop;
}
.modal {
z-index: $z-index-modal; // 模态框在背景上方
}
.tooltip {
z-index: $z-index-tooltip; // 提示框最高层
}
```
---
## 9. 常见组件样式
### 9.1 卡片Card
```uvue
<template>
<view class="card">
<view class="card-header">
<text class="card-title">卡片标题</text>
</view>
<view class="card-body">
<!-- 内容 -->
</view>
<view class="card-footer">
<!-- 底部 -->
</view>
</view>
</template>
<style scoped lang="scss">
.card {
background: $background-primary;
border-radius: $radius;
box-shadow: $shadow;
overflow: hidden;
}
.card-header {
padding: $space-md;
border-bottom: 1px solid $border-light;
}
.card-title {
font-size: $font-size-md;
font-weight: $font-weight-semibold;
color: $text-primary;
}
.card-body {
padding: $space-md;
}
.card-footer {
padding: $space-md;
border-top: 1px solid $border-light;
display: flex;
gap: $space-sm;
justify-content: flex-end;
}
</style>
```
### 9.2 按钮Button
```scss
.btn {
height: $btn-height;
padding: 0 $space-md;
border: none;
border-radius: $radius-sm;
font-size: $font-size;
font-weight: $font-weight-medium;
cursor: pointer;
transition: all $transition-duration $transition-timing;
display: inline-flex;
align-items: center;
justify-content: center;
gap: $space-xs;
// 主按钮
&.btn-primary {
background: $primary-color;
color: #fff;
&:active {
opacity: 0.8;
}
}
// 次按钮
&.btn-default {
background: $background-secondary;
color: $text-primary;
border: 1px solid $border-color;
&:active {
background: $border-light;
}
}
// 危险按钮
&.btn-danger {
background: $error-color;
color: #fff;
&:active {
opacity: 0.8;
}
}
// 尺寸
&.btn-sm {
height: $btn-height-sm;
font-size: $font-size-sm;
padding: 0 $space-sm;
}
&.btn-lg {
height: $btn-height-lg;
font-size: $font-size-md;
padding: 0 $space-lg;
}
// 禁用状态
&:disabled,
&.disabled {
opacity: 0.6;
cursor: not-allowed;
}
}
```
### 9.3 输入框Input
```scss
.input {
height: $input-height;
padding: 0 $space-sm;
border: 1px solid $border-color;
border-radius: $radius-xs;
font-size: $font-size;
color: $text-primary;
background: $background-primary;
transition: border-color $transition-duration $transition-timing;
&::placeholder {
color: $text-tertiary;
}
&:focus {
outline: none;
border-color: $primary-color;
box-shadow: 0 0 0 3px rgba($primary-color, 0.1);
}
&:disabled {
background: $background-secondary;
color: $text-disabled;
cursor: not-allowed;
}
// 尺寸变体
&.input-sm {
height: $input-height-sm;
}
&.input-lg {
height: $input-height-lg;
}
}
```
---
## 10. 完整示例:列表页面
```uvue
<template>
<view class="list-page">
<!-- 页面标题 -->
<view class="page-header">
<text class="page-title">数据列表</text>
<view class="page-actions">
<button class="btn btn-primary">新增</button>
<button class="btn btn-default">导出</button>
</view>
</view>
<!-- 搜索表单 -->
<view class="search-card">
<view class="form-item">
<text class="form-label">搜索:</text>
<input class="input" placeholder="请输入关键词" />
</view>
</view>
<!-- 列表内容 -->
<view class="list-card">
<view class="list-item" v-for="item in items" :key="item.id">
<view class="list-item-header">
<text class="list-item-title">{{ item.name }}</text>
<text class="list-item-status">{{ item.status }}</text>
</view>
<text class="list-item-desc">{{ item.description }}</text>
<view class="list-item-footer">
<text class="list-item-time">{{ item.createTime }}</text>
<view class="list-item-actions">
<button class="btn-link">编辑</button>
<button class="btn-link btn-danger">删除</button>
</view>
</view>
</view>
</view>
<!-- 分页 -->
<view class="pagination">
<button class="btn btn-sm">上一页</button>
<text>第 1 页,共 10 页</text>
<button class="btn btn-sm">下一页</button>
</view>
</view>
</template>
<script setup lang="uts">
import { ref } from 'vue'
const items = ref([
{ id: 1, name: '项目1', status: '进行中', description: '描述文本', createTime: '2024-01-01' },
{ id: 2, name: '项目2', status: '已完成', description: '描述文本', createTime: '2024-01-02' },
])
</script>
<style scoped lang="scss">
.list-page {
padding: $space-lg;
background: $background-tertiary;
}
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: $space-lg;
}
.page-title {
font-size: $font-size-lg;
font-weight: $font-weight-bold;
color: $text-primary;
}
.page-actions {
display: flex;
gap: $space-sm;
}
.search-card {
background: $background-primary;
border-radius: $radius;
padding: $space-md;
margin-bottom: $space-lg;
box-shadow: $shadow;
}
.form-item {
display: flex;
align-items: center;
gap: $space-md;
}
.form-label {
color: $text-secondary;
font-size: $font-size-sm;
}
.input {
height: $input-height;
padding: 0 $space-sm;
border: 1px solid $border-color;
border-radius: $radius-xs;
flex: 1;
}
.list-card {
background: $background-primary;
border-radius: $radius;
overflow: hidden;
box-shadow: $shadow;
margin-bottom: $space-lg;
}
.list-item {
padding: $space-md;
border-bottom: 1px solid $border-light;
&:last-child {
border-bottom: none;
}
}
.list-item-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: $space-sm;
}
.list-item-title {
font-size: $font-size-md;
font-weight: $font-weight-medium;
color: $text-primary;
}
.list-item-status {
font-size: $font-size-xs;
background: $background-secondary;
color: $text-secondary;
padding: $space-xs $space-sm;
border-radius: $radius-xs;
}
.list-item-desc {
font-size: $font-size-sm;
color: $text-secondary;
margin-bottom: $space-sm;
}
.list-item-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.list-item-time {
font-size: $font-size-xs;
color: $text-tertiary;
}
.list-item-actions {
display: flex;
gap: $space-sm;
}
.btn-link {
background: none;
border: none;
color: $primary-color;
padding: 0;
font-size: $font-size-sm;
cursor: pointer;
&.btn-danger {
color: $error-color;
}
}
.pagination {
display: flex;
justify-content: center;
align-items: center;
gap: $space-md;
padding: $space-lg 0;
}
</style>
```
---
## 总结
**必须遵循的规范**:
1. 所有色值必须使用 `$color-*` 变量
2. 所有间距必须使用 `$space-*` 变量
3. 所有圆角必须使用 `$radius-*` 变量
4. 所有阴影必须使用 `$shadow-*` 变量
5. 所有字体大小必须使用 `$font-size-*` 变量
6. 所有过渡必须使用 `$transition-*` 变量
**禁止**:
- 硬编码任何数值(色值、尺寸、间距等)
- 使用不规范的命名
- 创建局部样式变量与系统冲突
📝 **维护建议**:
- 定期审查样式规范的使用情况
- 在新增样式变量前,检查是否已有相近的
- 保持设计系统的一致性和可维护性
---
**文档版本**: 1.0
**最后更新**: 2026-01-31
**维护者**: AI Assistant