Просмотр исходного кода

fix: 修改事件表单折叠时节点大小问题

jiaxing.liao 1 неделя назад
Родитель
Сommit
91b800fed7

+ 1 - 1
src/renderer/src/lvgl-widgets/spinbox/index.ts

@@ -33,7 +33,7 @@ export default {
     }
     }
   ],
   ],
   defaultSchema: {
   defaultSchema: {
-    name: 'spinbox_1',
+    name: 'spinbox',
     props: {
     props: {
       x: 0,
       x: 0,
       y: 0,
       y: 0,

+ 3 - 0
src/renderer/src/views/designer/config/property/CusFormItem.vue

@@ -127,6 +127,7 @@
     <el-collapse
     <el-collapse
       v-if="!isFormItem && !schema?.render && !isStyle && schema.field !== 'part'"
       v-if="!isFormItem && !schema?.render && !isStyle && schema.field !== 'part'"
       :model-value="componentProps?.defaultCollapsed ? [] : [key]"
       :model-value="componentProps?.defaultCollapsed ? [] : [key]"
+      @change="(val) => emit('changeCollapse', val)"
     >
     >
       <el-collapse-item :title="schema.label" :name="key" style="margin-bottom: 12px">
       <el-collapse-item :title="schema.label" :name="key" style="margin-bottom: 12px">
         <el-card body-class="p-4px! pt-12px!" class="mb-8px!">
         <el-card body-class="p-4px! pt-12px!" class="mb-8px!">
@@ -238,6 +239,7 @@
 
 
 <script setup lang="tsx">
 <script setup lang="tsx">
 import type { ComponentSchema } from '@/lvgl-widgets/type'
 import type { ComponentSchema } from '@/lvgl-widgets/type'
+import type { CollapseModelValue } from 'element-plus'
 
 
 import { computed, defineComponent, nextTick, ref } from 'vue'
 import { computed, defineComponent, nextTick, ref } from 'vue'
 import { get, set } from 'lodash-es'
 import { get, set } from 'lodash-es'
@@ -275,6 +277,7 @@ defineOptions({
 
 
 const emit = defineEmits<{
 const emit = defineEmits<{
   changeStateStyle: [field: string, type: 'add' | 'delete']
   changeStateStyle: [field: string, type: 'add' | 'delete']
+  changeCollapse: [value: CollapseModelValue]
 }>()
 }>()
 
 
 const props = defineProps<{
 const props = defineProps<{

+ 30 - 21
src/renderer/src/views/designer/config/property/index.vue

@@ -8,13 +8,16 @@
       :model="projectStore.activeWidget"
       :model="projectStore.activeWidget"
     >
     >
       <el-row :gutter="12">
       <el-row :gutter="12">
-        <CusFormItem
+        <template
           v-for="(item, index) in formConfig.props || []"
           v-for="(item, index) in formConfig.props || []"
-          v-show="!item?.hideInForm"
           :key="item.valueType + '_' + index"
           :key="item.valueType + '_' + index"
-          :schema="item"
-          :formData="projectStore.activeWidget!"
-        />
+        >
+          <CusFormItem
+            v-if="!item?.hideInForm"
+            :schema="item"
+            :formData="projectStore.activeWidget!"
+          />
+        </template>
       </el-row>
       </el-row>
     </el-form>
     </el-form>
     <!-- 核心属性 -->
     <!-- 核心属性 -->
@@ -33,14 +36,17 @@
           :model="projectStore.activeWidget"
           :model="projectStore.activeWidget"
         >
         >
           <el-row :gutter="12">
           <el-row :gutter="12">
-            <CusFormItem
+            <template
               v-for="(item, index) in formConfig.coreProps || []"
               v-for="(item, index) in formConfig.coreProps || []"
-              v-show="!item?.hideInForm"
               :key="item.valueType + '_' + index"
               :key="item.valueType + '_' + index"
-              :schema="item"
-              :formData="projectStore.activeWidget!"
-              :widgetData="projectStore.activeWidget!"
-            />
+            >
+              <CusFormItem
+                v-if="!item?.hideInForm"
+                :schema="item"
+                :formData="projectStore.activeWidget!"
+                :widgetData="projectStore.activeWidget!"
+              />
+            </template>
           </el-row>
           </el-row>
         </el-form>
         </el-form>
       </el-collapse-item>
       </el-collapse-item>
@@ -87,18 +93,21 @@
           </el-form-item>
           </el-form-item>
 
 
           <el-row :gutter="12" v-show="part.expandStyle">
           <el-row :gutter="12" v-show="part.expandStyle">
-            <CusFormItem
+            <template
               v-for="(item, index) in formConfig.styles || []"
               v-for="(item, index) in formConfig.styles || []"
-              v-show="!item?.hideInForm"
               :key="item.valueType + '_' + index"
               :key="item.valueType + '_' + index"
-              :schema="item"
-              :formData="{
-                part,
-                ...styleFormData
-              }"
-              :widgetData="projectStore.activeWidget!"
-              @change-state-style="onChangeStateStyle"
-            />
+            >
+              <CusFormItem
+                v-if="!item?.hideInForm"
+                :schema="item"
+                :formData="{
+                  part,
+                  ...styleFormData
+                }"
+                :widgetData="projectStore.activeWidget!"
+                @change-state-style="onChangeStateStyle"
+              />
+            </template>
           </el-row>
           </el-row>
         </el-form>
         </el-form>
       </el-collapse-item>
       </el-collapse-item>

+ 1 - 0
src/renderer/src/views/designer/sidebar/Schema.vue

@@ -7,6 +7,7 @@
         value-format="json"
         value-format="json"
         :config="{ minimap: { enabled: true } }"
         :config="{ minimap: { enabled: true } }"
         :allow-fullscreen="false"
         :allow-fullscreen="false"
+        read-only
       />
       />
     </div>
     </div>
   </div>
   </div>

+ 28 - 3
src/renderer/src/views/designer/workspace/composite/eventEdit/ActionNode.vue

@@ -1,6 +1,9 @@
 <template>
 <template>
   <div class="min-h-32px bg-#4EB2BF rounded-4px flex items-start pr-4px">
   <div class="min-h-32px bg-#4EB2BF rounded-4px flex items-start pr-4px">
-    <div class="w-160px text-#fff grid place-items-center shrink-0 py-8px text-center">
+    <div
+      class="w-160px text-#fff grid place-items-center shrink-0 py-8px text-center"
+      v-if="!actionSchemas.length"
+    >
       {{ node.name }}
       {{ node.name }}
     </div>
     </div>
 
 
@@ -16,14 +19,15 @@
         </el-select>
         </el-select>
       </div>
       </div>
 
 
-      <div v-else-if="actionSchemas.length" class="pr-8px w-300px">
-        <el-form :model="formData" label-position="top">
+      <div v-else-if="actionSchemas.length" class="p-8px w-300px">
+        <el-form :model="formData" label-position="left">
           <CusFormItem
           <CusFormItem
             v-for="item in actionSchemas"
             v-for="item in actionSchemas"
             :key="item.field || item.label"
             :key="item.field || item.label"
             :schema="item"
             :schema="item"
             :form-data="formData"
             :form-data="formData"
             @change-state-style="handleStateStyleChange"
             @change-state-style="handleStateStyleChange"
+            @change-collapse="handleReRender"
           />
           />
         </el-form>
         </el-form>
       </div>
       </div>
@@ -51,6 +55,7 @@ import { LuTrash2 } from 'vue-icons-plus/lu'
 import { useProjectStore } from '@/store/modules/project'
 import { useProjectStore } from '@/store/modules/project'
 import CusFormItem from '@/views/designer/config/property/CusFormItem.vue'
 import CusFormItem from '@/views/designer/config/property/CusFormItem.vue'
 import { resolveActionDescriptor } from './config'
 import { resolveActionDescriptor } from './config'
+import MindMap from 'simple-mind-map'
 
 
 const emit = defineEmits<{
 const emit = defineEmits<{
   (e: 'delete', id: string): void
   (e: 'delete', id: string): void
@@ -59,6 +64,8 @@ const emit = defineEmits<{
 
 
 const props = defineProps<{
 const props = defineProps<{
   node: NodeItemType
   node: NodeItemType
+  mindMap?: MindMap
+  mindMapNode: any
 }>()
 }>()
 
 
 const projectStore = useProjectStore()
 const projectStore = useProjectStore()
@@ -99,6 +106,18 @@ const methodValue = computed({
   }
   }
 })
 })
 
 
+const handleReRender = () => {
+  setTimeout(() => {
+    const changed = props.mindMapNode?.reRender?.([], {
+      force: true
+    })
+
+    if (changed) {
+      props.mindMap?.render(() => {})
+    }
+  }, 0)
+}
+
 watch(
 watch(
   () => props.node.value,
   () => props.node.value,
   (val) => {
   (val) => {
@@ -154,3 +173,9 @@ const handleStateStyleChange = (_field: string, type: 'add' | 'delete') => {
   }
   }
 }
 }
 </script>
 </script>
+
+<style lang="less" scoped>
+:deep(.el-form-item__label) {
+  color: #fff;
+}
+</style>

+ 5 - 0
src/renderer/src/views/designer/workspace/composite/eventEdit/NodeItem.vue

@@ -68,6 +68,8 @@
   <ActionNode
   <ActionNode
     v-else-if="node.nodeType === 'action'"
     v-else-if="node.nodeType === 'action'"
     :node="node"
     :node="node"
+    :mindMap="mindMap"
+    :mindMapNode="mindMapNode"
     @delete="() => emit('delete', node.id)"
     @delete="() => emit('delete', node.id)"
     @update="(val) => emit('change', val)"
     @update="(val) => emit('change', val)"
   />
   />
@@ -92,6 +94,7 @@ import {
   isBuiltinTarget
   isBuiltinTarget
 } from './config'
 } from './config'
 import { useProjectStore } from '@/store/modules/project'
 import { useProjectStore } from '@/store/modules/project'
+import MindMap from 'simple-mind-map'
 
 
 const emit = defineEmits<{
 const emit = defineEmits<{
   (e: 'add', parentId: string, parentType: string, value: OptionType[]): void
   (e: 'add', parentId: string, parentType: string, value: OptionType[]): void
@@ -101,6 +104,8 @@ const emit = defineEmits<{
 
 
 const props = defineProps<{
 const props = defineProps<{
   node: NodeItemType
   node: NodeItemType
+  mindMap?: MindMap
+  mindMapNode?: any
 }>()
 }>()
 
 
 const projectStore = useProjectStore()
 const projectStore = useProjectStore()

+ 183 - 11
src/renderer/src/views/designer/workspace/composite/eventEdit/config.ts

@@ -7,7 +7,7 @@ import type {
 } from '@/types/event'
 } from '@/types/event'
 import type { OptionType } from './type'
 import type { OptionType } from './type'
 
 
-import { get } from 'lodash-es'
+import { get, set } from 'lodash-es'
 import { klona } from 'klona'
 import { klona } from 'klona'
 import { bfsWalk } from 'simple-mind-map/src/utils'
 import { bfsWalk } from 'simple-mind-map/src/utils'
 
 
@@ -839,9 +839,117 @@ function createSchemaDefaultValue(defaultRoot: any, schema: ComponentSchema) {
     if (currentValue !== undefined) return klona(currentValue)
     if (currentValue !== undefined) return klona(currentValue)
   }
   }
 
 
+  if (schema.valueType === 'group') {
+    return createGroupDefaultValue(defaultRoot, schema)
+  }
+
   return createDefaultValue(schema)
   return createDefaultValue(schema)
 }
 }
 
 
+function splitFieldPath(field?: string): string[] {
+  return String(field || '')
+    .split('.')
+    .map((item) => item.trim())
+    .filter(Boolean)
+}
+
+function joinFieldPath(paths: string[]): string {
+  return paths.filter(Boolean).join('.')
+}
+
+function getCommonFieldPrefix(fields: string[]): string[] {
+  const pathList = fields.map((item) => splitFieldPath(item)).filter((item) => item.length)
+  if (!pathList.length) return []
+
+  const [firstPath, ...restPaths] = pathList
+  let length = firstPath.length
+
+  restPaths.forEach((paths) => {
+    length = Math.min(length, paths.length)
+    for (let i = 0; i < length; i += 1) {
+      if (firstPath[i] !== paths[i]) {
+        length = i
+        break
+      }
+    }
+  })
+
+  return firstPath.slice(0, length)
+}
+
+function collectSchemaFields(schema?: ComponentSchema): string[] {
+  if (!schema) return []
+
+  const fields: string[] = []
+  if (schema.field) fields.push(schema.field)
+  ;(schema.children || []).forEach((child) => {
+    fields.push(...collectSchemaFields(child))
+  })
+
+  return fields
+}
+
+function getSchemaSourceBase(schema: ComponentSchema): string[] {
+  if (schema.field) return splitFieldPath(schema.field)
+  return getCommonFieldPrefix(collectSchemaFields(schema))
+}
+
+function getRelativeFieldPath(field: string | undefined, sourceBase: string[]): string[] {
+  const fieldPaths = splitFieldPath(field)
+  if (!sourceBase.length) return fieldPaths
+
+  const isSourceBaseMatched = sourceBase.every((item, index) => fieldPaths[index] === item)
+  return isSourceBaseMatched ? fieldPaths.slice(sourceBase.length) : fieldPaths
+}
+
+function getActionField(
+  field: string | undefined,
+  targetField: string,
+  sourceBase: string[]
+): string {
+  return joinFieldPath([targetField, ...getRelativeFieldPath(field, sourceBase)]) || targetField
+}
+
+function createGroupDefaultValue(defaultRoot: any, schema: ComponentSchema): Record<string, any> {
+  const result: Record<string, any> = {}
+  const sourceBase = getSchemaSourceBase(schema)
+
+  const appendValue = (item?: EventSettableSchema) => {
+    if (!item) return
+
+    if (item.valueType === 'dependency' && typeof item.dependency === 'function') {
+      const dependencySchemas = item.dependency(buildDependencyValues(item.name, defaultRoot))
+      const schemaList = Array.isArray(dependencySchemas) ? dependencySchemas : [dependencySchemas]
+      schemaList.forEach((schemaItem) => appendValue(schemaItem as EventSettableSchema))
+      return
+    }
+
+    if (item.valueType === 'group') {
+      const groupValue = createSchemaDefaultValue(defaultRoot, item)
+      const groupPath = item.field ? getRelativeFieldPath(item.field, sourceBase) : []
+
+      if (!groupPath.length) {
+        Object.assign(result, groupValue)
+        return
+      }
+
+      set(result, joinFieldPath(groupPath), groupValue)
+      return
+    }
+
+    if (!item.field) return
+
+    const nextValue = createSchemaDefaultValue(defaultRoot, item)
+    const targetPath = getRelativeFieldPath(item.field, sourceBase)
+
+    if (!targetPath.length) return
+    set(result, joinFieldPath(targetPath), nextValue)
+  }
+
+  ;(schema.children || []).forEach((item) => appendValue(item as EventSettableSchema))
+  return result
+}
+
 function cloneActionSchema(schema: ComponentSchema, targetField = 'payload'): ComponentSchema {
 function cloneActionSchema(schema: ComponentSchema, targetField = 'payload'): ComponentSchema {
   const cloned = klona(schema)
   const cloned = klona(schema)
   cloned.field = targetField
   cloned.field = targetField
@@ -859,18 +967,75 @@ function buildDependencyValues(names: string[] = [], defaultRoot: any) {
   }, {})
   }, {})
 }
 }
 
 
-function flattenEventSettableSchemas(
+function cloneEventActionSchema(
+  schema: ComponentSchema,
+  targetField = 'payload',
+  sourceBase = getSchemaSourceBase(schema)
+): ComponentSchema {
+  const rewriteSchema = (item: ComponentSchema): ComponentSchema => {
+    const cloned = klona(item)
+
+    if (cloned.field) {
+      cloned.field = getActionField(cloned.field, targetField, sourceBase)
+    }
+
+    if (cloned.valueType === 'dependency') {
+      const dependencySchema = cloned as EventSettableSchema
+      if (Array.isArray(dependencySchema.name)) {
+        dependencySchema.name = dependencySchema.name.map((name) =>
+          getActionField(name, targetField, sourceBase)
+        )
+      }
+    }
+
+    if (cloned.children?.length) {
+      cloned.children = cloned.children.map((child) => rewriteSchema(child))
+    }
+
+    if (cloned.componentProps?.defaultCollapsed) {
+      cloned.componentProps.defaultCollapsed = false
+    }
+
+    return cloned
+  }
+
+  return rewriteSchema(schema)
+}
+
+function flattenEventActionSchemas(
   items: EventSettableSchema[] = [],
   items: EventSettableSchema[] = [],
-  defaultRoot: any
+  defaultRoot: any,
+  pathTokens: string[] = []
 ): SchemaActionDescriptor[] {
 ): SchemaActionDescriptor[] {
   const result: SchemaActionDescriptor[] = []
   const result: SchemaActionDescriptor[] = []
 
 
-  items.forEach((item) => {
+  items.forEach((item, index) => {
     if (!item) return
     if (!item) return
 
 
+    const nextPathTokens = [
+      ...pathTokens,
+      `${item.field || getSchemaLabel(item) || 'item'}_${index}`
+    ]
+
     if (item.valueType === 'group') {
     if (item.valueType === 'group') {
+      if (item.canUseEventSet === true) {
+        result.push({
+          actionKey: item.field || `group.${nextPathTokens.join('.')}`,
+          label: getSchemaLabel(item),
+          groupKey: 'property',
+          groupLabel: 'Property',
+          groupOrder: 1,
+          schemas: [cloneEventActionSchema(item)],
+          defaultValue: createSchemaDefaultValue(defaultRoot, item)
+        })
+      }
+
       result.push(
       result.push(
-        ...flattenEventSettableSchemas((item.children || []) as EventSettableSchema[], defaultRoot)
+        ...flattenEventActionSchemas(
+          (item.children || []) as EventSettableSchema[],
+          defaultRoot,
+          nextPathTokens
+        )
       )
       )
       return
       return
     }
     }
@@ -878,7 +1043,13 @@ function flattenEventSettableSchemas(
     if (item.valueType === 'dependency' && typeof item.dependency === 'function') {
     if (item.valueType === 'dependency' && typeof item.dependency === 'function') {
       const dependencySchemas = item.dependency(buildDependencyValues(item.name, defaultRoot))
       const dependencySchemas = item.dependency(buildDependencyValues(item.name, defaultRoot))
       const schemaList = Array.isArray(dependencySchemas) ? dependencySchemas : [dependencySchemas]
       const schemaList = Array.isArray(dependencySchemas) ? dependencySchemas : [dependencySchemas]
-      result.push(...flattenEventSettableSchemas(schemaList as EventSettableSchema[], defaultRoot))
+      result.push(
+        ...flattenEventActionSchemas(
+          schemaList as EventSettableSchema[],
+          defaultRoot,
+          nextPathTokens
+        )
+      )
       return
       return
     }
     }
 
 
@@ -889,9 +1060,9 @@ function flattenEventSettableSchemas(
       actionKey: item.field!,
       actionKey: item.field!,
       label: getSchemaLabel(item),
       label: getSchemaLabel(item),
       groupKey: 'property',
       groupKey: 'property',
-      groupLabel: '属性',
+      groupLabel: 'Property',
       groupOrder: 1,
       groupOrder: 1,
-      schemas: [cloneActionSchema(item)],
+      schemas: [cloneEventActionSchema(item)],
       defaultValue: createSchemaDefaultValue(defaultRoot, item)
       defaultValue: createSchemaDefaultValue(defaultRoot, item)
     })
     })
   })
   })
@@ -954,11 +1125,11 @@ function getSchemaActionDescriptors(targetData?: WidgetEventTargetData): SchemaA
   if (!model) return []
   if (!model) return []
 
 
   return [
   return [
-    ...flattenEventSettableSchemas(
+    ...flattenEventActionSchemas(
       (model.config.props || []) as EventSettableSchema[],
       (model.config.props || []) as EventSettableSchema[],
       model.defaultSchema
       model.defaultSchema
     ),
     ),
-    ...flattenEventSettableSchemas(
+    ...flattenEventActionSchemas(
       (model.config.coreProps || []) as EventSettableSchema[],
       (model.config.coreProps || []) as EventSettableSchema[],
       model.defaultSchema
       model.defaultSchema
     ),
     ),
@@ -1234,10 +1405,11 @@ export function getTargetOptions(project?: IProject): OptionType[] {
 
 
       bfsWalk(page, (child) => {
       bfsWalk(page, (child) => {
         if (child.id === page.id) return
         if (child.id === page.id) return
+        if (!child.id) return
 
 
         options.push({
         options.push({
           label: `[${screen.name}] [${page.name}] ${child.name}`,
           label: `[${screen.name}] [${page.name}] ${child.name}`,
-          value: `widget:${child.id}`,
+          value: `${child.id}`,
           data: {
           data: {
             kind: 'widget',
             kind: 'widget',
             pageId: page.id,
             pageId: page.id,

+ 3 - 1
src/renderer/src/views/designer/workspace/composite/eventEdit/index.vue

@@ -29,7 +29,7 @@ import { getActionOptions, getBuiltinActionData, isBuiltinTarget } from './confi
 
 
 const containerRef = ref<HTMLElement | null>(null)
 const containerRef = ref<HTMLElement | null>(null)
 const { width, height } = useElementSize(containerRef)
 const { width, height } = useElementSize(containerRef)
-const mindMap = ref<MindMap | null>(null)
+const mindMap = ref<MindMap>()
 const mindMapData = ref<NodeItemType>()
 const mindMapData = ref<NodeItemType>()
 
 
 const projectStore = useProjectStore()
 const projectStore = useProjectStore()
@@ -439,9 +439,11 @@ watchOnce(
             return (
             return (
               <NodeItem
               <NodeItem
                 node={sourceData}
                 node={sourceData}
+                mindMapNode={node}
                 onAdd={handleAddNode}
                 onAdd={handleAddNode}
                 onDelete={handleDeleteNode}
                 onDelete={handleDeleteNode}
                 onChange={handleChangeNode}
                 onChange={handleChangeNode}
+                mindMap={mindMap.value}
               />
               />
             )
             )
           }
           }