Files
2026-05-23 14:05:22 +08:00

318 lines
14 KiB
HTML
Raw Permalink 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>步骤详解 - 创建 Helper 配置文件</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-green: #10b981;
--accent-green-light: #34d399;
--accent-cyan: #06b6d4;
--accent-purple: #8b5cf6;
--accent-orange: #f59e0b;
--shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.4);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.7;
padding: 2rem;
}
.container { max-width: 1000px; margin: 0 auto; }
.back-link {
display: inline-flex; align-items: center; gap: 0.5rem;
color: var(--accent-green-light); text-decoration: none;
margin-bottom: 2rem; padding: 0.5rem 1rem;
background: var(--bg-card); border-radius: 8px;
border: 1px solid var(--border-color); transition: all 0.2s ease;
}
.back-link:hover { background: var(--bg-card-hover); transform: translateX(-4px); }
.header {
background: var(--bg-card); border-radius: 16px; padding: 2rem;
margin-bottom: 2rem; border: 1px solid var(--border-color);
box-shadow: var(--shadow-lg); border-left: 4px solid var(--accent-green);
}
.step-badge {
display: inline-block; background: linear-gradient(135deg, #10b981 0%, #059669 100%);
color: white; padding: 0.3rem 1rem; border-radius: 20px;
font-size: 0.85rem; font-weight: 600; margin-bottom: 1rem;
}
.header h1 { font-size: 2rem; margin-bottom: 0.5rem; }
.header .desc { color: var(--text-secondary); font-size: 1rem; }
.section {
background: var(--bg-card); border-radius: 12px; padding: 1.5rem;
margin-bottom: 1.5rem; border: 1px solid var(--border-color);
}
.section h2 {
font-size: 1.3rem; margin-bottom: 1rem; color: var(--accent-green-light);
display: flex; align-items: center; gap: 0.5rem;
}
.section p { color: var(--text-secondary); margin-bottom: 1rem; }
.code-block {
background: var(--bg-secondary); padding: 1.25rem; border-radius: 8px;
font-family: 'Fira Code', 'Cascadia Code', monospace; font-size: 0.85rem;
color: var(--accent-cyan); overflow-x: auto; line-height: 1.6; margin-bottom: 1rem;
}
.code-block .comment { color: var(--text-muted); }
.code-block .keyword { color: var(--accent-purple); }
.code-block .string { color: var(--accent-green); }
.method-table { width: 100%; border-collapse: separate; border-spacing: 0; margin-top: 1rem; }
.method-table th {
background: var(--bg-secondary); padding: 0.75rem 1rem; text-align: left;
font-size: 0.85rem; color: var(--accent-orange); border-bottom: 1px solid var(--border-color);
}
.method-table td {
padding: 0.75rem 1rem; border-bottom: 1px solid var(--border-color);
font-size: 0.85rem; color: var(--text-secondary);
}
.method-table code {
background: rgba(6, 182, 212, 0.1); color: var(--accent-cyan);
padding: 0.15rem 0.4rem; border-radius: 4px; font-size: 0.8rem;
}
.info-grid {
display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1rem; margin-top: 1rem;
}
.info-card {
background: var(--bg-secondary); padding: 1rem; border-radius: 8px;
border: 1px solid var(--border-color);
}
.info-card h4 { font-size: 0.9rem; margin-bottom: 0.5rem; color: var(--accent-green-light); }
.info-card p { font-size: 0.85rem; color: var(--text-secondary); margin: 0; }
.file-path {
font-family: 'Fira 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;
}
ul { list-style: none; padding: 0; }
ul li { padding: 0.4rem 0; color: var(--text-secondary); display: flex; align-items: flex-start; gap: 0.5rem; }
ul li::before { content: "▸"; color: var(--accent-green); flex-shrink: 0; }
</style>
</head>
<body>
<div class="container">
<a href="../../物料组件添加流程.html" class="back-link">← 返回主文档</a>
<div class="header">
<div class="step-badge">步骤 3</div>
<h1>创建 Helper 配置文件</h1>
<p class="desc">定义物料组件的配置中心:物料面板、属性面板、拖拽行为等</p>
</div>
<div class="section">
<h2>📋 功能描述</h2>
<p>Helper 是物料组件的<strong>配置中枢</strong>,定义了组件在物料面板的显示信息、右侧属性面板的表单 schema、拖入画布时的默认数据、拖拽行为规则等。它是连接设计器 UI 和组件实例的桥梁。</p>
</div>
<div class="section">
<h2>🧩 模块描述</h2>
<p>Helper 对象被 <code>RegisterWidgetHelper.ts</code> 导入并注册到系统,主要提供以下能力:</p>
<ul>
<li><strong>物料面板配置</strong> - 控制组件在左侧面板的图标、名称、分类</li>
<li><strong>属性面板 Schema</strong> - 定义右侧属性面板的表单控件(输入框、选择器等)</li>
<li><strong>默认 Widget 数据</strong> - 拖入画布时生成的初始 schema</li>
<li><strong>拖拽行为</strong> - 控制组件拖入时的栅格占位</li>
<li><strong>选择框配置</strong> - 控制组件是否可选中、复制、删除、隐藏</li>
<li><strong>国际化路径</strong> - 指定需要国际化的属性路径</li>
</ul>
</div>
<div class="section">
<h2>📁 文件信息</h2>
<div class="info-grid">
<div class="info-card">
<h4>文件路径</h4>
<p><span class="file-path">packages/form-designer/src/config/widget-helper/&lt;组件名&gt;Helper.ts</span></p>
</div>
<div class="info-card">
<h4>操作类型</h4>
<p><strong style="color: #34d399;">新建</strong> - 创建 Helper 配置对象</p>
</div>
<div class="info-card">
<h4>导出方式</h4>
<p>默认导出 (export default) Helper 对象</p>
</div>
<div class="info-card">
<h4>所属层级</h4>
<p>页面设计器层 (packages/form-designer)</p>
</div>
</div>
</div>
<div class="section">
<h2>📊 Helper 接口方法</h2>
<table class="method-table">
<thead>
<tr>
<th>方法名</th>
<th>返回值</th>
<th>作用说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>type</code></td>
<td>WidgetType</td>
<td>组件唯一类型标识,与 WidgetType 枚举值对应</td>
</tr>
<tr>
<td><code>buildMaterialConfig()</code></td>
<td>MaterialConfig</td>
<td>物料面板显示配置:图标、名称、分类</td>
</tr>
<tr>
<td><code>buildSettings(params)</code></td>
<td>WidgetSettingsConfig[]</td>
<td>右侧属性面板的表单 schema(属性/样式/事件 tab</td>
</tr>
<tr>
<td><code>buildWidget(params)</code></td>
<td>WidgetSchema</td>
<td>拖入画布时生成的默认 schema(默认值、初始 props</td>
</tr>
<tr>
<td><code>dragInfo()</code></td>
<td>{ col: number }</td>
<td>拖拽时的栅格跨度(1-24</td>
</tr>
<tr>
<td><code>hasSelectBox()</code></td>
<td>SelectBoxConfig</td>
<td>是否可选中、可否复制/删除/隐藏等</td>
</tr>
<tr>
<td><code>collectLanguagePath()</code></td>
<td>{ paths: string[][] }</td>
<td>需要国际化的属性路径</td>
</tr>
</tbody>
</table>
</div>
<div class="section">
<h2>💻 完整代码示例</h2>
<div class="code-block">
<span class="comment">// packages/form-designer/src/config/widget-helper/MyNewComponentHelper.ts</span>
import { WidgetType } from '~@/types/WidgetType'
<span class="keyword">export default</span> {
<span class="comment">// 1. 组件类型标识</span>
type: WidgetType.MyNewComponent,
<span class="comment">// 2. 物料面板配置</span>
buildMaterialConfig() {
<span class="keyword">return</span> {
icon: <span class="string">'icon-text'</span>, <span class="comment">// 图标类名</span>
name: <span class="string">'MyNewComponent'</span>, <span class="comment">// 组件类型名</span>
title: <span class="string">'新组件'</span>, <span class="comment">// 显示名称(在物料面板中显示)</span>
category: <span class="string">'common'</span>, <span class="comment">// 分类:common/container/navigation 等</span>
}
},
<span class="comment">// 3. 右侧属性面板配置</span>
buildSettings(params) {
<span class="keyword">return</span> [
{
key: <span class="string">'property'</span>,
label: <span class="string">'属性设置'</span>,
type: <span class="string">'tab'</span>,
children: [
{
key: <span class="string">'content'</span>,
label: <span class="string">'文本内容'</span>,
type: <span class="string">'input'</span>, <span class="comment">// form-create 内置控件类型</span>
placeholder: <span class="string">'请输入内容'</span>,
},
{
key: <span class="string">'fontSize'</span>,
label: <span class="string">'字体大小'</span>,
type: <span class="string">'inputNumber'</span>,
min: 12,
max: 72,
},
{
key: <span class="string">'color'</span>,
label: <span class="string">'字体颜色'</span>,
type: <span class="string">'colorPicker'</span>,
},
],
},
]
},
<span class="comment">// 4. 拖入画布时生成的默认数据</span>
buildWidget(params) {
<span class="keyword">return</span> {
type: <span class="keyword">this</span>.type,
props: {
content: <span class="string">'默认文本'</span>,
fontSize: <span class="string">'14px'</span>,
color: <span class="string">'#333333'</span>,
},
}
},
<span class="comment">// 5. 拖拽行为配置</span>
dragInfo() {
<span class="keyword">return</span> {
col: 12, <span class="comment">// 占 12/24 栅格</span>
}
},
<span class="comment">// 6. 选择框配置</span>
hasSelectBox() {
<span class="keyword">return</span> {
selectable: <span class="keyword">true</span>, <span class="comment">// 是否可选中</span>
deletable: <span class="keyword">true</span>, <span class="comment">// 是否可删除</span>
copyable: <span class="keyword">true</span>, <span class="comment">// 是否可复制</span>
hideable: <span class="keyword">false</span>, <span class="comment">// 是否可隐藏</span>
}
},
<span class="comment">// 7. 国际化路径</span>
collectLanguagePath() {
<span class="keyword">return</span> {
paths: [
[<span class="string">'widget'</span>, <span class="string">'MyNewComponent'</span>, <span class="string">'content'</span>],
],
}
},
}
</div>
</div>
<div class="section">
<h2>⚠️ 注意事项</h2>
<ul>
<li><code>type</code> 必须与 WidgetType 枚举值完全一致</li>
<li><code>buildSettings</code> 中的 type 使用 form-create 内置控件类型</li>
<li><code>buildWidget</code> 返回的 props 结构需与 Vue 组件的 props 定义匹配</li>
<li>复杂组件可实现 <code>transformSchemaProperties</code><code>buildSchemaController</code> 方法</li>
</ul>
</div>
<div class="section" style="border-left: 4px solid var(--accent-green);">
<h2>➡️ 下一步</h2>
<p>完成 Helper 配置后,继续执行:</p>
<ul>
<li><strong>步骤 4</strong>:在 RegisterWidget.ts 中注册组件实例</li>
<li><strong>步骤 5</strong>:在 RegisterWidgetHelper.ts 中注册 Helper</li>
<li><strong>步骤 6</strong>:在 Material.ts 中注册物料面板分组</li>
</ul>
</div>
</div>
</body>
</html>