Selaa lähdekoodia

feat: 添加属性面板配置

Mickey Mike 2 viikkoa sitten
vanhempi
commit
e07ab79711

+ 373 - 0
src/renderer/src/views/designer/config/PropertyConfig.vue

@@ -0,0 +1,373 @@
+<template>
+  <div class="config pr-20px pl-20px h-[calc(100vh-198px)] overflow-auto">
+    <el-form label-position="top">
+      <el-collapse v-model="activeNames">
+        <el-collapse-item title="Transform" name="transform">
+          <div class="flex gap-10px">
+            <el-form-item v-if="hasKey('x')" label="X" class="flex-1">
+              <el-input v-model="data.x" />
+            </el-form-item>
+            <el-form-item v-if="hasKey('y')" label="Y" class="flex-1">
+              <el-input v-model="data.y" />
+            </el-form-item>
+          </div>
+          <div class="flex gap-10px">
+            <el-form-item v-if="hasKey('width')" label="宽度" class="flex-1">
+              <el-input v-model="data.width" />
+            </el-form-item>
+            <el-form-item v-if="hasKey('height')" label="高度" class="flex-1">
+              <el-input v-model="data.height" />
+            </el-form-item>
+          </div>
+
+          <el-form-item v-if="hasKey('parent')" label="父级组件">
+            <el-input v-model="data.parent" />
+          </el-form-item>
+          <el-form-item v-if="hasKey('text')" label="文本">
+            <el-input v-model="data.text" />
+          </el-form-item>
+          <el-form-item v-if="hasKey('align')" label="对齐方式">
+            <el-select v-model="data.align">
+              <el-option label="居中" value="center" />
+              <el-option label="左上" value="top_left" />
+              <el-option label="上中" value="top_center" />
+              <el-option label="右上" value="top_right" />
+              <el-option label="左下" value="bottom_left" />
+              <el-option label="下中" value="bottom_center" />
+              <el-option label="右下" value="bottom_right" />
+              <el-option label="左" value="left" />
+              <el-option label="右" value="right" />
+            </el-select>
+          </el-form-item>
+          <el-form-item v-if="hasKey('state')" label="状态">
+            <el-checkbox-group v-model="data.state">
+              <el-checkbox label="选中" value="checked" />
+              <el-checkbox label="禁用" value="disabled" />
+              <el-checkbox label="聚焦" value="focused" />
+              <el-checkbox label="按下" value="pressed" />
+              <el-checkbox label="编辑" value="edited" />
+            </el-checkbox-group>
+          </el-form-item>
+        </el-collapse-item>
+        <!-- 样式 -->
+        <el-collapse-item
+          v-if="hasKey('styleMain') || hasKey('styleItems')"
+          title="样式设置"
+          name="style"
+        >
+          <el-collapse-item v-if="hasKey('styleMain')" class="p-5px bg-#00000080" title="主体样式">
+            <el-collapse-item v-if="hasBackground" title="背景" class="p-5px">
+              <el-form-item v-if="hasKey('styleMain.borderRadius')" label="圆角">
+                <el-input-number v-model="data.styleMain.borderRadius" :min="0" />
+              </el-form-item>
+              <div class="flex gap-10px">
+                <el-form-item v-if="hasKey('styleMain.bgColor')" label="背景色" class="flex-1">
+                  <el-input v-model="data.styleMain.bgColor" />
+                </el-form-item>
+                <el-form-item v-if="hasKey('styleMain.bgAlpha')" label="透明度" class="flex-1">
+                  <el-input-number
+                    v-model="data.styleMain.bgAlpha"
+                    :min="0"
+                    :max="1"
+                    :step="0.01"
+                    class="flex-1 mr-5px"
+                  />
+                  <el-color-picker v-model="data.styleMain.bgColor" class="w-40px" />
+                </el-form-item>
+              </div>
+              <el-form-item
+                v-if="hasKey('styleMain.gradient')"
+                label="背景渐变色"
+                class="flex flex-1"
+              >
+                <el-input v-model="data.styleMain.gradient" class="flex-1" />
+                <el-color-picker v-model="data.styleMain.gradient" class="w-40px mr-5px ml-5px" />
+                <el-select
+                  v-if="hasKey('styleMain.gradient')"
+                  v-model="data.theme"
+                  placeholder="可选主题色"
+                  class="mt-10px"
+                />
+              </el-form-item>
+              <div class="flex gap-10px">
+                <el-form-item v-if="hasKey('styleMain.shade')" label="阴影" class="flex-1">
+                  <el-input-number v-model="data.styleMain.shade" :min="0" style="width: 100%" />
+                </el-form-item>
+                <el-form-item v-if="hasKey('styleMain.tint')" label="高光" class="flex-1">
+                  <el-input-number v-model="data.styleMain.tint" :min="0" style="width: 100%" />
+                </el-form-item>
+              </div>
+              <el-form-item v-if="hasKey('styleMain.gradientDirection')" label="渐变方向">
+                <el-select v-model="data.styleMain.gradientDirection">
+                  <el-option label="无" value="none" />
+                  <el-option label="横向" value="horizontal" />
+                  <el-option label="纵向" value="vertical" />
+                </el-select>
+              </el-form-item>
+              <el-form-item v-if="hasKey('styleMain.bgImage')" label="背景图片">
+                <el-input v-model="data.styleMain.bgImage" />
+              </el-form-item>
+            </el-collapse-item>
+            <el-collapse-item v-if="hasBorder" title="边框" class="p-5px">
+              <div class="flex flex-1 gap-10px">
+                <el-form-item v-if="hasKey('styleMain.borderColor')" label="颜色" class="flex-1">
+                  <el-input v-model="data.styleMain.borderColor" />
+                </el-form-item>
+                <el-form-item v-if="hasKey('styleMain.borderAlpha')" label="透明度" class="flex-1">
+                  <el-input-number
+                    v-model="data.styleMain.borderAlpha"
+                    :max="255"
+                    :min="0"
+                    class="flex-1"
+                  />
+                  <el-color-picker v-model="data.styleMain.borderColor" class="ml-10px w-40px" />
+                </el-form-item>
+              </div>
+              <el-select
+                v-if="hasKey('styleMain.borderColor')"
+                v-model="data.theme"
+                placeholder="可选主题色"
+                class="mt-10px mb-10px"
+              />
+              <el-form-item v-if="hasKey('styleMain.borderWidth')" label="宽度">
+                <el-input-number v-model="data.styleMain.borderWidth" :min="0" />
+              </el-form-item>
+              <el-form-item v-if="hasKey('styleMain.borderStyle')" label="样式">
+                <el-select v-model="data.styleMain.borderStyle">
+                  <el-option label="无" value="none" />
+                  <el-option label="实线" value="solid" />
+                  <el-option label="虚线" value="dashed" />
+                  <el-option label="点状" value="dotted" />
+                </el-select>
+              </el-form-item>
+            </el-collapse-item>
+            <el-collapse-item v-if="hasOutline" title="元素外框线" class="p-5px">
+              <div class="flex flex-1 gap-10px">
+                <el-form-item v-if="hasKey('styleMain.outlineColor')" label="颜色" class="flex-1">
+                  <el-input v-model="data.styleMain.outlineColor" />
+                </el-form-item>
+                <el-form-item v-if="hasKey('styleMain.outlineAlpha')" label="透明度" class="flex-1">
+                  <el-input-number
+                    v-model="data.styleMain.outlineAlpha"
+                    :max="255"
+                    :min="0"
+                    class="flex-1"
+                  />
+                  <el-color-picker v-model="data.styleMain.outlineColor" class="ml-10px w-40px" />
+                </el-form-item>
+              </div>
+              <el-select
+                v-if="hasKey('styleMain.outlineColor')"
+                v-model="data.theme"
+                placeholder="可选主题色"
+                class="mt-10px mb-10px"
+              />
+            </el-collapse-item>
+            <el-collapse-item v-if="hasBoxShadow" title="阴影效果" class="p-5px">
+              <div class="flex flex-1 gap-10px">
+                <el-form-item v-if="hasKey('styleMain.boxShadowColor')" label="颜色">
+                  <el-input v-model="data.styleMain.boxShadowColor" />
+                </el-form-item>
+                <el-form-item
+                  v-if="hasKey('styleMain.boxShadowAlpha')"
+                  label="透明度"
+                  class="flex-1"
+                >
+                  <el-input-number
+                    v-model="data.styleMain.boxShadowAlpha"
+                    :max="255"
+                    :min="0"
+                    class="flex-1"
+                  />
+                  <el-color-picker v-model="data.styleMain.boxShadowColor" class="ml-10px w-40px" />
+                </el-form-item>
+              </div>
+              <div class="flex gap-10px">
+                <el-form-item v-if="hasKey('styleMain.boxShadowX')" label="水平偏移" class="flex-1">
+                  <el-input-number
+                    v-model="data.styleMain.boxShadowX"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+                <el-form-item v-if="hasKey('styleMain.boxShadowY')" label="垂直偏移" class="flex-1">
+                  <el-input-number
+                    v-model="data.styleMain.boxShadowY"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </div>
+              <div class="flex gap-10px">
+                <el-form-item
+                  v-if="hasKey('styleMain.boxShadowBlur')"
+                  label="模糊距离"
+                  class="flex-1"
+                >
+                  <el-input-number
+                    v-model="data.styleMain.boxShadowBlur"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+                <el-form-item
+                  v-if="hasKey('styleMain.boxShadowSpread')"
+                  label="扩散距离"
+                  class="flex-1"
+                >
+                  <el-input-number
+                    v-model="data.styleMain.boxShadowSpread"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </div>
+            </el-collapse-item>
+            <el-collapse-item v-if="hasPadding" title="内边距" class="p-5px">
+              <div class="flex gap-10px">
+                <el-form-item v-if="hasKey('styleMain.paddingTop')" label="上" class="flex-1">
+                  <el-input-number
+                    v-model="data.styleMain.paddingTop"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+                <el-form-item v-if="hasKey('styleMain.paddingBottom')" label="下" class="flex-1">
+                  <el-input-number
+                    v-model="data.styleMain.paddingBottom"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </div>
+              <div class="flex gap-10px">
+                <el-form-item v-if="hasKey('styleMain.paddingLeft')" label="左" class="flex-1">
+                  <el-input-number
+                    v-model="data.styleMain.paddingLeft"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+                <el-form-item v-if="hasKey('styleMain.paddingRight')" label="右" class="flex-1">
+                  <el-input-number
+                    v-model="data.styleMain.paddingRight"
+                    :min="0"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </div>
+            </el-collapse-item>
+          </el-collapse-item>
+
+          <el-collapse-item v-if="hasKey('styleItems')" class="p-5px bg-#00000080" title="子项样式">
+            123
+          </el-collapse-item>
+        </el-collapse-item>
+
+        <!-- 事件 -->
+        <el-collapse-item v-if="hasKey('events')" title="事件" name="events">
+          <div class="flex justify-center items-center">
+            <el-button type="primary">添加事件</el-button>
+          </div>
+        </el-collapse-item>
+      </el-collapse>
+    </el-form>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, watch, defineEmits, computed } from 'vue'
+import type { Page } from '@/types/page'
+interface Emits {
+  (e: 'update:selected', val: Page['props']): void
+}
+const props = defineProps<{
+  selected?: Page['props']
+}>()
+const emit = defineEmits<Emits>()
+const data = ref<Page['props']>(props.selected || ({} as Page['props']))
+watch(data, (val) => emit('update:selected', val))
+const hasKey = (path: string) => {
+  const keys = path.split('.')
+  let obj = data.value as Page['props']
+
+  for (const key of keys) {
+    if (!obj || !Object.prototype.hasOwnProperty.call(obj, key)) {
+      return false
+    }
+    obj = obj[key]
+  }
+  return true
+}
+
+const activeNames = ref<string[]>(['transform', 'style'])
+
+const hasBackground = computed(() => {
+  const sm = data.value.styleMain || {}
+  return (
+    sm.borderRadius !== undefined ||
+    sm.bgColor !== undefined ||
+    sm.bgAlpha !== undefined ||
+    sm.gradient !== undefined ||
+    sm.shade !== undefined ||
+    sm.tint !== undefined ||
+    sm.gradientDirection !== undefined ||
+    sm.bgImage !== undefined
+  )
+})
+
+const hasBorder = computed(() => {
+  const sm = data.value.styleMain || {}
+  return (
+    sm.borderColor !== undefined ||
+    sm.borderAlpha !== undefined ||
+    sm.borderWidth !== undefined ||
+    sm.borderStyle !== undefined
+  )
+})
+
+const hasOutline = computed(() => {
+  const sm = data.value.styleMain || {}
+  return sm.outlineColor !== undefined || sm.outlineAlpha !== undefined
+})
+
+const hasBoxShadow = computed(() => {
+  const sm = data.value.styleMain || {}
+  return (
+    sm.boxShadowColor !== undefined ||
+    sm.boxShadowAlpha !== undefined ||
+    sm.boxShadowX !== undefined ||
+    sm.boxShadowY !== undefined ||
+    sm.boxShadowBlur !== undefined ||
+    sm.boxShadowSpread !== undefined
+  )
+})
+
+const hasPadding = computed(() => {
+  const sm = data.value.styleMain || {}
+  return (
+    sm.paddingTop !== undefined ||
+    sm.paddingBottom !== undefined ||
+    sm.paddingLeft !== undefined ||
+    sm.paddingRight !== undefined
+  )
+})
+</script>
+
+<style scoped lang="less">
+:deep(.el-form-item) {
+  margin-bottom: 5px;
+}
+// :deep(.el-input__wrapper) {
+//   box-shadow: none !important;
+//   border-radius: 0 !important;
+//   border: none !important;
+//   border-bottom: 1px solid #dcdfe6 !important;
+//   box-sizing: border-box !important;
+// }
+
+// :deep(.el-input__wrapper.is-focus) {
+//   box-shadow: none !important;
+//   border-bottom: 1px solid #409eff !important;
+// }
+</style>

+ 63 - 3
src/renderer/src/views/designer/config/index.vue

@@ -1,7 +1,9 @@
 <template>
   <div>
     <el-tabs size="small">
-      <el-tab-pane label="属性"></el-tab-pane>
+      <el-tab-pane label="属性">
+        <property-config v-model:selected="data" />
+      </el-tab-pane>
       <el-tab-pane label="变量"></el-tab-pane>
       <el-tab-pane label="动画"></el-tab-pane>
       <el-tab-pane label="多语言"></el-tab-pane>
@@ -10,6 +12,64 @@
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import { ref, watch } from 'vue'
+import PropertyConfig from './PropertyConfig.vue'
 
-<style scoped lang="less"></style>
+const data = ref({
+  type: 'lv_obj',
+  id: 'component-1',
+  x: 0,
+  y: 0,
+  width: 100,
+  height: 100,
+  parent: 'screen-1',
+  text: 'Hello World',
+  align: 'center',
+  state: [],
+  theme: '',
+  styleMain: {
+    borderRadius: 0,
+    bgColor: '#ffffff',
+    bgAlpha: 255,
+    gradient: '',
+    shade: 0,
+    tint: 0,
+    gradientDirection: 'none',
+    bgImage: '',
+    borderColor: '#000000',
+    borderAlpha: 1,
+    borderWidth: 0,
+    borderStyle: 'solid',
+    boxShadowSpread: 0,
+    boxShadow: '',
+    boxShadowBlur: 0,
+    boxShadowColor: '#000000',
+    boxShadowAlpha: 1,
+    outlineColor: '#ff0000',
+    outlineAlpha: 1,
+    outlineWidth: 0,
+    outlineStyle: 'solid',
+    boxShadowX: 0,
+    boxShadowY: 0
+  },
+  styleItems: {},
+  events: []
+})
+
+watch(
+  () => data.value,
+  (val) => {
+    console.log('Updated data:', val)
+  },
+  {
+    deep: true
+  }
+)
+</script>
+
+<style scoped lang="less">
+:deep(.el-tabs__nav-wrap.is-top) {
+  padding: 0 20px;
+}
+</style>

+ 1 - 1
src/renderer/src/views/designer/modals/projectModal/index.vue

@@ -447,7 +447,7 @@ const appStore = useAppStore()
 
 const form = ref<FormInstance>()
 // 显示模态框
-const showModal = ref(true)
+const showModal = ref(false)
 // 显示自定义屏幕模态框
 const showScreenModal = ref(false)
 // 自定义屏幕