feat: 完成组件化改造 - 支持作为可嵌入组件使用

- 创建 YysEditorEmbed.vue 嵌入式组件
- 实现 preview/edit 双模式
- 配置 Vite library mode 构建
- 生成 ES Module + UMD + CSS 构建产物
- 完善设计文档和使用文档
- 更新 plan.md 标记阶段 2 完成

构建产物:
- dist/yys-editor.es.js (155KB, gzip: 35KB)
- dist/yys-editor.umd.js (112KB, gzip: 31KB)
- dist/yys-editor.css (69KB, gzip: 33KB)

相关文档:
- docs/2design/ComponentArchitecture.md
- docs/3build/YysEditorEmbed.md
- docs/3build/EMBED_README.md
- docs/4test/BUILD_TEST_REPORT.md
This commit is contained in:
2026-02-20 17:23:59 +08:00
parent 92557d553b
commit 15bae3be81
13 changed files with 3553 additions and 424 deletions

345
examples/embed-demo.html Normal file
View File

@@ -0,0 +1,345 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>YysEditorEmbed 示例</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: #f5f5f5;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
h1 {
margin-bottom: 30px;
color: #333;
}
.example-section {
background: white;
border-radius: 8px;
padding: 20px;
margin-bottom: 30px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.example-section h2 {
margin-bottom: 15px;
color: #409eff;
font-size: 20px;
}
.example-section p {
margin-bottom: 15px;
color: #666;
line-height: 1.6;
}
.editor-wrapper {
border: 1px solid #ddd;
border-radius: 4px;
overflow: hidden;
}
.controls {
display: flex;
gap: 10px;
margin-bottom: 15px;
}
button {
padding: 8px 16px;
background: #409eff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
button:hover {
background: #66b1ff;
}
button:disabled {
background: #ccc;
cursor: not-allowed;
}
.preview-mode-demo {
position: relative;
cursor: pointer;
}
.preview-mode-demo:hover::after {
content: '点击编辑';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.7);
color: white;
padding: 10px 20px;
border-radius: 4px;
font-size: 16px;
}
.code-block {
background: #f6f8fa;
border: 1px solid #e1e4e8;
border-radius: 4px;
padding: 15px;
margin-top: 15px;
overflow-x: auto;
}
.code-block pre {
margin: 0;
font-family: 'Courier New', monospace;
font-size: 13px;
line-height: 1.5;
}
</style>
</head>
<body>
<div class="container">
<h1>🎨 YysEditorEmbed 组件示例</h1>
<!-- 示例 1编辑模式 -->
<div class="example-section">
<h2>示例 1编辑模式</h2>
<p>完整的编辑功能,包括工具栏、组件库和属性面板。</p>
<div class="controls">
<button onclick="saveData()">💾 保存数据</button>
<button onclick="loadData()">📂 加载数据</button>
<button onclick="clearData()">🗑️ 清空画布</button>
<button onclick="exportJSON()">📤 导出 JSON</button>
</div>
<div id="app-edit" class="editor-wrapper"></div>
<div class="code-block">
<pre>&lt;YysEditorEmbed
mode="edit"
:data="flowData"
:height="600"
@save="handleSave"
/&gt;</pre>
</div>
</div>
<!-- 示例 2预览模式 -->
<div class="example-section">
<h2>示例 2预览模式</h2>
<p>只读展示,不显示编辑工具。点击可切换到编辑模式。</p>
<div class="controls">
<button onclick="toggleMode()">🔄 切换模式</button>
</div>
<div id="app-preview" class="editor-wrapper preview-mode-demo"></div>
<div class="code-block">
<pre>&lt;YysEditorEmbed
mode="preview"
:data="flowData"
:height="400"
/&gt;</pre>
</div>
</div>
<!-- 示例 3自定义配置 -->
<div class="example-section">
<h2>示例 3自定义配置</h2>
<p>隐藏部分 UI 元素,自定义编辑器配置。</p>
<div class="controls">
<button onclick="toggleToolbar()">🔧 切换工具栏</button>
<button onclick="toggleComponentPanel()">📦 切换组件库</button>
<button onclick="togglePropertyPanel()">⚙️ 切换属性面板</button>
</div>
<div id="app-custom" class="editor-wrapper"></div>
<div class="code-block">
<pre>&lt;YysEditorEmbed
mode="edit"
:show-toolbar="false"
:show-component-panel="false"
:height="500"
/&gt;</pre>
</div>
</div>
<!-- 示例 4Wiki 块插件模式 -->
<div class="example-section">
<h2>示例 4Wiki 块插件模式</h2>
<p>模拟在 Wiki 中作为块插件使用的场景。</p>
<div class="controls">
<button onclick="openWikiEditor()">✏️ 编辑流程图</button>
</div>
<div id="app-wiki" class="editor-wrapper"></div>
<div class="code-block">
<pre>&lt;!-- 预览模式 --&gt;
&lt;div v-if="!isEditing" @click="startEdit"&gt;
&lt;YysEditorEmbed mode="preview" :data="flowData" /&gt;
&lt;/div&gt;
&lt;!-- 编辑模式(弹窗) --&gt;
&lt;el-dialog v-model="isEditing" fullscreen&gt;
&lt;YysEditorEmbed mode="edit" @save="handleSave" /&gt;
&lt;/el-dialog&gt;</pre>
</div>
</div>
</div>
<!-- 模拟 Vue 应用(实际使用时需要引入真实的 YysEditorEmbed 组件) -->
<script type="module">
// 这里是示例代码,实际使用时需要:
// import { createApp } from 'vue'
// import { YysEditorEmbed } from 'yys-editor'
// import 'yys-editor/style.css'
// 示例数据
const sampleData = {
nodes: [
{
id: 'node1',
type: 'rect',
x: 100,
y: 100,
text: { value: '开始' },
properties: {
width: 100,
height: 50
}
},
{
id: 'node2',
type: 'rect',
x: 300,
y: 100,
text: { value: '处理' },
properties: {
width: 100,
height: 50
}
}
],
edges: [
{
id: 'edge1',
type: 'polyline',
sourceNodeId: 'node1',
targetNodeId: 'node2'
}
]
}
// 全局函数(示例)
window.saveData = () => {
alert('保存数据功能需要在实际 Vue 应用中实现')
console.log('保存数据:', sampleData)
}
window.loadData = () => {
alert('加载数据功能需要在实际 Vue 应用中实现')
}
window.clearData = () => {
if (confirm('确定要清空画布吗?')) {
alert('清空功能需要在实际 Vue 应用中实现')
}
}
window.exportJSON = () => {
const dataStr = JSON.stringify(sampleData, null, 2)
const blob = new Blob([dataStr], { type: 'application/json' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'flow-data.json'
a.click()
}
window.toggleMode = () => {
alert('切换模式功能需要在实际 Vue 应用中实现')
}
window.toggleToolbar = () => {
alert('切换工具栏功能需要在实际 Vue 应用中实现')
}
window.toggleComponentPanel = () => {
alert('切换组件库功能需要在实际 Vue 应用中实现')
}
window.togglePropertyPanel = () => {
alert('切换属性面板功能需要在实际 Vue 应用中实现')
}
window.openWikiEditor = () => {
alert('打开编辑器功能需要在实际 Vue 应用中实现')
}
// 显示提示信息
console.log('这是一个示例页面,展示了 YysEditorEmbed 的使用方式。')
console.log('实际使用时,请参考文档集成真实的组件。')
console.log('示例数据:', sampleData)
</script>
<!-- 占位符(实际使用时会被 Vue 组件替换) -->
<script>
// 添加占位符内容
document.addEventListener('DOMContentLoaded', () => {
const placeholders = [
'app-edit',
'app-preview',
'app-custom',
'app-wiki'
]
placeholders.forEach(id => {
const el = document.getElementById(id)
if (el) {
el.innerHTML = `
<div style="
height: ${id === 'app-edit' ? '600px' : id === 'app-custom' ? '500px' : '400px'};
display: flex;
align-items: center;
justify-content: center;
background: #f9f9f9;
color: #999;
font-size: 16px;
">
<div style="text-align: center;">
<div style="font-size: 48px; margin-bottom: 10px;">🎨</div>
<div>YysEditorEmbed 组件占位符</div>
<div style="font-size: 12px; margin-top: 10px;">
实际使用时,这里会显示流程图编辑器
</div>
</div>
</div>
`
}
})
})
</script>
</body>
</html>