Browse Source

Merge branch 'main' of https://git.shalu.com/jiaxing.liao/sunmicro-lvgl-designer

jiaxing.liao 2 weeks ago
parent
commit
5a1778d70e

+ 33 - 0
src/renderer/src/constants/index.ts

@@ -222,3 +222,36 @@ export const symbols = [
   { label: 'LV_SYMBOL_NEW_LINE', value: '\xEF\xA2\xA2' },
   { label: 'LV_SYMBOL_DUMMY', value: '\xEF\xA3\xBF' }
 ]
+
+/**
+ * 文本显示位置
+ */
+
+export const textAlign = [
+  { label: '左', value: 'left' },
+  { label: '右', value: 'right' },
+  { label: '上', value: 'top' },
+  { label: '下', value: 'bottom' },
+  { label: '居中', value: 'center' }
+]
+
+/**
+ * 文本加粗
+ */
+
+export const textWeight = [
+  { label: '普通', value: 'normal' },
+  { label: '加粗', value: 'bold' }
+]
+
+/**
+ * 边框
+ */
+
+export const borderSides = [
+  { label: '全部', value: 'all' },
+  { label: '上', value: 'top' },
+  { label: '右', value: 'right' },
+  { label: '下', value: 'bottom' },
+  { label: '左', value: 'left' }
+]

+ 2 - 2
src/renderer/src/lvgl-widgets/button-matrix/index.ts

@@ -226,8 +226,8 @@ export default {
             : [
                 {
                   label: '内边距',
-                  field: 'shadow',
-                  valueType: 'shadow'
+                  field: 'padding',
+                  valueType: 'padding'
                 },
                 {
                   label: '间距',

+ 439 - 7
src/renderer/src/views/designer/config/PropertyConfig.vue

@@ -163,7 +163,7 @@
                 :key="prop.field"
               >
                 <el-form-item v-if="prop.field === 'part'" :label="prop.label" class="flex w-full">
-                  <div class="flex flex-1 justify-between items-center">
+                  <div class="flex flex-1 justify-between items-center gap-10px">
                     <!-- 模块 -->
                     <el-select v-model="moduleValue" @change="handlePartChange">
                       <el-option
@@ -202,7 +202,207 @@
                     :label="prop.label"
                     class="flex w-full"
                   >
-                    <el-input />
+                    <!-- 背景颜色 -->
+                    <template v-if="prop.field === 'background'">
+                      <template
+                        v-if="data.style?.[styleIndex]?.[prop.field]?.hasOwnProperty('color')"
+                      >
+                        <div class="flex [flex-direction:column] flex-1">
+                          <div class="flex flex-1">
+                            <el-color-picker
+                              v-model="data.style[styleIndex][prop.field].color"
+                              :show-alpha="true"
+                              :predefine="predefineColors"
+                            />
+                            <div class="ml-10px">
+                              {{ data.style[styleIndex][prop.field].color }}
+                            </div>
+                          </div>
+
+                          <template
+                            v-if="data.style?.[styleIndex]?.[prop.field]?.hasOwnProperty('image')"
+                          >
+                            <div class="flex flex-1 mt-10px">
+                              <div class="w-32px h-32px bg-#cccc mr-10px"></div>
+                              <el-color-picker
+                                v-model="data.style[styleIndex][prop.field].image.color"
+                                :show-alpha="true"
+                                :predefine="predefineColors"
+                              />
+                              <div class="ml-10px">
+                                {{ data.style[styleIndex][prop.field].image.color }}
+                              </div>
+                            </div>
+                          </template>
+                        </div>
+                      </template>
+                    </template>
+
+                    <!-- 字体 -->
+                    <div v-if="prop.field === 'text'" class="w-full">
+                      <div class="flex flex-1 gap-10px mb-10px">
+                        <el-color-picker
+                          v-model="data.style[styleIndex][prop.field].color"
+                          :show-alpha="true"
+                          :predefine="predefineColors"
+                        />
+                        <el-input-number
+                          v-model="data.style[styleIndex][prop.field].size"
+                          :min="0"
+                          placeholder="字体大小"
+                          class="flex-1"
+                        />
+                      </div>
+                      <div class="flex flex-1 gap-10px mb-10px">
+                        <el-select
+                          v-model="data.style[styleIndex][prop.field].weight"
+                          placeholder="字体加粗"
+                        >
+                          <el-option
+                            v-for="weight in textWeight"
+                            :key="weight.value"
+                            :label="weight.label"
+                            :value="weight.value"
+                          />
+                        </el-select>
+                        <el-select v-model="data.style[styleIndex][prop.field].family"></el-select>
+                      </div>
+                      <el-select
+                        v-model="data.style[styleIndex][prop.field].align"
+                        placeholder="对齐方式"
+                      >
+                        <el-option
+                          v-for="align in textAlign"
+                          :key="align.value"
+                          :label="align.label"
+                          :value="align.value"
+                        />
+                      </el-select>
+                    </div>
+
+                    <!-- 边框 -->
+                    <div v-if="prop.field === 'border'" class="w-full">
+                      <div class="flex flex-1 gap-10px mb-10px">
+                        <el-input-number
+                          v-model="data.style[styleIndex][prop.field].width"
+                          placeholder="边框大小"
+                          class="flex-1"
+                          :min="0"
+                        />
+                        <el-color-picker
+                          v-model="data.style[styleIndex][prop.field].color"
+                          :show-alpha="true"
+                          :predefine="predefineColors"
+                        />
+                      </div>
+                      <div class="flex flex-1 gap-10px">
+                        <el-select
+                          v-model="data.style[styleIndex][prop.field].side"
+                          multiple
+                          collapse-tags
+                          class="flex-1"
+                        >
+                          <el-option
+                            v-for="sides in borderSides"
+                            :key="sides.value"
+                            :label="sides.label"
+                            :value="sides.value"
+                          />
+                        </el-select>
+                        <el-input-number
+                          v-model="data.style[styleIndex][prop.field].radius"
+                          placeholder="圆角大小"
+                          class="flex-1"
+                          :min="0"
+                        />
+                      </div>
+                    </div>
+                    <!-- 阴影 -->
+                    <div v-if="prop.field === 'shadow'" class="w-full">
+                      <el-color-picker
+                        v-model="data.style[styleIndex][prop.field].color"
+                        :show-alpha="true"
+                        :predefine="predefineColors"
+                        class="mb-10px"
+                      />
+                      <div class="flex flex-1 gap-10px mb-10px">
+                        <el-input-number
+                          v-model="data.style[styleIndex][prop.field].x"
+                          placeholder="水平偏移"
+                          class="flex-1"
+                          :min="0"
+                        />
+                        <el-input-number
+                          v-model="data.style[styleIndex][prop.field].y"
+                          placeholder="垂直偏移"
+                          class="flex-1"
+                          :min="0"
+                        />
+                      </div>
+                      <div class="flex flex-1 gap-10px">
+                        <el-input-number
+                          v-model="data.style[styleIndex][prop.field].width"
+                          placeholder="模糊半径"
+                          class="flex-1"
+                          :min="0"
+                        />
+
+                        <el-input-number
+                          v-model="data.style[styleIndex][prop.field].spread"
+                          placeholder="阴影扩展半径"
+                          class="flex-1"
+                          :min="0"
+                        />
+                      </div>
+                    </div>
+                    <!-- 内边距 -->
+                    <div v-if="prop.field === 'padding'" class="w-full">
+                      <div class="flex flex-1 gap-10px mb-10px">
+                        <el-input-number
+                          v-model="data.style[styleIndex][prop.field].top"
+                          placeholder="内部上边距"
+                          class="flex-1"
+                          :min="0"
+                        />
+                        <el-input-number
+                          v-model="data.style[styleIndex][prop.field].right"
+                          placeholder="内部右边距"
+                          class="flex-1"
+                          :min="0"
+                        />
+                      </div>
+                      <div class="flex flex-1 gap-10px">
+                        <el-input-number
+                          v-model="data.style[styleIndex][prop.field].bottom"
+                          placeholder="内部下边距"
+                          class="flex-1"
+                          :min="0"
+                        />
+
+                        <el-input-number
+                          v-model="data.style[styleIndex][prop.field].left"
+                          placeholder="内部左边距"
+                          class="flex-1"
+                          :min="0"
+                        />
+                      </div>
+                    </div>
+                    <!-- 间距 -->
+                    <div v-if="prop.field === 'gap'" class="w-full flex flex-1 gap-10px">
+                      <el-input-number
+                        v-model="data.style[styleIndex][prop.field].row"
+                        placeholder="横向"
+                        class="flex-1"
+                        :min="0"
+                      />
+
+                      <el-input-number
+                        v-model="data.style[styleIndex][prop.field].column"
+                        placeholder="纵向"
+                        class="flex-1"
+                        :min="0"
+                      />
+                    </div>
                   </el-form-item>
 
                   <!-- 动态显示依赖项 -->
@@ -212,6 +412,215 @@
                       :key="dependency.field"
                       :label="dependency.label"
                     >
+                      <!-- 背景颜色 -->
+                      <template v-if="dependency.field === 'background'">
+                        <template
+                          v-if="
+                            data.style?.[styleIndex]?.[dependency.field]?.hasOwnProperty('color')
+                          "
+                        >
+                          <div class="flex [flex-direction:column] flex-1">
+                            <div class="flex flex-1">
+                              <el-color-picker
+                                v-model="data.style[styleIndex][dependency.field].color"
+                                :show-alpha="true"
+                                :predefine="predefineColors"
+                              />
+                              <div class="ml-10px">
+                                {{ data.style[styleIndex][dependency.field].color }}
+                              </div>
+                            </div>
+
+                            <template
+                              v-if="
+                                data.style?.[styleIndex]?.[dependency.field]?.hasOwnProperty(
+                                  'image'
+                                )
+                              "
+                            >
+                              <div class="flex flex-1 mt-10px">
+                                <div class="w-32px h-32px bg-#cccc mr-10px"></div>
+                                <el-color-picker
+                                  v-model="data.style[styleIndex][dependency.field].image.color"
+                                  :show-alpha="true"
+                                  :predefine="predefineColors"
+                                />
+                                <div class="ml-10px">
+                                  {{ data.style[styleIndex][dependency.field].image.color }}
+                                </div>
+                              </div>
+                            </template>
+                          </div>
+                        </template>
+                      </template>
+
+                      <!-- 字体 -->
+                      <div v-if="dependency.field === 'text'" class="w-full">
+                        <div class="flex flex-1 gap-10px mb-10px">
+                          <el-color-picker
+                            v-model="data.style[styleIndex][dependency.field].color"
+                            :show-alpha="true"
+                            :predefine="predefineColors"
+                          />
+                          <el-input-number
+                            v-model="data.style[styleIndex][dependency.field].size"
+                            :min="0"
+                            placeholder="字体大小"
+                            class="flex-1"
+                          />
+                        </div>
+                        <div class="flex flex-1 gap-10px mb-10px">
+                          <el-select
+                            v-model="data.style[styleIndex][dependency.field].weight"
+                            placeholder="字体加粗"
+                          >
+                            <el-option
+                              v-for="weight in textWeight"
+                              :key="weight.value"
+                              :label="weight.label"
+                              :value="weight.value"
+                            />
+                          </el-select>
+                          <el-select
+                            v-model="data.style[styleIndex][dependency.field].family"
+                          ></el-select>
+                        </div>
+                        <el-select
+                          v-model="data.style[styleIndex][dependency.field].align"
+                          placeholder="对齐方式"
+                        >
+                          <el-option
+                            v-for="align in textAlign"
+                            :key="align.value"
+                            :label="align.label"
+                            :value="align.value"
+                          />
+                        </el-select>
+                      </div>
+
+                      <!-- 边框 -->
+                      <div v-if="dependency.field === 'border'" class="w-full">
+                        <div class="flex flex-1 gap-10px mb-10px">
+                          <el-input-number
+                            v-model="data.style[styleIndex][dependency.field].width"
+                            placeholder="边框大小"
+                            class="flex-1"
+                            :min="0"
+                          />
+                          <el-color-picker
+                            v-model="data.style[styleIndex][dependency.field].color"
+                            :show-alpha="true"
+                            :predefine="predefineColors"
+                          />
+                        </div>
+                        <div class="flex flex-1 gap-10px">
+                          <el-select
+                            v-model="data.style[styleIndex][dependency.field].side"
+                            multiple
+                            collapse-tags
+                            class="flex-1"
+                          >
+                            <el-option
+                              v-for="sides in borderSides"
+                              :key="sides.value"
+                              :label="sides.label"
+                              :value="sides.value"
+                            />
+                          </el-select>
+                          <el-input-number
+                            v-model="data.style[styleIndex][dependency.field].radius"
+                            placeholder="圆角大小"
+                            class="flex-1"
+                            :min="0"
+                          />
+                        </div>
+                      </div>
+                      <!-- 阴影 -->
+                      <div v-if="dependency.field === 'shadow'" class="w-full">
+                        <el-color-picker
+                          v-model="data.style[styleIndex][dependency.field].color"
+                          :show-alpha="true"
+                          :predefine="predefineColors"
+                          class="mb-10px"
+                        />
+                        <div class="flex flex-1 gap-10px mb-10px">
+                          <el-input-number
+                            v-model="data.style[styleIndex][dependency.field].x"
+                            placeholder="水平偏移"
+                            class="flex-1"
+                            :min="0"
+                          />
+                          <el-input-number
+                            v-model="data.style[styleIndex][dependency.field].y"
+                            placeholder="垂直偏移"
+                            class="flex-1"
+                            :min="0"
+                          />
+                        </div>
+                        <div class="flex flex-1 gap-10px">
+                          <el-input-number
+                            v-model="data.style[styleIndex][dependency.field].width"
+                            placeholder="模糊半径"
+                            class="flex-1"
+                            :min="0"
+                          />
+
+                          <el-input-number
+                            v-model="data.style[styleIndex][dependency.field].spread"
+                            placeholder="阴影扩展半径"
+                            class="flex-1"
+                            :min="0"
+                          />
+                        </div>
+                      </div>
+                      <!-- 内边距 -->
+                      <div v-if="dependency.field === 'padding'" class="w-full">
+                        <div class="flex flex-1 gap-10px mb-10px">
+                          <el-input-number
+                            v-model="data.style[styleIndex][dependency.field].top"
+                            placeholder="内部上边距"
+                            class="flex-1"
+                            :min="0"
+                          />
+                          <el-input-number
+                            v-model="data.style[styleIndex][dependency.field].right"
+                            placeholder="内部右边距"
+                            class="flex-1"
+                            :min="0"
+                          />
+                        </div>
+                        <div class="flex flex-1 gap-10px">
+                          <el-input-number
+                            v-model="data.style[styleIndex][dependency.field].bottom"
+                            placeholder="内部下边距"
+                            class="flex-1"
+                            :min="0"
+                          />
+
+                          <el-input-number
+                            v-model="data.style[styleIndex][dependency.field].left"
+                            placeholder="内部左边距"
+                            class="flex-1"
+                            :min="0"
+                          />
+                        </div>
+                      </div>
+                      <!-- 间距 -->
+                      <div v-if="dependency.field === 'gap'" class="w-full flex flex-1 gap-10px">
+                        <el-input-number
+                          v-model="data.style[styleIndex][dependency.field].row"
+                          placeholder="横向"
+                          class="flex-1"
+                          :min="0"
+                        />
+
+                        <el-input-number
+                          v-model="data.style[styleIndex][dependency.field].column"
+                          placeholder="纵向"
+                          class="flex-1"
+                          :min="0"
+                        />
+                      </div>
                     </el-form-item>
                   </template>
                 </template>
@@ -225,10 +634,11 @@
 </template>
 
 <script setup lang="ts">
-import { ref, watch } from 'vue'
+import { ref, watch, computed } from 'vue'
 import type { Page } from '@/types/page'
 import LvglWidgets from '@/lvgl-widgets'
 import { View } from '@element-plus/icons-vue'
+import { textAlign, textWeight, borderSides } from '@/constants'
 import { SplitterCollapse, SplitterCollapseItem } from '@/components/SplitterCollapse'
 
 interface Emits {
@@ -245,8 +655,8 @@ watch(
   () => props.selected,
   (value) => {
     if (value) {
-      moduleValue.value = LvglWidgets[data.value.type]?.parts[0].name
-      stateValue.value = LvglWidgets[data.value.type]?.parts[0].stateList[0]
+      moduleValue.value = LvglWidgets[data.value.type]?.parts[0].name || 'main'
+      stateValue.value = LvglWidgets[data.value.type]?.parts[0].stateList[0] || 'default'
       data.value = value || ({} as Page['props'])
       console.log(value)
     }
@@ -255,9 +665,25 @@ watch(
 
 const activeNames = ref<string[]>(['基本属性', '位置/大小', '添加标识', '删除标识'])
 
-const moduleValue = ref('main')
-const stateValue = ref('default')
+const moduleValue = ref('')
+const stateValue = ref('')
 const visibleStyle = ref(true)
+const predefineColors = [
+  '#ff4500',
+  '#ff8c00',
+  '#ffd700',
+  '#90ee90',
+  '#00ced1',
+  '#1e90ff',
+  '#c71585',
+  'rgba(255, 69, 0, 0.68)',
+  'rgb(255, 120, 0)',
+  'hsv(51, 100, 98)',
+  'hsva(120, 40, 94, 0.5)',
+  'hsl(181, 100%, 37%)',
+  'hsla(209, 100%, 56%, 0.73)',
+  '#c7158577'
+]
 
 const loadStyle = async (name) => {
   try {
@@ -268,6 +694,12 @@ const loadStyle = async (name) => {
   }
 }
 
+const styleIndex = computed(() => {
+  return data.value.style.findIndex(
+    (item) => item.part.name === moduleValue.value && item.part.state === stateValue.value
+  )
+})
+
 const getStateList = (partName) => {
   const part = LvglWidgets[data.value.type].parts.find((item) => item.name === partName)
   return part ? part.stateList : []