|
|
@@ -1,8 +1,33 @@
|
|
|
<template>
|
|
|
<div class="h5-editor-container">
|
|
|
+ <!-- 标题编辑栏 -->
|
|
|
+ <div class="title-bar">
|
|
|
+ <el-input v-model="pageTitle" placeholder="输入落地页标题" class="title-input" />
|
|
|
+ </div>
|
|
|
<el-row :gutter="16" class="editor-wrapper">
|
|
|
- <!-- 左侧:组件面板 -->
|
|
|
- <el-col :span="4" class="left-panel">
|
|
|
+ <!-- 左上:页面选择面板 -->
|
|
|
+ <el-col :span="3" class="page-panel">
|
|
|
+ <div class="panel-header">
|
|
|
+ <h3>页面选择</h3>
|
|
|
+ </div>
|
|
|
+ <div class="page-list">
|
|
|
+ <div
|
|
|
+ v-for="page in pageList"
|
|
|
+ :key="page.pageStep"
|
|
|
+ class="page-card"
|
|
|
+ :class="{active: currentPageStep === page.pageStep}"
|
|
|
+ @click="switchPage(page.pageStep)"
|
|
|
+ >
|
|
|
+ <div class="page-icon">
|
|
|
+ <i :class="page.icon"></i>
|
|
|
+ </div>
|
|
|
+ <div class="page-name">{{ page.name }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 左下:组件面板 -->
|
|
|
+ <el-col :span="3" class="left-panel">
|
|
|
<div class="panel-header">
|
|
|
<h3>组件库</h3>
|
|
|
</div>
|
|
|
@@ -30,7 +55,7 @@
|
|
|
</el-col>
|
|
|
|
|
|
<!-- 中间:预览区域 -->
|
|
|
- <el-col :span="11" class="center-panel">
|
|
|
+ <el-col :span="10" class="center-panel">
|
|
|
<div class="panel-header">
|
|
|
<h3>页面预览</h3>
|
|
|
<span class="device-info">手机预览 (375px)</span>
|
|
|
@@ -70,7 +95,7 @@
|
|
|
</el-col>
|
|
|
|
|
|
<!-- 右侧:属性面板 -->
|
|
|
- <el-col :span="9" class="right-panel">
|
|
|
+ <el-col :span="8" class="right-panel">
|
|
|
<div class="panel-header">
|
|
|
<h3>属性设置</h3>
|
|
|
</div>
|
|
|
@@ -128,6 +153,14 @@ export default {
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
+ pageTitle: '',
|
|
|
+ currentPageStep: 'home',
|
|
|
+ pageList: [
|
|
|
+ { pageStep: 'home', name: '首页', icon: 'el-icon-house' },
|
|
|
+ { pageStep: 'appletLand', name: '小程序授权页', icon: 'el-icon-document' },
|
|
|
+ { pageStep: 'purchaseSuccess', name: '小程序出码页', icon: 'el-icon-success' }
|
|
|
+ ],
|
|
|
+ configList: [],
|
|
|
componentList: [{
|
|
|
groupName: '基础控件',
|
|
|
comps: [
|
|
|
@@ -187,14 +220,79 @@ export default {
|
|
|
methods: {
|
|
|
initData(json) {
|
|
|
try {
|
|
|
- this.list = JSON.parse(json)
|
|
|
+ const data = JSON.parse(json)
|
|
|
+ // 支持新格式
|
|
|
+ if (data.pageTitle !== undefined) {
|
|
|
+ this.pageTitle = data.pageTitle
|
|
|
+ this.configList = data.configList || []
|
|
|
+ // 初始化configList,确保所有页面都存在
|
|
|
+ this.initializeConfigList()
|
|
|
+ // 加载首页数据
|
|
|
+ this.switchPage('home')
|
|
|
+ } else {
|
|
|
+ // 兼容旧格式(直接是数组)
|
|
|
+ this.configList = [{
|
|
|
+ pageStep: 'home',
|
|
|
+ moduleList: Array.isArray(data) ? data : []
|
|
|
+ }, {
|
|
|
+ pageStep: 'appletLand',
|
|
|
+ moduleList: []
|
|
|
+ }, {
|
|
|
+ pageStep: 'purchaseSuccess',
|
|
|
+ moduleList: []
|
|
|
+ }]
|
|
|
+ this.list = this.configList[0].moduleList
|
|
|
+ }
|
|
|
} catch (e) {
|
|
|
+ // 初始化为新格式
|
|
|
+ this.pageTitle = ''
|
|
|
+ this.configList = [{
|
|
|
+ pageStep: 'home',
|
|
|
+ moduleList: []
|
|
|
+ }, {
|
|
|
+ pageStep: 'appletLand',
|
|
|
+ moduleList: []
|
|
|
+ }, {
|
|
|
+ pageStep: 'purchaseSuccess',
|
|
|
+ moduleList: []
|
|
|
+ }]
|
|
|
this.list = []
|
|
|
}
|
|
|
// 重置选中状态和属性表单
|
|
|
this.form = {}
|
|
|
this.index = -1
|
|
|
},
|
|
|
+ initializeConfigList() {
|
|
|
+ const pageSteps = ['home', 'appletLand', 'purchaseSuccess']
|
|
|
+ pageSteps.forEach(pageStep => {
|
|
|
+ if (!this.configList.find(config => config.pageStep === pageStep)) {
|
|
|
+ this.configList.push({
|
|
|
+ pageStep: pageStep,
|
|
|
+ moduleList: []
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ switchPage(pageStep) {
|
|
|
+ // 保存当前页面的数据
|
|
|
+ const currentConfig = this.configList.find(config => config.pageStep === this.currentPageStep)
|
|
|
+ if (currentConfig) {
|
|
|
+ currentConfig.moduleList = this.list
|
|
|
+ }
|
|
|
+
|
|
|
+ // 切换到新页面
|
|
|
+ this.currentPageStep = pageStep
|
|
|
+ const newConfig = this.configList.find(config => config.pageStep === pageStep)
|
|
|
+ if (newConfig) {
|
|
|
+ this.list = newConfig.moduleList || []
|
|
|
+ } else {
|
|
|
+ this.list = []
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重置选中和表单
|
|
|
+ this.form = {}
|
|
|
+ this.index = -1
|
|
|
+ },
|
|
|
end() {
|
|
|
|
|
|
},
|
|
|
@@ -490,50 +588,22 @@ export default {
|
|
|
}
|
|
|
return data
|
|
|
},
|
|
|
- select(index) {
|
|
|
- this.index = index
|
|
|
- // 更新所有元素的active状态
|
|
|
- this.list.forEach((item, i) => {
|
|
|
- this.$set(item, 'active', i === index)
|
|
|
- })
|
|
|
- // 直接绑定list中的对象
|
|
|
- this.form = this.list[index]
|
|
|
- },
|
|
|
- del() {
|
|
|
- if (this.index >= 0 && this.index < this.list.length) {
|
|
|
- this.list.splice(this.index, 1)
|
|
|
- this.form = {}
|
|
|
- this.index = -1
|
|
|
- }
|
|
|
- },
|
|
|
- /** 处理删除操作 */
|
|
|
- handleDelete(index) {
|
|
|
- this.index = index
|
|
|
- this.list.splice(index, 1)
|
|
|
- this.form = {}
|
|
|
- this.index = -1
|
|
|
- },
|
|
|
- updateForm(newForm) {
|
|
|
- // 更新表单数据
|
|
|
- if (this.index < 0 || this.index >= this.list.length) {
|
|
|
- return
|
|
|
+ /** 获取完整的页面数据(新格式JSON) */
|
|
|
+ getPageData() {
|
|
|
+ // 保存当前页面数据
|
|
|
+ const currentConfig = this.configList.find(config => config.pageStep === this.currentPageStep)
|
|
|
+ if (currentConfig) {
|
|
|
+ currentConfig.moduleList = this.list
|
|
|
}
|
|
|
-
|
|
|
- Object.assign(this.form, newForm)
|
|
|
-
|
|
|
- // 更新列表中的数据
|
|
|
- for (const key in newForm) {
|
|
|
- if (Object.hasOwnProperty.call(newForm, key)) {
|
|
|
- // 如果是嵌套对象,递归更新
|
|
|
- if (typeof newForm[key] === 'object' && newForm[key] !== null) {
|
|
|
- for (const nestedKey in newForm[key]) {
|
|
|
- this.$set(this.list[this.index][key], nestedKey, newForm[key][nestedKey])
|
|
|
- }
|
|
|
- } else {
|
|
|
- this.$set(this.list[this.index], key, newForm[key])
|
|
|
- }
|
|
|
- }
|
|
|
+
|
|
|
+ return {
|
|
|
+ pageTitle: this.pageTitle,
|
|
|
+ configList: this.configList
|
|
|
}
|
|
|
+ },
|
|
|
+ /** 获取JSON字符串 */
|
|
|
+ getJsonString() {
|
|
|
+ return JSON.stringify(this.getPageData())
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -547,6 +617,30 @@ export default {
|
|
|
flex-direction: column;
|
|
|
}
|
|
|
|
|
|
+// 标题编辑栏
|
|
|
+.title-bar {
|
|
|
+ padding: 12px 16px;
|
|
|
+ background: #fff;
|
|
|
+ border-bottom: 1px solid #e8e8e8;
|
|
|
+ flex-shrink: 0;
|
|
|
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
|
|
|
+
|
|
|
+ .title-input {
|
|
|
+ height: 36px;
|
|
|
+
|
|
|
+ ::v-deep .el-input__inner {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #303133;
|
|
|
+ padding: 0 12px;
|
|
|
+
|
|
|
+ &::placeholder {
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
.editor-wrapper {
|
|
|
height: 100%;
|
|
|
padding: 0;
|
|
|
@@ -579,7 +673,85 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 左侧组件面板
|
|
|
+// 页面选择面板
|
|
|
+.page-panel {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 100%;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 0;
|
|
|
+ overflow: hidden;
|
|
|
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
+
|
|
|
+ .page-list {
|
|
|
+ flex: 1;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding: 12px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 6px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background: #d0d0d0;
|
|
|
+ border-radius: 3px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: #aaa;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .page-card {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ padding: 12px 8px;
|
|
|
+ border: 2px solid #e8e8e8;
|
|
|
+ border-radius: 6px;
|
|
|
+ background: #f9f9f9;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ user-select: none;
|
|
|
+
|
|
|
+ .page-icon {
|
|
|
+ font-size: 24px;
|
|
|
+ color: #409eff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .page-name {
|
|
|
+ font-size: 11px;
|
|
|
+ color: #606266;
|
|
|
+ text-align: center;
|
|
|
+ word-break: break-word;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ border-color: #409eff;
|
|
|
+ background: #e6f2ff;
|
|
|
+ box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ border-color: #409eff;
|
|
|
+ background: #d3e8ff;
|
|
|
+ font-weight: 600;
|
|
|
+ box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
|
|
|
+
|
|
|
+ .page-name {
|
|
|
+ color: #409eff;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 左下组件面板
|
|
|
.left-panel {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|