移动端样式系统概览
介绍
RuoYi-Plus-UniApp 移动端采用了完善的样式系统架构,结合 UniApp 内置样式变量、WD UI 组件库样式体系和 SCSS 预处理器,为开发者提供了灵活、可定制、高度统一的样式解决方案。样式系统基于 BEM 命名规范,支持主题定制、CSS 变量、暗黑模式,并提供了丰富的混合宏和工具函数,大大提升了样式开发效率和代码可维护性。
核心特性:
- 双层变量体系 - UniApp 内置变量 + WD UI 自定义变量,提供 200+ 可配置样式变量
- BEM 命名规范 - 采用 Block__Element--Modifier 命名方式,样式结构清晰易维护
- CSS Variables 主题 - 基于 CSS 自定义属性实现主题切换,支持亮色/暗黑模式
- SCSS 工具集 - 提供完整的混合宏和函数库,包括文本省略、边框、箭头等常用样式
- 响应式设计 - 使用 rpx 单位自适应不同屏幕尺寸
- 组件化样式 - 每个组件独立样式文件,支持按需加载和主题定制
样式系统为移动端提供了统一的视觉语言和开发规范,确保应用在不同平台(H5、小程序、App)上呈现一致的用户体验。通过 CSS 变量和 SCSS 预处理器的结合,开发者可以轻松实现主题切换、品牌定制和样式扩展。
样式架构
目录结构
plus-app/
├── style/
│ └── index.scss # 全局样式入口(主题定制)
├── uni.scss # UniApp 内置样式变量
└── wd/
└── components/
└── common/
└── abstracts/
├── _config.scss # BEM 命名配置
├── _function.scss # SCSS 工具函数
├── _mixin.scss # SCSS 混合宏
└── variable.scss # WD UI 样式变量(200+ 变量)样式加载顺序
样式系统采用分层架构,按照以下顺序加载:
- UniApp 内置变量 (
uni.scss) - 提供跨平台基础样式变量 - WD UI 配置 (
_config.scss) - BEM 命名空间和分隔符配置 - WD UI 函数 (
_function.scss) - 样式工具函数 - WD UI 混合宏 (
_mixin.scss) - 可复用样式片段 - WD UI 变量 (
variable.scss) - 组件样式变量定义 - 全局样式 (
style/index.scss) - 应用级样式定制 - 组件样式 - 各组件独立样式文件
这种分层架构确保了样式的可维护性和可扩展性,同时避免了样式冲突和重复定义。
样式继承关系
uni.scss (UniApp 基础)
↓
_config.scss (BEM 配置)
↓
_function.scss (工具函数)
↓
_mixin.scss (混合宏,依赖 config 和 function)
↓
variable.scss (样式变量,依赖 function)
↓
组件样式 (使用 mixin 和 variable)
↓
应用样式 (style/index.scss,可覆盖变量)UniApp 内置样式变量
变量分类
UniApp 提供了一套完整的内置样式变量,位于 uni.scss 文件中,这些变量在整个项目中全局可用,无需导入即可使用。
颜色变量
/* 行为相关颜色 */
$uni-color-primary: #007aff; // 主题色
$uni-color-success: #4cd964; // 成功色
$uni-color-warning: #f0ad4e; // 警告色
$uni-color-error: #dd524d; // 错误色
/* 文字基本颜色 */
$uni-text-color:#333; // 基本色
$uni-text-color-inverse:#fff; // 反色
$uni-text-color-grey:#999; // 辅助灰色
$uni-text-color-placeholder: #808080; // 占位文字
$uni-text-color-disable:#c0c0c0; // 禁用文字
/* 背景颜色 */
$uni-bg-color:#ffffff; // 主背景
$uni-bg-color-grey:#f8f8f8; // 灰色背景
$uni-bg-color-hover:#f1f1f1; // 点击状态
$uni-bg-color-mask:rgba(0, 0, 0, 0.4); // 遮罩
/* 边框颜色 */
$uni-border-color:#c8c7cc; // 边框色使用说明:
- 这些变量在所有 SCSS 文件中自动可用
- 建议优先使用 UniApp 变量保持跨平台一致性
- 可以在
uni.scss中修改变量值实现全局主题定制
尺寸变量
/* 文字尺寸 */
$uni-font-size-sm: 12px; // 小号字体
$uni-font-size-base: 14px; // 基础字体
$uni-font-size-lg: 16px; // 大号字体
/* 图片尺寸 */
$uni-img-size-sm: 20px; // 小图标
$uni-img-size-base: 26px; // 基础图标
$uni-img-size-lg: 40px; // 大图标
/* 圆角尺寸 */
$uni-border-radius-sm: 2px; // 小圆角
$uni-border-radius-base: 3px; // 基础圆角
$uni-border-radius-lg: 6px; // 大圆角
$uni-border-radius-circle: 50%; // 圆形
/* 间距尺寸 */
$uni-spacing-row-sm: 5px; // 水平小间距
$uni-spacing-row-base: 10px; // 水平基础间距
$uni-spacing-row-lg: 15px; // 水平大间距
$uni-spacing-col-sm: 4px; // 垂直小间距
$uni-spacing-col-base: 8px; // 垂直基础间距
$uni-spacing-col-lg: 12px; // 垂直大间距
/* 透明度 */
$uni-opacity-disabled: 0.3; // 禁用态透明度使用示例:
<template>
<view class="container">
<text class="title">标题文字</text>
<view class="button">按钮</view>
</view>
</template>
<style lang="scss" scoped>
.container {
padding: $uni-spacing-row-base $uni-spacing-col-base;
background-color: $uni-bg-color;
}
.title {
font-size: $uni-font-size-lg;
color: $uni-text-color;
margin-bottom: $uni-spacing-row-sm;
}
.button {
padding: $uni-spacing-row-base $uni-spacing-col-lg;
background-color: $uni-color-primary;
color: $uni-text-color-inverse;
border-radius: $uni-border-radius-base;
&:hover {
background-color: $uni-bg-color-hover;
}
}
</style>文章场景变量
/* 文章相关颜色和尺寸 */
$uni-color-title: #2C405A; // 文章标题颜色
$uni-font-size-title: 20px; // 标题字号
$uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle: 26px; // 二级标题字号
$uni-color-paragraph: #3F536E; // 段落颜色
$uni-font-size-paragraph: 15px; // 段落字号应用场景:
这些变量专门为富文本、文章详情等内容型页面设计,提供了清晰的视觉层次:
<template>
<view class="article">
<text class="article-title">文章标题</text>
<text class="article-subtitle">副标题</text>
<text class="article-paragraph">
文章内容段落文字...
</text>
</view>
</template>
<style lang="scss" scoped>
.article {
padding: 32rpx;
&-title {
font-size: $uni-font-size-title;
color: $uni-color-title;
font-weight: bold;
margin-bottom: 16rpx;
}
&-subtitle {
font-size: $uni-font-size-subtitle;
color: $uni-color-subtitle;
margin-bottom: 24rpx;
}
&-paragraph {
font-size: $uni-font-size-paragraph;
color: $uni-color-paragraph;
line-height: 1.6;
}
}
</style>变量定制
全局定制
在 uni.scss 文件中修改变量值可实现全局主题定制:
/* 自定义主题色 */
$uni-color-primary: #1890ff; // 改为蓝色主题
$uni-color-success: #52c41a; // 改为绿色成功
$uni-color-warning: #faad14; // 改为橙色警告
$uni-color-error: #f5222d; // 改为红色错误
/* 自定义文字大小 */
$uni-font-size-base: 16px; // 放大基础字号
/* 自定义圆角 */
$uni-border-radius-base: 8px; // 增大圆角组件级定制
在具体组件中可以覆盖或组合使用这些变量:
<style lang="scss" scoped>
.custom-button {
// 使用 UniApp 变量
background-color: $uni-color-primary;
color: $uni-text-color-inverse;
// 组合使用
padding: $uni-spacing-row-lg $uni-spacing-col-lg;
border-radius: $uni-border-radius-lg;
font-size: $uni-font-size-lg;
// 覆盖定制
&.large {
padding: calc($uni-spacing-row-lg * 1.5) calc($uni-spacing-col-lg * 2);
font-size: calc($uni-font-size-lg * 1.2);
}
}
</style>WD UI 样式系统
BEM 命名规范
WD UI 组件库采用 BEM(Block Element Modifier)命名规范,提供清晰的样式结构和良好的可维护性。
配置定义
在 _config.scss 中定义了 BEM 命名规则:
$namespace: 'wd'; // 命名空间
$elementSeparator: '__'; // 元素分隔符
$modifierSeparator: '--'; // 修饰符分隔符
$state-prefix: 'is-'; // 状态前缀命名结构
.wd-{block} // 块
.wd-{block}__{element} // 元素
.wd-{block}--{modifier} // 修饰符
.wd-{block}.is-{state} // 状态实际示例:
// 按钮组件
.wd-button { } // 块: 按钮
.wd-button__icon { } // 元素: 按钮内的图标
.wd-button--primary { } // 修饰符: 主要按钮类型
.wd-button.is-disabled { } // 状态: 禁用状态
.wd-button.is-loading { } // 状态: 加载状态
// 单元格组件
.wd-cell { } // 块: 单元格
.wd-cell__title { } // 元素: 标题
.wd-cell__value { } // 元素: 值
.wd-cell__label { } // 元素: 描述
.wd-cell--large { } // 修饰符: 大尺寸
.wd-cell.is-link { } // 状态: 可点击链接混合宏使用
WD UI 提供了一套完整的 BEM 混合宏,简化样式编写:
// 定义块
@include b(button) {
display: inline-flex;
// 定义元素
@include e(icon) {
margin-right: 8rpx;
}
// 定义修饰符
@include m(primary) {
background-color: $-color-theme;
color: $-color-white;
}
@include m(large) {
height: $-button-large-height;
font-size: $-button-large-fs;
}
// 定义状态
@include when(disabled) {
opacity: $-button-disabled-opacity;
cursor: not-allowed;
}
@include when(loading) {
pointer-events: none;
}
}生成的 CSS:
.wd-button {
display: inline-flex;
}
.wd-button__icon {
margin-right: 8rpx;
}
.wd-button--primary {
background-color: var(--wot-color-theme, #4d80f0);
color: var(--wot-color-white, rgb(255, 255, 255));
}
.wd-button--large {
height: var(--wot-button-large-height, 88rpx);
font-size: var(--wot-button-large-fs, 32rpx);
}
.wd-button.is-disabled {
opacity: var(--wot-button-disabled-opacity, 0.6);
cursor: not-allowed;
}
.wd-button.is-loading {
pointer-events: none;
}深度样式穿透
对于需要穿透 scoped 样式的场景,提供了 edeep 和 mdeep 混合宏:
@include b(popup) {
// 普通元素定义
@include e(container) {
position: relative;
}
// 穿透样式定义
@include edeep(content) {
// 这里的样式会穿透 scoped
padding: 32rpx;
}
// 穿透修饰符
@include mdeep(center) {
display: flex;
justify-content: center;
}
}生成的 CSS:
.wd-popup__container {
position: relative;
}
:deep() .wd-popup__content {
padding: 32rpx;
}
:deep() .wd-popup--center {
display: flex;
justify-content: center;
}样式变量体系
WD UI 定义了 200+ 个样式变量,涵盖主题色、组件样式、尺寸间距等各个方面。所有变量都基于 CSS Variables 实现,支持动态主题切换。
主题色变量
/* 主色调 */
$-color-theme: var(--wot-color-theme, #4d80f0); // 主题色
$-color-white: var(--wot-color-white, rgb(255, 255, 255)); // 白色
$-color-black: var(--wot-color-black, rgb(0, 0, 0)); // 黑色
/* 辅助色 */
$-color-success: var(--wot-color-success, #34d19d); // 成功色
$-color-warning: var(--wot-color-warning, #f0883a); // 警告色
$-color-danger: var(--wot-color-danger, #fa4350); // 危险色
$-color-purple: var(--wot-color-purple, #8268de); // 紫色
$-color-yellow: var(--wot-color-yellow, #f0cd1d); // 黄色
$-color-blue: var(--wot-color-blue, #2bb3ed); // 蓝色
$-color-info: var(--wot-color-info, #909399); // 信息色
/* 灰度色 */
$-color-gray-1: var(--wot-color-gray-1, #f9f9f9); // 最浅
$-color-gray-2: var(--wot-color-gray-2, #f2f3f5);
$-color-gray-3: var(--wot-color-gray-3, #ebedf0);
$-color-gray-4: var(--wot-color-gray-4, #dcdee0);
$-color-gray-5: var(--wot-color-gray-5, #c8c9cc);
$-color-gray-6: var(--wot-color-gray-6, #969799);
$-color-gray-7: var(--wot-color-gray-7, #646566);
$-color-gray-8: var(--wot-color-gray-8, #323233); // 最深使用示例:
<template>
<view class="card">
<view class="card-header">标题</view>
<view class="card-body">内容</view>
<view class="card-footer">
<view class="btn btn-primary">确定</view>
<view class="btn btn-default">取消</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.card {
background: $-color-white;
border: 1px solid $-color-gray-3;
border-radius: 16rpx;
&-header {
padding: 32rpx;
border-bottom: 1px solid $-color-gray-2;
font-weight: 500;
}
&-body {
padding: 32rpx;
color: $-color-gray-7;
}
&-footer {
padding: 24rpx 32rpx;
display: flex;
gap: 16rpx;
}
}
.btn {
flex: 1;
height: 72rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8rpx;
&-primary {
background: $-color-theme;
color: $-color-white;
}
&-default {
background: $-color-gray-2;
color: $-color-gray-7;
}
}
</style>文字颜色变量
/* 浅色背景下的文字颜色 */
$-color-title: var(--wot-color-title, #000); // 标题/重要正文
$-color-content: var(--wot-color-content, #262626); // 普通正文
$-color-secondary: var(--wot-color-secondary, #595959); // 次要信息
$-color-aid: var(--wot-color-aid, #8c8c8c); // 辅助文字
$-color-tip: var(--wot-color-tip, #bfbfbf); // 失效/默认提示
$-color-border: var(--wot-color-border, #d9d9d9); // 边框线
$-color-border-light: var(--wot-color-border-light, #e8e8e8); // 分割线
$-color-bg: var(--wot-color-bg, #f5f5f5); // 背景色
/* 透明度文字颜色 */
$-font-gray-1: var(--wot-font-gray-1, rgba(0, 0, 0, 0.9)); // 主要文字
$-font-gray-2: var(--wot-font-gray-2, rgba(0, 0, 0, 0.6)); // 次要文字
$-font-gray-3: var(--wot-font-gray-3, rgba(0, 0, 0, 0.4)); // 辅助文字
$-font-gray-4: var(--wot-font-gray-4, rgba(0, 0, 0, 0.26)); // 禁用文字
$-font-white-1: var(--wot-font-white-1, rgba(255, 255, 255, 1)); // 白色主要
$-font-white-2: var(--wot-font-white-2, rgba(255, 255, 255, 0.55)); // 白色次要
$-font-white-3: var(--wot-font-white-3, rgba(255, 255, 255, 0.35)); // 白色辅助
$-font-white-4: var(--wot-font-white-4, rgba(255, 255, 255, 0.22)); // 白色禁用应用场景:
<template>
<view class="info-card">
<text class="title">这是标题文字</text>
<text class="content">这是普通正文内容</text>
<text class="secondary">这是次要信息文字</text>
<text class="aid">这是辅助引导文字</text>
<text class="tip">这是失效提示文字</text>
</view>
</template>
<style lang="scss" scoped>
.info-card {
padding: 32rpx;
background: $-color-white;
text {
display: block;
margin-bottom: 16rpx;
}
.title {
font-size: 32rpx;
color: $-color-title; // rgba(0, 0, 0, 1) 或 #000
font-weight: 600;
}
.content {
font-size: 28rpx;
color: $-color-content; // #262626
line-height: 1.5;
}
.secondary {
font-size: 28rpx;
color: $-color-secondary; // #595959
}
.aid {
font-size: 24rpx;
color: $-color-aid; // #8c8c8c
}
.tip {
font-size: 24rpx;
color: $-color-tip; // #bfbfbf
}
}
</style>暗黑模式变量
/* 暗黑模式颜色 */
$-dark-background: var(--wot-dark-background, #131313); // 主背景
$-dark-background2: var(--wot-dark-background2, #1b1b1b); // 次背景
$-dark-background3: var(--wot-dark-background3, #141414); // 三级背景
$-dark-background4: var(--wot-dark-background4, #323233); // 四级背景
$-dark-background5: var(--wot-dark-background5, #646566); // 五级背景
$-dark-background6: var(--wot-dark-background6, #380e08); // 危险背景
$-dark-background7: var(--wot-dark-background7, #707070); // 禁用背景
$-dark-color: var(--wot-dark-color, $-color-white); // 主文字色
$-dark-color2: var(--wot-dark-color2, #f2270c); // 强调色
$-dark-color3: var(--wot-dark-color3, rgba(232, 230, 227, 0.8)); // 次要文字
$-dark-color-gray: var(--wot-dark-color-gray, $-color-secondary); // 灰色文字
$-dark-border-color: var(--wot-dark-border-color, #3a3a3c); // 边框色暗黑模式适配示例:
<template>
<view class="theme-card" :class="{ 'is-dark': isDark }">
<view class="card-bg">背景层</view>
<text class="card-text">文字内容</text>
<view class="card-border">边框</view>
</view>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const isDark = ref(false)
</script>
<style lang="scss" scoped>
.theme-card {
padding: 32rpx;
background: $-color-white;
color: $-color-title;
border: 1px solid $-color-border;
// 暗黑模式样式
&.is-dark {
background: $-dark-background;
color: $-dark-color;
border-color: $-dark-border-color;
.card-bg {
background: $-dark-background2;
}
.card-text {
color: $-dark-color3;
}
}
}
.card-bg {
padding: 24rpx;
background: $-color-bg;
margin-bottom: 16rpx;
}
.card-text {
font-size: 28rpx;
color: $-color-content;
margin-bottom: 16rpx;
}
.card-border {
padding: 16rpx;
border: 1px solid $-color-border;
}
</style>字体变量
/* 文字字号 */
$-fs-big: var(--wot-fs-big, 48rpx); // 大型标题
$-fs-important: var(--wot-fs-important, 38rpx); // 重要数据
$-fs-title: var(--wot-fs-title, 32rpx); // 标题/重要正文
$-fs-content: var(--wot-fs-content, 28rpx); // 普通正文
$-fs-secondary: var(--wot-fs-secondary, 24rpx); // 次要信息
$-fs-aid: var(--wot-fs-aid, 20rpx); // 辅助文字
/* 文字字重 */
$-fw-medium: var(--wot-fw-medium, 500); // PingFangSC-Medium
$-fw-semibold: var(--wot-fw-semibold, 600); // PingFangSC-Semibold字体使用示例:
<template>
<view class="typography">
<text class="big-title">大型标题 48rpx</text>
<text class="important">重要数据 38rpx</text>
<text class="title">标题文字 32rpx</text>
<text class="content">正文内容 28rpx</text>
<text class="secondary">次要信息 24rpx</text>
<text class="aid">辅助文字 20rpx</text>
</view>
</template>
<style lang="scss" scoped>
.typography {
padding: 32rpx;
text {
display: block;
margin-bottom: 24rpx;
}
.big-title {
font-size: $-fs-big;
font-weight: $-fw-semibold;
color: $-color-title;
}
.important {
font-size: $-fs-important;
font-weight: $-fw-medium;
color: $-color-theme;
}
.title {
font-size: $-fs-title;
font-weight: $-fw-medium;
color: $-color-title;
}
.content {
font-size: $-fs-content;
color: $-color-content;
line-height: 1.5;
}
.secondary {
font-size: $-fs-secondary;
color: $-color-secondary;
}
.aid {
font-size: $-fs-aid;
color: $-color-aid;
}
}
</style>尺寸变量
/* 通用尺寸 */
$-size-side-padding: var(--wot-size-side-padding, 30rpx); // 屏幕两边留白
$-size-side-padding-small: var(--wot-size-side-padding-small, 12rpx); // 小留白这些尺寸变量用于保持应用的整体一致性:
<template>
<view class="page">
<view class="section">
<text class="section-title">标准间距示例</text>
<view class="content">
内容区域使用标准边距
</view>
</view>
<view class="compact-section">
<text class="section-title">紧凑间距示例</text>
<view class="content">
内容区域使用紧凑边距
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.page {
min-height: 100vh;
background: $-color-bg;
}
.section {
// 使用标准边距
padding: 32rpx $-size-side-padding;
background: $-color-white;
margin-bottom: 20rpx;
.section-title {
font-size: $-fs-title;
font-weight: $-fw-medium;
color: $-color-title;
margin-bottom: 16rpx;
}
.content {
font-size: $-fs-content;
color: $-color-content;
line-height: 1.5;
}
}
.compact-section {
// 使用紧凑边距
padding: 24rpx $-size-side-padding-small;
background: $-color-white;
.section-title {
font-size: $-fs-content;
color: $-color-title;
margin-bottom: 12rpx;
}
.content {
font-size: $-fs-secondary;
color: $-color-secondary;
line-height: 1.4;
}
}
</style>组件变量
WD UI 为每个组件都定义了专属的样式变量,以 Button 按钮组件为例:
/* Button 按钮变量 */
$-button-disabled-opacity: var(--wot-button-disabled-opacity, 0.6);
$-button-small-height: var(--wot-button-small-height, 48rpx);
$-button-small-padding: var(--wot-button-small-padding, 0 24rpx);
$-button-small-fs: var(--wot-button-small-fs, $-fs-secondary);
$-button-small-radius: var(--wot-button-small-radius, 4rpx);
$-button-small-loading: var(--wot-button-small-loading, 28rpx);
$-button-medium-height: var(--wot-button-medium-height, 72rpx);
$-button-medium-padding: var(--wot-button-medium-padding, 0 32rpx);
$-button-medium-fs: var(--wot-button-medium-fs, $-fs-content);
$-button-medium-radius: var(--wot-button-medium-radius, 8rpx);
$-button-medium-loading: var(--wot-button-medium-loading, 36rpx);
$-button-large-height: var(--wot-button-large-height, 88rpx);
$-button-large-padding: var(--wot-button-large-padding, 0 72rpx);
$-button-large-fs: var(--wot-button-large-fs, $-fs-title);
$-button-large-radius: var(--wot-button-large-radius, 16rpx);
$-button-large-loading: var(--wot-button-large-loading, 48rpx);
$-button-primary-color: var(--wot-button-primary-color, $-color-white);
$-button-primary-bg-color: var(--wot-button-primary-bg-color, $-color-theme);
$-button-success-color: var(--wot-button-success-color, $-color-white);
$-button-success-bg-color: var(--wot-button-success-bg-color, $-color-success);
$-button-warning-color: var(--wot-button-warning-color, $-color-white);
$-button-warning-bg-color: var(--wot-button-warning-bg-color, $-color-warning);
$-button-error-color: var(--wot-button-error-color, $-color-white);
$-button-error-bg-color: var(--wot-button-error-bg-color, $-color-danger);每个组件都有类似的变量定义,详细列表请参考 variable.scss 文件。
SCSS 混合宏
WD UI 提供了一套完善的 SCSS 混合宏,简化常用样式的编写。
BEM 混合宏
/**
* Block - 定义块
*/
@include b(card) {
background: white;
}
// 生成: .wd-card { background: white; }
/**
* Element - 定义元素
*/
@include b(card) {
@include e(header) {
padding: 16rpx;
}
@include e(body) {
padding: 32rpx;
}
}
// 生成:
// .wd-card__header { padding: 16rpx; }
// .wd-card__body { padding: 32rpx; }
/**
* Modifier - 定义修饰符
*/
@include b(card) {
@include m(shadow) {
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
}
@include m(bordered) {
border: 1px solid #eee;
}
}
// 生成:
// .wd-card--shadow { box-shadow: ...; }
// .wd-card--bordered { border: ...; }
/**
* When - 定义状态
*/
@include b(card) {
@include when(disabled) {
opacity: 0.6;
}
@include when(active) {
transform: scale(0.98);
}
}
// 生成:
// .wd-card.is-disabled { opacity: 0.6; }
// .wd-card.is-active { transform: scale(0.98); }组合使用示例:
@include b(list-item) {
display: flex;
padding: 24rpx 32rpx;
background: $-color-white;
// 元素: 图标
@include e(icon) {
width: 48rpx;
height: 48rpx;
margin-right: 16rpx;
}
// 元素: 内容
@include e(content) {
flex: 1;
@include e(title) {
font-size: $-fs-content;
color: $-color-title;
}
@include e(desc) {
font-size: $-fs-secondary;
color: $-color-secondary;
margin-top: 8rpx;
}
}
// 元素: 箭头
@include e(arrow) {
width: 24rpx;
height: 24rpx;
color: $-color-border;
}
// 修饰符: 大尺寸
@include m(large) {
padding: 32rpx;
@include me(icon) {
width: 64rpx;
height: 64rpx;
}
}
// 状态: 禁用
@include when(disabled) {
opacity: 0.5;
cursor: not-allowed;
}
// 状态: 活动
@include when(active) {
background: $-color-gray-1;
}
}生成的 CSS 结构:
.wd-list-item { display: flex; padding: 24rpx 32rpx; background: #fff; }
.wd-list-item__icon { width: 48rpx; height: 48rpx; margin-right: 16rpx; }
.wd-list-item__content { flex: 1; }
.wd-list-item__content__title { font-size: 28rpx; color: #000; }
.wd-list-item__content__desc { font-size: 24rpx; color: #595959; margin-top: 8rpx; }
.wd-list-item__arrow { width: 24rpx; height: 24rpx; color: #d9d9d9; }
.wd-list-item--large { padding: 32rpx; }
.wd-list-item--large .wd-list-item__icon { width: 64rpx; height: 64rpx; }
.wd-list-item.is-disabled { opacity: 0.5; cursor: not-allowed; }
.wd-list-item.is-active { background: #f9f9f9; }文本处理混合宏
/**
* 单行文本省略
*/
@mixin lineEllipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// 使用示例
.title {
@include lineEllipsis;
max-width: 200rpx;
}
/**
* 多行文本省略
* @param {number} $lineNumber - 显示行数,默认 3
*/
@mixin multiEllipsis($lineNumber: 3) {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: $lineNumber;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-word;
}
// 使用示例
.description {
@include multiEllipsis(2); // 显示 2 行
}
.content {
@include multiEllipsis(5); // 显示 5 行
}实际应用:
<template>
<view class="card-list">
<view class="card-item">
<text class="card-title">这是一个很长的标题文字会被截断显示省略号</text>
<text class="card-desc">
这是一段很长的描述文字内容,
超过两行会被截断并显示省略号,
用户可以通过点击查看完整内容
</text>
</view>
</view>
</template>
<style lang="scss" scoped>
.card-item {
padding: 24rpx;
background: $-color-white;
margin-bottom: 16rpx;
}
.card-title {
display: block;
font-size: $-fs-title;
color: $-color-title;
margin-bottom: 12rpx;
// 单行省略
@include lineEllipsis;
}
.card-desc {
display: block;
font-size: $-fs-content;
color: $-color-content;
line-height: 1.5;
// 两行省略
@include multiEllipsis(2);
}
</style>边框混合宏
/**
* 0.5px 边框 - 指定方向
* @param {string} $direction - 方向: "top" | "bottom"
* @param {size} $left - 左侧偏移量
* @param {color} $color - 边框颜色
*/
@mixin halfPixelBorder($direction: "bottom", $left: 0, $color: $-color-border-light) {
position: relative;
&::after {
position: absolute;
display: block;
content: "";
width: calc(100% - #{$left});
height: 1px;
left: $left;
background: $color;
transform: scaleY(0.5);
@if ($direction == "bottom") {
bottom: 0;
} @else {
top: 0;
}
}
}
/**
* 0.5px 边框 - 环绕
* @param {color} $color - 边框颜色
*/
@mixin halfPixelBorderSurround($color: $-color-border-light) {
position: relative;
&::after {
position: absolute;
display: block;
content: ' ';
pointer-events: none;
width: 200%;
height: 200%;
left: 0;
top: 0;
border: 1px solid $color;
transform: scale(0.5);
box-sizing: border-box;
transform-origin: left top;
}
}使用示例:
<template>
<view class="list">
<view class="list-item">底部 0.5px 边框</view>
<view class="list-item">底部 0.5px 边框</view>
<view class="bordered-box">环绕 0.5px 边框</view>
</view>
</template>
<style lang="scss" scoped>
.list-item {
padding: 32rpx;
background: $-color-white;
// 底部边框,左侧偏移 32rpx
@include halfPixelBorder("bottom", 32rpx, $-color-border-light);
}
.bordered-box {
margin: 32rpx;
padding: 32rpx;
background: $-color-white;
border-radius: 16rpx;
// 四周环绕边框
@include halfPixelBorderSurround($-color-border);
}
</style>其他实用混合宏
/**
* 清除浮动
*/
@mixin clearFloat {
&::after {
display: block;
content: "";
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
}
/**
* 清除按钮默认样式
*/
@mixin buttonClear {
outline: none;
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
background: transparent;
}
// 使用示例
button {
@include buttonClear;
// 自定义按钮样式
padding: 16rpx 32rpx;
border: 1px solid $-color-theme;
color: $-color-theme;
}箭头混合宏
/**
* 三角形箭头(适用于透明背景)
* @param {size} $size - 三角形高度,底边为 $size * 2
* @param {color} $bg - 三角形背景颜色
*/
@mixin triangleArrow($size, $bg) {
@include e(arrow) {
position: absolute;
width: 0;
height: 0;
}
@include e(arrow-down) {
border-left: $size solid transparent;
border-right: $size solid transparent;
border-top: $size solid $bg;
transform: translateX(-50%);
bottom: calc(-1 * #{$size});
}
@include e(arrow-up) {
border-left: $size solid transparent;
border-right: $size solid transparent;
border-bottom: $size solid $bg;
transform: translateX(-50%);
top: calc(-1 * #{$size});
}
@include e(arrow-left) {
border-top: $size solid transparent;
border-bottom: $size solid transparent;
border-right: $size solid $bg;
transform: translateY(-50%);
left: calc(-1 * #{$size});
}
@include e(arrow-right) {
border-top: $size solid transparent;
border-bottom: $size solid transparent;
border-left: $size solid $bg;
transform: translateY(-50%);
right: calc(-1 * #{$size});
}
}
/**
* 正方形箭头(适用于不透明背景)
* @param {size} $size - 正方形边长
* @param {color} $bg - 正方形背景颜色
* @param {number} $z-index - z-index 属性值
* @param {shadow} $box-shadow - 阴影
*/
@mixin squareArrow($size, $bg, $z-index, $box-shadow) {
@include e(arrow) {
position: absolute;
width: $size;
height: $size;
z-index: $z-index;
}
@include e(arrow-down) {
transform: translateX(-50%);
bottom: 0;
&:after {
content: "";
width: $size;
height: $size;
background-color: $bg;
position: absolute;
left: 0;
bottom: calc(-1 * #{$size} / 2);
transform: rotateZ(45deg);
box-shadow: $box-shadow;
}
}
// arrow-up, arrow-left, arrow-right 类似...
}箭头使用示例:
<template>
<view class="tooltip">
<view class="tooltip-content">提示内容</view>
<view class="tooltip__arrow-down"></view>
</view>
</template>
<style lang="scss" scoped>
@include b(tooltip) {
position: relative;
padding: 16rpx 24rpx;
background: $-color-gray-8;
color: $-color-white;
border-radius: 8rpx;
// 生成三角形箭头
@include triangleArrow(12rpx, $-color-gray-8);
}
// 使用时只需添加对应类名
// <view class="tooltip__arrow-down"></view> 向下箭头
// <view class="tooltip__arrow-up"></view> 向上箭头
// <view class="tooltip__arrow-left"></view> 向左箭头
// <view class="tooltip__arrow-right"></view> 向右箭头
</style>SCSS 工具函数
WD UI 提供了一套工具函数用于样式计算和主题处理。
字符串处理函数
/**
* 将选择器转换为字符串
*/
@function selectorToString($selector) {
$selector: inspect($selector);
$selector: str-slice($selector, 2, -2);
@return $selector;
}
/**
* 判断选择器是否包含修饰符
*/
@function containsModifier($selector) {
$selector: selectorToString($selector);
@if str-index($selector, $modifierSeparator) {
@return true;
} @else {
@return false;
}
}
/**
* 判断选择器是否包含伪类
*/
@function containsPseudo($selector) {
$selector: selectorToString($selector);
@if str-index($selector, ':') {
@return true;
} @else {
@return false;
}
}这些函数主要用于 BEM 混合宏的内部实现,一般不需要直接使用。
主题色函数
/**
* 主题色变换
* @param {color} $theme-color - 主题色
* @param {string} $type - 变暗 'dark' 或变亮 'light'
* @param {color} $mix-color - 自定义混色
*/
@function themeColor($theme-color, $type: "", $mix-color: "") {
@if $default-theme != #4d80f0 {
@if $type == "dark" {
@return darken($theme-color, 10%);
} @else if $type == "light" {
@return lighten($theme-color, 10%);
} @else {
@return $theme-color;
}
} @else {
@return $mix-color;
}
}
/**
* 渐变色生成
* @param {angle} $deg - 渐变角度
* @param {color} $theme-color - 主题色
* @param {list} $set - 明暗设置列表
* @param {list} $color-list - 渐变色列表
* @param {list} $per-list - 渐变位置列表
*/
@function resultColor($deg, $theme-color, $set, $color-list, $per-list) {
$len: length($color-list);
$arg: $deg;
@for $i from 1 through $len {
$arg: $arg + "," + themeColor($theme-color, nth($set, $i), nth($color-list, $i)) + " " + nth($per-list, $i);
}
@return linear-gradient(unquote($arg));
}主题色函数使用示例:
// 定义主题色
$primary-color: #4d80f0;
.button {
background: $primary-color;
&:hover {
// 变暗 10%
background: themeColor($primary-color, "dark");
}
&.light {
// 变亮 10%
background: themeColor($primary-color, "light");
}
}
// 渐变按钮
.gradient-button {
background: resultColor(
90deg, // 渐变角度
$primary-color, // 主题色
("", "light"), // 明暗设置
(#667eea, #764ba2), // 渐变色
(0%, 100%) // 位置
);
}主题定制
CSS Variables 定制
WD UI 所有样式变量都基于 CSS Variables 实现,可以在运行时动态修改主题。
全局主题定制
在 style/index.scss 中定义全局主题变量:
:root,
page {
// 修改主题色
--wot-color-theme: #1890ff;
// 修改成功色
--wot-color-success: #52c41a;
// 修改警告色
--wot-color-warning: #faad14;
// 修改危险色
--wot-color-danger: #f5222d;
// 修改按钮相关
--wot-button-primary-bg-color: #1890ff;
--wot-button-large-height: 96rpx;
--wot-button-large-radius: 48rpx;
// 修改字体大小
--wot-fs-title: 36rpx;
--wot-fs-content: 30rpx;
}组件级定制
可以为特定组件实例定义自定义样式:
<template>
<wd-button class="custom-button" type="primary">
自定义按钮
</wd-button>
</template>
<style lang="scss" scoped>
.custom-button {
// 仅修改这个按钮的样式
--wot-button-primary-bg-color: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
--wot-button-large-height: 100rpx;
--wot-button-large-radius: 50rpx;
}
</style>动态主题切换
通过 JavaScript 动态修改 CSS Variables:
<template>
<view class="theme-demo">
<view class="theme-buttons">
<button @click="setTheme('blue')">蓝色主题</button>
<button @click="setTheme('green')">绿色主题</button>
<button @click="setTheme('purple')">紫色主题</button>
</view>
<view class="demo-content">
<wd-button type="primary">主题按钮</wd-button>
<wd-badge :value="10">徽标</wd-badge>
</view>
</view>
</template>
<script lang="ts" setup>
const themes = {
blue: {
'--wot-color-theme': '#1890ff',
'--wot-color-success': '#52c41a'
},
green: {
'--wot-color-theme': '#52c41a',
'--wot-color-success': '#1890ff'
},
purple: {
'--wot-color-theme': '#722ed1',
'--wot-color-success': '#eb2f96'
}
}
const setTheme = (themeName: 'blue' | 'green' | 'purple') => {
const theme = themes[themeName]
const root = document.documentElement || document.querySelector('page')
Object.keys(theme).forEach(key => {
root.style.setProperty(key, theme[key])
})
}
</script>暗黑模式支持
WD UI 内置了暗黑模式支持,通过切换类名即可启用暗黑模式。
暗黑模式配置
<template>
<view :class="{ 'dark-mode': isDark }">
<view class="page-content">
<!-- 页面内容 -->
</view>
</view>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const isDark = ref(false)
const toggleDarkMode = () => {
isDark.value = !isDark.value
}
</script>
<style lang="scss" scoped>
.page-content {
background: $-color-white;
color: $-color-title;
// 暗黑模式样式
.dark-mode & {
background: $-dark-background;
color: $-dark-color;
}
}
</style>暗黑模式 CSS Variables
也可以通过 CSS Variables 实现暗黑模式:
:root {
--bg-color: #ffffff;
--text-color: #000000;
--border-color: #e8e8e8;
}
// 暗黑模式变量
.dark-mode {
--bg-color: #131313;
--text-color: #ffffff;
--border-color: #3a3a3c;
}
// 使用变量
.container {
background: var(--bg-color);
color: var(--text-color);
border: 1px solid var(--border-color);
}响应式设计
rpx 单位
RuoYi-Plus-UniApp 移动端统一使用 rpx 单位实现响应式布局。rpx 是 UniApp 提供的响应式单位,会根据屏幕宽度自动计算。
rpx 计算规则:
- 设计稿基准: 750rpx = 屏幕宽度
- iPhone6 (375px): 1rpx = 0.5px
- iPhone6 Plus (414px): 1rpx = 0.552px
使用示例:
<template>
<view class="responsive-box">
<view class="box-header">
<text class="title">响应式标题</text>
</view>
<view class="box-body">
<text class="content">响应式内容区域</text>
</view>
</view>
</template>
<style lang="scss" scoped>
.responsive-box {
width: 750rpx; // 满屏宽度
padding: 32rpx; // 内边距
background: $-color-white;
}
.box-header {
height: 88rpx; // 固定高度
padding: 0 32rpx;
border-bottom: 1px solid $-color-border-light;
.title {
font-size: 32rpx; // 字体大小
line-height: 88rpx;
}
}
.box-body {
padding: 24rpx 32rpx;
.content {
font-size: 28rpx;
line-height: 1.5;
}
}
</style>屏幕尺寸适配
对于不同尺寸的设备,可以使用条件编译或媒体查询:
<style lang="scss" scoped>
.container {
padding: 32rpx;
// 平板尺寸
@media screen and (min-width: 768px) {
padding: 64rpx;
max-width: 1200rpx;
margin: 0 auto;
}
// 大屏幕
@media screen and (min-width: 1024px) {
padding: 96rpx;
}
}
// 使用条件编译
.platform-box {
width: 750rpx;
// #ifdef H5
max-width: 750px;
margin: 0 auto;
// #endif
// #ifdef MP-WEIXIN
width: 100%;
// #endif
}
</style>安全区域适配
针对刘海屏、底部导航栏等特殊区域的适配:
<template>
<view class="page">
<view class="safe-area-top"></view>
<view class="content">
<!-- 页面内容 -->
</view>
<view class="safe-area-bottom"></view>
</view>
</template>
<style lang="scss" scoped>
.safe-area-top {
height: constant(safe-area-inset-top); // iOS 11.2+
height: env(safe-area-inset-top); // iOS 11.2+
}
.safe-area-bottom {
height: constant(safe-area-inset-bottom);
height: env(safe-area-inset-bottom);
}
// 或使用 padding
.page {
padding-top: constant(safe-area-inset-top);
padding-top: env(safe-area-inset-top);
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
</style>最佳实践
1. 优先使用设计变量
始终优先使用预定义的设计变量,而不是硬编码数值:
❌ 不推荐:
<style lang="scss" scoped>
.text {
font-size: 28rpx;
color: #262626;
margin-bottom: 16rpx;
}
</style>✅ 推荐:
<style lang="scss" scoped>
.text {
font-size: $-fs-content;
color: $-color-content;
margin-bottom: 16rpx;
}
</style>2. 遵循 BEM 命名规范
保持样式结构清晰,使用 BEM 命名:
❌ 不推荐:
<template>
<view class="card">
<view class="header">
<text class="title">标题</text>
</view>
</view>
</template>
<style lang="scss" scoped>
.card { }
.header { } // 太通用,易冲突
.title { } // 太通用,易冲突
</style>✅ 推荐:
<template>
<view class="product-card">
<view class="product-card__header">
<text class="product-card__title">标题</text>
</view>
</view>
</template>
<style lang="scss" scoped>
@include b(product-card) {
padding: 32rpx;
@include e(header) {
margin-bottom: 16rpx;
}
@include e(title) {
font-size: $-fs-title;
color: $-color-title;
}
}
</style>3. 合理使用混合宏
对于常用样式,使用混合宏避免重复代码:
❌ 不推荐:
<style lang="scss" scoped>
.title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.subtitle {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>✅ 推荐:
<style lang="scss" scoped>
.title {
@include lineEllipsis;
font-size: $-fs-title;
}
.subtitle {
@include lineEllipsis;
font-size: $-fs-content;
}
</style>4. 组件样式隔离
始终使用 scoped 避免样式污染:
<style lang="scss" scoped>
// 这些样式只在当前组件生效
.container {
padding: 32rpx;
}
</style>5. 性能优化
避免过深的选择器嵌套,保持样式简洁:
❌ 不推荐:
<style lang="scss" scoped>
.page {
.container {
.content {
.item {
.title {
.text {
color: red; // 6 层嵌套
}
}
}
}
}
}
</style>✅ 推荐:
<style lang="scss" scoped>
.page-container { }
.content-item { }
.item-title {
.text {
color: red; // 2 层嵌套
}
}
</style>6. 主题定制集中管理
将主题定制集中在 style/index.scss 中:
// style/index.scss
:root,
page {
// 品牌色定制
--wot-color-theme: #1890ff;
--wot-color-success: #52c41a;
--wot-color-warning: #faad14;
--wot-color-danger: #f5222d;
// 字体定制
--wot-fs-big: 52rpx;
--wot-fs-title: 36rpx;
--wot-fs-content: 30rpx;
// 圆角定制
--wot-button-large-radius: 48rpx;
--wot-button-medium-radius: 24rpx;
}7. 响应式图片
使用 mode 属性正确处理图片显示:
<template>
<view class="image-container">
<!-- 保持比例,完整显示 -->
<image src="..." mode="aspectFit" class="image-fit" />
<!-- 保持比例,填充容器 -->
<image src="..." mode="aspectFill" class="image-fill" />
<!-- 裁剪居中 -->
<image src="..." mode="scaleToFill" class="image-scale" />
</view>
</template>
<style lang="scss" scoped>
.image-container {
width: 750rpx;
height: 400rpx;
}
.image-fit,
.image-fill,
.image-scale {
width: 100%;
height: 100%;
}
</style>常见问题
1. 样式不生效
问题原因:
- 选择器权重不够
- 样式被覆盖
scoped作用域限制- 变量未导入
解决方案:
<template>
<view class="custom-button">
<wd-button>按钮</wd-button>
</view>
</template>
<style lang="scss" scoped>
// 方案 1: 提高选择器权重
.custom-button {
:deep(.wd-button) {
background: red;
}
}
// 方案 2: 使用 !important (不推荐)
.custom-button :deep(.wd-button) {
background: red !important;
}
// 方案 3: 使用 CSS Variables
.custom-button {
--wot-button-primary-bg-color: red;
}
</style>2. rpx 和 px 混用问题
问题原因:
- 混用导致不同设备显示不一致
- 边框使用 rpx 可能出现模糊
解决方案:
<style lang="scss" scoped>
.container {
// ✅ 布局、间距、字体使用 rpx
width: 750rpx;
padding: 32rpx;
font-size: 28rpx;
// ✅ 边框使用 px 或 1px
border: 1px solid $-color-border;
// ❌ 避免边框使用 rpx
// border: 2rpx solid $-color-border; // 可能模糊
}
</style>3. 暗黑模式适配不完整
问题原因:
- 部分颜色硬编码
- 未使用暗黑模式变量
- 图片未适配暗黑模式
解决方案:
<template>
<view :class="{ 'dark-mode': isDark }">
<view class="card">
<image
:src="isDark ? darkLogo : lightLogo"
class="logo"
/>
<text class="title">标题</text>
</view>
</view>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const isDark = ref(false)
const lightLogo = '/static/logo-light.png'
const darkLogo = '/static/logo-dark.png'
</script>
<style lang="scss" scoped>
.card {
// ✅ 使用变量
background: $-color-white;
color: $-color-title;
border: 1px solid $-color-border;
// ❌ 避免硬编码
// background: #ffffff;
// color: #000000;
// 暗黑模式
.dark-mode & {
background: $-dark-background;
color: $-dark-color;
border-color: $-dark-border-color;
}
}
</style>4. 样式变量修改不生效
问题原因:
- 修改了 SCSS 变量而不是 CSS 变量
- 变量作用域问题
- 缓存未清除
解决方案:
<style lang="scss" scoped>
// ❌ 错误: 修改 SCSS 变量(编译时固定)
// $-color-theme: red;
// ✅ 正确: 修改 CSS 变量(运行时可变)
.custom-component {
--wot-color-theme: red;
--wot-button-primary-bg-color: red;
}
// 或在全局修改
:root {
--wot-color-theme: red;
}
</style>5. 1px 边框在不同设备显示粗细不一
问题原因:
- 不同设备像素比不同
- 未使用
hairline或transform: scaleY(0.5)
解决方案:
<style lang="scss" scoped>
.border-box {
// 方案 1: 使用混合宏
@include halfPixelBorder("bottom", 0, $-color-border);
}
.border-box-2 {
// 方案 2: 手动实现
position: relative;
&::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
background: $-color-border;
transform: scaleY(0.5);
}
}
.border-box-3 {
// 方案 3: 使用 1px(在高清屏上可能较粗)
border-bottom: 1px solid $-color-border;
}
</style>6. 组件样式穿透不生效
问题原因:
- Vue 3 中
/deep/和>>>已废弃 - 未正确使用
:deep()
解决方案:
<template>
<view class="wrapper">
<wd-button class="custom-btn">按钮</wd-button>
</view>
</template>
<style lang="scss" scoped>
.wrapper {
// ✅ Vue 3 正确写法
:deep(.wd-button) {
background: red;
}
// ❌ Vue 2 写法(已废弃)
// /deep/ .wd-button { }
// >>> .wd-button { }
}
// 或使用 WD UI 的深度混合宏
@include b(wrapper) {
@include edeep(button) {
background: red;
}
}
</style>通过本文档,你应该已经全面了解了 RuoYi-Plus-UniApp 移动端的样式系统架构、使用方法和最佳实践。样式系统提供了完善的设计变量、BEM 命名规范、SCSS 工具集和主题定制能力,能够满足各种样式开发需求。在实际开发中,遵循最佳实践,合理使用样式变量和混合宏,可以大大提升开发效率和代码可维护性。
