Skip to content

Commit f7477c3

Browse files
author
puhui999
committed
【缺陷修复】商城装修:解决模版修改不生效的问题
1 parent 9c2b13f commit f7477c3

File tree

2 files changed

+101
-51
lines changed

2 files changed

+101
-51
lines changed

src/components/DiyEditor/index.vue

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@
1212
<el-button-group class="header-right">
1313
<el-tooltip content="重置">
1414
<el-button @click="handleReset">
15-
<Icon icon="system-uicons:reset-alt" :size="24" />
15+
<Icon :size="24" icon="system-uicons:reset-alt" />
1616
</el-button>
1717
</el-tooltip>
18-
<el-tooltip content="预览" v-if="previewUrl">
18+
<el-tooltip v-if="previewUrl" content="预览">
1919
<el-button @click="handlePreview">
20-
<Icon icon="ep:view" :size="24" />
20+
<Icon :size="24" icon="ep:view" />
2121
</el-button>
2222
</el-tooltip>
2323
<el-tooltip content="保存">
2424
<el-button @click="handleSave">
25-
<Icon icon="ep:check" :size="24" />
25+
<Icon :size="24" icon="ep:check" />
2626
</el-button>
2727
</el-tooltip>
2828
</el-button-group>
@@ -31,21 +31,21 @@
3131
<!-- 中心区域 -->
3232
<el-container class="editor-container">
3333
<!-- 左侧:组件库(ComponentLibrary) -->
34-
<ComponentLibrary ref="componentLibrary" :list="libs" v-if="libs && libs.length > 0" />
34+
<ComponentLibrary v-if="libs && libs.length > 0" ref="componentLibrary" :list="libs" />
3535
<!-- 中心:设计区域(ComponentContainer) -->
3636
<div class="editor-center page-prop-area" @click="handlePageSelected">
3737
<!-- 手机顶部 -->
3838
<div class="editor-design-top">
3939
<!-- 手机顶部状态栏 -->
40-
<img src="@/assets/imgs/diy/statusBar.png" alt="" class="status-bar" />
40+
<img alt="" class="status-bar" src="@/assets/imgs/diy/statusBar.png" />
4141
<!-- 手机顶部导航栏 -->
4242
<ComponentContainer
4343
v-if="showNavigationBar"
44+
:active="selectedComponent?.id === navigationBarComponent.id"
4445
:component="navigationBarComponent"
4546
:show-toolbar="false"
46-
:active="selectedComponent?.id === navigationBarComponent.id"
47-
@click="handleNavigationBarSelected"
4847
class="cursor-pointer!"
48+
@click="handleNavigationBarSelected"
4949
/>
5050
</div>
5151
<!-- 绝对定位的组件:例如 弹窗、浮动按钮等 -->
@@ -55,63 +55,63 @@
5555
@click="handleComponentSelected(component, index)"
5656
>
5757
<component
58-
v-if="component.position === 'fixed' && selectedComponent?.uid === component.uid"
5958
:is="component.id"
59+
v-if="component.position === 'fixed' && selectedComponent?.uid === component.uid"
6060
:property="component.property"
6161
/>
6262
</div>
6363
<!-- 手机页面编辑区域 -->
6464
<el-scrollbar
65-
height="100%"
66-
wrap-class="editor-design-center page-prop-area"
67-
view-class="phone-container"
6865
:view-style="{
6966
backgroundColor: pageConfigComponent.property.backgroundColor,
7067
backgroundImage: `url(${pageConfigComponent.property.backgroundImage})`
7168
}"
69+
height="100%"
70+
view-class="phone-container"
71+
wrap-class="editor-design-center page-prop-area"
7272
>
7373
<draggable
74-
class="page-prop-area drag-area"
7574
v-model="pageComponents"
76-
item-key="index"
7775
:animation="200"
76+
:force-fallback="true"
77+
class="page-prop-area drag-area"
7878
filter=".component-toolbar"
7979
ghost-class="draggable-ghost"
80-
:force-fallback="true"
8180
group="component"
81+
item-key="index"
8282
@change="handleComponentChange"
8383
>
8484
<template #item="{ element, index }">
8585
<ComponentContainer
8686
v-if="!element.position || element.position === 'center'"
87-
:component="element"
8887
:active="selectedComponentIndex === index"
89-
:can-move-up="index > 0"
9088
:can-move-down="index < pageComponents.length - 1"
91-
@move="(direction) => handleMoveComponent(index, direction)"
89+
:can-move-up="index > 0"
90+
:component="element"
91+
@click="handleComponentSelected(element, index)"
9292
@copy="handleCopyComponent(index)"
9393
@delete="handleDeleteComponent(index)"
94-
@click="handleComponentSelected(element, index)"
94+
@move="(direction) => handleMoveComponent(index, direction)"
9595
/>
9696
</template>
9797
</draggable>
9898
</el-scrollbar>
9999
<!-- 手机底部导航 -->
100100
<div v-if="showTabBar" :class="['editor-design-bottom', 'component', 'cursor-pointer!']">
101101
<ComponentContainer
102+
:active="selectedComponent?.id === tabBarComponent.id"
102103
:component="tabBarComponent"
103104
:show-toolbar="false"
104-
:active="selectedComponent?.id === tabBarComponent.id"
105105
@click="handleTabBarSelected"
106106
/>
107107
</div>
108108
<!-- 固定布局的组件 操作按钮区 -->
109109
<div class="fixed-component-action-group">
110110
<el-tag
111111
v-if="showPageConfig"
112-
size="large"
113112
:effect="selectedComponent?.uid === pageConfigComponent.uid ? 'dark' : 'plain'"
114113
:type="selectedComponent?.uid === pageConfigComponent.uid ? '' : 'info'"
114+
size="large"
115115
@click="handleComponentSelected(pageConfigComponent)"
116116
>
117117
<Icon :icon="pageConfigComponent.icon" :size="12" />
@@ -120,10 +120,10 @@
120120
<template v-for="(component, index) in pageComponents" :key="index">
121121
<el-tag
122122
v-if="component.position === 'fixed'"
123-
size="large"
124-
closable
125123
:effect="selectedComponent?.uid === component.uid ? 'dark' : 'plain'"
126124
:type="selectedComponent?.uid === component.uid ? '' : 'info'"
125+
closable
126+
size="large"
127127
@click="handleComponentSelected(component)"
128128
@close="handleDeleteComponent(index)"
129129
>
@@ -134,11 +134,11 @@
134134
</div>
135135
</div>
136136
<!-- 右侧:属性面板(ComponentContainerProperty) -->
137-
<el-aside class="editor-right" width="350px" v-if="selectedComponent?.property">
137+
<el-aside v-if="selectedComponent?.property" class="editor-right" width="350px">
138138
<el-card
139-
shadow="never"
140139
body-class="h-[calc(100%-var(--el-card-padding)-var(--el-card-padding))]"
141140
class="h-full"
141+
shadow="never"
142142
>
143143
<!-- 组件名称 -->
144144
<template #header>
@@ -152,8 +152,8 @@
152152
view-class="p-[var(--el-card-padding)] p-b-[calc(var(--el-card-padding)+var(--el-card-padding))] property"
153153
>
154154
<component
155-
:key="selectedComponent?.uid || selectedComponent?.id"
156155
:is="selectedComponent?.id + 'Property'"
156+
:key="selectedComponent?.uid || selectedComponent?.id"
157157
v-model="selectedComponent.property"
158158
/>
159159
</el-scrollbar>
@@ -166,8 +166,8 @@
166166
<Dialog v-model="previewDialogVisible" title="预览" width="700">
167167
<div class="flex justify-around">
168168
<IFrame
169-
class="w-375px border-4px border-rounded-8px border-solid p-2px h-667px!"
170169
:src="previewUrl"
170+
class="w-375px border-4px border-rounded-8px border-solid p-2px h-667px!"
171171
/>
172172
<div class="flex flex-col">
173173
<el-text>手机扫码预览</el-text>
@@ -179,6 +179,7 @@
179179
<script lang="ts">
180180
// 注册所有的组件
181181
import { components } from './components/mobile/index'
182+
182183
export default {
183184
components: { ...components }
184185
}
@@ -257,6 +258,11 @@ watch(
257258
258259
// 保存
259260
const handleSave = () => {
261+
// 发送保存通知
262+
emits('save')
263+
}
264+
// 监听配置修改
265+
const pageConfigChange = () => {
260266
const pageConfig = {
261267
page: pageConfigComponent.value.property,
262268
navigationBar: navigationBarComponent.value.property,
@@ -272,10 +278,19 @@ const handleSave = () => {
272278
// 发送数据更新通知
273279
const modelValue = isString(props.modelValue) ? JSON.stringify(pageConfig) : pageConfig
274280
emits('update:modelValue', modelValue)
275-
// 发送保存通知
276-
emits('save', pageConfig)
277281
}
278-
282+
watch(
283+
() => [
284+
pageConfigComponent.value.property,
285+
navigationBarComponent.value.property,
286+
tabBarComponent.value.property,
287+
pageComponents.value
288+
],
289+
() => {
290+
pageConfigChange()
291+
},
292+
{ deep: true }
293+
)
279294
// 处理页面选中:显示属性表单
280295
const handlePageSelected = (event: any) => {
281296
if (!props.showPageConfig) return
@@ -547,6 +562,7 @@ $toolbar-height: 42px;
547562
:deep(.el-tag) {
548563
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
549564
border: none;
565+
550566
.el-tag__content {
551567
width: 100%;
552568
display: flex;

src/views/mall/promotion/diy/template/decorate.vue

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22
<DiyEditor
33
v-if="formData && !formLoading"
44
v-model="currentFormData!.property"
5-
:title="templateItems[selectedTemplateItem].name"
65
:libs="libs"
6+
:preview-url="previewUrl"
7+
:show-navigation-bar="selectedTemplateItem !== 0"
78
:show-page-config="selectedTemplateItem !== 0"
89
:show-tab-bar="selectedTemplateItem === 0"
9-
:show-navigation-bar="selectedTemplateItem !== 0"
10-
:preview-url="previewUrl"
11-
@save="submitForm"
10+
:title="templateItems[selectedTemplateItem].name"
1211
@reset="handleEditorReset"
12+
@save="submitForm"
1313
>
1414
<template #toolBarLeft>
1515
<el-radio-group
16-
v-model="selectedTemplateItem"
16+
:model-value="selectedTemplateItem"
1717
class="h-full!"
1818
@change="handleTemplateItemChange"
1919
>
@@ -26,13 +26,14 @@
2626
</template>
2727
</DiyEditor>
2828
</template>
29-
<script setup lang="ts">
29+
<script lang="ts" setup>
3030
// TODO @疯狂:要不要建个 decorate 目录,然后挪进去,改成 index.vue,这样可以更明确看到是个独立界面哈,更好找
3131
import * as DiyTemplateApi from '@/api/mall/promotion/diy/template'
3232
import * as DiyPageApi from '@/api/mall/promotion/diy/page'
3333
import { useTagsViewStore } from '@/store/modules/tagsView'
3434
import { DiyComponentLibrary, PAGE_LIBS } from '@/components/DiyEditor/util' // 商城的 DIY 组件,在 DiyEditor 目录下
3535
import { toNumber } from 'lodash-es'
36+
import { isEmpty } from '@/utils/is'
3637
3738
/** 装修模板表单 */
3839
defineOptions({ name: 'DiyTemplateDecorate' })
@@ -52,6 +53,10 @@ const formData = ref<DiyTemplateApi.DiyTemplatePropertyVO>()
5253
const formRef = ref() // 表单 Ref
5354
// 当前编辑的属性
5455
const currentFormData = ref<DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO>()
56+
// templateItem 对应的缓存
57+
const currentFormDataMap = ref<
58+
Map<string, DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO>
59+
>(new Map())
5560
// 商城 H5 预览地址
5661
const previewUrl = ref('')
5762
@@ -60,8 +65,6 @@ const getPageDetail = async (id: any) => {
6065
formLoading.value = true
6166
try {
6267
formData.value = await DiyTemplateApi.getDiyTemplateProperty(id)
63-
currentFormData.value = formData.value
64-
6568
// 拼接手机预览链接
6669
const domain = import.meta.env.VITE_MALL_H5_DOMAIN
6770
previewUrl.value = `${domain}/#/pages/index/index?templateId=${formData.value.id}`
@@ -75,19 +78,31 @@ const templateLibs = [] as DiyComponentLibrary[]
7578
// 当前组件库
7679
const libs = ref<DiyComponentLibrary[]>(templateLibs)
7780
// 模板选项切换
78-
const handleTemplateItemChange = () => {
81+
const handleTemplateItemChange = (val: number) => {
82+
// 缓存模版编辑数据
83+
currentFormDataMap.value.set(
84+
templateItems[selectedTemplateItem.value].name,
85+
currentFormData.value!
86+
)
87+
// 读取模版缓存
88+
const data = currentFormDataMap.value.get(templateItems[val].name)
89+
90+
// 切换模版
91+
selectedTemplateItem.value = val
7992
// 编辑模板
80-
if (selectedTemplateItem.value === 0) {
93+
if (val === 0) {
8194
libs.value = templateLibs
82-
currentFormData.value = formData.value
95+
currentFormData.value = isEmpty(data) ? formData.value : data
8396
return
8497
}
8598
8699
// 编辑页面
87100
libs.value = PAGE_LIBS
88-
currentFormData.value = formData.value!.pages.find(
89-
(page: DiyPageApi.DiyPageVO) => page.name === templateItems[selectedTemplateItem.value].name
90-
)
101+
currentFormData.value = isEmpty(data)
102+
? formData.value!.pages.find(
103+
(page: DiyPageApi.DiyPageVO) => page.name === templateItems[val].name
104+
)
105+
: data
91106
}
92107
93108
// 提交表单
@@ -97,12 +112,25 @@ const submitForm = async () => {
97112
// 提交请求
98113
formLoading.value = true
99114
try {
100-
if (selectedTemplateItem.value === 0) {
101-
// 提交模板属性
102-
await DiyTemplateApi.updateDiyTemplateProperty(unref(formData)!)
103-
} else {
115+
// 对所有的 templateItems 都进行保存,有缓存则保存缓存,解决都有修改时只保存了当前所编辑的 templateItem,导致装修效果存在差异
116+
for (let i = 0; i < templateItems.length; i++) {
117+
const data = currentFormDataMap.value.get(templateItems[i].name) as any
118+
// 情况一:基础设置
119+
if (i === 0) {
120+
// 提交模板属性
121+
await DiyTemplateApi.updateDiyTemplateProperty(isEmpty(data) ? unref(formData)! : data)
122+
continue
123+
}
104124
// 提交页面属性
105-
await DiyPageApi.updateDiyPageProperty(unref(currentFormData)!)
125+
// 情况二:提交当前正在编辑的页面
126+
if (currentFormData.value?.name.includes(templateItems[i].name)) {
127+
await DiyPageApi.updateDiyPageProperty(unref(currentFormData)!)
128+
continue
129+
}
130+
// 情况三:提交页面编辑缓存
131+
if (!isEmpty(data)) {
132+
await DiyPageApi.updateDiyPageProperty(data!)
133+
}
106134
}
107135
message.success('保存成功')
108136
} finally {
@@ -140,10 +168,16 @@ const recoverPageIndex = () => {
140168
const pageIndex = toNumber(sessionStorage.getItem(DIY_PAGE_INDEX_KEY)) || 0
141169
// 移除标记
142170
sessionStorage.removeItem(DIY_PAGE_INDEX_KEY)
171+
172+
// 重新初始化数据
173+
currentFormData.value = formData.value
174+
currentFormDataMap.value = new Map<
175+
string,
176+
DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO
177+
>()
143178
// 切换页面
144179
if (pageIndex !== selectedTemplateItem.value) {
145-
selectedTemplateItem.value = pageIndex
146-
handleTemplateItemChange()
180+
handleTemplateItemChange(pageIndex)
147181
}
148182
}
149183
//#endregion

0 commit comments

Comments
 (0)