【缺陷修复】商城装修:解决模版修改不生效的问题

This commit is contained in:
puhui999 2024-12-05 17:46:36 +08:00
parent 9c2b13f2d0
commit f7477c3264
2 changed files with 101 additions and 51 deletions

View File

@ -12,17 +12,17 @@
<el-button-group class="header-right"> <el-button-group class="header-right">
<el-tooltip content="重置"> <el-tooltip content="重置">
<el-button @click="handleReset"> <el-button @click="handleReset">
<Icon icon="system-uicons:reset-alt" :size="24" /> <Icon :size="24" icon="system-uicons:reset-alt" />
</el-button> </el-button>
</el-tooltip> </el-tooltip>
<el-tooltip content="预览" v-if="previewUrl"> <el-tooltip v-if="previewUrl" content="预览">
<el-button @click="handlePreview"> <el-button @click="handlePreview">
<Icon icon="ep:view" :size="24" /> <Icon :size="24" icon="ep:view" />
</el-button> </el-button>
</el-tooltip> </el-tooltip>
<el-tooltip content="保存"> <el-tooltip content="保存">
<el-button @click="handleSave"> <el-button @click="handleSave">
<Icon icon="ep:check" :size="24" /> <Icon :size="24" icon="ep:check" />
</el-button> </el-button>
</el-tooltip> </el-tooltip>
</el-button-group> </el-button-group>
@ -31,21 +31,21 @@
<!-- 中心区域 --> <!-- 中心区域 -->
<el-container class="editor-container"> <el-container class="editor-container">
<!-- 左侧组件库ComponentLibrary --> <!-- 左侧组件库ComponentLibrary -->
<ComponentLibrary ref="componentLibrary" :list="libs" v-if="libs && libs.length > 0" /> <ComponentLibrary v-if="libs && libs.length > 0" ref="componentLibrary" :list="libs" />
<!-- 中心设计区域ComponentContainer --> <!-- 中心设计区域ComponentContainer -->
<div class="editor-center page-prop-area" @click="handlePageSelected"> <div class="editor-center page-prop-area" @click="handlePageSelected">
<!-- 手机顶部 --> <!-- 手机顶部 -->
<div class="editor-design-top"> <div class="editor-design-top">
<!-- 手机顶部状态栏 --> <!-- 手机顶部状态栏 -->
<img src="@/assets/imgs/diy/statusBar.png" alt="" class="status-bar" /> <img alt="" class="status-bar" src="@/assets/imgs/diy/statusBar.png" />
<!-- 手机顶部导航栏 --> <!-- 手机顶部导航栏 -->
<ComponentContainer <ComponentContainer
v-if="showNavigationBar" v-if="showNavigationBar"
:active="selectedComponent?.id === navigationBarComponent.id"
:component="navigationBarComponent" :component="navigationBarComponent"
:show-toolbar="false" :show-toolbar="false"
:active="selectedComponent?.id === navigationBarComponent.id"
@click="handleNavigationBarSelected"
class="cursor-pointer!" class="cursor-pointer!"
@click="handleNavigationBarSelected"
/> />
</div> </div>
<!-- 绝对定位的组件例如 弹窗浮动按钮等 --> <!-- 绝对定位的组件例如 弹窗浮动按钮等 -->
@ -55,43 +55,43 @@
@click="handleComponentSelected(component, index)" @click="handleComponentSelected(component, index)"
> >
<component <component
v-if="component.position === 'fixed' && selectedComponent?.uid === component.uid"
:is="component.id" :is="component.id"
v-if="component.position === 'fixed' && selectedComponent?.uid === component.uid"
:property="component.property" :property="component.property"
/> />
</div> </div>
<!-- 手机页面编辑区域 --> <!-- 手机页面编辑区域 -->
<el-scrollbar <el-scrollbar
height="100%"
wrap-class="editor-design-center page-prop-area"
view-class="phone-container"
:view-style="{ :view-style="{
backgroundColor: pageConfigComponent.property.backgroundColor, backgroundColor: pageConfigComponent.property.backgroundColor,
backgroundImage: `url(${pageConfigComponent.property.backgroundImage})` backgroundImage: `url(${pageConfigComponent.property.backgroundImage})`
}" }"
height="100%"
view-class="phone-container"
wrap-class="editor-design-center page-prop-area"
> >
<draggable <draggable
class="page-prop-area drag-area"
v-model="pageComponents" v-model="pageComponents"
item-key="index"
:animation="200" :animation="200"
:force-fallback="true"
class="page-prop-area drag-area"
filter=".component-toolbar" filter=".component-toolbar"
ghost-class="draggable-ghost" ghost-class="draggable-ghost"
:force-fallback="true"
group="component" group="component"
item-key="index"
@change="handleComponentChange" @change="handleComponentChange"
> >
<template #item="{ element, index }"> <template #item="{ element, index }">
<ComponentContainer <ComponentContainer
v-if="!element.position || element.position === 'center'" v-if="!element.position || element.position === 'center'"
:component="element"
:active="selectedComponentIndex === index" :active="selectedComponentIndex === index"
:can-move-up="index > 0"
:can-move-down="index < pageComponents.length - 1" :can-move-down="index < pageComponents.length - 1"
@move="(direction) => handleMoveComponent(index, direction)" :can-move-up="index > 0"
:component="element"
@click="handleComponentSelected(element, index)"
@copy="handleCopyComponent(index)" @copy="handleCopyComponent(index)"
@delete="handleDeleteComponent(index)" @delete="handleDeleteComponent(index)"
@click="handleComponentSelected(element, index)" @move="(direction) => handleMoveComponent(index, direction)"
/> />
</template> </template>
</draggable> </draggable>
@ -99,9 +99,9 @@
<!-- 手机底部导航 --> <!-- 手机底部导航 -->
<div v-if="showTabBar" :class="['editor-design-bottom', 'component', 'cursor-pointer!']"> <div v-if="showTabBar" :class="['editor-design-bottom', 'component', 'cursor-pointer!']">
<ComponentContainer <ComponentContainer
:active="selectedComponent?.id === tabBarComponent.id"
:component="tabBarComponent" :component="tabBarComponent"
:show-toolbar="false" :show-toolbar="false"
:active="selectedComponent?.id === tabBarComponent.id"
@click="handleTabBarSelected" @click="handleTabBarSelected"
/> />
</div> </div>
@ -109,9 +109,9 @@
<div class="fixed-component-action-group"> <div class="fixed-component-action-group">
<el-tag <el-tag
v-if="showPageConfig" v-if="showPageConfig"
size="large"
:effect="selectedComponent?.uid === pageConfigComponent.uid ? 'dark' : 'plain'" :effect="selectedComponent?.uid === pageConfigComponent.uid ? 'dark' : 'plain'"
:type="selectedComponent?.uid === pageConfigComponent.uid ? '' : 'info'" :type="selectedComponent?.uid === pageConfigComponent.uid ? '' : 'info'"
size="large"
@click="handleComponentSelected(pageConfigComponent)" @click="handleComponentSelected(pageConfigComponent)"
> >
<Icon :icon="pageConfigComponent.icon" :size="12" /> <Icon :icon="pageConfigComponent.icon" :size="12" />
@ -120,10 +120,10 @@
<template v-for="(component, index) in pageComponents" :key="index"> <template v-for="(component, index) in pageComponents" :key="index">
<el-tag <el-tag
v-if="component.position === 'fixed'" v-if="component.position === 'fixed'"
size="large"
closable
:effect="selectedComponent?.uid === component.uid ? 'dark' : 'plain'" :effect="selectedComponent?.uid === component.uid ? 'dark' : 'plain'"
:type="selectedComponent?.uid === component.uid ? '' : 'info'" :type="selectedComponent?.uid === component.uid ? '' : 'info'"
closable
size="large"
@click="handleComponentSelected(component)" @click="handleComponentSelected(component)"
@close="handleDeleteComponent(index)" @close="handleDeleteComponent(index)"
> >
@ -134,11 +134,11 @@
</div> </div>
</div> </div>
<!-- 右侧属性面板ComponentContainerProperty --> <!-- 右侧属性面板ComponentContainerProperty -->
<el-aside class="editor-right" width="350px" v-if="selectedComponent?.property"> <el-aside v-if="selectedComponent?.property" class="editor-right" width="350px">
<el-card <el-card
shadow="never"
body-class="h-[calc(100%-var(--el-card-padding)-var(--el-card-padding))]" body-class="h-[calc(100%-var(--el-card-padding)-var(--el-card-padding))]"
class="h-full" class="h-full"
shadow="never"
> >
<!-- 组件名称 --> <!-- 组件名称 -->
<template #header> <template #header>
@ -152,8 +152,8 @@
view-class="p-[var(--el-card-padding)] p-b-[calc(var(--el-card-padding)+var(--el-card-padding))] property" view-class="p-[var(--el-card-padding)] p-b-[calc(var(--el-card-padding)+var(--el-card-padding))] property"
> >
<component <component
:key="selectedComponent?.uid || selectedComponent?.id"
:is="selectedComponent?.id + 'Property'" :is="selectedComponent?.id + 'Property'"
:key="selectedComponent?.uid || selectedComponent?.id"
v-model="selectedComponent.property" v-model="selectedComponent.property"
/> />
</el-scrollbar> </el-scrollbar>
@ -166,8 +166,8 @@
<Dialog v-model="previewDialogVisible" title="预览" width="700"> <Dialog v-model="previewDialogVisible" title="预览" width="700">
<div class="flex justify-around"> <div class="flex justify-around">
<IFrame <IFrame
class="w-375px border-4px border-rounded-8px border-solid p-2px h-667px!"
:src="previewUrl" :src="previewUrl"
class="w-375px border-4px border-rounded-8px border-solid p-2px h-667px!"
/> />
<div class="flex flex-col"> <div class="flex flex-col">
<el-text>手机扫码预览</el-text> <el-text>手机扫码预览</el-text>
@ -179,6 +179,7 @@
<script lang="ts"> <script lang="ts">
// //
import { components } from './components/mobile/index' import { components } from './components/mobile/index'
export default { export default {
components: { ...components } components: { ...components }
} }
@ -257,6 +258,11 @@ watch(
// //
const handleSave = () => { const handleSave = () => {
//
emits('save')
}
//
const pageConfigChange = () => {
const pageConfig = { const pageConfig = {
page: pageConfigComponent.value.property, page: pageConfigComponent.value.property,
navigationBar: navigationBarComponent.value.property, navigationBar: navigationBarComponent.value.property,
@ -272,10 +278,19 @@ const handleSave = () => {
// //
const modelValue = isString(props.modelValue) ? JSON.stringify(pageConfig) : pageConfig const modelValue = isString(props.modelValue) ? JSON.stringify(pageConfig) : pageConfig
emits('update:modelValue', modelValue) emits('update:modelValue', modelValue)
//
emits('save', pageConfig)
} }
watch(
() => [
pageConfigComponent.value.property,
navigationBarComponent.value.property,
tabBarComponent.value.property,
pageComponents.value
],
() => {
pageConfigChange()
},
{ deep: true }
)
// //
const handlePageSelected = (event: any) => { const handlePageSelected = (event: any) => {
if (!props.showPageConfig) return if (!props.showPageConfig) return
@ -547,6 +562,7 @@ $toolbar-height: 42px;
:deep(.el-tag) { :deep(.el-tag) {
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1); box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
border: none; border: none;
.el-tag__content { .el-tag__content {
width: 100%; width: 100%;
display: flex; display: flex;

View File

@ -2,18 +2,18 @@
<DiyEditor <DiyEditor
v-if="formData && !formLoading" v-if="formData && !formLoading"
v-model="currentFormData!.property" v-model="currentFormData!.property"
:title="templateItems[selectedTemplateItem].name"
:libs="libs" :libs="libs"
:preview-url="previewUrl"
:show-navigation-bar="selectedTemplateItem !== 0"
:show-page-config="selectedTemplateItem !== 0" :show-page-config="selectedTemplateItem !== 0"
:show-tab-bar="selectedTemplateItem === 0" :show-tab-bar="selectedTemplateItem === 0"
:show-navigation-bar="selectedTemplateItem !== 0" :title="templateItems[selectedTemplateItem].name"
:preview-url="previewUrl"
@save="submitForm"
@reset="handleEditorReset" @reset="handleEditorReset"
@save="submitForm"
> >
<template #toolBarLeft> <template #toolBarLeft>
<el-radio-group <el-radio-group
v-model="selectedTemplateItem" :model-value="selectedTemplateItem"
class="h-full!" class="h-full!"
@change="handleTemplateItemChange" @change="handleTemplateItemChange"
> >
@ -26,13 +26,14 @@
</template> </template>
</DiyEditor> </DiyEditor>
</template> </template>
<script setup lang="ts"> <script lang="ts" setup>
// TODO @ decorate index.vue // TODO @ decorate index.vue
import * as DiyTemplateApi from '@/api/mall/promotion/diy/template' import * as DiyTemplateApi from '@/api/mall/promotion/diy/template'
import * as DiyPageApi from '@/api/mall/promotion/diy/page' import * as DiyPageApi from '@/api/mall/promotion/diy/page'
import { useTagsViewStore } from '@/store/modules/tagsView' import { useTagsViewStore } from '@/store/modules/tagsView'
import { DiyComponentLibrary, PAGE_LIBS } from '@/components/DiyEditor/util' // DIY DiyEditor import { DiyComponentLibrary, PAGE_LIBS } from '@/components/DiyEditor/util' // DIY DiyEditor
import { toNumber } from 'lodash-es' import { toNumber } from 'lodash-es'
import { isEmpty } from '@/utils/is'
/** 装修模板表单 */ /** 装修模板表单 */
defineOptions({ name: 'DiyTemplateDecorate' }) defineOptions({ name: 'DiyTemplateDecorate' })
@ -52,6 +53,10 @@ const formData = ref<DiyTemplateApi.DiyTemplatePropertyVO>()
const formRef = ref() // Ref const formRef = ref() // Ref
// //
const currentFormData = ref<DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO>() const currentFormData = ref<DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO>()
// templateItem
const currentFormDataMap = ref<
Map<string, DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO>
>(new Map())
// H5 // H5
const previewUrl = ref('') const previewUrl = ref('')
@ -60,8 +65,6 @@ const getPageDetail = async (id: any) => {
formLoading.value = true formLoading.value = true
try { try {
formData.value = await DiyTemplateApi.getDiyTemplateProperty(id) formData.value = await DiyTemplateApi.getDiyTemplateProperty(id)
currentFormData.value = formData.value
// //
const domain = import.meta.env.VITE_MALL_H5_DOMAIN const domain = import.meta.env.VITE_MALL_H5_DOMAIN
previewUrl.value = `${domain}/#/pages/index/index?templateId=${formData.value.id}` previewUrl.value = `${domain}/#/pages/index/index?templateId=${formData.value.id}`
@ -75,19 +78,31 @@ const templateLibs = [] as DiyComponentLibrary[]
// //
const libs = ref<DiyComponentLibrary[]>(templateLibs) const libs = ref<DiyComponentLibrary[]>(templateLibs)
// //
const handleTemplateItemChange = () => { const handleTemplateItemChange = (val: number) => {
//
currentFormDataMap.value.set(
templateItems[selectedTemplateItem.value].name,
currentFormData.value!
)
//
const data = currentFormDataMap.value.get(templateItems[val].name)
//
selectedTemplateItem.value = val
// //
if (selectedTemplateItem.value === 0) { if (val === 0) {
libs.value = templateLibs libs.value = templateLibs
currentFormData.value = formData.value currentFormData.value = isEmpty(data) ? formData.value : data
return return
} }
// //
libs.value = PAGE_LIBS libs.value = PAGE_LIBS
currentFormData.value = formData.value!.pages.find( currentFormData.value = isEmpty(data)
(page: DiyPageApi.DiyPageVO) => page.name === templateItems[selectedTemplateItem.value].name ? formData.value!.pages.find(
) (page: DiyPageApi.DiyPageVO) => page.name === templateItems[val].name
)
: data
} }
// //
@ -97,12 +112,25 @@ const submitForm = async () => {
// //
formLoading.value = true formLoading.value = true
try { try {
if (selectedTemplateItem.value === 0) { // templateItems templateItem
// for (let i = 0; i < templateItems.length; i++) {
await DiyTemplateApi.updateDiyTemplateProperty(unref(formData)!) const data = currentFormDataMap.value.get(templateItems[i].name) as any
} else { //
if (i === 0) {
//
await DiyTemplateApi.updateDiyTemplateProperty(isEmpty(data) ? unref(formData)! : data)
continue
}
// //
await DiyPageApi.updateDiyPageProperty(unref(currentFormData)!) //
if (currentFormData.value?.name.includes(templateItems[i].name)) {
await DiyPageApi.updateDiyPageProperty(unref(currentFormData)!)
continue
}
//
if (!isEmpty(data)) {
await DiyPageApi.updateDiyPageProperty(data!)
}
} }
message.success('保存成功') message.success('保存成功')
} finally { } finally {
@ -140,10 +168,16 @@ const recoverPageIndex = () => {
const pageIndex = toNumber(sessionStorage.getItem(DIY_PAGE_INDEX_KEY)) || 0 const pageIndex = toNumber(sessionStorage.getItem(DIY_PAGE_INDEX_KEY)) || 0
// //
sessionStorage.removeItem(DIY_PAGE_INDEX_KEY) sessionStorage.removeItem(DIY_PAGE_INDEX_KEY)
//
currentFormData.value = formData.value
currentFormDataMap.value = new Map<
string,
DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO
>()
// //
if (pageIndex !== selectedTemplateItem.value) { if (pageIndex !== selectedTemplateItem.value) {
selectedTemplateItem.value = pageIndex handleTemplateItemChange(pageIndex)
handleTemplateItemChange()
} }
} }
//#endregion //#endregion