Developer Guide · v1.0

开发与对接文档

面向 PHP / ThinkPHP / 传统 CMS 的接入说明。翊象 UI 不依赖构建工具,也不需要 jQuery; 引入核心 CSS / JS 资源即可获得完整的设计系统、三态主题、弹窗、组件与全站免刷新能力。

快速接入

把 css/、js/、assets/ 拷贝到项目静态目录,在页面 <head> 中按顺序引入:

<link rel="stylesheet" href="css/yixiang.core.css">
<link rel="stylesheet" href="css/yixiang.layout.css">
<link rel="stylesheet" href="css/yixiang.components.css">
<link rel="stylesheet" href="css/yixiang.modal.css">   <!-- 需要弹窗时 -->
<link rel="stylesheet" href="css/yixiang.mobile.css">
<link rel="stylesheet" href="css/yixiang.ajax.css">     <!-- 需要加载动画时 -->

<script src="js/yixiang.modal.js"></script>           <!-- 需要弹窗时 -->
<script src="js/yixiang.components.js"></script>
<script src="js/yixiang.ajax.js"></script>             <!-- 需要 AJAX / PJAX 时 -->
零依赖:不再需要 jQuery、jquery.pjax 或 NProgress。旧版 js/yixiang.pjax.js 仅作兼容保留,不要与新引擎同时加载。

资源与目录

文件作用是否必需
yixiang.core.css设计令牌(CSS 变量)、重置、排版、深浅色变量是
yixiang.layout.css前台/后台布局、页头、侧栏、栅格工具类、主题切换器是
yixiang.components.css按钮、卡片、表单、标签、表格、下拉、Tabs、图表、待办是
yixiang.mobile.css≤1024 / 768 / 480 响应式规则是
yixiang.modal.cssYixiangModal 弹窗样式按需
yixiang.ajax.css顶部进度条与可选全屏 Loading按需
yixiang.components.js主题、侧栏抽屉、下拉、Tabs、声明式 Modal是
yixiang.modal.jsYixiangModal 独立弹窗引擎按需
yixiang.ajax.js全局 AJAX、PJAX、加载动画(可开关)按需

页面骨架

前台页面

页头必须放在 #pjax-container 内部,这样从首页透明头部切换到内容页实心头部时,头部会随页面一起替换。

<div class="yx-app">
  <div id="pjax-container" style="flex: 1; display: flex; flex-direction: column;">
    <header class="yx-header yx-header-transparent">…</header>
    <main>…</main>
    <footer>…</footer>
  </div>
</div>

后台 / 控制台页面

<div class="yx-app yx-layout-sidebar">
  <aside class="yx-sidebar">…</aside>
  <main class="yx-main">
    <header class="yx-main-header">…</header>
    <div id="pjax-container" class="yx-content">…</div>
  </main>
</div>

侧栏菜单链接加 data-pjax 即可启用免刷新;跨布局(前台 ↔ 后台 ↔ 控制台)会自动整页跳转。

全局 AJAX / PJAX / 加载动画

新引擎独立成文件,三个能力可以分别开关:全局 AJAX(fetch/XHR 计数 + 加载动画)、PJAX(免刷新导航)、Loading(顶部进度条 / 全屏遮罩)。

引入与配置

<script src="js/yixiang.ajax.js"
        data-ajax="true"
        data-pjax="true"
        data-loading="true"
        data-overlay="false"
        data-container="#pjax-container"
        data-timeout="10000"></script>
配置项默认值说明
ajaxtrue拦截全局 fetch / XHR,自动显示加载动画
pjaxtrue拦截 a[data-pjax] 实现免刷新导航
loadingtrue显示顶部进度条
overlayfalse额外显示全屏 Loading 遮罩
container#pjax-container被替换的容器选择器
fragment#pjax-container从响应 HTML 中提取的片段选择器
timeout10000PJAX 超时(毫秒),超时回退整页跳转
cachefalse是否缓存 PJAX 片段(内存 Map)
sameLayoutOnlytrue仅同布局页面之间启用 PJAX
scrollToToptruePJAX 完成后回到顶部
minDuration260进度条最短展示时间,避免闪烁
errorFallbacktrue请求失败时回退整页跳转

运行时开关

// 只关闭 PJAX,保留全局 AJAX 与加载动画
YixiangAjax.disable('pjax');
YixiangAjax.enable('pjax');

// 关闭全屏 Loading / 顶部进度条
YixiangAjax.configure({ loading: false, overlay: false });

// 一键关闭全部能力
YixiangAjax.disable();

// 查看当前配置
YixiangAjax.getConfig();

也可以让运营同学直接在后台切换:站点设置 → 性能与导航。开关保存到服务端全局配置,对所有访客生效;保存成功/失败都会弹窗提示。

全局站点设置接口

所有页面初始化时会读取同一份配置,管理员在后台保存后,其他访客下次打开或切换页面即生效。

GET  /api/site-settings

{
  "ajax": true,
  "pjax": true,
  "loading": true,
  "overlay": false
}

POST /api/site-settings
Content-Type: application/json

{ "pjax": false }   // 支持只提交需要修改的字段,返回保存后的完整配置
  • 前端通过 YixiangAjax.saveSiteSettings({ pjax: false }) 保存。
  • 请求地址可用脚本属性覆盖:data-settings-url="/admin/site-settings"。
  • 生产环境务必在 POST 接口上增加管理员鉴权与 CSRF 校验。
  • 本地 serve.py 已实现该接口并写入 site-config.json,可直接体验“管理员改一次,所有浏览器生效”。

发起请求

// 自动带进度条(内部使用原生 fetch,不会重复计数)
const response = await YixiangAjax.request('/api/articles', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ title: 'Hello' })
});
const json = await response.json();

// 单次请求不显示加载动画
fetch('/api/ping', { yxLoading: false });

// 编程式导航
YixiangAjax.navigate('/admin_article.html');

事件

事件触发时机
yx:ajax:ready引擎初始化完成
yx:loading:start / yx:loading:end加载动画开始 / 结束
yx:pjax:start开始 PJAX 请求
yx:pjax:success内容替换完成
yx:pjax:error请求失败(默认回退整页)
yx:pjax:end请求结束(无论成功失败)
yx:pjax:loaded组件已重新初始化、导航与面包屑已同步

服务端要求

  • 响应必须是完整 HTML,并包含 #pjax-container(引擎会从中提取内容)。
  • 可选读取 X-PJAX: true 与 X-PJAX-Container 请求头做差异化输出。
  • PJAX 只替换容器内容,不会重新加载页面级 CSS/JS;公共资源请在所有页面统一引入。
  • 容器内的行内 <script> 会自动执行;外链脚本需加 data-reload 才会重新执行。

主题系统

支持 浅色(默认)、深色、跟随系统 三种模式,偏好保存在 localStorage.yx-theme。

// 切换并持久化
YixiangComponents.applyThemeMode('light');   // 浅色
YixiangComponents.applyThemeMode('dark');    // 深色
YixiangComponents.applyThemeMode('system');  // 跟随系统

YixiangComponents.getThemeMode();            // 读取当前模式

// 监听主题变化
document.addEventListener('yixiang:themechange', function (event) {
  console.log(event.detail.theme, event.detail.mode);
});

头部主题切换器使用 data-theme-value 菜单项,图标由 html[data-theme-mode] 自动切换,无需额外 JS。

组件速查

组件关键类名 / 属性
按钮yx-btn + yx-btn-primary/default/ghost/text/success/danger,尺寸 yx-btn-sm/lg/icon
卡片yx-card、yx-card-header/body/footer、yx-card-hover
表单yx-form-group、yx-form-label、yx-input/textarea/select
标签yx-badge + yx-badge-primary/success/warning/danger/neutral
表格yx-table-wrapper > yx-table
下拉yx-dropdown > [data-toggle="dropdown"] + yx-dropdown-menu
Tabs[data-toggle="tabs"]、yx-tabs-nav、yx-tab-item[data-target]、yx-tab-pane
主题切换yx-theme-switch + data-theme-value

完整示例可直接查看 组件文档页。

富文本编辑器

基于 Quill 1.3.7(BSD-3-Clause)与本地 Coolapk 表情面板实现,支持标题、加粗、斜体、下划线、删除线、列表、引用、代码块、链接、图片、对齐、撤销重做与 Emoji 表情选择。

<link rel="stylesheet" href="lib/quill/quill.snow.css">
<link rel="stylesheet" href="css/yixiang.editor.css">

<script src="lib/quill/quill.min.js"></script>
<script src="js/yixiang.emoji.js"></script>
<script src="js/yixiang.editor.js"></script>
// 打开新建文章编辑器 / Open the article editor
YixiangEditor.open();

// 打开编辑模式 / Open edit mode
YixiangEditor.open({ mode: 'edit', title: '文章标题', html: '<p>正文</p>' });

// 发布后监听 / Listen to publish event
document.addEventListener('yx:article:published', function (event) {
  console.log(event.detail);
});

编辑器支持 Ctrl/⌘ + S 保存草稿、Esc 关闭,发布/草稿均为模拟异步请求。

扩展弹层:Tabs / Drawer / Photos / Tips

翊象 UI 内置的高频扩展能力,API 原生、可独立调用:

// 标签页弹层 / Tabbed dialog
YixiangModal.tabs({
  title: '内容详情',
  tabs: [
    { title: '概览', content: '<p>概览内容</p>' },
    { title: '高级', content: '<p>高级设置</p>' }
  ]
});

// 右侧抽屉 / Right drawer
YixiangModal.drawer({
  title: '筛选条件',
  content: '<p>抽屉内容</p>',
  btn: ['应用筛选', '重置']
});

// 图片预览 / Photo viewer
YixiangModal.photos({
  photos: ['assets/images/demo-1.svg', 'assets/images/demo-2.svg'],
  index: 0
});

// 气泡提示 / Tooltip
YixiangModal.tips('这是一个气泡提示 ✨', targetElement, { placement: 'bottom', time: 2600 });

Loading 支持卡片式、无卡片与全屏遮罩:YixiangModal.load({ text, card, shade, time })。

CMS 对接示例

ThinkPHP 控制器

public function article()
{
    $list = Db::name('article')->order('id desc')->paginate(10);
    $this->assign('list', $list);
    return $this->fetch(); // 返回完整页面(含 #pjax-container)
}

模板片段

<div id="pjax-container" class="yx-content">
  <div class="yx-page-header">
    <h1 class="yx-page-title">文章管理</h1>
  </div>

  <div class="yx-card">
    <div class="yx-table-wrapper">
      <table class="yx-table">…</table>
    </div>
  </div>
</div>

表单 AJAX 提交

document.querySelector('#article-form').addEventListener('submit', async function (event) {
  event.preventDefault();

  const response = await YixiangAjax.request(this.action, {
    method: 'POST',
    body: new FormData(this)
  });

  const result = await response.json();
  if (result.code === 0) {
    YixiangModal.msg('保存成功', { icon: 'success' });
    YixiangAjax.navigate('/admin_article.html');
  } else {
    YixiangModal.alert(result.message, { icon: 'error' });
  }
});
表单提交会自动触发顶部进度条;如果后端返回 JSON,请确保 Content-Type: application/json。

常见问题

1. 直接双击 HTML,PJAX 不生效?

浏览器会限制 file:// 下的 XHR/fetch。请用 python serve.py 或任意 HTTP 服务器访问。

2. PJAX 后组件失效?

组件使用事件委托,正常情况下无需手动绑定。若自行扩展了 DOM 级插件,请在 yx:pjax:loaded 事件中重新初始化:

document.addEventListener('yx:pjax:loaded', function () {
  // 重新初始化第三方插件
});

3. 点击后台链接为什么整页刷新?

前台、后台 admin_*、控制台 console_* 属于三种布局。引擎默认只在同布局内 PJAX,跨布局整页跳转以避免侧栏/头部错乱。

4. 如何彻底关闭免刷新?

移除 data-pjax 属性,或执行 YixiangAjax.disable('pjax');也可以给链接加 data-no-pjax。

5. 进度条不显示?

检查是否引入 css/yixiang.ajax.css、YixiangAjax.isEnabled('loading') 是否为 true,以及脚本标签是否设置了 data-loading="false"。

6. 能和旧版 jQuery PJAX 共存吗?

不能同时加载。新版已完全替代 js/yixiang.pjax.js 与 NProgress,请从页面移除旧脚本和 nprogress.css。

7. 版本

当前框架、组件与脚本统一为 v1.0。