Bläddra i källkod

【代码优化】MALL: 修复模板装修时组件属性响应式丢失的问题

puhui999 7 månader sedan
förälder
incheckning
625426566c

+ 3 - 3
src/components/DiyEditor/components/mobile/NavigationBar/index.vue

@@ -4,7 +4,7 @@
       <div v-for="(cell, cellIndex) in cellList" :key="cellIndex" :style="getCellStyle(cell)">
         <span v-if="cell.type === 'text'">{{ cell.text }}</span>
         <img v-else-if="cell.type === 'image'" :src="cell.imgUrl" alt="" class="h-full w-full" />
-        <SearchBar v-else :property="getSearchProp" />
+        <SearchBar v-else :property="getSearchProp(cell)" />
       </div>
     </div>
     <img
@@ -51,14 +51,14 @@ const getCellStyle = (cell: NavigationBarCellProperty) => {
   } as StyleValue
 }
 // 获得搜索框属性
-const getSearchProp = (cell: NavigationBarCellProperty) => {
+const getSearchProp = computed(() => (cell: NavigationBarCellProperty) => {
   return {
     height: 30,
     showScan: false,
     placeholder: cell.placeholder,
     borderRadius: cell.borderRadius
   } as SearchProperty
-}
+})
 </script>
 <style lang="scss" scoped>
 .navigation-bar {

+ 31 - 13
src/components/DiyEditor/index.vue

@@ -110,7 +110,7 @@
           <el-tag
             v-if="showPageConfig"
             :effect="selectedComponent?.uid === pageConfigComponent.uid ? 'dark' : 'plain'"
-            :type="selectedComponent?.uid === pageConfigComponent.uid ? '' : 'info'"
+            :type="selectedComponent?.uid === pageConfigComponent.uid ? 'primary' : 'info'"
             size="large"
             @click="handleComponentSelected(pageConfigComponent)"
           >
@@ -121,7 +121,7 @@
             <el-tag
               v-if="component.position === 'fixed'"
               :effect="selectedComponent?.uid === component.uid ? 'dark' : 'plain'"
-              :type="selectedComponent?.uid === component.uid ? '' : 'info'"
+              :type="selectedComponent?.uid === component.uid ? 'primary' : 'info'"
               closable
               size="large"
               @click="handleComponentSelected(component)"
@@ -191,7 +191,7 @@ import { cloneDeep, includes } from 'lodash-es'
 import { component as PAGE_CONFIG_COMPONENT } from '@/components/DiyEditor/components/mobile/PageConfig/config'
 import { component as NAVIGATION_BAR_COMPONENT } from './components/mobile/NavigationBar/config'
 import { component as TAB_BAR_COMPONENT } from './components/mobile/TabBar/config'
-import { isString } from '@/utils/is'
+import { isEmpty, isString } from '@/utils/is'
 import { DiyComponent, DiyComponentLibrary, PageConfig } from '@/components/DiyEditor/util'
 import { componentConfigs } from '@/components/DiyEditor/components/mobile'
 import { array, oneOfType } from 'vue-types'
@@ -238,24 +238,42 @@ const props = defineProps({
 watch(
   () => props.modelValue,
   () => {
-    const modelValue = isString(props.modelValue)
-      ? (JSON.parse(props.modelValue) as PageConfig)
-      : props.modelValue
-    pageConfigComponent.value.property = modelValue?.page || PAGE_CONFIG_COMPONENT.property
+    const modelValue =
+      isString(props.modelValue) && !isEmpty(props.modelValue)
+        ? (JSON.parse(props.modelValue) as PageConfig)
+        : props.modelValue
+    pageConfigComponent.value.property =
+      (typeof modelValue !== 'string' && modelValue?.page) || PAGE_CONFIG_COMPONENT.property
     navigationBarComponent.value.property =
-      modelValue?.navigationBar || NAVIGATION_BAR_COMPONENT.property
-    tabBarComponent.value.property = modelValue?.tabBar || TAB_BAR_COMPONENT.property
+      (typeof modelValue !== 'string' && modelValue?.navigationBar) ||
+      NAVIGATION_BAR_COMPONENT.property
+    tabBarComponent.value.property =
+      (typeof modelValue !== 'string' && modelValue?.tabBar) || TAB_BAR_COMPONENT.property
     // 查找对应的页面组件
-    pageComponents.value = (modelValue?.components || []).map((item) => {
-      const component = componentConfigs[item.id]
-      return { ...component, property: item.property }
-    })
+    pageComponents.value = ((typeof modelValue !== 'string' && modelValue?.components) || []).map(
+      (item) => {
+        const component = componentConfigs[item.id]
+        return { ...component, property: item.property }
+      }
+    )
   },
   {
     immediate: true
   }
 )
 
+/** 选择组件修改其属性后更新它的配置 */
+watch(
+  selectedComponent,
+  (val: any) => {
+    if (!val || selectedComponentIndex.value === -1) {
+      return
+    }
+    pageComponents.value[selectedComponentIndex.value] = selectedComponent.value!
+  },
+  { deep: true }
+)
+
 // 保存
 const handleSave = () => {
   // 发送保存通知

+ 4 - 28
src/components/InputWithColor/index.vue

@@ -1,7 +1,7 @@
 <template>
-  <el-input v-model="valueRef" v-bind="$attrs">
+  <el-input v-model="modelValue" v-bind="$attrs">
     <template #append>
-      <el-color-picker v-model="colorRef" :predefine="PREDEFINE_COLORS" />
+      <el-color-picker v-model="color" :predefine="PREDEFINE_COLORS" />
     </template>
   </el-input>
 </template>
@@ -9,6 +9,7 @@
 <script lang="ts" setup>
 import { propTypes } from '@/utils/propTypes'
 import { PREDEFINE_COLORS } from '@/utils/color'
+import { useVModels } from '@vueuse/core'
 
 /**
  * 带颜色选择器输入框
@@ -19,33 +20,8 @@ const props = defineProps({
   modelValue: propTypes.string.def('').isRequired,
   color: propTypes.string.def('').isRequired
 })
-
-watch(
-  () => props.modelValue,
-  (val: string) => {
-    if (val === unref(valueRef)) return
-    valueRef.value = val
-  }
-)
-
 const emit = defineEmits(['update:modelValue', 'update:color'])
-
-// 输入框的值
-const valueRef = ref(props.modelValue)
-watch(
-  () => valueRef.value,
-  (val: string) => {
-    emit('update:modelValue', val)
-  }
-)
-// 颜色
-const colorRef = ref(props.color)
-watch(
-  () => colorRef.value,
-  (val: string) => {
-    emit('update:color', val)
-  }
-)
+const { modelValue, color } = useVModels(props, emit)
 </script>
 <style scoped lang="scss">
 :deep(.el-input-group__append) {

+ 16 - 8
src/views/mall/promotion/diy/template/decorate.vue

@@ -52,7 +52,9 @@ const formLoading = ref(false) // 表单的加载中:1)修改时的数据加
 const formData = ref<DiyTemplateApi.DiyTemplatePropertyVO>()
 const formRef = ref() // 表单 Ref
 // 当前编辑的属性
-const currentFormData = ref<DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO>()
+const currentFormData = ref<DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO>({
+  property: ''
+} as DiyPageApi.DiyPageVO)
 // templateItem 对应的缓存
 const currentFormDataMap = ref<
   Map<string, DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO>
@@ -92,17 +94,21 @@ const handleTemplateItemChange = (val: number) => {
   // 编辑模板
   if (val === 0) {
     libs.value = templateLibs
-    currentFormData.value = isEmpty(data) ? formData.value : data
+    currentFormData.value = (isEmpty(data) ? formData.value : data) as
+      | DiyTemplateApi.DiyTemplatePropertyVO
+      | DiyPageApi.DiyPageVO
     return
   }
 
   // 编辑页面
   libs.value = PAGE_LIBS
-  currentFormData.value = isEmpty(data)
-    ? formData.value!.pages.find(
-        (page: DiyPageApi.DiyPageVO) => page.name === templateItems[val].name
-      )
-    : data
+  currentFormData.value = (
+    isEmpty(data)
+      ? formData.value!.pages.find(
+          (page: DiyPageApi.DiyPageVO) => page.name === templateItems[val].name
+        )
+      : data
+  ) as DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO
 }
 
 // 提交表单
@@ -170,7 +176,9 @@ const recoverPageIndex = () => {
   sessionStorage.removeItem(DIY_PAGE_INDEX_KEY)
 
   // 重新初始化数据
-  currentFormData.value = formData.value
+  currentFormData.value = formData.value as
+    | DiyTemplateApi.DiyTemplatePropertyVO
+    | DiyPageApi.DiyPageVO
   currentFormDataMap.value = new Map<
     string,
     DiyTemplateApi.DiyTemplatePropertyVO | DiyPageApi.DiyPageVO