v1.0.0
组件 40+ 个

Laimi UI · 移动端 / PC 通用组件库

一套零依赖的原生 CSS + JS 组件标准,覆盖后台管理、门店收银、移动端页面等场景。
引入两个文件即可使用全部组件,所有交互自带键盘快捷键与移动端适配。

原生 JS · 无第三方依赖 移动端 / PC 双端适配 CSS 变量主题 Enter 确认 / Esc 取消 容器自动创建

概览这套 UI 是什么

Laimi UI 由三部分组成:一份样式表、一份交互脚本、一份演示页。样式与交互完全分离,业务页面只需要写 HTML 结构,剩下的样式和交互由组件库负责。

文件作用说明
laimi.css组件样式库全部组件样式 + CSS 变量主题,约 82 KB
laimi.js交互库弹窗、Toast、下拉、选择器、抽屉等交互,约 80 KB
web移动通用.html组件演示页所有组件的可视化示例,可作为页面骨架参考
docs.html本文档使用说明、API 参考、代码示例
设计原则:① 只写结构、不写样式;② 组件之间互不干扰,缺元素不报错;③ 所有弹层统一支持 Enter 确认 / Esc 取消;④ 移动端优先,PC 端自适应。

快速开始4 步接入

1. 引入文件

把 laimi.css 与 laimi.js 放到项目目录,在页面中引入。图标库使用阿里 iconfont,按需引入。

html
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_5238787_v163maxwpnj.css?t=1">
<link rel="stylesheet" href="laimi.css">

<!-- 页面底部 -->
<script src="laimi.js"></script>

2. 拆成 inc_head / inc_top / inc_nav

实际项目把公共部分拆成 include 文件,每个页面只写自己的内容。顶部栏与左侧栏的 id 必须原样保留(shopSelector、shopName、smsBalance、msgBtn、supportBtn、topbarUser、appSidebar、sidebarToggle),组件库靠这些 id 自动绑定交互,缺了对应交互就不会生效。

php · inc_head.php
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $lm_page_title; ?> - 来米软件</title>

<!-- 图标库(阿里 iconfont · 项目 5238787) -->
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_5238787_v163maxwpnj.css?t=1">
<!-- 组件库样式 -->
<link rel="stylesheet" href="laimi_ui/laimi.css">
php · inc_top.php
<?php
// 顶部栏需要的数据:门店名、用户姓名、角色、短信余额
$lm_shop_name = $GLOBALS['gshop']['shop_name'] ?? '解放东路店';
$lm_user_name = $GLOBALS['guser']['user_name'] ?? '刘明轩';
$lm_role      = ($GLOBALS['_SESSION']['login_type'] == 1) ? '超级管理员' : '操作员';
$lm_avatar    = $lm_user_name !== '' ? mb_substr($lm_user_name, 0, 1, 'utf-8') : '用';
$lm_sms_count = 0;
if (!empty($GLOBALS['gcompany']['company_sms_level'])) { $lm_sms_count = $GLOBALS['gcompany']['company_sms_ycount']; }
$lm_cur = basename($_SERVER['PHP_SELF']);
?>
<header class="app-topbar">
  <!-- 左段:Logo + 店名 -->
  <div class="topbar-left">
    <div class="topbar-logo">
      <div class="logo-icon">M</div>
      <span>我的软件</span>
    </div>
    <div class="shop-selector" id="shopSelector">
      <span id="shopName"><?php echo $lm_shop_name; ?></span>
      <i class="iconfont icon-angle-down"></i>
    </div>
  </div>

  <!-- 中段:导航 -->
  <nav class="topbar-center">
    <a class="topbar-nav-item<?php if($lm_cur == 'main.php') echo ' active'; ?>" href="main.php"><span class="nav-icon"><i class="iconfont icon-gongzuotai"></i></span>工作台</a>
    <a class="topbar-nav-item<?php if($lm_cur == 'b_pay.php') echo ' active'; ?>" href="b_pay.php"><span class="nav-icon"><i class="iconfont icon-jiaoyimingxi"></i></span>收银台</a>
    <a class="topbar-nav-item<?php if($lm_cur == 'v_list.php') echo ' active'; ?>" href="v_list.php"><span class="nav-icon"><i class="iconfont icon-yuyue"></i></span>预约</a>
    <a class="topbar-nav-item<?php if($lm_cur == 'o_writeoff.php') echo ' active'; ?>" href="o_writeoff.php"><span class="nav-icon"><i class="iconfont icon-meituan2"></i></span>核销</a>
    <a class="topbar-nav-item<?php if($lm_cur == 'd_sms.php') echo ' active'; ?>" href="d_sms.php"><span class="nav-icon"><i class="iconfont icon-shouzhitongji"></i></span>营销</a>
    <a class="topbar-nav-item<?php if($lm_cur == 'p_trade1.php') echo ' active'; ?>" href="p_trade1.php"><span class="nav-icon"><i class="iconfont icon-shezhi"></i></span>统计</a>
  </nav>

  <!-- 右段:余额 / 消息 / 客服 / 用户 -->
  <div class="topbar-right">
    <div class="topbar-sms" id="smsBalance" title="查看短信余额">
      <span class="sms-icon"><i class="iconfont icon-duanxin1"></i></span>
      <span>短信余额 <b class="fs-16"><?php echo $lm_sms_count; ?></b> 条</span>
    </div>
    <button class="topbar-action" id="msgBtn" title="系统消息">
      <i class="iconfont icon-bell"></i><span class="action-badge"></span>
    </button>
    <button class="topbar-action" id="supportBtn" title="联系客服">
      <i class="iconfont icon-headphones"></i>
    </button>
    <div class="topbar-user" id="topbarUser">
      <div class="user-avatar"><?php echo $lm_avatar; ?></div>
      <div class="user-info">
        <div class="user-name"><?php echo $lm_user_name; ?></div>
        <div class="user-role"><?php echo $lm_role; ?></div>
      </div>
      <span class="user-arrow"><i class="iconfont icon-angle-down"></i></span>
    </div>
  </div>
</header>
php · inc_nav.php
<?php $lm_cur = basename($_SERVER['PHP_SELF']); ?>
<aside class="app-sidebar" id="appSidebar">
  <button class="sidebar-toggle" id="sidebarToggle">
    <span class="arrow">‹</span>
  </button>
  <div class="sidebar-menu">
    <div class="sidebar-group">
      <div class="sidebar-group-title">门店管理</div>
      <a class="sidebar-item<?php if($lm_cur == 'm_list.php') echo ' active'; ?>" href="m_list.php"><span class="item-icon"><i class="iconfont icon-huiyuandenglu"></i></span><span class="item-text">会员</span></a>
      <a class="sidebar-item<?php if($lm_cur == 'm_detail.php') echo ' active'; ?>" href="m_detail.php"><span class="item-icon"><i class="iconfont icon-wpforms"></i></span><span class="item-text">明细</span></a>
      <!-- 提成:二级菜单内容直接写在本文件里,data-submenu-for 与上级 data-submenu 对应 -->
      <a class="sidebar-item" data-submenu="ticheng"><span class="item-icon"><i class="iconfont icon-tichengjilu"></i></span><span class="item-text">提成</span><span class="item-arrow">›</span></a>
      <div class="sidebar-submenu" data-submenu-for="ticheng">
        <div class="submenu-title">提成管理</div>
        <a class="submenu-item" href="t_list.php"><i class="iconfont icon-caret-right1"></i><span>提成明细</span></a>
        <a class="submenu-item" href="t_stat.php"><i class="iconfont icon-caret-right1"></i><span>提成统计</span></a>
        <a class="submenu-item" href="t_salary.php"><i class="iconfont icon-caret-right1"></i><span>工资核算</span></a>
      </div>
      <!-- 库存 -->
      <a class="sidebar-item" data-submenu="stock"><span class="item-icon"><i class="iconfont icon-kucunchaxun1"></i></span><span class="item-text">库存</span><span class="item-arrow">›</span></a>
      <div class="sidebar-submenu" data-submenu-for="stock">
        <div class="submenu-title">库存管理</div>
        <a class="submenu-item" href="s_in.php"><i class="iconfont icon-caret-right1"></i><span>商品入库</span></a>
        <a class="submenu-item" href="s_out.php"><i class="iconfont icon-caret-right1"></i><span>商品出库</span></a>
        <a class="submenu-item" href="s_log.php"><i class="iconfont icon-caret-right1"></i><span>出入库查询</span></a>
        <a class="submenu-item" href="s_check.php"><i class="iconfont icon-caret-right1"></i><span>库存盘点</span></a>
        <a class="submenu-item" href="s_stat.php"><i class="iconfont icon-caret-right1"></i><span>库存统计</span></a>
      </div>
      <a class="sidebar-item"><span class="item-icon"><i class="iconfont icon-gongziticheng"></i></span><span class="item-text">收支</span></a>
    </div>
    <div class="sidebar-group">
      <div class="sidebar-group-title">营销触达</div>
      <!-- 短信 -->
      <a class="sidebar-item" data-submenu="sms"><span class="item-icon"><i class="iconfont icon-duanxin3"></i></span><span class="item-text">短信</span><span class="item-arrow">›</span></a>
      <div class="sidebar-submenu" data-submenu-for="sms">
        <div class="submenu-title">短信群发</div>
        <a class="submenu-item" href="d_template.php"><i class="iconfont icon-caret-right1"></i><span>短信模板</span></a>
        <a class="submenu-item" href="d_send.php"><i class="iconfont icon-caret-right1"></i><span>短信群发</span></a>
        <a class="submenu-item" href="d_log.php"><i class="iconfont icon-caret-right1"></i><span>群发记录</span></a>
      </div>
      <a class="sidebar-item"><span class="item-icon"><i class="iconfont icon-tixing2"></i></span><span class="item-text">提醒</span></a>
    </div>
    <div class="sidebar-group">
      <div class="sidebar-group-title">系统设置</div>
      <a class="sidebar-item"><span class="item-icon"><i class="iconfont icon-shezhi"></i></span><span class="item-text">设置</span></a>
      <a class="sidebar-item"><span class="item-icon"><i class="iconfont icon-jiaocheng"></i></span><span class="item-text">教程</span></a>
    </div>
  </div>
</aside>

3. 完整页面(首页示例)

新建 index.php,把下面整段粘进去就能跑:头部、顶部栏、左侧栏都用 include 引入上一步的文件($lm_page_title 决定页面标题);内容区放概览卡片 + 列表;底部引 laimi.js。

php · index.php
<?php $lm_page_title = '工作台'; ?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <?php include 'inc_head.php'; ?>
</head>
<body>
  <div class="app-layout">
    <?php include 'inc_top.php'; ?>
    <div class="app-body">
      <?php include 'inc_nav.php'; ?>
      <main class="app-content">
        <!-- 见下方「内容区」 -->
      </main>
    </div>
  </div>
  <script src="laimi_ui/laimi.js"></script>
</body>
</html>
html · 内容区(放进 .app-content)
<div class="content-header">
  <div>
    <h1 class="content-title">
      <span class="title-icon"><i class="iconfont icon-gongzuotai"></i></span>
      今日工作台
    </h1>
    <div class="breadcrumb">
      <span>首页</span><span class="sep">/</span><span class="current">工作台</span>
    </div>
  </div>
</div>

<!-- 数据概览 -->
<div class="row">
  <div class="col col-3">
    <div class="card"><div class="card-body">
      <div class="fs-12" style="color:var(--color-text-muted);">今日营业额</div>
      <div class="fs-20" style="font-weight:700;margin-top:6px;">¥ 12,860.00</div>
    </div></div>
  </div>
  <div class="col col-3">
    <div class="card"><div class="card-body">
      <div class="fs-12" style="color:var(--color-text-muted);">今日客流</div>
      <div class="fs-20" style="font-weight:700;margin-top:6px;">48 人</div>
    </div></div>
  </div>
  <div class="col col-3">
    <div class="card"><div class="card-body">
      <div class="fs-12" style="color:var(--color-text-muted);">今日预约</div>
      <div class="fs-20" style="font-weight:700;margin-top:6px;">16 单</div>
    </div></div>
  </div>
  <div class="col col-3">
    <div class="card"><div class="card-body">
      <div class="fs-12" style="color:var(--color-text-muted);">新增会员</div>
      <div class="fs-20" style="font-weight:700;margin-top:6px;">9 人</div>
    </div></div>
  </div>
</div>

<!-- 今日订单 -->
<div class="card">
  <div class="card-header">
    <div class="card-header-title">
      <span class="card-header-icon"><i class="iconfont icon-mingxi"></i></span>今日订单
    </div>
    <div class="card-header-actions">
      <button class="btn btn-sm btn-outline">查看全部</button>
    </div>
  </div>
  <div class="card-body">
    <div class="table-wrapper">
      <table class="table table-hover table-align-middle">
        <thead>
          <tr><th>时间</th><th>会员</th><th>项目</th><th>金额</th><th>状态</th></tr>
        </thead>
        <tbody>
          <tr><td>10:24</td><td>刘明轩</td><td>玫瑰精油护理</td><td>¥298.00</td><td><span class="tag tag-success">已完成</span></td></tr>
          <tr><td>11:05</td><td>陈静怡</td><td>日式美睫嫁接</td><td>¥398.00</td><td><span class="tag tag-warning">服务中</span></td></tr>
          <tr><td>13:40</td><td>王梓涵</td><td>头皮护理</td><td>¥168.00</td><td><span class="tag tag-success">已完成</span></td></tr>
        </tbody>
      </table>
    </div>
  </div>
</div>

4. 调用组件

弹层类组件用 JS 调用,普通组件只写 HTML 即可。例如:

javascript
// 轻提示
toast('保存成功', 'success');

// 确认框
confirmBox('确定要删除这条记录吗?', () => {
  toast('已删除', 'success');
});

// 通用弹窗
openModal({
  title: '新增会员',
  size: 'md',
  body: '<div class="form-group">...</div>',
  onConfirm: () => toast('已提交')
});
点击体验
toast / openModal / showLoading 等 API 全部挂在 window 上,页面脚本里可直接调用。Toast、Loading、弹窗的容器由库自动创建,无需手写。

主题与变量CSS 变量

全部颜色、圆角、阴影、尺寸都通过 CSS 变量定义在 :root 上。修改一个变量即可全站生效,无需改组件代码。

品牌色与功能色

--color-primary
#5b5bef 品牌主色
--color-success
#10b981 成功
--color-warning
#f59e0b 警告 / 强调
--color-danger
#ef4444 危险
--color-info
#06b6d4 信息
--color-purple
#8b5cf6 紫色

文字与背景

变量值用途
--color-text#1e2a3a主文字
--color-text-secondary#3e4d5f次级文字
--color-text-muted#7b8a9e辅助 / 说明文字
--color-text-disabled#b8c4d2禁用文字
--color-bg#f2f4f8页面背景
--color-bg-card#ffffff卡片背景
--color-bg-hover#f0f4fc悬停背景
--color-border#dce3ec常规边框
--color-border-light#eef2f7浅边框 / 分割线

圆角 / 阴影 / 尺寸

变量值用途
--radius-sm / md / lg / xl8 / 12 / 16 / 20 px圆角档位
--shadow-sm / md / lg—卡片、弹层阴影
--shadow-pop—弹出层阴影
--topbar-height64px顶部栏高度
--sidebar-width180px左侧栏展开宽度
--sidebar-collapsed64px左侧栏折叠宽度
--dropdown-max-h240px下拉面板统一最大高度

换色 / 暗色模式

给 <html> 加 data-theme 即可切换;也可以直接覆写 --color-primary 换品牌色(浅色变体由 color-mix() 自动派生)。

html
<!-- 预设主题:green / purple / orange / red / dark -->
<html data-theme="dark">

<!-- 自定义品牌色(写在 laimi.css 之后) -->
<style>
  :root { --color-primary: #1677ff; }
</style>
本项目已固定使用默认蓝紫主题,不再提供主题色选择面板。若需换色,直接改 --color-primary 一处即可,--color-primary-light / --color-primary-border 会自动跟随。

布局骨架顶部栏 + 左侧栏 + 内容区

布局由 .app-layout 统一管理:顶部栏 position: fixed,左侧栏可折叠,内容区自动偏移。

结构说明
.app-layout最外层容器,管理整体高度与偏移
.app-topbar顶部栏,三段式:.topbar-left / .topbar-center / .topbar-right
.topbar-logoLogo + 系统名(.logo-icon 为方形图标)
.shop-selector门店切换入口,点击弹出门店列表(id 需为 shopSelector,名称 id 为 shopName)
.topbar-nav-item中部导航项,加 .active 高亮;.nav-icon 包裹图标
.app-body顶部栏下方主体,包含左侧栏与内容区
.app-sidebar左侧栏,含 .sidebar-toggle 折叠按钮、.sidebar-menu 菜单
.sidebar-group / -title菜单分组与分组标题
.sidebar-item菜单项,.item-icon / .item-text / .item-arrow;data-submenu="xx" 触发二级弹层
.app-content内容区,含 .content-header / .content-title / .breadcrumb

完整骨架代码

html
<div class="app-layout">

  <!-- 顶部栏 -->
  <header class="app-topbar">
    <div class="topbar-left">
      <div class="topbar-logo">
        <div class="logo-icon">M</div>
        <span>我的软件</span>
      </div>
      <div class="shop-selector" id="shopSelector">
        <span id="shopName">解放东路店</span>
        <i class="iconfont icon-angle-down"></i>
      </div>
    </div>

    <nav class="topbar-center">
      <a class="topbar-nav-item active">
        <span class="nav-icon"><i class="iconfont icon-gongzuotai"></i></span>工作台
      </a>
      <a class="topbar-nav-item">
        <span class="nav-icon"><i class="iconfont icon-jiaoyimingxi"></i></span>收银台
      </a>
    </nav>

    <div class="topbar-right">
      <div class="topbar-sms" id="smsBalance" title="查看短信余额">
        <span class="sms-icon"><i class="iconfont icon-duanxin1"></i></span>
        <span>短信余额 <b class="fs-16">12,680</b> 条</span>
      </div>
      <button class="topbar-action" id="msgBtn" title="系统消息">
        <i class="iconfont icon-bell"></i><span class="action-badge"></span>
      </button>
      <button class="topbar-action" id="supportBtn" title="联系客服">
        <i class="iconfont icon-headphones"></i>
      </button>
      <div class="topbar-user" id="topbarUser">
        <div class="user-avatar">刘</div>
        <div class="user-info">
          <div class="user-name">刘明轩</div>
          <div class="user-role">超级管理员</div>
        </div>
        <span class="user-arrow"><i class="iconfont icon-angle-down"></i></span>
      </div>
    </div>
  </header>

  <div class="app-body">
    <!-- 左侧栏 -->
    <aside class="app-sidebar" id="appSidebar">
      <button class="sidebar-toggle" id="sidebarToggle"><span class="arrow">‹</span></button>
      <div class="sidebar-menu">
        <div class="sidebar-group">
          <div class="sidebar-group-title">门店管理</div>
          <a class="sidebar-item active">
            <span class="item-icon"><i class="iconfont icon-huiyuandenglu"></i></span>
            <span class="item-text">会员</span>
          </a>
          <a class="sidebar-item" data-submenu="stock">
            <span class="item-icon"><i class="iconfont icon-kucunchaxun1"></i></span>
            <span class="item-text">库存</span><span class="item-arrow">›</span>
          </a>
        </div>
      </div>
    </aside>

    <!-- 内容区 -->
    <main class="app-content">
      <div class="content-header">
        <div>
          <h1 class="content-title">
            <span class="title-icon"><i class="iconfont icon-gongzuotai"></i></span>
            今日工作台
          </h1>
          <div class="breadcrumb">
            <span>首页</span><span class="sep">/</span><span class="current">工作台</span>
          </div>
        </div>
      </div>

      <!-- 页面内容 -->
    </main>
  </div>
</div>
折叠按钮 #sidebarToggle、门店切换 #shopSelector、用户下拉 #topbarUser 由组件库自动绑定交互,只要 id 一致即可。data-submenu="xx" 的菜单项会自动弹出二级菜单层。

图标规范阿里 iconfont

全站统一使用 iconfont 图标,禁止使用 emoji。写法为 <i class="iconfont icon-图标名"></i>。

html
<!-- 基础用法 -->
<i class="iconfont icon-bell"></i>

<!-- 按钮内图标(自动带右间距) -->
<button class="btn btn-primary">
  <i class="iconfont icon-check-circle"></i> 确认提交
</button>

<!-- 图标颜色继承父级,用 style 或 CSS 控制 -->
<i class="iconfont icon-trash-can" style="color:var(--color-danger);"></i>
常用图标
工作台 会员 预约 短信 库存 统计 设置 用户
图标库更新:图标网址变更时,只需替换 <link> 的 href;图标内容更新后浏览器未生效时,把 ?t= 后的数字 +1 强制刷新缓存。完整图标清单见 图标解析.html。

按钮.btn

基础类 .btn,配合颜色类与尺寸类使用。颜色类:btn-primary / btn-success / btn-warning / btn-danger / btn-outline / btn-outline-primary / btn-ghost / btn-blue / btn-green / btn-orange / btn-red。尺寸类:btn-xs / btn-sm / btn-lg。

效果预览
html
<button class="btn btn-primary">主色</button>
<button class="btn btn-danger">危险</button>
<button class="btn btn-outline-primary">主色描边</button>
<button class="btn btn-sm btn-primary">小按钮</button>
<button class="btn" disabled>禁用</button>

<!-- 带图标 -->
<button class="btn btn-success"><i class="iconfont icon-check-circle"></i> 确认</button>

<!-- 药丸按钮 -->
<button class="pill-btn pill-btn-solid">预约列表</button>
<button class="pill-btn pill-btn-light">+ 新增预约</button>

标签 / 徽标 / 头像.tag / .badge / .avatar

标签
默认 主要 成功 警告 危险 信息 紫色 描边 带圆点
徽标
5 12 完成 警告
头像
刘
刘
刘
M
html
<span class="tag tag-success">成功</span>
<span class="tag tag-warning tag-dot">进行中</span>

<span class="badge badge-primary">12</span>
<span class="badge badge-dot" style="background:var(--color-success)"></span>

<div class="avatar avatar-sm">刘</div>
<div class="avatar avatar-lg">刘</div>
<div class="avatar avatar-gradient">M</div>

卡片.card

标准卡片由 .card-header / .card-body / .card-footer 组成;变体:card-bordered(描边)、card-flat(无阴影)、card-glow(悬停光晕)。

效果预览
任务列表
完成项目需求文档
截止日期:2026-10-01
进行中
审核设计稿
提交人:设计组
已完成
描边卡片
card-bordered
扁平卡片
card-flat
发光卡片
card-glow
html
<div class="card">
  <div class="card-header">
    <span class="card-header-title">
      <span class="card-header-icon"><i class="iconfont icon-wpforms"></i></span>
      任务列表
    </span>
    <div class="card-header-actions">
      <button class="btn-icon" title="编辑"><i class="iconfont icon-user-edit"></i></button>
    </div>
  </div>

  <div class="card-body">
    <!-- 列表项 -->
    <div class="card-list-item">
      <div class="card-list-icon" style="background:var(--color-primary-light);color:var(--color-primary);">
        <i class="iconfont icon-circle"></i>
      </div>
      <div class="card-list-body">
        <div class="card-list-title">完成项目需求文档</div>
        <div class="card-list-desc">截止日期:2026-10-01</div>
      </div>
      <span class="tag tag-warning tag-dot">进行中</span>
    </div>
  </div>

  <div class="card-footer">
    <button class="btn btn-sm btn-outline">取消</button>
    <button class="btn btn-sm btn-primary">确认</button>
  </div>
</div>

<!-- 并排卡片 -->
<div class="card-row">
  <div class="card card-bordered">...</div>
  <div class="card card-flat">...</div>
  <div class="card card-glow">...</div>
</div>

表格.table

用 .table-wrapper 包裹实现横向滚动。table-hover 悬停高亮,table-striped 斑马纹。

效果预览
姓名部门状态操作
张三技术部在职
李四产品部休假
王五设计部在职
html
<div class="table-wrapper">
  <table class="table table-hover">
    <thead>
      <tr><th>姓名</th><th>部门</th><th>状态</th><th>操作</th></tr>
    </thead>
    <tbody>
      <tr>
        <td>张三</td>
        <td>技术部</td>
        <td><span class="tag tag-success tag-dot">在职</span></td>
        <td><button class="btn btn-xs btn-outline-primary">编辑</button></td>
      </tr>
    </tbody>
  </table>
</div>
表格正文默认字号 14px。表格颜色使用主题变量,切换主题时自动跟随。变体类还有 table-bordered / table-sm(紧凑)。

表格扩展.cell-stack / .cell-avatar / .table-scroll-x / .table-sm

在基础表格之上提供四种常用扩展:两行数据单元格、头像单元格、横向滚动容器、紧凑尺寸。单元格结构类都作用于 .table 内部,可与 table-hover / table-align-middle 自由组合。

类名作用用法
.cell-stack单元格内两行文本容器内部放 .cell-main / .cell-sub
.cell-main主标题(深色、中等字重)放在 .cell-stack 内
.cell-sub副标题(浅灰、小字)放在 .cell-stack 内
.cell-avatar头像 + 两行文本组合内部放 .avatar 与 .cell-stack
.cell-actions操作按钮横排紧凑组包住多个 .btn.btn-xs
.table-scroll-x横向滚动容器(表格 min-width 720px)替代 .table-wrapper 作为外层
.table-sm紧凑表格(减小内边距)加在 .table 上
.table-align-middle表头 / 单元格垂直居中加在 .table 上
两行数据表格(主副标题)
商品信息单价库存状态
玫瑰精油护理SPA · 60分钟
¥29812在售
日式美睫嫁接美睫 · 90分钟
¥3988在售
采耳舒缓护理采耳 · 45分钟
¥1680缺货
html
<div class="table-wrapper" style="margin-bottom:0;">
  <table class="table table-hover table-align-middle">
    <thead><tr><th style="width:35%;">商品信息</th><th>单价</th><th>库存</th><th>状态</th></tr></thead>
    <tbody>
      <tr>
        <td><div class="cell-stack"><span class="cell-main">玫瑰精油护理</span><span class="cell-sub">SPA · 60分钟</span></div></td>
        <td>¥298</td><td>12</td><td><span class="tag tag-success tag-dot">在售</span></td>
      </tr>
      <tr>
        <td><div class="cell-stack"><span class="cell-main">日式美睫嫁接</span><span class="cell-sub">美睫 · 90分钟</span></div></td>
        <td>¥398</td><td>8</td><td><span class="tag tag-success tag-dot">在售</span></td>
      </tr>
      <tr>
        <td><div class="cell-stack"><span class="cell-main">采耳舒缓护理</span><span class="cell-sub">采耳 · 45分钟</span></div></td>
        <td>¥168</td><td>0</td><td><span class="tag tag-danger tag-dot">缺货</span></td>
      </tr>
    </tbody>
  </table>
</div>
带头像的表格
会员手机号等级操作
刘
刘明轩注册于 2025-03-12
138****1234 黄金
陈
陈思琪注册于 2025-06-08
159****5678 铂金
html
<div class="table-wrapper" style="margin-bottom:0;">
  <table class="table table-hover table-align-middle">
    <thead><tr><th style="width:40%;">会员</th><th>手机号</th><th>等级</th><th>操作</th></tr></thead>
    <tbody>
      <tr>
        <td>
          <div class="cell-avatar">
            <div class="avatar avatar-gradient">刘</div>
            <div class="cell-stack"><span class="cell-main">刘明轩</span><span class="cell-sub">注册于 2025-03-12</span></div>
          </div>
        </td>
        <td>138****1234</td>
        <td><span class="tag tag-primary tag-dot">黄金</span></td>
        <td><div class="cell-actions"><button class="btn btn-xs btn-outline-primary">详情</button><button class="btn btn-xs btn-outline">编辑</button></div></td>
      </tr>
      <tr>
        <td>
          <div class="cell-avatar">
            <div class="avatar" style="background:var(--color-success-light);color:var(--color-success);">陈</div>
            <div class="cell-stack"><span class="cell-main">陈思琪</span><span class="cell-sub">注册于 2025-06-08</span></div>
          </div>
        </td>
        <td>159****5678</td>
        <td><span class="tag tag-success tag-dot">铂金</span></td>
        <td><div class="cell-actions"><button class="btn btn-xs btn-outline-primary">详情</button><button class="btn btn-xs btn-outline">编辑</button></div></td>
      </tr>
    </tbody>
  </table>
</div>
多列数据表格(横向滚动)
订单编号会员项目金额支付方式服务技师门店下单时间状态
#20260929001刘明轩玫瑰精油护理¥298微信支付小美解放东路店2026-09-29 09:12已完成
#20260929002陈思琪日式美睫嫁接¥398支付宝小丽解放东路店2026-09-29 10:05服务中
html
<div class="table-scroll-x">
  <table class="table table-hover table-align-middle">
    <thead><tr><th>订单编号</th><th>会员</th><th>项目</th><th>金额</th><th>支付方式</th><th>服务技师</th><th>门店</th><th>下单时间</th><th>状态</th></tr></thead>
    <tbody>
      <tr><td>#20260929001</td><td>刘明轩</td><td>玫瑰精油护理</td><td>¥298</td><td>微信支付</td><td>小美</td><td>解放东路店</td><td>2026-09-29 09:12</td><td><span class="tag tag-success tag-dot">已完成</span></td></tr>
      <tr><td>#20260929002</td><td>陈思琪</td><td>日式美睫嫁接</td><td>¥398</td><td>支付宝</td><td>小丽</td><td>解放东路店</td><td>2026-09-29 10:05</td><td><span class="tag tag-warning tag-dot">服务中</span></td></tr>
    </tbody>
  </table>
</div>
紧凑表格(table-sm)
时间项目技师状态
09:00玫瑰精油护理小美已完成
10:00日式美睫嫁接小丽进行中
11:00采耳舒缓护理小芳待开始
html
<div class="table-wrapper" style="margin-bottom:0;">
  <table class="table table-sm table-hover table-align-middle">
    <thead><tr><th>时间</th><th>项目</th><th>技师</th><th>状态</th></tr></thead>
    <tbody>
      <tr><td>09:00</td><td>玫瑰精油护理</td><td>小美</td><td><span class="tag tag-success tag-dot">已完成</span></td></tr>
      <tr><td>10:00</td><td>日式美睫嫁接</td><td>小丽</td><td><span class="tag tag-warning tag-dot">进行中</span></td></tr>
      <tr><td>11:00</td><td>采耳舒缓护理</td><td>小芳</td><td><span class="tag tag-info tag-dot">待开始</span></td></tr>
    </tbody>
  </table>
</div>

表格批量选择.table-checkbox / .table-select-bar

在表格上加复选框实现批量操作:表格 id 固定为 batchTable,表头全选框 id 固定为 checkAll,行内复选框加 .row-check,底部 .table-select-bar 实时显示已选数量(#selectedCount 由组件库自动更新,全选后自动显示半选态)。

类名 / id作用
.table-checkbox表格复选框(跟随主题色)
#checkAll表头全选框,自动显示半选状态
.row-check行内复选框
.table-select-bar表格下方批量操作条(主色浅底)
.select-count已选数量文案,内部 <b id="selectedCount"> 自动更新
效果预览
会员 手机号 等级 余额
刘
刘明轩注册于 2025-03-12
138****1234 黄金 ¥2,860.00
陈
陈思琪注册于 2025-06-08
159****5678 铂金 ¥5,320.00
王
王雅婷注册于 2025-09-21
186****9012 白银 ¥860.00
已选 0 项
html
<table class="table table-hover table-align-middle" id="batchTable">
  <thead>
    <tr>
      <th style="width:40px;"><input type="checkbox" class="table-checkbox" id="checkAll"></th>
      <th>会员</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><input type="checkbox" class="table-checkbox row-check"></td>
      <td>刘明轩</td>
    </tr>
  </tbody>
</table>

<!-- 底部批量操作条:已选数量自动更新 -->
<div class="table-select-bar">
  <span class="select-count">已选 <b id="selectedCount">0</b> 项</span>
  <div class="select-actions">
    <button class="btn btn-sm btn-outline-primary">批量打标签</button>
    <button class="btn btn-sm btn-danger">删除</button>
  </div>
</div>
表格 id 必须是 batchTable、全选框 id 必须是 checkAll,否则联动不生效。

顶部通知条.notice-bar

页面顶部的横幅提示,结构为「图标 + 文案 + 操作 + 关闭」。默认主色,可用 notice-success / notice-warning / notice-danger / notice-plain 切换语义色;点右侧 ✕ 会淡出并移除。

类名作用
.notice-bar通知条容器(默认主色)
.notice-icon左侧图标,颜色跟随语义色
.notice-text正文,支持 <b> 强调
.notice-action右侧文字操作(可点击)
.notice-close关闭按钮,自动绑定淡出移除
notice-success / -warning / -danger / -plain语义色变体
效果预览
系统将于今晚 23:00 - 24:00 升级维护,期间收银功能暂停使用。 查看详情
昨日经营报表已生成,可前往「统计」查看。
有 3 名会员的会员卡即将到期,建议及时提醒续费。 去提醒
库存告警:2 个商品已低于安全库存。 去补货
html
<div class="notice-bar">
  <span class="notice-icon"><i class="iconfont icon-bullhorn"></i></span>
  <span class="notice-text">系统将于今晚 <b>23:00 - 24:00</b> 升级维护。</span>
  <span class="notice-action">查看详情</span>
  <button class="notice-close" title="关闭">✕</button>
</div>

<!-- 语义色:notice-success / notice-warning / notice-danger / notice-plain -->
<div class="notice-bar notice-warning">...</div>

下拉刷新 / 上拉加载.pull-refresh / .load-more

列表顶部的「下拉刷新」与底部的「上拉加载更多」。加上 .loading 后图标自动旋转并禁止重复点击,适合接入真实请求。

效果预览
下拉刷新
上拉加载更多
html
<!-- 列表顶部 -->
<div class="pull-refresh">
  <i class="iconfont icon-recycle"></i><span>下拉刷新</span>
</div>

<!-- 列表底部 -->
<div class="load-more">
  <i class="iconfont icon-hourglass-half"></i><span>上拉加载更多</span>
</div>
加载中加 .loading 类,图标自动旋转并禁止重复点击;请求结束后移除即可。

表单.form-group / .form-input

表单结构:.form-row(一行多列)→ .form-group(字段)→ .form-label + 控件 + .form-hint(说明)。

效果预览
html
<div class="form-row">
  <div class="form-group">
    <label class="form-label">用户名 <span class="required">*</span></label>
    <input type="text" class="form-input" placeholder="请输入用户名">
    <div class="form-hint">用于登录,4-20 个字符</div>
  </div>

  <div class="form-group">
    <label class="form-label">带图标输入框</label>
    <div class="input-icon-wrapper">
      <span class="input-icon"><i class="iconfont icon-search"></i></span>
      <input type="text" class="form-input" placeholder="搜索内容...">
    </div>
  </div>
</div>

<!-- 下拉选择 / 开关 -->
<select class="form-select"><option>北京</option></select>
<label class="switch">
  <input type="checkbox" checked><span class="switch-slider"></span>
</label>

数字加减框.number-input-group

结构为「减号按钮 + 数字输入 + 加号按钮」,按钮通过 data-target 指向输入框 id、data-step 指定步长,由组件库自动绑定。
尺寸档位:number-input-group-lg / -sm / -xs / -mini;竖直紧凑排列加 .num-vertical(可叠加 num-vertical-mini)。小数用 data-decimals="1" 控制位数。

效果预览
html
<!-- 横向:减 - 输入 - 加 -->
<div class="number-input-group">
  <button class="number-btn" data-target="num1" data-step="-1">−</button>
  <input type="number" class="number-input" id="num1" value="1" min="1" max="99">
  <button class="number-btn" data-target="num1" data-step="1">+</button>
</div>

<!-- 小数:data-decimals 控制小数位 -->
<div class="number-input-group">
  <button class="number-btn" data-target="num2" data-step="-0.1">−</button>
  <input type="number" class="number-input" id="num2" value="1.5" min="0" max="99" data-decimals="1">
  <button class="number-btn" data-target="num2" data-step="0.1">+</button>
</div>

<!-- 竖直紧凑:输入在左,加减在右上下排列 -->
<div class="number-input-group num-vertical num-vertical-mini">
  <input type="number" class="number-input" id="num3" value="1" min="0" max="99">
  <div class="num-vertical-btns">
    <button class="number-btn" data-target="num3" data-step="1">+</button>
    <button class="number-btn" data-target="num3" data-step="-1">−</button>
  </div>
</div>
到达 min / max 边界时,对应方向的按钮会自动置灰禁用。

搜索筛选栏.filter-bar

列表页顶部的筛选组合。容器 .filter-bar 使用 flex 自动换行,.filter-item 为单个筛选项(关键词项加 filter-item-keyword 占更宽),按钮组用 .filter-actions。窄屏自动变成一列。下面给出四种常用组合:关键词、会员搜索、日期区间、综合筛选栏。

① 关键词 + 下拉选择 + 查询
② 会员搜索(输入联想 + 下拉候选)
聚焦即展开候选、输入实时过滤;选中后姓名回填输入框,会员 ID 写入 .member-search-value。候选数据可用容器的 data-members(JSON 数组)传入,不传则用内置演示数据。
③ 日期区间(从日期到日期)
至
两个日期框复用 picker-date,无需额外 JS;快捷按钮加 data-range-preset(today / 7d / 30d / month)即可自动回填并高亮。
④ 综合筛选栏(会员 + 日期区间 + 两个下拉 + 查询)
至
html
<!-- ① 关键词 + 下拉选择 + 查询 -->
<form class="filter-bar" onsubmit="return false;">
  <div class="filter-item filter-item-keyword">
    <div class="input-icon-wrapper">
      <span class="input-icon"><i class="iconfont icon-search"></i></span>
      <input type="text" class="form-input" placeholder="会员姓名 / 手机号 / 订单号">
    </div>
  </div>
  <div class="filter-item">
    <select class="form-select">
      <option>全部状态</option>
      <option>已完成</option>
      <option>服务中</option>
      <option>待服务</option>
    </select>
  </div>
  <div class="filter-item filter-actions">
    <button class="btn btn-primary" type="button"><i class="iconfont icon-search"></i> 查询</button>
    <button class="btn btn-outline" type="button"><i class="iconfont icon-recycle"></i> 重置</button>
  </div>
</form>

<!-- ② 会员搜索(输入联想 + 下拉候选) -->
<div class="member-search" style="max-width:360px;">
  <div class="input-icon-wrapper">
    <span class="input-icon"><i class="iconfont icon-search"></i></span>
    <input type="text" class="form-input member-search-input" placeholder="输入会员姓名或手机号" autocomplete="off">
  </div>
  <input type="hidden" class="member-search-value">
  <div class="member-search-panel"></div>
</div>

<!-- ③ 日期区间(从日期到日期) -->
<div style="max-width:440px;">
  <div class="date-range">
    <div class="picker-trigger">
      <input type="text" class="form-input picker-date date-range-start" placeholder="开始日期" readonly>
    </div>
    <span class="date-range-sep">至</span>
    <div class="picker-trigger">
      <input type="text" class="form-input picker-date date-range-end" placeholder="结束日期" readonly>
    </div>
  </div>
  <div class="date-range-presets">
    <button class="date-range-chip" type="button" data-range-preset="today">今天</button>
    <button class="date-range-chip" type="button" data-range-preset="7d">近 7 天</button>
    <button class="date-range-chip" type="button" data-range-preset="30d">近 30 天</button>
    <button class="date-range-chip" type="button" data-range-preset="month">本月</button>
  </div>
</div>

<!-- ④ 综合筛选栏:会员 + 日期区间 + 两个下拉 + 查询(快捷区间放重置后面) -->
<form class="filter-bar" onsubmit="return false;">
  <div class="filter-item filter-item-keyword">
    <div class="member-search">
      <div class="input-icon-wrapper">
        <span class="input-icon"><i class="iconfont icon-search"></i></span>
        <input type="text" class="form-input member-search-input" placeholder="搜索会员姓名 / 手机号" autocomplete="off">
      </div>
      <input type="hidden" class="member-search-value">
      <div class="member-search-panel"></div>
    </div>
  </div>
  <div class="filter-item" style="flex:1 1 300px;">
    <div class="date-range">
      <div class="picker-trigger">
        <input type="text" class="form-input picker-date date-range-start" placeholder="开始日期" readonly>
      </div>
      <span class="date-range-sep">至</span>
      <div class="picker-trigger">
        <input type="text" class="form-input picker-date date-range-end" placeholder="结束日期" readonly>
      </div>
    </div>
  </div>
  <div class="filter-item">
    <select class="form-select">
      <option>全部门店</option>
      <option>旗舰店</option>
      <option>社区店</option>
    </select>
  </div>
  <div class="filter-item">
    <select class="form-select">
      <option>全部状态</option>
      <option>已完成</option>
      <option>服务中</option>
      <option>待服务</option>
      <option>已取消</option>
    </select>
  </div>
  <div class="filter-item filter-actions">
    <button class="btn btn-primary" type="button"><i class="iconfont icon-search"></i> 查询</button>
    <button class="btn btn-outline" type="button"><i class="iconfont icon-recycle"></i> 重置</button>
    <div class="date-range-presets">
      <button class="date-range-chip" type="button" data-range-preset="today">今天</button>
      <button class="date-range-chip" type="button" data-range-preset="7d">近 7 天</button>
      <button class="date-range-chip" type="button" data-range-preset="month">本月</button>
    </div>
  </div>
</form>
javascript
// 会员搜索候选数据:写在容器 data-members 上(JSON 数组),不写则用内置演示数据
<div class="member-search"
     data-members='[{"id":"M1001","name":"刘明轩","phone":"13800001234","level":"黄金"},
                    {"id":"M1002","name":"陈静怡","phone":"13900008821","level":"铂金"}]'>

// 读取选中结果:姓名在输入框,ID 在隐藏域
const keyword = document.querySelector('.member-search-input').value;  // 刘明轩
const memberId = document.querySelector('.member-search-value').value; // M1001

// 收集整个筛选栏的条件
function collectFilter(form) {
  return {
    memberId: form.querySelector('.member-search-value')?.value || '',
    keyword: form.querySelector('.member-search-input')?.value || '',
    start: form.querySelector('.date-range-start')?.value || '',
    end: form.querySelector('.date-range-end')?.value || '',
    selects: Array.from(form.querySelectorAll('.form-select')).map(s => s.value)
  };
}
日期区间与会员搜索均无需额外初始化:日期框复用 picker-date,会员搜索、快捷区间按钮由库在加载时自动绑定。

金额输入框.money-input-group

收银 / 结算场景专用:左侧固定 ¥ 前缀,输入自动加千分位、限制两位小数,失焦时补齐两位小数。给 input 加 .money-input 即自动绑定,无需额外 JS。

效果预览
¥
自动千分位、只允许两位小数、失焦格式化
¥
html
<div class="money-input-group">
  <span class="money-prefix">¥</span>
  <input type="text" class="money-input" placeholder="0.00">
</div>
取值时用 parseFloat(input.value.replace(/,/g, '')) 去掉千分位。

大备注框.remark-box

多行备注输入:头部标题 + 工具栏,中部 textarea,底部字数统计。字数达上限时计数变红,data-remark-clear 按钮一键清空,加 remark-box-lg 可增大高度。

类名作用
.remark-box外层容器(聚焦时主色描边)
.remark-box-head头部:标题 + 工具按钮
.remark-box-textarea多行输入区(可拖拽调整高度)
.remark-box-foot底部:提示 + 字数统计
.remark-box-count字数统计,内部 <b> 自动更新,超限加 .over
data-remark-clear点击清空输入框
效果预览
会员备注
支持换行,右下角可拖拽调整高度 0 / 500
html
<div class="remark-box">
  <div class="remark-box-head">
    <div class="remark-box-title">会员备注</div>
    <div class="remark-box-tools">
      <button class="remark-box-tool" type="button" data-remark-clear>清空</button>
    </div>
  </div>
  <textarea class="remark-box-textarea" maxlength="500" placeholder="填写备注"></textarea>
  <div class="remark-box-foot">
    <span>支持换行</span>
    <span class="remark-box-count"><b>0</b> / 500</span>
  </div>
</div>

项目 / 商品选择器.goods-picker

带搜索过滤的多选列表,常用于开单时挑选服务项目或商品。结构为「搜索框 + 列表 + 底部已选汇总」。搜索框 id 固定 goodsSearch、列表 id 固定 goodsList,点击 .goods-item 切换选中态,底部 #goodsCount 自动统计。

效果预览
玫瑰精油护理
玫瑰精油护理
60分钟 · ¥298
日式美睫嫁接
日式美睫嫁接
90分钟 · ¥398
采耳舒缓护理
采耳舒缓护理
45分钟 · ¥168
肩颈放松按摩
肩颈放松按摩
40分钟 · ¥228
html
<div class="goods-picker">
  <div class="goods-search">
    <div class="input-icon-wrapper">
      <span class="input-icon"><i class="iconfont icon-search"></i></span>
      <input type="text" class="form-input" id="goodsSearch" placeholder="搜索项目 / 商品名称">
    </div>
  </div>
  <div class="goods-list" id="goodsList">
    <div class="goods-item" data-name="玫瑰精油护理" data-price="298">
      <div class="goods-thumb"><img src="..." alt=""></div>
      <div class="goods-info">
        <div class="goods-name">玫瑰精油护理</div>
        <div class="goods-meta">60分钟 · ¥298</div>
      </div>
      <span class="goods-check"><i class="iconfont icon-check"></i></span>
    </div>
  </div>
  <div class="goods-footer">
    <span class="goods-selected">已选 <b id="goodsCount">0</b> 项</span>
    <button class="btn btn-sm btn-primary" id="goodsConfirm">确认添加</button>
  </div>
</div>

验证码.verify-code-group

两种形态:一体式 .verify-code-group(输入框与按钮合并)和分行式 .verify-code-row。按钮 onclick="startCountdown(this)" 触发 60 秒倒计时。

效果预览
60 秒倒计时,含手机号校验
html
<!-- 一体式 -->
<div class="verify-code-group">
  <input type="tel" class="verify-code-input" placeholder="请输入手机号码" maxlength="11">
  <button class="verify-code-btn" onclick="startCountdown(this)">获取验证码</button>
</div>

<!-- 分行式 -->
<div class="verify-code-row">
  <div class="verify-code-input-wrap">
    <input type="tel" class="verify-code-input" placeholder="请输入手机号码" maxlength="11">
  </div>
  <button class="verify-code-btn" onclick="startCountdown(this)">获取验证码</button>
</div>

日期 / 时间选择下拉面板 + 滚轮选择器

三种交互:PC 端使用下拉面板(input.picker-date / input.picker-time / input.picker-datetime 自动绑定,无遮罩);移动端使用滚轮选择器(data-wheel="date|time|datetime",弹窗内上下滑动)。picker-datetime 把日期与时间集成在同一面板,输出 YYYY-MM-DD HH:mm:ss。窄屏或触屏设备会自动切换到滚轮模式。

效果预览
下拉面板,无遮罩
下拉面板,无遮罩
同一面板内选日期与时间
html
<!-- 下拉面板(自动绑定) -->
<div class="picker-trigger">
  <input type="text" class="form-input picker-date" placeholder="点击选择日期" readonly>
</div>
<div class="picker-trigger">
  <input type="text" class="form-input picker-time" placeholder="点击选择时间" readonly>
</div>
<!-- 日期 + 时间一体选择(输出 2026-09-29 14:30:00) -->
<div class="picker-trigger">
  <input type="text" class="form-input picker-datetime" placeholder="点击选择日期时间" readonly>
</div>

<!-- 滚轮选择器(自动绑定) -->
<button class="btn btn-outline-primary" data-wheel="date">滚轮选择日期</button>
<button class="btn btn-outline-primary" data-wheel="time">滚轮选择时间</button>
<button class="btn btn-outline-primary" data-wheel="datetime">滚轮选择日期时间</button>
javascript
// 主动调用滚轮选择器,回调返回格式化字符串
openWheelDatePicker(val => console.log('日期:' + val));           // 2026-09-29
openWheelTimePicker(val => console.log('时间:' + val));           // 14:30:00
openWheelDateTimePicker(val => console.log('日期时间:' + val));   // 2026-09-29 14:30:00

选项卡.tabs

结构:.tabs 内放 .tab-item[data-tab],面板为 .tab-panel#对应id。药丸样式加 .tabs-pill。

效果预览
推荐内容面板
热门内容面板
最新内容面板
概述面板(药丸式)
明细面板(药丸式)
统计面板(药丸式)
html
<div class="tabs">
  <button class="tab-item active" data-tab="t1">推荐</button>
  <button class="tab-item" data-tab="t2">热门</button>
  <button class="tab-item" data-tab="t3">最新</button>
</div>
<div class="tab-panel active" id="t1">推荐内容面板</div>
<div class="tab-panel" id="t2">热门内容面板</div>
<div class="tab-panel" id="t3">最新内容面板</div>

<!-- 药丸样式 -->
<div class="tabs tabs-pill">...</div>

分页.pagination

三种形态:标准分页(#paginationDemo 由库自动渲染)、简单上一页/下一页(.pagination-simple)、带每页条数(.pagination-with-size)。

效果预览
第 1 / 20 页
共 186 条记录
每页 条
html
<!-- 标准分页:库会自动渲染,容器 id 固定为 paginationDemo -->
<div class="pagination" id="paginationDemo"></div>

<!-- 简单分页 -->
<div class="pagination-simple" id="paginationSimple">
  <button class="btn btn-sm btn-outline" data-pg-prev>‹ 上一页</button>
  <span class="page-info">第 <strong>1</strong> / 20 页</span>
  <button class="btn btn-sm btn-outline" data-pg-next>下一页 ›</button>
</div>

<!-- 带每页条数 -->
<div class="pagination-with-size">
  <span>共 186 条记录</span>
  <select class="page-size-select" id="pageSizeSelect">
    <option>10</option><option selected>20</option><option>50</option>
  </select>
</div>

进度条 / 步骤条.progress / .steps

效果预览
主色进度 60%
成功进度 100%
步骤条
✓
填写信息
2
确认订单
3
完成
html
<!-- 进度条:width 控制进度,success / warning / danger 换色 -->
<div class="progress"><div class="progress-bar" style="width:60%"></div></div>
<div class="progress"><div class="progress-bar success" style="width:100%"></div></div>

<!-- 步骤条:done / active / 默认 -->
<div class="steps">
  <div class="step done"><div class="step-num">✓</div><div class="step-text">填写信息</div><div class="step-line"></div></div>
  <div class="step active"><div class="step-num">2</div><div class="step-text">确认订单</div><div class="step-line"></div></div>
  <div class="step"><div class="step-num">3</div><div class="step-text">完成</div></div>
</div>

骨架屏 / 空状态.skeleton / .empty

效果预览
暂无数据
html
<!-- 骨架屏 -->
<div class="skeleton" style="height:20px;width:60%;"></div>

<!-- 空状态 -->
<div class="empty">
  <div class="empty-icon"><i class="iconfont icon-box"></i></div>
  <div class="empty-text">暂无数据</div>
</div>

图文 / 列表卡片.media-card

首页、工作台最常用的卡片形态。由 .media-card-head(标题 + 更多)+ .media-list → .media-item 组成;列表项可带缩略图 .media-item-thumb、主副标题、右侧徽标。

效果预览
库存预警
全部
玫瑰精油
SPA耗材
仅剩 3
一次性采耳工具
采耳耗材
仅剩 5
热门项目
全部
玫瑰精油护理
玫瑰精油护理
60 分钟 · ¥298
热销
日式美睫嫁接
日式美睫嫁接
90 分钟 · ¥398
推荐
html
<div class="media-card">
  <div class="media-card-head">
    <div class="media-card-title"><i class="iconfont icon-exclamation-triangle"></i>库存预警</div>
    <span class="media-card-more" data-media-more>全部 <i class="iconfont icon-angle-right"></i></span>
  </div>
  <div class="media-list">

    <!-- 纯文字列表项 -->
    <div class="media-item">
      <div class="media-item-main">
        <div class="media-item-title">玫瑰精油</div>
        <div class="media-item-sub">SPA耗材</div>
      </div>
      <span class="media-item-badge">仅剩 3</span>
    </div>

    <!-- 带缩略图的列表项 -->
    <div class="media-item">
      <div class="media-item-thumb"><img src="图片地址" alt=""></div>
      <div class="media-item-main">
        <div class="media-item-title">玫瑰精油护理</div>
        <div class="media-item-sub">60 分钟 · ¥298</div>
      </div>
      <span class="media-item-badge badge-primary">热销</span>
    </div>
  </div>
</div>
徽标颜色类:badge-primary / badge-success / badge-warning / badge-danger;不带类时为中性灰。点击列表项 / 更多由页面自行处理。

业务卡片.card-birthday / .card-add

工作台常用的「提醒卡 + 快捷入口」组合:.card-birthday 用于提醒类卡片(带角标数字),.card-add 用于新增入口。

效果预览
会员生日
今日生日提醒
2
+
新增会员
+
新增预约
html
<!-- 提醒卡片 -->
<div class="card-birthday">
  <div class="birthday-icon"><i class="iconfont icon-birthday-cake"></i></div>
  <div class="birthday-body">
    <div class="birthday-title">会员生日</div>
    <div class="birthday-sub">今日生日提醒</div>
  </div>
  <div class="birthday-count">2</div>
</div>

<!-- 快捷新增入口 -->
<div class="card-row">
  <div class="card-add">
    <div class="add-icon" style="background:var(--color-success);">+</div>
    <div class="add-title">新增会员</div>
  </div>
  <div class="card-add">
    <div class="add-icon" style="background:var(--color-warning);">+</div>
    <div class="add-title">新增预约</div>
  </div>
</div>

时间轴.timeline / .timeline-item

纵向时间轴,用于展示流程进度、操作日志、订单流转等。结构:.timeline(列表)→ .timeline-item(节点)→ .timeline-badge(圆点)+ .timeline-content(卡片)。连接竖线由 ::before 自动绘制,最后一个节点自动收尾,无需手动处理。

类名作用
.timeline时间轴容器(ul)
.timeline-item单个节点(li),自动绘制连接竖线
.timeline-badge左侧圆形节点,默认主色;可加 success / warning / danger
.timeline-content右侧内容卡片(悬停加深阴影)
.timeline-header标题行:左标题 + 右时间,窄屏自动换行
.timeline-title节点标题
.timeline-time右侧时间文本(浅灰小字)
.timeline-desc描述正文
.timeline-footer底部信息行(常放状态标签 + 操作人)
效果预览
  • 预约确认 2026-09-29 09:00
    刘明轩 已成功预约「玫瑰精油护理」,服务技师:小美
  • 客户到店 2026-09-29 09:10
    会员 刘明轩 已到店,前台接待并确认服务项目。
  • 服务中 2026-09-29 09:20
    技师 小美 开始为会员提供玫瑰精油护理服务,预计 60 分钟。
  • 订单完成 2026-09-29 10:25
    订单 #20260929001 已结算,金额 ¥298,支付方式:微信支付。
html
<ul class="timeline">
  <li class="timeline-item">
    <!-- 圆点:默认主色,可加 success / warning / danger -->
    <div class="timeline-badge success"><i class="iconfont icon-check"></i></div>
    <div class="timeline-content">
      <div class="timeline-header">
        <span class="timeline-title">预约确认</span>
        <span class="timeline-time">2026-09-29 09:00</span>
      </div>
      <div class="timeline-desc">刘明轩 已成功预约「玫瑰精油护理」,服务技师:小美</div>
      <div class="timeline-footer">
        <span class="tag tag-success tag-dot">已完成</span>
        <span>操作人:系统</span>
      </div>
    </div>
  </li>

  <li class="timeline-item">
    <div class="timeline-badge"><i class="iconfont icon-user"></i></div>
    <div class="timeline-content">...</div>
  </li>
</ul>

栅格系统.row / .col

12 列等宽栅格:col-1 ~ col-12;五等分 col-5th;偏移 col-offset-*;响应式 col-resp。

效果预览
col-4
col-4
col-4
col-6
col-3
col-3
1/5
1/5
1/5
1/5
1/5
html
<div class="row">
  <div class="col col-4">1/3</div>
  <div class="col col-4">1/3</div>
  <div class="col col-4">1/3</div>
</div>

<div class="row">
  <div class="col col-6">1/2</div>
  <div class="col col-3">1/4</div>
  <div class="col col-3">1/4</div>
</div>

<!-- 五等分 -->
<div class="row">
  <div class="col col-5th">1/5</div>
  <div class="col col-5th">1/5</div>
  <div class="col col-5th">1/5</div>
  <div class="col col-5th">1/5</div>
  <div class="col col-5th">1/5</div>
</div>

文字大小.fs-12 ~ .fs-20

字号工具类:fs-12 / fs-14(正文默认)/ fs-16 / fs-18 / fs-20。

效果预览
12px 辅助说明文字
14px 正文默认
16px 小标题
18px 标题
20px 大标题
html
<span class="fs-12">辅助说明文字</span>
<span class="fs-14">正文默认</span>
<span class="fs-16">小标题</span>
<span class="fs-18">标题</span>
<span class="fs-20">大标题</span>

移动端底部导航.mobile-tabbar

固定底部 Tab 导航:.tabbar-item[data-tab] 对应页面 .tab-page[data-page],点击自动切换高亮与页面。角标用 .tab-badge。

效果预览
模拟手机窗口
首页
12
今日订单
¥8,520
今日营业额
会员
5
今日新增
1,286
会员总数
消息
系统将于今晚 23:00 升级维护10:24
我的
刘明轩
超级管理员
首页
会员
消息3
我的
html
<div class="mobile-frame">
  <div class="mobile-tab-view">
    <div class="tab-page active" data-page="home">首页内容</div>
    <div class="tab-page" data-page="member">会员内容</div>
  </div>

  <div class="mobile-tabbar">
    <div class="tabbar-item active" data-tab="home">
      <span class="tab-icon"><i class="iconfont icon-gongzuotai"></i></span>
      <span class="tab-label">首页</span>
    </div>
    <div class="tabbar-item" data-tab="member">
      <span class="tab-icon"><i class="iconfont icon-huiyuan"></i></span>
      <span class="tab-label">会员</span>
    </div>
    <div class="tabbar-item" data-tab="msg">
      <span class="tab-icon"><i class="iconfont icon-comment-dots"></i></span>
      <span class="tab-label">消息</span>
      <span class="tab-badge">3</span>   <!-- 未读角标 -->
    </div>
  </div>
</div>

抽屉.drawer

左右两侧滑出的面板。左侧用于菜单导航,右侧用于筛选条件。结构固定:外层 .drawer-mask#drawerMask,内层 .drawer#appDrawer(右侧抽屉加 .drawer-right,id 为 drawerRightMask / appDrawerRight)。触发按钮加 data-open="drawer" 或 data-open="drawerRight"。

效果预览(点击体验)
html
<!-- 触发按钮 -->
<button class="btn" data-open="drawer">打开左侧抽屉</button>
<button class="btn" data-open="drawerRight">打开右侧抽屉</button>

<!-- 左侧抽屉容器 -->
<div class="drawer-mask" id="drawerMask">
  <div class="drawer" id="appDrawer">
    <div class="drawer-header">
      <div class="drawer-title">菜单导航</div>
      <button class="drawer-close" data-drawer-close>✕</button>
    </div>
    <div class="drawer-body">
      <ul class="drawer-menu">
        <li class="drawer-menu-item active">首页</li>
        <li class="drawer-menu-item">会员管理<span class="menu-badge">12</span></li>
        <!-- 二级菜单:data-submenu-toggle 控制展开 -->
        <li class="drawer-menu-item" data-submenu-toggle>预约管理<span class="arrow">▶</span></li>
        <ul class="drawer-submenu">
          <li class="drawer-menu-item">今日预约</li>
          <li class="drawer-menu-item">预约列表</li>
        </ul>
      </ul>
    </div>
    <div class="drawer-footer">v1.0.0</div>
  </div>
</div>

<!-- 右侧抽屉容器(筛选面板) -->
<div class="drawer-mask" id="drawerRightMask">
  <div class="drawer drawer-right" id="appDrawerRight">
    <div class="drawer-header">
      <div class="drawer-title">筛选条件</div>
      <button class="drawer-close" data-drawer-right-close>✕</button>
    </div>
    <div class="drawer-body">
      <div class="drawer-section">
        <div class="drawer-section-title">项目类型</div>
        <div class="drawer-tag-row">
          <span class="drawer-tag active">全部</span>
          <span class="drawer-tag">护理</span>
        </div>
      </div>
    </div>
    <div class="drawer-actions">
      <button class="btn" data-drawer-right-close>重置</button>
      <button class="btn btn-primary" data-drawer-right-close>确定</button>
    </div>
  </div>
</div>
容器 id 必须为 drawerMask / appDrawer / drawerRightMask / appDrawerRight,否则交互不生效。点击遮罩、按 Esc 均可关闭。

顶部快捷菜单.topbar(面板)

从顶部下拉的快捷操作面板,常用于「新建 / 收银 / 报表」等高频入口。容器 id 固定为 topbarMask / topbarPanel,触发按钮加 data-open="topbar"。

效果预览
html
<button class="btn" data-open="topbar">打开快捷菜单</button>

<div class="topbar-mask" id="topbarMask">
  <div class="topbar" id="topbarPanel">
    <div class="topbar-header">
      <div class="topbar-title">快捷操作</div>
      <button class="topbar-close" data-topbar-close>✕</button>
    </div>
    <div class="topbar-body">
      <!-- 图标九宫格 -->
      <div class="topbar-icon-grid">
        <div class="topbar-icon-item">
          <span class="icon-circle"><i class="iconfont icon-user-plus"></i></span>
          <span class="icon-label">新增会员</span>
        </div>
        <div class="topbar-icon-item">
          <span class="icon-circle icon-circle-green"><i class="iconfont icon-yuyue1"></i></span>
          <span class="icon-label">新增预约</span>
        </div>
      </div>
      <!-- 菜单列表 -->
      <ul class="topbar-menu">
        <li class="topbar-menu-item">系统设置<span class="menu-desc">版本 1.0.0</span></li>
        <li class="topbar-menu-item">消息通知<span class="menu-badge">5</span></li>
      </ul>
    </div>
  </div>
</div>

底部操作面板.actionsheet

从底部升起的选择面板,移动端常用。容器 id 固定为 actionsheetMask / actionsheetPanel,触发按钮加 data-open="actionsheet",取消按钮加 data-actionsheet-cancel。

效果预览
html
<button class="btn" data-open="actionsheet">打开底部面板</button>

<div class="actionsheet-mask" id="actionsheetMask">
  <div class="actionsheet" id="actionsheetPanel">
    <div class="actionsheet-header">选择操作</div>
    <div class="actionsheet-menu">
      <div class="actionsheet-menu-item">拍照</div>
      <div class="actionsheet-menu-item">从相册选择</div>
      <div class="actionsheet-menu-item danger">删除</div>
    </div>
    <div class="actionsheet-cancel" data-actionsheet-cancel>取消</div>
  </div>
</div>

Tip 气泡.tip-trigger

点击触发的轻量气泡提示。data-tip 为内容,data-placement 控制气泡相对触发元素的方向,取值 top(默认)/ bottom / left / right。悬停提示用 .hover-tip-wrapper,方向同样由 data-placement 控制。

data-placement气泡位置小箭头朝向
top(默认)触发元素上方向下 ↓
bottom触发元素下方向上 ↑
left触发元素左侧向右 →
right触发元素右侧向左 ←
效果预览 · 点击气泡
上
下
左
右
效果预览 · 悬停气泡
悬停(上):鼠标移到这里上方悬停提示气泡。 悬停(下):鼠标移到这里下方悬停提示气泡。 悬停(左):鼠标移到这里左侧悬停提示气泡。 悬停(右):鼠标移到这里右侧悬停提示气泡。
html
<!-- 点击气泡:data-placement 控制方向 top / bottom / left / right,省略则默认 top -->
<div class="tip-trigger" data-placement="top" data-tip="气泡在触发元素上方">
  <span class="dot"></span> 上
</div>
<div class="tip-trigger" data-placement="bottom" data-tip="气泡在触发元素下方">下</div>
<div class="tip-trigger" data-placement="left" data-tip="气泡在触发元素左侧">左</div>
<div class="tip-trigger" data-placement="right" data-tip="气泡在触发元素右侧">右</div>

<!-- 悬停气泡:方向同样用 data-placement 控制 -->
<span class="hover-tip-wrapper" data-placement="right">
  鼠标移到这里
  <span class="hover-tip-content">右侧悬停提示气泡。</span>
</span>

Toast 轻提示toast(message, type, duration)

顶部居中的轻量提示,自动消失。容器 #toastContainer 由库自动创建,无需手写。

参数类型默认值说明
messagestring—提示文字(支持 HTML)
typestring'info'success / error / warning / info
durationnumber2500停留毫秒数
效果预览
javascript
toast('保存成功', 'success');
toast('网络异常,请重试', 'error');
toast('库存不足,请注意', 'warning');
toast('已复制到剪贴板');                 // 默认 info
toast('这条提示停留 5 秒', 'info', 5000);

Loading 加载showLoading / hideLoading

全屏加载遮罩,容器 #loadingMask 由库自动创建。

javascript
showLoading('正在提交...');       // 显示,可传自定义文案
setTimeout(hideLoading, 2000);   // 隐藏

// 典型用法
showLoading();
fetch('/api/save').then(() => {
  hideLoading();
  toast('保存成功', 'success');
}).catch(() => {
  hideLoading();
  toast('保存失败', 'error');
});
效果预览

弹窗系统openModal / alertBox / confirmBox / promptBox

统一的弹窗 API,支持普通 / 大 / 表单 / iframe 四种形态与 4 个尺寸档位。所有弹窗与提示框均支持 Enter 确认、Esc 取消(输入框内回车同样确认,多行文本除外)。

openModal(options)

参数类型默认值说明
titlestring'提示'标题,可含图标 HTML
bodystring''内容 HTML
sizestring'sm'sm / md / lg / xl
iframestring''传入地址则以 iframe 方式加载,忽略 body
scrollablebooleanfalse内容超出高度时是否可滚动
buttonsarray[{text:'确定',type:'primary'}]按钮配置数组,见下表
onOpenfunctionnull打开后回调,参数为弹窗容器 DOM,用于绑定内部元素
onConfirmfunctionnull点确定 / 按 Enter 触发
onCancelfunctionnull点取消 / 按 Esc 触发

buttons 数组项:text(按钮文字)、type(primary 或 outline)、onOk(box)(点击回调)、close(设为 false 时点击不关闭,用于表单校验失败时保留弹窗)。

javascript
// 1. 普通弹窗
openModal({
  title: '普通弹窗',
  body: '支持 <strong>HTML</strong> 内容',
  onConfirm: () => toast('已确认')
});

// 2. 大弹窗(可滚动)
openModal({
  title: '详情预览',
  size: 'lg',
  scrollable: true,
  body: '<div>...</div>'
});

// 3. 表单弹窗:校验失败时不关闭
openModal({
  title: '新增会员',
  size: 'md',
  body: '<input class="form-input" id="mName">',
  buttons: [
    { text: '取消', type: 'outline' },
    { text: '保存', type: 'primary', close: false,
      onOk: () => {
        const name = document.getElementById('mName').value.trim();
        if (!name) { toast('请输入姓名', 'error'); return; }  // 不关闭,留在弹窗
        toast('已保存:' + name, 'success');
      }
    }
  ]
});

// 4. iframe 弹窗
openModal({ title: '选择商品', size: 'xl', iframe: '/goods/select.html' });

// 5. 打开后操作内部元素
openModal({
  title: '绑定事件',
  body: '<button id="innerBtn">内部按钮</button>',
  onOpen: (box) => {
    box.querySelector('#innerBtn').addEventListener('click', () => toast('点击了内部按钮'));
  }
});

快捷方法

javascript
// Alert 提示
alertBox('这是一个提示', '提示');

// Confirm 确认(点确定执行回调)
confirmBox('确定要删除吗?此操作不可撤销。', () => {
  toast('已删除', 'success');
});

// Prompt 输入(回调接收输入值)
promptBox('请输入你的名字:', '', (val) => {
  toast('你输入了:' + val);
});
效果预览
弹窗底部会显示 Enter 确认 / Esc 取消 快捷键提示。最后一个按钮自动成为回车确认目标。点遮罩也可关闭。

验证码倒计时startCountdown(btn)

给按钮绑定 60 秒倒计时。若按钮位于 .verify-code-group 内且输入框为 type="tel",会先校验手机号。

javascript
<button class="verify-code-btn" onclick="startCountdown(this)">获取验证码</button>

<!-- 也可在脚本中绑定 -->
<script>
  document.querySelector('#sendCodeBtn').addEventListener('click', function () {
    startCountdown(this);
  });
</script>

滚轮选择器openWheelDatePicker / openWheelTimePicker

移动端风格的上下滑动选择器,在弹窗内使用,同样支持 Enter 确认 / Esc 取消。

javascript
openWheelDatePicker(function (val) {
  console.log('选择的日期:', val);   // "2026-09-29"
});

openWheelTimePicker(function (val) {
  console.log('选择的时间:', val);   // "14:30:00"
});

// 不传回调时,默认用 toast 显示结果

data-* 自动绑定免写 JS

大部分交互通过 data-* 属性自动绑定,页面无需写一行 JavaScript。下表为完整清单。

属性可用值作用
data-toastsuccess / error / warning / info点击弹出对应类型的 Toast
data-loading—点击显示 Loading 1.5 秒
data-modalalert / confirm / prompt / open / large / form / iframe点击打开对应弹窗
data-opendrawer / drawerRight / topbar / actionsheet点击打开对应面板
data-drawer-close—关闭左侧抽屉
data-drawer-right-close—关闭右侧抽屉
data-topbar-close—关闭顶部快捷菜单
data-actionsheet-cancel—关闭底部操作面板
data-submenu-toggle—抽屉内二级菜单展开 / 收起
data-submenu自定义 key侧边栏菜单项,触发二级弹出菜单
data-dropdown—标记下拉容器(可不写,按 .dropdown 识别)
data-value字符串下拉选项的值,选中后写入 .dropdown-value
data-tab目标面板 id选项卡按钮 / 底部导航项
data-page页面 key底部导航对应的页面
data-target输入框 id数字加减按钮的目标输入框
data-step数字数字加减按钮的步长(可为小数)
data-decimals数字输入框保留的小数位
data-wheeldate / time点击打开滚轮选择器
data-tip / data-placement文本 / top | bottom | left | rightTip 气泡内容与方向(默认 top)
data-media-more—图文卡片「全部」入口
data-pg-prev / data-pg-next—简单分页上一页 / 下一页
data-close—弹窗内关闭按钮
自动绑定在页面加载时执行一次,动态插入的元素不会被自动绑定。动态内容请在插入后手动绑定事件,或使用 openModal 的 onOpen 回调。

交互规范统一行为约定

场景约定行为
弹窗确认Enter 触发最后一个按钮 / onConfirm;输入框内回车同样确认,多行文本 textarea 除外
弹窗取消Esc 触发 onCancel 并关闭;点遮罩同样关闭
逐层关闭Esc 按「下拉 → 弹窗 → 抽屉 → 顶部菜单 → 底部面板」顺序逐层关闭
抽屉 / 面板点击遮罩关闭、Esc 关闭;打开一个面板时自动关闭其他面板
下拉菜单点击外部区域关闭;同一时间只允许一个下拉展开
数字加减到达 min / max 时对应按钮自动禁用
焦点管理弹窗打开后自动聚焦主按钮;Prompt 自动聚焦输入框
快捷键提示弹窗底部固定显示 Enter / Esc 提示标签
视觉约定:重要信息(如开课时间、库存、储值余额、到期时间、次卡次数)使用橙色并适当放大;普通说明文字用默认字号;过期时间不加粗;操作入口优先用文字按钮(查看 / 明细 / 删除)而非图标;选择类元素整行可点,不依赖小复选框。

开发规范团队约定

目录与引入

  • 组件库文件固定为 laimi.css 与 laimi.js,放置于 laimi_ui/ 目录。
  • 页面只写结构,不重复实现组件样式;页面独有样式单独写在页面 <style> 中,统一用 lmcard- 前缀,避免污染全局。
  • 页面逻辑与全局交互分离:全局交互(折叠、下拉、弹层、快捷键)由 laimi.js 统一负责,页面脚本只处理业务逻辑。
  • 修改源码前先备份,备份文件放在 Web 目录之外,避免源码通过 HTTP 泄露。

命名约定

  • 组件类名使用语义化短横线命名:.card-list-item、.media-item-badge。
  • 页面专属样式使用 lmcard- 前缀,例如 .lmcard-stat。
  • 状态类统一用 .active(选中/高亮)、.open(展开)、.disabled(禁用)。
  • 图标统一 <i class="iconfont icon-xxx"></i>,不使用 emoji。

布局约定

  • 顶部栏 position: fixed + z-index: 99990,左侧栏 z-index: 99980,保证二级弹层不被遮挡。
  • 绝对定位元素的参照容器需显式设置 position: relative。
  • 顶部栏高度、侧栏宽度统一使用 CSS 变量(--topbar-height / --sidebar-width),不要写死数值。
  • 主题变量必须在 <head> 同步应用,脚本不要加 defer / async,避免颜色闪烁。

表格与列表

  • 表格正文默认 14px,颜色使用主题变量。
  • 操作列优先使用文字按钮,不使用小图标;员工筛选等选择元素用标签式小按钮,独立成行放在表格上方。
  • 下拉分组遵循 layui 风格:分组标题为 0.75rem 浅灰小字(左内边距 10px),选项缩进一级(左内边距 22px),不使用背景块或竖色条。

常见问题FAQ

组件没反应 / 样式没生效?

按顺序检查:① laimi.css 是否引入且路径正确;② laimi.js 是否在 </body> 前引入;③ 容器 id 是否与文档一致(抽屉、顶部菜单、底部面板对 id 有硬性要求);④ 浏览器控制台是否有报错。

动态插入的 HTML 里按钮点了没反应?

data-* 绑定只在页面加载时执行一次。动态内容需在插入后手动绑定事件,或放在 openModal 的 onOpen 回调里绑定。

想换品牌色怎么办?

在 laimi.css 之后写一段 :root { --color-primary: #1677ff; } 即可,浅色变体会由 color-mix() 自动派生。

为什么页面没有抽屉/顶部菜单也不报错?

组件库对所有面板交互都做了元素存在判断,页面未放置对应容器时静默跳过,不影响其他组件。Toast、Loading、弹窗容器则由库自动创建。

图标显示成方框?

说明 iconfont 未加载或图标名不存在。检查 <link> 地址是否可访问,并把 ?t= 后的数字 +1 强制刷新缓存。图标名以 图标解析.html 为准。

移动端和 PC 端表现不一致?

日期 / 时间选择器会根据屏幕宽度与触屏能力自动切换:宽屏用下拉面板,窄屏 / 触屏用滚轮选择器。左侧栏在 < 768px 时自动折叠为图标模式。

Laimi UI v1.0.0 · 移动端 / PC 通用组件库 · 本文档由组件库自身构建
菜单导航
  • 首页
  • 会员管理12
  • 预约管理▶
    • 今日预约
    • 预约列表
    • 排班设置
  • 卡项管理
  • 数据统计
筛选条件
项目类型
全部 护理 美睫 美甲 SPA
库存区间
至
快捷排序
库存升序 最近入库 销量优先
快捷操作
新增会员
新增预约
收银
报表
  • 系统设置版本 1.0.0
  • 消息通知5
  • 打开抽屉菜单
选择操作
拍照
从相册选择
删除
取消