Regression / regression (push) Canceled after 0s
本提交含两条并行工作线,因互相咬合(package.json scripts、regression.yml、 npm run build 链)无法按文件干净拆分,故合并为一次自洽提交。 ## 详情页减重(本轮主任务:修复「AI 干太重」) - 导航收敛:宽屏只用右侧目录、≤1200px 只用页内 sticky 导航,纯 CSS 媒体查询 实现(不引入 JS 宽度监听)。此前两套导航同时可见,active 状态互相打架。 - 入口去重:标题区由「查看示例/在线测试/契约 JSON」三个减为「在线测试」一个; 契约 JSON 归入实现资源;删除示例底部重复的「在线测试」。 - 示例工具栏:删除与目录锚点重复的示例下拉选择器;「全部展开代码」只在 示例数 >1 时出现(103 个组件里 49 个仅 1 个示例,此前恒显示)。 - 重复文案:示例区两句同义导语合并为一句。 - 首页 CTA 由 5 个减为 2 个(浏览组件/快速开始),测试总览入口挂到已有的 通过率统计卡上,不再另占 Hero 按钮。 - 统一详情取数:抽出 fetchDetail/loadDetail 作为 details/*.json 的唯一路径, FAQ 不再自行 fetch 一遍,与组件页共用缓存与失败兜底。 ## i18n - 删除 12 组重复键(含整段 FAQ 说明),字典 604 → 585 唯一键。 - 删除本次改动产生的 6 个死键。 - verify-i18n.mjs 新增 `unique dictionary keys` 断言:重复键在对象字面量里 是静默的后值覆盖,此前无从发现;现由门禁拦住。 ## 文档事实修正(实测为准) - TESTING/CONTRIBUTING:79 → 103 组件;旧断言数改为回指 tests/report.json。 - PLATFORMS:移动端 108 文件/18 端 → 282 文件/47 端;契约 5 → 47; 令牌 17 → 15;uni-app SFC 21 → 50。 - AGENTS:断言 1405/18 页 → 1464/103 页(PC)、807/47 页(移动端)。 - package.json:YOUR-ACCOUNT 占位 → gitea 实址与 kole-ui.mymoyu.top。 ## 品牌标识(并行会话成果,一并入库) - brand-mark.json 收归真源,build:brand 生成 favicon 与单色 SVG; PC 与移动端共用资产,verify:brand 24 条断言。 - regression.yml 增加 verify:brand 步骤。 ## 门禁与验收 新增工具:verify-component-page.mjs(86 条真实浏览器断言,随详情页改造同步 更新为「只允许一套导航可见」)、verify-brand-mark.mjs、lib/i18n-dead-keys.mjs (只读诊断)。 回归:PC 100%(1464/1464,103 页,N/A 50)· 移动端 100%(807/807,47 页)。 门禁:component-page 86 · i18n 17 · brand 24 · routes all · smoke all · theme OK · isolation 31 · nav all · examples 9 · api-docs 10 · mobile-docs 12。 已知未做:i18n 另有约 44 条历史死键(非本次产生),已记为 ROADMAP S8-P6; 顶栏与悬浮区的两个主题入口为刻意设计(verify-theme 断言其互斥),未删。
511 lines
41 KiB
HTML
511 lines
41 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<script>
|
||
(function () {
|
||
var m = 'auto';
|
||
try { var v = localStorage.getItem('kole-mode'); if (v === 'light' || v === 'dark' || v === 'auto') m = v; } catch (e) {}
|
||
var dark = m === 'dark' || (m === 'auto' && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||
document.documentElement.classList.toggle('kole-dark', !!dark);
|
||
document.documentElement.style.colorScheme = dark ? 'dark' : 'light';
|
||
})();
|
||
</script>
|
||
<link rel="icon" href="../assets/kole-mark.svg">
|
||
<meta name="theme-color" content="#FFFFFF" media="(prefers-color-scheme: light)">
|
||
<meta name="theme-color" content="#1C1F26" media="(prefers-color-scheme: dark)">
|
||
<title>设计规范 — Kole UI Mobile</title>
|
||
<meta name="description" content="Kole UI 移动端设计规范(设计令牌):15 个 --kole-m-* 触控/安全区/字号令牌,以及从 PC 令牌层继承的颜色、字体、圆角与阴影。">
|
||
<link rel="stylesheet" href="../../.design_library/kole-ui-mobile/colors_and_type.css">
|
||
<link rel="stylesheet" href="style.css">
|
||
</head>
|
||
<body>
|
||
<header class="m-top">
|
||
<div class="m-top-inner">
|
||
<a class="m-logo" href="index.html">
|
||
<span class="m-logo-mark" data-brand-mark="mono" aria-hidden="true"></span>
|
||
<span class="m-logo-text">Kole UI<em>移动端</em></span>
|
||
</a>
|
||
<div class="m-ver-picker" id="m-ver-picker">
|
||
<button id="m-ver-trigger" class="m-ver-trigger" type="button" data-single="1" aria-haspopup="listbox" aria-expanded="false" aria-label="选择版本" title="文档版本(清单来自部署根的 versions.json)">
|
||
<span id="m-ver">v1.0.0</span>
|
||
<svg class="m-ver-caret" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
|
||
</button>
|
||
<div id="m-ver-menu" class="m-ver-menu hidden" role="listbox" aria-label="文档版本">
|
||
<div class="m-ver-menu-head" id="m-ver-head">文档版本</div>
|
||
</div>
|
||
</div>
|
||
<nav class="m-nav"> <a href="index.html">组件总览</a>
|
||
<a href="guide.html">快速开始</a>
|
||
<a href="design.html" class="active" aria-current="page">设计规范</a>
|
||
<a href="faq.html">常见问题</a>
|
||
<a href="changelog.html">更新日志</a></nav>
|
||
<div class="m-mode">
|
||
<button id="m-mode-trigger" class="m-mode-trigger" type="button" aria-haspopup="listbox" aria-expanded="false" aria-label="主题模式" title="主题模式">
|
||
<svg class="m-mode-icon" id="m-icon-moon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
|
||
<svg class="m-mode-icon" id="m-icon-sun" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="display:none"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>
|
||
<svg class="m-mode-icon" id="m-icon-auto" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="display:none"><rect x="3" y="4" width="18" height="13" rx="2"/><path d="M8 21h8M12 17v4"/></svg>
|
||
<span id="m-mode-cur">自动模式</span>
|
||
<svg class="m-mode-caret" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
|
||
</button>
|
||
<div id="m-mode-menu" class="m-menu hidden" role="listbox" aria-label="主题模式">
|
||
<div class="m-menu-head">主题模式</div>
|
||
<button class="m-menu-opt" type="button" role="option" data-mode="light" aria-selected="false"><span data-mode-label="light">日间模式</span></button>
|
||
<button class="m-menu-opt" type="button" role="option" data-mode="dark" aria-selected="false"><span data-mode-label="dark">夜间模式</span></button>
|
||
<button class="m-menu-opt" type="button" role="option" data-mode="auto" aria-selected="true"><span data-mode-label="auto">自动模式</span></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="m-body">
|
||
<details class="m-side" open>
|
||
<summary><span>移动端导航</span><span class="cur">设计规范</span></summary>
|
||
<nav>
|
||
<div class="m-side-section"><span>平台</span></div>
|
||
<a class="m-side-link m-side-platform" href="../index.html"><span class="sp-top"><span class="sp-name">PC 端组件</span></span><span class="sp-sub">103 个中后台组件 · 5 端</span></a>
|
||
<a class="m-side-link m-side-platform" href="index.html"><span class="sp-top"><span class="sp-name">移动端组件</span><span class="sp-badge">当前</span></span><span class="sp-sub">47 个组件 · 6 端 · 含 uni-app</span></a>
|
||
<div class="m-side-section"><span>开发指南</span></div>
|
||
<a class="m-side-link" href="index.html">组件总览</a>
|
||
<a class="m-side-link" href="guide.html">快速开始</a>
|
||
<a class="m-side-link is-active" href="design.html" aria-current="page">设计规范</a>
|
||
<a class="m-side-link" href="faq.html">常见问题</a>
|
||
<a class="m-side-link" href="changelog.html">更新日志</a>
|
||
<a class="m-side-link" href="platform.html">平台与端<em>移动端</em></a>
|
||
<a class="m-side-link" href="../../tests/mobile/index.html" target="_blank">测试与回归<em>移动端</em></a>
|
||
<div class="m-side-section"><span>组件</span><span class="cnt">47</span></div>
|
||
<div class="m-side-group"><span>通用</span><span class="cnt">5</span></div>
|
||
<a class="m-side-link" href="component/mobile-button.html">按钮<em>Button</em></a>
|
||
<a class="m-side-link" href="component/mobile-divider.html">分割线<em>Divider</em></a>
|
||
<a class="m-side-link" href="component/mobile-icon.html">图标<em>Icon</em></a>
|
||
<a class="m-side-link" href="component/mobile-layout.html">布局<em>Layout</em></a>
|
||
<a class="m-side-link" href="component/mobile-link.html">链接<em>Link</em></a>
|
||
<div class="m-side-group"><span>导航</span><span class="cnt">6</span></div>
|
||
<a class="m-side-link" href="component/navbar.html">顶部导航栏<em>NavBar</em></a>
|
||
<a class="m-side-link" href="component/tabbar.html">底部标签栏<em>TabBar</em></a>
|
||
<a class="m-side-link" href="component/mobile-grid.html">宫格<em>Grid</em></a>
|
||
<a class="m-side-link" href="component/mobile-steps.html">步骤条<em>Steps</em></a>
|
||
<a class="m-side-link" href="component/mobile-segmented.html">分段器<em>Segmented</em></a>
|
||
<a class="m-side-link" href="component/mobile-sticky.html">吸顶容器<em>Sticky</em></a>
|
||
<div class="m-side-group"><span>数据录入</span><span class="cnt">16</span></div>
|
||
<a class="m-side-link" href="component/mobile-numberkeyboard.html">数字键盘<em>NumberKeyboard</em></a>
|
||
<a class="m-side-link" href="component/mobile-datepicker.html">日期选择器<em>DatePicker</em></a>
|
||
<a class="m-side-link" href="component/mobile-input.html">输入框<em>Input</em></a>
|
||
<a class="m-side-link" href="component/mobile-search.html">搜索框<em>Search</em></a>
|
||
<a class="m-side-link" href="component/mobile-stepper.html">步进器<em>Stepper</em></a>
|
||
<a class="m-side-link" href="component/mobile-switch.html">开关<em>Switch</em></a>
|
||
<a class="m-side-link" href="component/mobile-textarea.html">多行文本框<em>Textarea</em></a>
|
||
<a class="m-side-link" href="component/mobile-checkbox.html">多选框<em>Checkbox</em></a>
|
||
<a class="m-side-link" href="component/mobile-form.html">表单<em>Form</em></a>
|
||
<a class="m-side-link" href="component/mobile-radio.html">单选框<em>Radio</em></a>
|
||
<a class="m-side-link" href="component/mobile-rate.html">评分<em>Rate</em></a>
|
||
<a class="m-side-link" href="component/mobile-slider.html">滑动选择器<em>Slider</em></a>
|
||
<a class="m-side-link" href="component/mobile-cascader.html">级联选择器<em>Cascader</em></a>
|
||
<a class="m-side-link" href="component/mobile-colorpicker.html">颜色选择器<em>ColorPicker</em></a>
|
||
<a class="m-side-link" href="component/mobile-picker.html">选择器<em>Picker</em></a>
|
||
<a class="m-side-link" href="component/mobile-upload.html">上传<em>Upload</em></a>
|
||
<div class="m-side-group"><span>数据展示</span><span class="cnt">8</span></div>
|
||
<a class="m-side-link" href="component/cell.html">单元格<em>Cell</em></a>
|
||
<a class="m-side-link" href="component/mobile-badge.html">徽标<em>Badge</em></a>
|
||
<a class="m-side-link" href="component/mobile-tag.html">标签<em>Tag</em></a>
|
||
<a class="m-side-link" href="component/mobile-avatar.html">头像<em>Avatar</em></a>
|
||
<a class="m-side-link" href="component/mobile-list.html">列表<em>List</em></a>
|
||
<a class="m-side-link" href="component/mobile-collapse.html">折叠面板<em>Collapse</em></a>
|
||
<a class="m-side-link" href="component/mobile-table.html">表格<em>Table</em></a>
|
||
<a class="m-side-link" href="component/mobile-typography.html">排版<em>Typography</em></a>
|
||
<div class="m-side-group"><span>反馈</span><span class="cnt">12</span></div>
|
||
<a class="m-side-link" href="component/actionsheet.html">动作面板<em>ActionSheet</em></a>
|
||
<a class="m-side-link" href="component/pullrefresh.html">下拉刷新<em>PullRefresh</em></a>
|
||
<a class="m-side-link" href="component/swipecell.html">滑动单元格<em>SwipeCell</em></a>
|
||
<a class="m-side-link" href="component/mobile-popup.html">弹出层<em>Popup</em></a>
|
||
<a class="m-side-link" href="component/mobile-toast.html">轻提示<em>Toast</em></a>
|
||
<a class="m-side-link" href="component/mobile-dialog.html">对话框<em>Dialog</em></a>
|
||
<a class="m-side-link" href="component/mobile-noticebar.html">通知栏<em>NoticeBar</em></a>
|
||
<a class="m-side-link" href="component/mobile-loading.html">加载<em>Loading</em></a>
|
||
<a class="m-side-link" href="component/mobile-progress.html">进度条<em>Progress</em></a>
|
||
<a class="m-side-link" href="component/mobile-message.html">消息通知<em>Message</em></a>
|
||
<a class="m-side-link" href="component/mobile-overlay.html">遮罩层<em>Overlay</em></a>
|
||
<a class="m-side-link" href="component/mobile-popover.html">弹出气泡<em>Popover</em></a>
|
||
</nav>
|
||
</details>
|
||
<main class="m-main">
|
||
<section class="m-hero">
|
||
<h1>设计规范</h1>
|
||
<p>与 PC 的「设计规范」同口径,本页讲移动端的令牌体系。移动端令牌层只有一层新增:<b>15 个 <code>--kole-m-*</code></b>(触控尺寸、安全区、移动端字号、手势动效)。
|
||
颜色、字体族、圆角、阴影<b>不复制</b>——通过 <code>@import</code> 继承 PC 令牌,改一处两端同时生效。</p>
|
||
</section>
|
||
|
||
<section class="m-block">
|
||
<h2>令牌文件</h2>
|
||
<table class="m-table">
|
||
<thead><tr><th>文件</th><th>作用</th></tr></thead>
|
||
<tbody>
|
||
<tr><td><code>.design_library/kole-ui/colors_and_type.css</code></td><td>PC 令牌(75 个 <code>--kole-*</code>):品牌色、文字色、边框、圆角、阴影、间距、字号 —— 两端共用</td></tr>
|
||
<tr><td><code>.design_library/kole-ui-mobile/colors_and_type.css</code></td><td>移动端令牌层:<code>@import</code> 上一行 + 本节列出的 <code>--kole-m-*</code></td></tr>
|
||
<tr><td><code>dist/mobile/tokens/tokens.css</code></td><td>上两者合成的<b>自包含单文件</b>(消费端只引这一个)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
|
||
<section class="m-block">
|
||
<h2>移动端自有令牌(<code>--kole-m-*</code>)</h2>
|
||
<table class="m-table">
|
||
<thead><tr><th>令牌</th><th>值</th><th>用途</th></tr></thead>
|
||
<tbody>
|
||
<tr><td><code>--kole-m-touch-target</code></td><td><code>44px</code></td><td>可点区域最小边长</td></tr>
|
||
<tr><td><code>--kole-m-navbar-height</code></td><td><code>44px</code></td><td>顶部导航栏内容高度(不含安全区)</td></tr>
|
||
<tr><td><code>--kole-m-tabbar-height</code></td><td><code>50px</code></td><td>底部标签栏内容高度(不含安全区)</td></tr>
|
||
<tr><td><code>--kole-m-action-height</code></td><td><code>56px</code></td><td>动作面板 / 列表行高度</td></tr>
|
||
<tr><td><code>--kole-m-gutter</code></td><td><code>16px</code></td><td>页面左右留白</td></tr>
|
||
<tr><td><code>--kole-m-hit-slack</code></td><td><code>8px</code></td><td>视觉尺寸不足 44px 时的扩展点击热区</td></tr>
|
||
<tr><td><code>--kole-m-safe-top</code></td><td><code>0px</code></td><td>顶部安全区;支持 env() 时由 @supports 覆盖为 env(safe-area-inset-top)</td></tr>
|
||
<tr><td><code>--kole-m-safe-bottom</code></td><td><code>0px</code></td><td>底部安全区;支持 env() 时由 @supports 覆盖为 env(safe-area-inset-bottom)</td></tr>
|
||
<tr><td><code>--kole-m-font-size-title</code></td><td><code>17px</code></td><td>导航栏标题</td></tr>
|
||
<tr><td><code>--kole-m-font-size-body</code></td><td><code>16px</code></td><td>正文 / 列表项</td></tr>
|
||
<tr><td><code>--kole-m-font-size-label</code></td><td><code>14px</code></td><td>次级说明</td></tr>
|
||
<tr><td><code>--kole-m-font-size-caption</code></td><td><code>11px</code></td><td>标签栏文字</td></tr>
|
||
<tr><td><code>--kole-m-duration-slide</code></td><td><code>240ms</code></td><td>面板/抽屉滑出</td></tr>
|
||
<tr><td><code>--kole-m-duration-refresh</code></td><td><code>300ms</code></td><td>下拉刷新回弹</td></tr>
|
||
<tr><td><code>--kole-m-ease-slide</code></td><td><code>cubic-bezier(.32, .72, 0, 1)</code></td><td></td></tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
|
||
<section class="m-block">
|
||
<h2>移动端组件实际用到的继承令牌</h2>
|
||
<p>下表的 PC 令牌由移动端 47 个组件的样式表实际引用(构建时扫描得出)。它们定义在 PC 令牌文件里,值随 PC 主题变化 —— 移动端不需要、也不应该重新定义同名令牌。</p>
|
||
<table class="m-table">
|
||
<thead><tr><th>令牌</th><th>值</th><th>被哪些组件使用</th></tr></thead>
|
||
<tbody>
|
||
<tr><td><code>--kole-color-border</code></td><td><code>#E8ECF1</code></td><td>顶部导航栏、底部标签栏、动作面板、下拉刷新、按钮、单元格、分割线、对话框、宫格、步骤条、数字键盘、日期选择器、列表、折叠面板、输入框、搜索框、步进器、多行文本框、多选框、表单、单选框、滑动选择器、级联选择器、颜色选择器、消息通知、选择器、弹出气泡、分段器、吸顶容器、表格、上传</td></tr>
|
||
<tr><td><code>--kole-color-brand</code></td><td><code>#2F54EB</code></td><td>顶部导航栏、底部标签栏、下拉刷新、按钮、标签、对话框、宫格、步骤条、通知栏、数字键盘、日期选择器、图标、链接、加载、头像、折叠面板、进度条、输入框、搜索框、开关、多行文本框、多选框、表单、单选框、评分、滑动选择器、级联选择器、颜色选择器、选择器、弹出气泡、分段器、吸顶容器、表格、排版、上传</td></tr>
|
||
<tr><td><code>--kole-color-brand-active</code></td><td><code>#10239E</code></td><td>按钮、数字键盘、链接、搜索框、表单、上传</td></tr>
|
||
<tr><td><code>--kole-color-brand-bg</code></td><td><code>#F0F5FF</code></td><td>顶部导航栏、底部标签栏、动作面板、下拉刷新、按钮、标签、通知栏、日期选择器、链接、加载、步进器、多选框、单选框、滑动选择器、级联选择器、选择器、吸顶容器、表格、排版、上传</td></tr>
|
||
<tr><td><code>--kole-color-card-bg</code></td><td><code>#FFFFFF</code></td><td>顶部导航栏、底部标签栏、动作面板、下拉刷新、滑动单元格、按钮、单元格、弹出层、对话框、宫格、步骤条、数字键盘、日期选择器、加载、头像、列表、折叠面板、进度条、输入框、搜索框、步进器、开关、多行文本框、多选框、表单、单选框、评分、滑动选择器、级联选择器、颜色选择器、消息通知、选择器、弹出气泡、分段器、吸顶容器、表格、上传</td></tr>
|
||
<tr><td><code>--kole-color-disabled-bg</code></td><td><code>#F5F5F5</code></td><td>按钮、标签、数字键盘、链接、头像、进度条、输入框、搜索框、步进器、多行文本框、多选框、表单、单选框、滑动选择器、颜色选择器、分段器、上传</td></tr>
|
||
<tr><td><code>--kole-color-error</code></td><td><code>#CF1322</code></td><td>底部标签栏、动作面板、滑动单元格、按钮、徽标、标签、对话框、步骤条、通知栏、图标、链接、进度条、输入框、多行文本框、表单、颜色选择器、消息通知、上传</td></tr>
|
||
<tr><td><code>--kole-color-focus-ring</code></td><td><code>rgba(47, 84, 235, 0.2)</code></td><td>顶部导航栏、底部标签栏、动作面板、下拉刷新、滑动单元格、按钮、单元格、标签、弹出层、对话框、宫格、通知栏、数字键盘、日期选择器、链接、头像、列表、折叠面板、输入框、搜索框、步进器、开关、多行文本框、多选框、表单、单选框、评分、滑动选择器、级联选择器、颜色选择器、消息通知、选择器、弹出气泡、分段器、吸顶容器、表格、排版、上传</td></tr>
|
||
<tr><td><code>--kole-color-icon-inactive</code></td><td><code>#8F8F8F</code></td><td>开关、评分</td></tr>
|
||
<tr><td><code>--kole-color-info</code></td><td><code>#096DD9</code></td><td>消息通知</td></tr>
|
||
<tr><td><code>--kole-color-mask</code></td><td><code>rgba(0, 0, 0, 0.45)</code></td><td>动作面板、弹出层、对话框、日期选择器、加载、级联选择器、颜色选择器、遮罩层、选择器、上传</td></tr>
|
||
<tr><td><code>--kole-color-mask-strong</code></td><td><code>rgba(0, 0, 0, 0.85)</code></td><td>轻提示、遮罩层</td></tr>
|
||
<tr><td><code>--kole-color-page-bg</code></td><td><code>#F5F7FA</code></td><td>动作面板、布局、列表、级联选择器</td></tr>
|
||
<tr><td><code>--kole-color-success</code></td><td><code>#2E7D0A</code></td><td>下拉刷新、标签、通知栏、图标、链接、头像、进度条、消息通知、排版、上传</td></tr>
|
||
<tr><td><code>--kole-color-table-header-bg</code></td><td><code>#FAFAFA</code></td><td>滑动单元格、单元格、标签、弹出层、对话框、宫格、通知栏、数字键盘、布局、头像、列表、折叠面板、步进器、开关、多选框、表单、单选框、级联选择器、消息通知、选择器、弹出气泡、分段器、表格、上传</td></tr>
|
||
<tr><td><code>--kole-color-tag-green-bg</code></td><td><code>#F6FFED</code></td><td>标签、通知栏</td></tr>
|
||
<tr><td><code>--kole-color-text-body</code></td><td><code>#262626</code></td><td>顶部导航栏、动作面板、下拉刷新、滑动单元格、按钮、单元格、弹出层、对话框、宫格、步骤条、数字键盘、日期选择器、布局、加载、列表、折叠面板、进度条、输入框、搜索框、步进器、开关、多行文本框、多选框、表单、单选框、评分、滑动选择器、级联选择器、颜色选择器、消息通知、选择器、弹出气泡、分段器、表格、排版、上传</td></tr>
|
||
<tr><td><code>--kole-color-text-disabled</code></td><td><code>#BFBFBF</code></td><td>顶部导航栏、底部标签栏、动作面板、按钮、单元格、标签、对话框、宫格、数字键盘、链接、头像、列表、折叠面板、输入框、搜索框、步进器、开关、多行文本框、多选框、表单、单选框、评分、滑动选择器、级联选择器、颜色选择器、选择器、分段器、表格、上传</td></tr>
|
||
<tr><td><code>--kole-color-text-inverse</code></td><td><code>#FFFFFF</code></td><td>底部标签栏、滑动单元格、按钮、徽标、轻提示、步骤条、数字键盘、头像、进度条、多选框、表单、单选框、颜色选择器、上传</td></tr>
|
||
<tr><td><code>--kole-color-text-placeholder</code></td><td><code>#767676</code></td><td>单元格、列表、折叠面板、输入框、搜索框、多行文本框、多选框、表单、单选框、滑动选择器、级联选择器</td></tr>
|
||
<tr><td><code>--kole-color-text-secondary</code></td><td><code>#6E6E6E</code></td><td>底部标签栏、动作面板、下拉刷新、滑动单元格、单元格、分割线、标签、弹出层、对话框、步骤条、数字键盘、图标、布局、加载、头像、列表、折叠面板、输入框、搜索框、步进器、多行文本框、多选框、表单、单选框、评分、滑动选择器、级联选择器、颜色选择器、消息通知、分段器、吸顶容器、表格、排版、上传</td></tr>
|
||
<tr><td><code>--kole-color-text-tertiary</code></td><td><code>#595959</code></td><td>排版</td></tr>
|
||
<tr><td><code>--kole-color-text-title</code></td><td><code>#1F2329</code></td><td>顶部导航栏、滑动单元格、单元格、对话框、日期选择器、列表、折叠面板、多选框、表单、单选框、级联选择器、选择器、弹出气泡、吸顶容器、排版、上传</td></tr>
|
||
<tr><td><code>--kole-color-tooltip-bg</code></td><td><code>#1F2329</code></td><td>轻提示</td></tr>
|
||
<tr><td><code>--kole-color-warning</code></td><td><code>#8C5A00</code></td><td>标签、通知栏、图标、消息通知</td></tr>
|
||
<tr><td><code>--kole-duration-base</code></td><td><code>0.3s</code></td><td>顶部导航栏、上传</td></tr>
|
||
<tr><td><code>--kole-duration-fast</code></td><td><code>0.2s</code></td><td>按钮、链接、颜色选择器、弹出气泡、分段器</td></tr>
|
||
<tr><td><code>--kole-ease-out</code></td><td><code>ease-out</code></td><td>下拉刷新、进度条、弹出气泡</td></tr>
|
||
<tr><td><code>--kole-ease-standard</code></td><td><code>ease</code></td><td>顶部导航栏、动作面板、按钮、链接、折叠面板、输入框、搜索框、开关、多行文本框、多选框、单选框、滑动选择器、颜色选择器、分段器、上传</td></tr>
|
||
<tr><td><code>--kole-font-family</code></td><td><code>"PingFang SC", "Source Han Sans SC", "Source Han Sans", "Microsoft YaHei", "Inter", "DIN", -apple-system, "Segoe UI", sans-serif</code></td><td>顶部导航栏、底部标签栏、动作面板、下拉刷新、滑动单元格、徽标、标签、弹出层、轻提示、对话框、宫格、步骤条、通知栏、数字键盘、日期选择器、加载、头像、列表、折叠面板、进度条、级联选择器、颜色选择器、消息通知、选择器、弹出气泡、分段器、吸顶容器、表格、排版、上传</td></tr>
|
||
<tr><td><code>--kole-font-family-num</code></td><td><code>"Inter", "DIN", "Segoe UI", sans-serif</code></td><td>底部标签栏、颜色选择器、表格、上传</td></tr>
|
||
<tr><td><code>--kole-icon-size-16</code></td><td><code>16px</code></td><td>图标、加载、消息通知</td></tr>
|
||
<tr><td><code>--kole-icon-size-20</code></td><td><code>20px</code></td><td>底部标签栏、下拉刷新、图标</td></tr>
|
||
<tr><td><code>--kole-icon-size-24</code></td><td><code>24px</code></td><td>图标</td></tr>
|
||
<tr><td><code>--kole-radius-base</code></td><td><code>4px</code></td><td>顶部导航栏、动作面板、按钮、数字键盘、日期选择器、输入框、搜索框、步进器、多行文本框、表单、级联选择器、颜色选择器、消息通知、选择器、弹出气泡、分段器、吸顶容器、表格、排版、上传</td></tr>
|
||
<tr><td><code>--kole-radius-large</code></td><td><code>8px</code></td><td>弹出层、轻提示、对话框、日期选择器、加载、折叠面板、级联选择器、选择器</td></tr>
|
||
<tr><td><code>--kole-radius-medium</code></td><td><code>6px</code></td><td>布局、头像、弹出气泡</td></tr>
|
||
<tr><td><code>--kole-radius-small</code></td><td><code>2px</code></td><td>徽标、链接、多选框</td></tr>
|
||
<tr><td><code>--kole-shadow-high</code></td><td><code>0 8px 24px rgba(0, 0, 0, 0.12)</code></td><td>加载</td></tr>
|
||
<tr><td><code>--kole-shadow-low</code></td><td><code>0 1px 4px rgba(0, 0, 0, 0.06)</code></td><td>顶部导航栏、开关、滑动选择器、分段器</td></tr>
|
||
<tr><td><code>--kole-shadow-medium</code></td><td><code>0 4px 12px rgba(0, 0, 0, 0.08)</code></td><td>消息通知、弹出气泡、吸顶容器</td></tr>
|
||
<tr><td><code>--kole-space-12</code></td><td><code>12px</code></td><td>动作面板、滑动单元格、按钮、单元格、分割线、弹出层、布局、加载、列表、折叠面板、进度条、输入框、搜索框、步进器、开关、多行文本框、多选框、表单、单选框、滑动选择器、颜色选择器、消息通知、弹出气泡、分段器、吸顶容器、表格、上传</td></tr>
|
||
<tr><td><code>--kole-space-16</code></td><td><code>16px</code></td><td>按钮、弹出层、轻提示、宫格、步骤条、布局、折叠面板、多选框、表单、单选框、颜色选择器、弹出气泡、分段器、上传</td></tr>
|
||
<tr><td><code>--kole-space-20</code></td><td><code>20px</code></td><td>按钮、轻提示、对话框、加载</td></tr>
|
||
<tr><td><code>--kole-space-24</code></td><td><code>24px</code></td><td>布局、加载</td></tr>
|
||
<tr><td><code>--kole-space-4</code></td><td><code>4px</code></td><td>顶部导航栏、底部标签栏、滑动单元格、按钮、徽标、标签、步骤条、日期选择器、图标、链接、进度条、表单、级联选择器、选择器、弹出气泡、表格、上传</td></tr>
|
||
<tr><td><code>--kole-space-40</code></td><td><code>40px</code></td><td>列表、级联选择器、表格</td></tr>
|
||
<tr><td><code>--kole-space-48</code></td><td><code>48px</code></td><td>通知栏</td></tr>
|
||
<tr><td><code>--kole-space-8</code></td><td><code>8px</code></td><td>顶部导航栏、动作面板、下拉刷新、单元格、分割线、标签、弹出层、轻提示、对话框、宫格、步骤条、通知栏、日期选择器、布局、加载、列表、输入框、搜索框、步进器、开关、多行文本框、多选框、表单、单选框、评分、级联选择器、颜色选择器、消息通知、选择器、弹出气泡、吸顶容器、排版、上传</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
|
||
<section class="m-block">
|
||
<h2>三条约定</h2>
|
||
<ul>
|
||
<li><b>单位</b>:移动端 Web 端(css / html / jsx / vue2 / vue3)用 <code>px</code>,触摸目标由 <code>--kole-m-touch-target</code>(44px)保证;<b>uni-app 端</b>用 <code>rpx</code>(750rpx = 视口宽度),组件内以同名令牌覆盖成 rpx 值(如 <code>--kole-m-touch-target: 88rpx</code>)。</li>
|
||
<li><b>安全区</b>:<code>--kole-m-safe-top/bottom</code> 用 <code>@supports (padding-top: env(safe-area-inset-top))</code> 探测后取 <code>env()</code>,不支持时为 <code>0px</code>(老浏览器拿到的是合法值,而不是被丢弃的声明)。页面需带 <code>viewport-fit=cover</code>。</li>
|
||
<li><b>明暗模式</b>:由 <code>html.kole-dark</code> 承担,颜色令牌在 PC 令牌文件里成对定义;移动端令牌层<b>不</b>定义颜色,因此暗色下不会出现"两端调色不一致"。</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="m-block">
|
||
<h2>改令牌的正确姿势</h2>
|
||
<div class="m-code">
|
||
<div class="m-code-head"><span>只改一处,两端同时生效</span><button class="m-copy" type="button" data-copy="code-token-edit">复制</button></div>
|
||
<pre id="code-token-edit"><code>/* PC 令牌(颜色 / 字体 / 圆角 / 阴影):两端共用 —— 改这里 */
|
||
/* .design_library/kole-ui/colors_and_type.css */
|
||
:root { --kole-color-brand: #2F54EB; }
|
||
|
||
/* 移动端自有令牌(触控 / 安全区 / 字号):只影响移动端 —— 改这里 */
|
||
/* .design_library/kole-ui-mobile/colors_and_type.css */
|
||
:root { --kole-m-touch-target: 44px; }
|
||
|
||
/* 组件里的尺寸默认走令牌,业务侧可覆盖:
|
||
.kole-m-pullrefresh { --kole-m-pullrefresh-threshold: 80px; } */</code></pre>
|
||
</div>
|
||
</section>
|
||
|
||
<footer class="m-foot">
|
||
<p>生成物:本页由 <code>node tools/build-mobile.mjs</code> 生成(令牌表来自令牌文件与组件样式表的实际扫描),请勿手改。</p>
|
||
<p>相关:<a href="./platform.html">平台与端</a> · <a href="./guide.html">快速开始</a></p>
|
||
</footer>
|
||
</main>
|
||
</div>
|
||
<script>
|
||
(function () {
|
||
/* 左栏:≤1000px 默认收起(手机上不让导航占满一屏),跨断点时同步一次;不监听 resize,
|
||
免得跟用户手动的展开/收起抢状态。桌面不设 open 之外的动作。 */
|
||
var side = document.querySelector('details.m-side');
|
||
if (side && window.matchMedia) {
|
||
var mq = window.matchMedia('(max-width: 1000px)');
|
||
var sync = function () { if (mq.matches) side.removeAttribute('open'); else side.setAttribute('open', ''); };
|
||
sync();
|
||
if (mq.addEventListener) mq.addEventListener('change', sync);
|
||
else if (mq.addListener) mq.addListener(sync);
|
||
}
|
||
/* 单演示预览帧按内容高度自适应(同源可读 contentDocument;上限 360px、下限 140px)。
|
||
固定高度会在内容少的演示上留一大片空白(实测 SwipeCell 单个演示只用 ~120px)。 */
|
||
function fitDemoFrames() {
|
||
var frames = document.querySelectorAll('.m-demo-stage iframe');
|
||
Array.prototype.forEach.call(frames, function (f) {
|
||
var fit = function () {
|
||
try {
|
||
var d = f.contentDocument;
|
||
if (!d || !d.body) return;
|
||
/* 只量 body.scrollHeight:documentElement.scrollHeight 等于**帧视口高度**(html 撑满视口),
|
||
拿它做 max 会形成「帧高→视口高→量到的高度」反馈环,永远收敛在初始值(实测锁在 308px)。 */
|
||
var h = d.body.scrollHeight;
|
||
if (!h) h = d.documentElement ? d.documentElement.scrollHeight : 0;
|
||
if (!h) return;
|
||
f.style.height = Math.min(360, Math.max(140, h + 8)) + 'px';
|
||
} catch (e) { /* 跨源或未就绪:保持 CSS 兜底高度 */ }
|
||
};
|
||
f.addEventListener('load', function () { fit(); setTimeout(fit, 300); });
|
||
fit();
|
||
});
|
||
}
|
||
fitDemoFrames();
|
||
window.addEventListener('load', fitDemoFrames);
|
||
/* 主题模式(三态):与 PC 完全同一约定 —— localStorage[kole-mode] ∈ light|dark|auto,
|
||
auto 跟随系统,反色靠 html.kole-dark(令牌文件里已写好该组,两端共用一份令牌)。
|
||
用户在 PC 站选夜间,进移动端站也是夜间。 */
|
||
var MODE_KEY = 'kole-mode';
|
||
var MODE_LABEL = { light: '日间模式', dark: '夜间模式', auto: '自动模式' };
|
||
function readMode() {
|
||
try { var v = localStorage.getItem(MODE_KEY); if (v === 'light' || v === 'dark' || v === 'auto') return v; } catch (e) {}
|
||
return 'auto';
|
||
}
|
||
function systemDark() {
|
||
return !!(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||
}
|
||
function applyMode(mode) {
|
||
var dark = mode === 'dark' || (mode === 'auto' && systemDark());
|
||
document.documentElement.classList.toggle('kole-dark', dark);
|
||
document.documentElement.style.colorScheme = dark ? 'dark' : 'light';
|
||
var cur = document.getElementById('m-mode-cur');
|
||
if (cur) cur.textContent = MODE_LABEL[mode] || MODE_LABEL.auto;
|
||
Array.prototype.forEach.call(document.querySelectorAll('.m-menu-opt'), function (o) {
|
||
o.setAttribute('aria-selected', o.getAttribute('data-mode') === mode ? 'true' : 'false');
|
||
});
|
||
/* 三态图标与 PC 同口径:显式选择时按时态给图标(日间=月亮 / 夜间=太阳),
|
||
自动模式下恒为「跟随系统」的显示器图标(此时两个显式图标都不显示)。 */
|
||
var moon = document.getElementById('m-icon-moon');
|
||
var sun = document.getElementById('m-icon-sun');
|
||
var auto = document.getElementById('m-icon-auto');
|
||
if (moon) moon.style.display = (mode === 'light') ? '' : 'none';
|
||
if (sun) sun.style.display = (mode === 'dark') ? '' : 'none';
|
||
if (auto) auto.style.display = (mode === 'auto') ? '' : 'none';
|
||
}
|
||
function bindModeMenu() {
|
||
var trigger = document.getElementById('m-mode-trigger');
|
||
var menu = document.getElementById('m-mode-menu');
|
||
if (!trigger || !menu) return;
|
||
var close = function (refocus) {
|
||
menu.classList.add('hidden'); trigger.setAttribute('aria-expanded', 'false');
|
||
if (refocus) trigger.focus();
|
||
};
|
||
trigger.addEventListener('click', function () {
|
||
var open = menu.classList.toggle('hidden');
|
||
trigger.setAttribute('aria-expanded', open ? 'false' : 'true');
|
||
});
|
||
trigger.addEventListener('keydown', function (e) {
|
||
if (e.key === 'Escape') close(true);
|
||
});
|
||
Array.prototype.forEach.call(menu.querySelectorAll('.m-menu-opt'), function (opt) {
|
||
opt.addEventListener('click', function () {
|
||
var mode = opt.getAttribute('data-mode');
|
||
try { localStorage.setItem(MODE_KEY, mode); } catch (e) {}
|
||
applyMode(mode);
|
||
close(true);
|
||
});
|
||
});
|
||
document.addEventListener('click', function (e) {
|
||
if (!menu.classList.contains('hidden') && !menu.contains(e.target) && !trigger.contains(e.target)) close(false);
|
||
});
|
||
document.addEventListener('keydown', function (e) {
|
||
if (e.key === 'Escape' && !menu.classList.contains('hidden')) close(true);
|
||
});
|
||
/* 自动模式下跟随系统切换 */
|
||
if (window.matchMedia) {
|
||
var mq = window.matchMedia('(prefers-color-scheme: dark)');
|
||
var onChange = function () { if (readMode() === 'auto') applyMode('auto'); };
|
||
if (mq.addEventListener) mq.addEventListener('change', onChange);
|
||
else if (mq.addListener) mq.addListener(onChange);
|
||
}
|
||
applyMode(readMode());
|
||
}
|
||
bindModeMenu();
|
||
/* 版本下拉:与 PC 顶栏同一实现口径 —— 清单从部署根取(<prefix>/versions.json 与
|
||
<prefix>/site/versions.json 两份按序尝试,取有可用条目的那份),拿不到就退回不可点的
|
||
纯角标(data-single="1"),不留一个点不开的下拉。
|
||
清单不许把用户带去外站:path 只允许 ".."(站点根自身)或 x.y.z 快照目录名。 */
|
||
var VERSION_KEY_PATH = '..';
|
||
function isValidVersionPath(p) {
|
||
if (typeof p !== 'string' || !p.length || p.indexOf('\\') >= 0 || p.indexOf('//') >= 0) return false;
|
||
if (p === VERSION_KEY_PATH) return true;
|
||
return /^\d+\.\d+\.\d+$/.test(p);
|
||
}
|
||
/* 清单里的 path 相对部署根,".." = /site/、x.y.z = /x.y.z/site/。
|
||
当前页可能不在部署根下(快照页),故先还原部署根绝对路径再算回相对当前页。 */
|
||
function versionHref(absSite) {
|
||
var i = location.pathname.indexOf('/site/');
|
||
var prefix = i >= 0 ? location.pathname.slice(0, i) : '';
|
||
if (!prefix || absSite.indexOf(prefix + '/') !== 0) return absSite;
|
||
var rest = absSite.slice(prefix.length + 1);
|
||
var up = '';
|
||
var segs = prefix.slice(1).split('/');
|
||
for (var k = 0; k < segs.length; k++) up += "../";
|
||
return up + rest;
|
||
}
|
||
function buildVersionList(doc) {
|
||
var raw = doc && doc.versions;
|
||
if (!raw || !raw.length) return [];
|
||
var i = location.pathname.indexOf('/site/');
|
||
var prefix = i >= 0 ? location.pathname.slice(0, i) : '';
|
||
var list = [];
|
||
for (var k = 0; k < raw.length; k++) {
|
||
var v = raw[k] || {};
|
||
var ver = v.version ? String(v.version) : '';
|
||
var path = v.path ? String(v.path) : '';
|
||
if (!ver || !isValidVersionPath(path)) continue;
|
||
var absSite = (path === VERSION_KEY_PATH ? '' : '/' + path) + '/site/';
|
||
list.push({ version: ver, date: v.date ? String(v.date) : '', latest: !!v.latest, href: versionHref(absSite), absSite: absSite, current: false });
|
||
}
|
||
if (list.length) {
|
||
/* 当前版本 = 绝对路径上命中的最长前缀(最具体的那个)——与 PC 的判定一致,
|
||
快照页与根站点都能算对。 */
|
||
var here = location.pathname;
|
||
var best = -1;
|
||
for (var j = 0; j < list.length; j++) {
|
||
if (here.indexOf(list[j].absSite) === 0 && list[j].absSite.length > best) best = list[j].absSite.length;
|
||
}
|
||
for (var m = 0; m < list.length; m++) list[m].current = best >= 0 && list[m].absSite.length === best;
|
||
if (best < 0 && list[0]) list[0].current = true;
|
||
}
|
||
return list;
|
||
}
|
||
function bindVersionMenu() {
|
||
var trigger = document.getElementById('m-ver-trigger');
|
||
var menu = document.getElementById('m-ver-menu');
|
||
var chip = document.getElementById('m-ver');
|
||
if (!trigger || !menu) return;
|
||
var close = function (refocus) {
|
||
menu.classList.add('hidden'); trigger.setAttribute('aria-expanded', 'false');
|
||
if (refocus) trigger.focus();
|
||
};
|
||
var interactive = false;
|
||
var render = function (list) {
|
||
interactive = !!(list && list.length);
|
||
/* 只有清单拿不到才退回纯角标;只要有一版就是下拉(里面至少能看清当前是哪个版本) */
|
||
trigger.setAttribute('data-single', interactive ? '0' : '1');
|
||
if (!interactive) { menu.classList.add("hidden"); return; }
|
||
var cur = null;
|
||
for (var k = 0; k < list.length; k++) if (list[k].current) cur = list[k];
|
||
if (chip) chip.textContent = 'v' + ((cur && cur.version) || VERSION);
|
||
/* 重建选项(幂等:重复调用不会叠加) */
|
||
Array.prototype.slice.call(menu.querySelectorAll('.m-ver-opt')).forEach(function (n) { n.remove(); });
|
||
list.forEach(function (it) {
|
||
var opt = document.createElement('button');
|
||
opt.type = 'button'; opt.className = 'm-ver-opt'; opt.setAttribute('role', 'option');
|
||
opt.setAttribute('data-version', it.version);
|
||
opt.setAttribute('aria-selected', it.current ? 'true' : 'false');
|
||
var tag = it.current ? '当前浏览' : (it.latest ? '最新版' : (it.date || ''));
|
||
opt.innerHTML = '<span class="m-ver-opt-num">v' + it.version + '</span><span class="m-ver-opt-tag">' + tag + '</span>';
|
||
if (it.href) opt.setAttribute('data-href', it.href);
|
||
opt.addEventListener("click", function () {
|
||
if (!it.current && it.href) location.href = it.href;
|
||
else close(true);
|
||
});
|
||
menu.appendChild(opt);
|
||
});
|
||
};
|
||
trigger.addEventListener('click', function () {
|
||
if (!interactive) return;
|
||
if (menu.classList.contains('hidden')) { menu.classList.remove('hidden'); trigger.setAttribute('aria-expanded', 'true'); }
|
||
else close(false);
|
||
});
|
||
trigger.addEventListener('keydown', function (e) {
|
||
if (!interactive) return;
|
||
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { e.preventDefault(); menu.classList.remove('hidden'); trigger.setAttribute('aria-expanded', 'true'); }
|
||
else if (e.key === 'Escape') close(true);
|
||
});
|
||
document.addEventListener('click', function (e) {
|
||
if (!menu.classList.contains('hidden') && !menu.contains(e.target) && !trigger.contains(e.target)) close(false);
|
||
});
|
||
document.addEventListener('keydown', function (e) {
|
||
if (e.key === 'Escape' && !menu.classList.contains('hidden')) close(true);
|
||
});
|
||
/* 两份清单按序尝试(不并行:快照页那份必然 404,并行会把 404 记进控制台,
|
||
而站点门禁的「零控制台错误」是硬断言)。 */
|
||
if (!window.fetch || location.protocol === 'file:') return;
|
||
var i = location.pathname.indexOf('/site/');
|
||
if (i < 0) return;
|
||
var prefix = location.pathname.slice(0, i);
|
||
var urls = [prefix + '/versions.json', prefix + '/site/versions.json'];
|
||
var attempt = function (idx) {
|
||
if (idx >= urls.length) return;
|
||
fetch(urls[idx], { cache: 'no-store' })
|
||
.then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.json(); })
|
||
.then(function (doc) { var list = buildVersionList(doc); if (list.length) render(list); else attempt(idx + 1); })
|
||
.catch(function () { attempt(idx + 1); });
|
||
};
|
||
attempt(0);
|
||
}
|
||
bindVersionMenu();
|
||
function done(btn) {
|
||
var old = btn.textContent; btn.textContent = '已复制'; btn.classList.add('is-done');
|
||
setTimeout(function () { btn.textContent = old; btn.classList.remove('is-done'); }, 1200);
|
||
}
|
||
document.addEventListener('click', function (e) {
|
||
var btn = e.target && e.target.closest ? e.target.closest('.m-copy') : null;
|
||
if (!btn) return;
|
||
var src = document.getElementById(btn.getAttribute('data-copy') || '');
|
||
var text = src ? (src.innerText || src.textContent || '') : '';
|
||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||
navigator.clipboard.writeText(text).then(function () { done(btn); }, function () { fallback(btn, text); });
|
||
} else { fallback(btn, text); }
|
||
});
|
||
function fallback(btn, text) {
|
||
try {
|
||
var ta = document.createElement('textarea'); ta.value = text; ta.setAttribute('readonly', '');
|
||
ta.style.position = 'fixed'; ta.style.opacity = '0'; document.body.appendChild(ta);
|
||
ta.select(); document.execCommand("copy"); document.body.removeChild(ta); done(btn);
|
||
} catch (err) { btn.textContent = '复制失败'; }
|
||
}
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|