|
|
@@ -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>
|
|
|
|
|
|
<!-- 动态显示依赖项 -->
|
|
|
@@ -225,10 +425,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 +446,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 +456,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 +485,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 : []
|