Browse Source

fix: 修改优化主题

jiaxing.liao 3 weeks ago
parent
commit
ad4e7aee52

+ 14 - 2
src/renderer/src/lvgl-widgets/button-matrix/ButtonMatrix.vue

@@ -26,10 +26,16 @@
           )
         }"
       >
-        <ImageBg
+        <!-- <ImageBg
           v-if="getBtnStyle(item)?.imageSrc"
           :src="getBtnStyle(item)?.imageSrc"
           :image-color-style="getBtnStyle(item)?.imageStyle"
+        /> -->
+        <!-- 不使用自定义 -->
+        <ImageBg
+          v-if="styleMap?.itemsStyle?.imageSrc"
+          :src="styleMap?.itemsStyle?.imageSrc"
+          :image-color-style="styleMap?.itemsStyle?.imageStyle"
         />
         <span class="z-2" :style="item.resolvedStyle" v-html="item.resolvedText.text"></span>
       </div>
@@ -77,8 +83,14 @@ const projectStore = useProjectStore()
  * 获取自定义样式
  */
 const getBtnStyle = (btnItem: ButtonItem) => {
-  const style = btnItem.style.find((item) => item.part.state === 'default') || {}
+  // 获取主题背景
+  const style =
+    btnItem.style.find(
+      (item) => item.part.state === 'default' && item.theme === projectStore.project?.currentTheme
+    ) || {}
+
   const styleMap: Record<string, any> = {}
+
   Object.keys(style).forEach((key) => {
     assign(styleMap, getStyle(key, style?.[key]))
 

+ 5 - 4
src/renderer/src/lvgl-widgets/hooks/useWidgetStyle.ts

@@ -3,6 +3,7 @@ import { useProjectStore } from '@/store/modules/project'
 import { assign } from 'lodash-es'
 import { ref, watch } from 'vue'
 import { generateCssGradient } from '@/utils'
+import { DEFAULT_THEME_KEY } from '@/constants'
 
 import type { IStyleConfig, PartItem } from '../type'
 import type { CSSProperties } from 'vue'
@@ -251,8 +252,8 @@ export const useWidgetStyle = (param: StyleParam) => {
 
   const handleStyle = () => {
     const { part, state, styles = [], props } = param.props
-    const currentTheme = projectStore.project?.currentTheme || 'default_theme'
-    const getStyleTheme = (styleItem: any) => styleItem?.theme || 'default_theme'
+    const currentTheme = projectStore.project?.currentTheme || DEFAULT_THEME_KEY
+    const getStyleTheme = (styleItem: any) => styleItem?.theme || DEFAULT_THEME_KEY
     parts.forEach((partItem) => {
       styleMap.value[`${partItem.name}Style`] = {}
       // 从控件配置的样式列表查找对应样式
@@ -265,12 +266,12 @@ export const useWidgetStyle = (param: StyleParam) => {
           getStyleTheme(s) === currentTheme
       )
 
-      if (!style && currentTheme !== 'default_theme') {
+      if (!style && currentTheme !== DEFAULT_THEME_KEY) {
         style = styles.find(
           (s) =>
             s.part?.name === partItem.name &&
             s.part?.state === (part === partItem.name ? state : partItem.stateList?.[0]) &&
-            getStyleTheme(s) === 'default_theme'
+            getStyleTheme(s) === DEFAULT_THEME_KEY
         )
       }
 

+ 83 - 10
src/renderer/src/views/designer/config/property/index.vue

@@ -56,6 +56,16 @@
           label-position="left"
           :model="projectStore.activeWidget"
         >
+          <el-form-item
+            v-if="formConfig.styles?.find((item) => item.field === 'part')"
+            label="主题"
+            label-width="60px"
+            class="mb-12px!"
+          >
+            <el-select v-model="editTheme" class="w-full" :options="themeOptions">
+            </el-select>
+          </el-form-item>
+
           <el-form-item
             v-if="formConfig.styles?.find((item) => item.field === 'part')"
             label="模块/状态"
@@ -100,6 +110,7 @@ import CusFormItem from './CusFormItem.vue'
 import { useProjectStore } from '@/store/modules/project'
 import componentMap from '@/lvgl-widgets'
 import StylePart from './components/StylePart.vue'
+import { DEFAULT_THEME_KEY } from '@/constants'
 
 import { LuSliders } from 'vue-icons-plus/lu'
 import { IoColorPaletteOutline } from 'vue-icons-plus/io'
@@ -118,10 +129,19 @@ const part = ref<{
   state: '',
   expandStyle: true
 })
+
+const editTheme = ref(DEFAULT_THEME_KEY)
+
+const getStyleTheme = (item?: Record<string, any>) => {
+  return item?.theme || DEFAULT_THEME_KEY
+}
 // 样式表单数据
 const styleFormData = computed(() => {
   const item = projectStore.activeWidget?.style?.find(
-    (item) => item?.part.name === part.value?.name && item?.part.state === part.value?.state
+    (item) =>
+      item?.part.name === part.value?.name &&
+      item?.part.state === part.value?.state &&
+      getStyleTheme(item) === editTheme.value
   )
 
   return item
@@ -137,17 +157,58 @@ const parts = computed(() => {
   return projectStore.activeWidget ? componentMap[projectStore.activeWidget.type].parts : []
 })
 
+// 主题选项
+const themeOptions = computed(() => {
+  return projectStore.project?.themes.map((item) => ({
+    label: `${item.key}${item.description ? `(${item.description})` : ''}`,
+    value: item.key
+  }))
+})
+
+watch(
+  () => projectStore.project?.themes?.map((item) => item.key).join('|'),
+  () => {
+    const themeKeys = projectStore.project?.themes?.map((item) => item.key) || []
+    if (!themeKeys.length) {
+      editTheme.value = DEFAULT_THEME_KEY
+      return
+    }
+    if (!themeKeys.includes(editTheme.value)) {
+      editTheme.value = projectStore.project?.currentTheme || themeKeys[0]
+    }
+  },
+  {
+    immediate: true
+  }
+)
+
+const setPartByEditThemeStyle = () => {
+  const widgetStyles = projectStore.activeWidget?.style || []
+  const currentPartThemeStyle = widgetStyles.find(
+    (item) =>
+      item?.part?.name === part.value.name &&
+      item?.part?.state === part.value.state &&
+      getStyleTheme(item) === editTheme.value
+  )
+  const currentThemeStyle = widgetStyles.find((item) => getStyleTheme(item) === editTheme.value)
+  const fallbackThemeStyle = widgetStyles.find((item) => getStyleTheme(item) === DEFAULT_THEME_KEY)
+  const fallbackStyle = widgetStyles[0]
+  const first = currentPartThemeStyle || currentThemeStyle || fallbackThemeStyle || fallbackStyle
+
+  if (first) {
+    part.value.name = first.part.name
+    part.value.state = first.part.state
+  }
+  part.value.expandStyle = true
+}
+
 provide('parts', parts)
 
 watch(
   () => projectStore.activeWidget?.id,
   () => {
-    const first = projectStore.activeWidget?.style?.[0]
-    if (first) {
-      part.value.name = first.part.name
-      part.value.state = first.part.state
-      part.value.expandStyle = true
-    }
+    editTheme.value = projectStore.project?.currentTheme || DEFAULT_THEME_KEY
+    setPartByEditThemeStyle()
     scrollContainerRef.value?.scrollTo({
       top: 0
     })
@@ -157,6 +218,13 @@ watch(
   }
 )
 
+watch(
+  () => editTheme.value,
+  () => {
+    setPartByEditThemeStyle()
+  }
+)
+
 watch(
   () => part.value,
   ({ name, state }) => {
@@ -212,7 +280,8 @@ const onChangeStateStyle = (field: string, type: 'add' | 'delete') => {
         part: {
           name: part.value.name,
           state: part.value.state
-        }
+        },
+        theme: editTheme.value
       })
       projectStore.activeWidget?.style?.push(result)
     }
@@ -236,14 +305,18 @@ const onChangeStyleByState = (type: 'add' | 'delete') => {
       part: {
         name: part.value.name,
         state: part.value.state
-      }
+      },
+      theme: editTheme.value
     })
     projectStore.activeWidget?.style?.push(result)
   } else {
     // 删除样式
     const index =
       projectStore.activeWidget?.style.findIndex(
-        (item) => item.part.name === part.value.name && item.part.state === part.value.state
+        (item) =>
+          item.part.name === part.value.name &&
+          item.part.state === part.value.state &&
+          getStyleTheme(item) === editTheme.value
       ) ?? -1
     if (index !== -1) {
       projectStore.activeWidget?.style.splice(index, 1)

+ 7 - 7
src/renderer/src/views/designer/sidebar/components/ThemeModal.vue

@@ -1,11 +1,11 @@
 <template>
   <el-dialog v-model="visible" title="主题设置" width="760px" append-to-body align-center draggable>
     <div class="flex items-center justify-between mb-12px">
-      <div class="text-12px text-text-secondary">支持行内新增和修改主题</div>
-      <el-button type="primary" @click="handleStartCreate" :disabled="isEditingAny"
-        >新增主题</el-button
+      <el-button type="primary" text @click="handleStartCreate" :disabled="isEditingAny"
+        >+新增主题</el-button
       >
     </div>
+    <div class="text-12px text-text-secondary mb-12px">支持行内新增和修改主题</div>
 
     <el-table :data="tableRows" border row-key="__sourceKey">
       <el-table-column prop="key" label="主题名称" min-width="220">
@@ -29,7 +29,7 @@
         </template>
       </el-table-column>
 
-      <el-table-column prop="description" label="描述" min-width="240">
+      <el-table-column prop="description" label="描述">
         <template #default="{ row }">
           <el-input
             v-if="isEditingRow(row)"
@@ -48,7 +48,7 @@
         </template>
       </el-table-column>
 
-      <el-table-column label="操作" width="200" align="center">
+      <el-table-column label="操作" width="150" align="center">
         <template #default="{ row }">
           <template v-if="isEditingRow(row)">
             <el-button type="primary" text @click="handleSaveRow(row)">保存</el-button>
@@ -220,7 +220,7 @@ const handleSaveRow = (row: TableThemeRow) => {
   const description = editForm.value.description.trim()
 
   if (row.__sourceKey === DEFAULT_THEME_KEY && key !== DEFAULT_THEME_KEY) {
-    ElMessage.warning('default_theme 不允许修改主题名称')
+    ElMessage.warning(`${DEFAULT_THEME_KEY} 不允许修改主题名称`)
     return
   }
 
@@ -261,7 +261,7 @@ const handleSaveRow = (row: TableThemeRow) => {
 const handleDeleteTheme = (themeKey: string) => {
   if (!ensureProject()) return
   if (themeKey === DEFAULT_THEME_KEY) {
-    ElMessage.warning('default_theme 不允许删除')
+    ElMessage.warning(`${DEFAULT_THEME_KEY} 不允许删除`)
     return
   }
 

+ 21 - 1
src/renderer/src/views/designer/workspace/stage/index.vue

@@ -31,6 +31,21 @@
           <span style="margin-right: 12px">{{ $t('resolution') }}:</span>
           <span>{{ screen?.width }} * {{ screen?.height }}</span>
           <span class="ml-8px">{{ screen?.screenDirection }}</span>
+          <span class="ml-8px flex items-center gap-4px theme"
+            >主题:
+            <el-select
+              :model-value="projectStore.project?.currentTheme"
+              size="small"
+              style="width: 120px"
+              @change="(val) => projectStore.setCurrentTheme(val)"
+              :options="
+                projectStore.project?.themes.map((item) => ({
+                  value: item.key,
+                  label: `${item.key}(${item.description})`
+                }))
+              "
+            />
+          </span>
         </div>
         <div class="bottom-right flex items-center gap-8px">
           <el-tooltip content="屏幕布局">
@@ -324,7 +339,12 @@ defineExpose({
   width: 0;
   height: 0;
 }
-::v-deep(.el-slider) {
+:deep(.el-slider) {
   --el-slider-button-size: 10px;
 }
+.theme {
+  :deep(.el-select__wrapper) {
+    box-shadow: none;
+  }
+}
 </style>