Files
wukuang/docs/物料组件添加流程.html
T
2026-05-23 14:05:22 +08:00

328 lines
26 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>物料组件添加流程 - 灵枢低代码平台</title>
<style>
:root {
--bg-primary: #0a0e1a; --bg-secondary: #111827; --bg-card: #1a2035;
--bg-card-hover: #1f2a45; --border-color: #2d3a5c; --text-primary: #e2e8f0;
--text-secondary: #94a3b8; --text-muted: #64748b;
--accent-blue: #3b82f6; --accent-blue-light: #60a5fa;
--accent-green: #10b981; --accent-green-light: #34d399;
--accent-orange: #f59e0b; --accent-orange-light: #fbbf24;
--accent-purple: #8b5cf6; --accent-purple-light: #a78bfa;
--accent-red: #ef4444; --accent-pink: #ec4899; --accent-cyan: #06b6d4;
--gradient-blue: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
--gradient-green: linear-gradient(135deg, #10b981 0%, #059669 100%);
--gradient-orange: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
--gradient-purple: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
--gradient-pink: linear-gradient(135deg, #ec4899 0%, #db2777 100%);
--shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.4); --shadow-md: 0 4px 20px rgba(0, 0, 0, 0.3);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background: var(--bg-primary); color: var(--text-primary); line-height: 1.6; padding: 2rem; }
.container { max-width: 1400px; margin: 0 auto; }
.header { text-align: center; padding: 3rem 2rem; background: var(--bg-card); border-radius: 16px; margin-bottom: 2.5rem; border: 1px solid var(--border-color); box-shadow: var(--shadow-lg); }
.header h1 { font-size: 2.5rem; background: linear-gradient(135deg, #60a5fa, #a78bfa, #f472b6); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; margin-bottom: 0.75rem; }
.header .subtitle { color: var(--text-secondary); font-size: 1.1rem; }
.header .stats { display: flex; justify-content: center; gap: 3rem; margin-top: 2rem; padding-top: 2rem; border-top: 1px solid var(--border-color); }
.stat-item { text-align: center; }
.stat-number { font-size: 2.5rem; font-weight: bold; background: linear-gradient(135deg, #60a5fa, #a78bfa); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
.stat-label { color: var(--text-muted); font-size: 0.9rem; margin-top: 0.25rem; }
.section { margin-bottom: 2.5rem; }
.section-title { font-size: 1.5rem; color: var(--text-primary); margin-bottom: 1.5rem; padding-left: 1rem; border-left: 4px solid var(--accent-blue); }
.flowchart-container { background: var(--bg-card); border-radius: 16px; padding: 2rem; border: 1px solid var(--border-color); box-shadow: var(--shadow-lg); overflow-x: auto; }
.flowchart { display: flex; flex-direction: column; align-items: center; gap: 0; min-width: 800px; padding: 1rem 0; }
.flow-row { display: flex; align-items: center; justify-content: center; gap: 1.5rem; width: 100%; }
.flow-node { padding: 1rem 1.5rem; border-radius: 10px; text-align: center; min-width: 180px; position: relative; transition: all 0.3s ease; }
.flow-node:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.flow-node.clickable { cursor: pointer; text-decoration: none; color: inherit; display: block; }
.flow-node.clickable::after { content: "🔍 点击查看详解"; position: absolute; bottom: -8px; left: 50%; transform: translateX(-50%) scale(0); background: var(--accent-blue); color: white; padding: 0.2rem 0.6rem; border-radius: 10px; font-size: 0.65rem; white-space: nowrap; transition: transform 0.2s ease; pointer-events: none; }
.flow-node.clickable:hover::after { transform: translateX(-50%) scale(1); }
.flow-node.start { background: var(--gradient-green); color: white; border-radius: 50px; padding: 1rem 2.5rem; }
.flow-node.step { background: var(--bg-secondary); border: 2px solid var(--accent-blue); }
.flow-node.step .step-num { position: absolute; top: -12px; left: -12px; width: 28px; height: 28px; background: var(--gradient-blue); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 0.85rem; }
.flow-node.step.create { border-color: var(--accent-green); }
.flow-node.step.create .step-num { background: var(--gradient-green); }
.flow-node.step.modify { border-color: var(--accent-orange); }
.flow-node.step.modify .step-num { background: var(--gradient-orange); }
.flow-node.step.type { border-color: var(--accent-purple); }
.flow-node.step.type .step-num { background: var(--gradient-purple); }
.flow-node.end { background: var(--gradient-pink); color: white; border-radius: 50px; padding: 1rem 2.5rem; }
.flow-node h4 { font-size: 0.95rem; margin-bottom: 0.25rem; }
.flow-node p { font-size: 0.75rem; color: var(--text-secondary); margin: 0; }
.flow-arrow { color: var(--accent-blue); font-size: 1.8rem; margin: 0.5rem 0; }
.flow-arrow-h { color: var(--text-muted); font-size: 1.5rem; }
.flow-branch { display: flex; align-items: flex-start; gap: 2rem; width: 100%; justify-content: center; }
.flow-branch-item { display: flex; flex-direction: column; align-items: center; }
.flow-label { font-size: 0.8rem; color: var(--text-muted); margin-top: 0.25rem; background: var(--bg-secondary); padding: 0.2rem 0.6rem; border-radius: 4px; }
.file-table { width: 100%; border-collapse: separate; border-spacing: 0; background: var(--bg-card); border-radius: 12px; overflow: hidden; border: 1px solid var(--border-color); box-shadow: var(--shadow-lg); }
.file-table thead { background: linear-gradient(135deg, #1e3a5f 0%, #1a2744 100%); }
.file-table th { padding: 1rem 1.25rem; text-align: left; font-weight: 600; color: var(--text-primary); font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.05em; }
.file-table td { padding: 1rem 1.25rem; border-top: 1px solid var(--border-color); font-size: 0.9rem; }
.file-table tbody tr { transition: background 0.2s ease; }
.file-table tbody tr:hover { background: var(--bg-card-hover); }
.file-path { font-family: 'Fira Code', 'Cascadia Code', monospace; font-size: 0.8rem; color: var(--accent-cyan); background: rgba(6, 182, 212, 0.1); padding: 0.25rem 0.5rem; border-radius: 4px; word-break: break-all; }
.badge { display: inline-block; padding: 0.2rem 0.6rem; border-radius: 20px; font-size: 0.7rem; font-weight: 600; text-transform: uppercase; }
.badge-create { background: rgba(16, 185, 129, 0.2); color: var(--accent-green-light); border: 1px solid rgba(16, 185, 129, 0.3); }
.badge-modify { background: rgba(245, 158, 11, 0.2); color: var(--accent-orange-light); border: 1px solid rgba(245, 158, 11, 0.3); }
.badge-optional { background: rgba(100, 116, 139, 0.2); color: var(--text-muted); border: 1px solid rgba(100, 116, 139, 0.3); }
.scenario-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 1.5rem; }
.scenario-card { background: var(--bg-card); border-radius: 12px; padding: 1.5rem; border: 1px solid var(--border-color); transition: all 0.3s ease; }
.scenario-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.scenario-card h3 { font-size: 1.2rem; margin-bottom: 0.75rem; display: flex; align-items: center; gap: 0.5rem; }
.scenario-card .icon { font-size: 1.5rem; }
.scenario-card p { color: var(--text-secondary); font-size: 0.9rem; margin-bottom: 1rem; }
.scenario-card .file-count { font-size: 2rem; font-weight: bold; margin-bottom: 0.5rem; }
.scenario-card.pure-widget .file-count { color: var(--accent-green); }
.scenario-card.field-widget .file-count { color: var(--accent-orange); }
.scenario-card.pure-field .file-count { color: var(--accent-purple); }
.steps-detail { display: flex; flex-direction: column; gap: 1.5rem; }
.step-detail { background: var(--bg-card); border-radius: 12px; padding: 1.5rem; border: 1px solid var(--border-color); border-left: 4px solid var(--accent-blue); }
.step-detail.create-step { border-left-color: var(--accent-green); }
.step-detail.modify-step { border-left-color: var(--accent-orange); }
.step-detail.type-step { border-left-color: var(--accent-purple); }
.step-header { display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem; }
.step-number { width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 1.1rem; flex-shrink: 0; }
.create-step .step-number { background: var(--gradient-green); }
.modify-step .step-number { background: var(--gradient-orange); }
.type-step .step-number { background: var(--gradient-purple); }
.step-title { font-size: 1.1rem; font-weight: 600; }
.step-content { padding-left: 3.5rem; }
.step-content p { color: var(--text-secondary); margin-bottom: 0.75rem; }
.step-content .code-block { background: var(--bg-secondary); padding: 0.75rem 1rem; border-radius: 8px; font-family: 'Fira Code', 'Cascadia Code', monospace; font-size: 0.8rem; color: var(--accent-cyan); overflow-x: auto; margin-top: 0.5rem; }
.step-content ul { list-style: none; padding: 0; }
.step-content ul li { padding: 0.4rem 0; color: var(--text-secondary); display: flex; align-items: flex-start; gap: 0.5rem; }
.step-content ul li::before { content: "▸"; color: var(--accent-blue); flex-shrink: 0; }
.architecture-diagram { background: var(--bg-card); border-radius: 16px; padding: 2rem; border: 1px solid var(--border-color); box-shadow: var(--shadow-lg); }
.arch-layer { display: flex; align-items: center; margin-bottom: 1.5rem; gap: 1rem; }
.arch-layer:last-child { margin-bottom: 0; }
.arch-label { min-width: 140px; padding: 0.75rem 1rem; border-radius: 8px; text-align: center; font-weight: 600; font-size: 0.85rem; }
.arch-label.types { background: var(--gradient-purple); }
.arch-label.form-designer { background: var(--gradient-blue); }
.arch-label.business { background: var(--gradient-green); }
.arch-label.modeling { background: var(--gradient-orange); }
.arch-label.mobile { background: var(--gradient-pink); }
.arch-files { display: flex; flex-wrap: wrap; gap: 0.5rem; flex: 1; }
.arch-file { padding: 0.4rem 0.75rem; background: var(--bg-secondary); border-radius: 6px; font-size: 0.75rem; font-family: 'Fira Code', monospace; color: var(--text-secondary); border: 1px solid var(--border-color); transition: all 0.2s ease; }
.arch-file:hover { border-color: var(--accent-blue); color: var(--accent-blue-light); }
.arch-file.highlight { border-color: var(--accent-green); color: var(--accent-green-light); background: rgba(16, 185, 129, 0.1); }
.arch-arrow { text-align: center; color: var(--text-muted); font-size: 1.2rem; margin: 0.5rem 0; padding-left: 140px; }
.footer { text-align: center; padding: 2rem; color: var(--text-muted); font-size: 0.85rem; border-top: 1px solid var(--border-color); margin-top: 3rem; }
@media (max-width: 768px) { body { padding: 1rem; } .header h1 { font-size: 1.8rem; } .header .stats { flex-direction: column; gap: 1.5rem; } .scenario-cards { grid-template-columns: 1fr; } .file-table { font-size: 0.8rem; } .file-table th, .file-table td { padding: 0.75rem; } }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>设计页面添加物料组件 - 文件改动分析</h1>
<p class="subtitle">灵枢低代码平台 (LCDP) · 物料组件开发完整指南 · 点击流程图节点查看详细文档</p>
<div class="stats">
<div class="stat-item"><div class="stat-number">7</div><div class="stat-label">必改文件数</div></div>
<div class="stat-item"><div class="stat-number">3</div><div class="stat-label">场景类型</div></div>
<div class="stat-item"><div class="stat-number">5</div><div class="stat-label">层级涉及</div></div>
</div>
</div>
<div class="section">
<h2 class="section-title">三种开发场景</h2>
<div class="scenario-cards">
<div class="scenario-card pure-widget">
<h3><span class="icon">🧩</span> 纯物料组件</h3>
<div class="file-count">7 个文件</div>
<p>不对应业务字段类型,仅是页面设计器中的纯 UI/交互/容器能力。如 CommonBtn、CommonTxt、GroupPanel、Tabs 等。</p>
<p><strong>推荐参考样板</strong>CommonBtn、GroupPanel</p>
</div>
<div class="scenario-card field-widget">
<h3><span class="icon">🔗</span> 字段类型 + 物料组件</h3>
<div class="file-count">20+ 个文件</div>
<p>既有业务字段定义,又有页面物料渲染。如金额、币种、手机号码、业务组织/人员等。</p>
<p><strong>推荐参考样板</strong>mobile-number</p>
</div>
<div class="scenario-card pure-field">
<h3><span class="icon">📝</span> 纯字段类型</h3>
<div class="file-count">5 个文件</div>
<p>只存在于业务模型,没有页面物料组件。如 BinaryObject 等仅服务后端的字段类型。</p>
<p><strong>推荐参考样板</strong>BinaryObject</p>
</div>
</div>
</div>
<div class="section">
<h2 class="section-title">纯物料组件添加流程图(点击节点下钻查看详解)</h2>
<div class="flowchart-container">
<div class="flowchart">
<div class="flow-node start">
<h4>开始:新增纯物料组件</h4>
<p>如 CommonBtn、GroupPanel 等</p>
</div>
<div class="flow-arrow"></div>
<div class="flow-row">
<a href="widget-steps/01-widget-type.html" target="_blank" class="flow-node clickable step type">
<div class="step-num">1</div>
<h4>定义 WidgetType</h4>
<p>packages/types/widget-pc/WidgetType.ts</p>
</a>
</div>
<div class="flow-arrow"></div>
<div class="flow-row">
<a href="widget-steps/02-vue-component.html" target="_blank" class="flow-node clickable step create">
<div class="step-num">2</div>
<h4>创建 Vue 组件</h4>
<p>form-designer/src/config/widget/xxx.vue</p>
</a>
<div class="flow-arrow-h">+</div>
<a href="widget-steps/03-helper-config.html" target="_blank" class="flow-node clickable step create">
<div class="step-num">3</div>
<h4>创建 Helper 配置</h4>
<p>form-designer/src/config/widget-helper/xxx.ts</p>
</a>
</div>
<div class="flow-arrow"></div>
<div class="flow-row">
<a href="widget-steps/04-register-widget.html" target="_blank" class="flow-node clickable step modify">
<div class="step-num">4</div>
<h4>注册组件实例</h4>
<p>RegisterWidget.ts</p>
</a>
<div class="flow-arrow-h">+</div>
<a href="widget-steps/05-register-helper.html" target="_blank" class="flow-node clickable step modify">
<div class="step-num">5</div>
<h4>注册 Helper</h4>
<p>RegisterWidgetHelper.ts</p>
</a>
<div class="flow-arrow-h">+</div>
<a href="widget-steps/06-material-panel.html" target="_blank" class="flow-node clickable step modify">
<div class="step-num">6</div>
<h4>注册物料面板</h4>
<p>Material.ts</p>
</a>
</div>
<div class="flow-arrow"></div>
<div class="flow-row">
<a href="widget-steps/07-i18n.html" target="_blank" class="flow-node clickable step modify">
<div class="step-num">7</div>
<h4>补充国际化</h4>
<p>form-designer/src/locales/model/Info.json</p>
</a>
</div>
<div class="flow-arrow"></div>
<div class="flow-branch">
<div class="flow-branch-item">
<a href="widget-steps/08-optional-steps.html" target="_blank" class="flow-node clickable step modify" style="border-style: dashed; opacity: 0.7; text-decoration: none; color: inherit;">
<h4>可选:自定义设置项/移动端</h4>
<p>settings-helper + widget-mobile</p>
</a>
<div class="flow-label">按需补充</div>
</div>
</div>
<div class="flow-arrow"></div>
<div class="flow-node end">
<h4>完成:物料组件已添加</h4>
<p>可在设计器中拖拽使用</p>
</div>
</div>
</div>
</div>
<div class="section">
<h2 class="section-title">纯物料组件 - 文件改动清单(7个必改)</h2>
<table class="file-table">
<thead><tr><th style="width: 60px;">步骤</th><th>文件路径</th><th style="width: 100px;">操作</th><th>作用说明</th></tr></thead>
<tbody>
<tr><td><strong>1</strong></td><td><span class="file-path">packages/types/widget-pc/WidgetType.ts</span></td><td><span class="badge badge-modify">修改</span></td><td>在 WidgetType 枚举中添加新组件类型值,作为全局唯一标识</td></tr>
<tr><td><strong>2</strong></td><td><span class="file-path">packages/form-designer/src/config/widget/&lt;组件名&gt;.vue</span></td><td><span class="badge badge-create">新建</span></td><td>实际的 Vue 渲染组件,定义 UI 结构和样式</td></tr>
<tr><td><strong>3</strong></td><td><span class="file-path">packages/form-designer/src/config/widget-helper/&lt;组件名&gt;Helper.ts</span></td><td><span class="badge badge-create">新建</span></td><td>Helper 配置对象,实现 buildMaterialConfig、buildSettings、buildWidget、dragInfo 等接口</td></tr>
<tr><td><strong>4</strong></td><td><span class="file-path">packages/form-designer/src/config/RegisterWidget.ts</span></td><td><span class="badge badge-modify">修改</span></td><td>导入 Vue 组件并在 SYS_COMPS_MAP 中注册:[WidgetType.Xxx]: { instance: XxxWidget }</td></tr>
<tr><td><strong>5</strong></td><td><span class="file-path">packages/form-designer/src/config/RegisterWidgetHelper.ts</span></td><td><span class="badge badge-modify">修改</span></td><td>导入 Helper 并添加到 SYS_WIDGET_HELPERS 数组</td></tr>
<tr><td><strong>6</strong></td><td><span class="file-path">packages/form-designer/src/config/Material.ts</span></td><td><span class="badge badge-modify">修改</span></td><td>在对应分组(通用/容器/导航等)的 widgetTypeList 中添加 WidgetType,使其出现在左侧物料面板</td></tr>
<tr><td><strong>7</strong></td><td><span class="file-path">packages/form-designer/src/locales/model/Info.json</span></td><td><span class="badge badge-modify">修改</span></td><td>添加物料显示名称、属性面板文案等国际化文案</td></tr>
</tbody>
</table>
</div>
<div class="section">
<h2 class="section-title">架构分层与文件分布</h2>
<div class="architecture-diagram">
<div class="arch-layer">
<div class="arch-label types">共享契约层<br><small>packages/types</small></div>
<div class="arch-files"><span class="arch-file highlight">WidgetType.ts</span><span class="arch-file">FieldType.ts</span><span class="arch-file">SettingType.ts</span><span class="arch-file">registry.ts</span></div>
</div>
<div class="arch-arrow">↓ 类型定义</div>
<div class="arch-layer">
<div class="arch-label form-designer">页面设计器层<br><small>packages/form-designer</small></div>
<div class="arch-files"><span class="arch-file highlight">Material.ts</span><span class="arch-file highlight">RegisterWidget.ts</span><span class="arch-file highlight">RegisterWidgetHelper.ts</span><span class="arch-file highlight">widget/*.vue</span><span class="arch-file highlight">widget-helper/*.ts</span><span class="arch-file">RegisterSettings.ts</span><span class="arch-file">settings-helper/*.ts</span><span class="arch-file highlight">locales/Info.json</span></div>
</div>
<div class="arch-arrow">↓ (纯物料通常不涉及以下层)</div>
<div class="arch-layer">
<div class="arch-label business">业务组件层<br><small>packages/business-components</small></div>
<div class="arch-files"><span class="arch-file" style="opacity: 0.5;">enum/settings/&lt;field&gt;/</span><span class="arch-file" style="opacity: 0.5;">utils/*Utils.ts</span><span class="arch-file" style="opacity: 0.5;">service/*.ts</span></div>
</div>
<div class="arch-arrow">↓ (纯物料通常不涉及以下层)</div>
<div class="arch-layer">
<div class="arch-label modeling">建模层<br><small>apps/lcdp</small></div>
<div class="arch-files"><span class="arch-file" style="opacity: 0.5;">FieldType.ts</span><span class="arch-file" style="opacity: 0.5;">helper/&lt;field&gt;/Schema.ts</span><span class="arch-file" style="opacity: 0.5;">modeling.json</span></div>
</div>
<div class="arch-arrow">↓ (按需)</div>
<div class="arch-layer">
<div class="arch-label mobile">移动端镜像层<br><small>form-designer/widget-mobile</small></div>
<div class="arch-files"><span class="arch-file" style="opacity: 0.5;">widget/*.vue</span><span class="arch-file" style="opacity: 0.5;">widget-helper/*.ts</span><span class="arch-file" style="opacity: 0.5;">Material.ts</span></div>
</div>
</div>
<p style="margin-top: 1rem; color: var(--text-muted); font-size: 0.85rem;"><span style="color: var(--accent-green);"></span> 高亮文件 = 纯物料组件必改文件 &nbsp;&nbsp;<span style="opacity: 0.5;"></span> 灰色文件 = 纯物料通常可跳过</p>
</div>
<div class="section">
<h2 class="section-title">注册执行链</h2>
<div class="flowchart-container">
<div class="flowchart">
<div class="flow-row"><div class="flow-node step" style="border-color: var(--accent-purple);"><h4>RegisterWeb.ts</h4><p>setPcConfigAll()</p></div></div>
<div class="flow-arrow">↓ 调用 setConfigAll(PC, config)</div>
<div class="flow-row"><div class="flow-node step" style="border-color: var(--accent-purple);"><h4>registry.ts</h4><p>registerConfigAll(platform)</p></div></div>
<div class="flow-arrow">↓ 依次调用</div>
<div class="flow-row">
<div class="flow-node step create" style="min-width: 150px;"><h4>register/widget.ts</h4><p>注册 widget 实例</p></div>
<div class="flow-arrow-h">+</div>
<div class="flow-node step create" style="min-width: 150px;"><h4>register/material.ts</h4><p>注册物料面板</p></div>
<div class="flow-arrow-h">+</div>
<div class="flow-node step create" style="min-width: 150px;"><h4>register/setting.ts</h4><p>注册设置项</p></div>
<div class="flow-arrow-h">+</div>
<div class="flow-node step create" style="min-width: 150px;"><h4>register/helper.ts</h4><p>注册 helper</p></div>
</div>
</div>
</div>
</div>
<div class="section">
<h2 class="section-title">最小验证建议</h2>
<table class="file-table">
<thead><tr><th>场景</th><th>验证方式</th></tr></thead>
<tbody>
<tr><td><strong>纯物料组件</strong></td><td><span class="file-path">pnpm form-designer:dev</span> → 访问 <code>/designer/:pageId</code><br><span style="color: var(--text-muted); margin-top: 0.5rem; display: inline-block;">验证:左侧物料面板出现新组件 → 拖入画布 → 右侧属性面板正常 → 画布渲染正常</span></td></tr>
<tr><td><strong>运行型物料</strong></td><td>额外验证:<code>/form/:pageId</code><code>/list/:pageId</code><br><span style="color: var(--text-muted); margin-top: 0.5rem; display: inline-block;">验证:运行时页面能正确渲染该组件</span></td></tr>
</tbody>
</table>
</div>
<div class="footer">
<p>灵枢低代码平台 · 物料组件开发指南 · 基于当前 Live Source 分析</p>
<p style="margin-top: 0.5rem;">文档生成日期:2026-05-13</p>
</div>
</div>
</body>
</html>