Browse Source

feat: 添加变量/动画/多语言属性面板

Mickey Mike 1 day ago
parent
commit
297d71edb3

+ 4 - 0
src/renderer/components.d.ts

@@ -48,6 +48,7 @@ declare module 'vue' {
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElOption: typeof import('element-plus/es')['ElOption']
+    ElOptiop: typeof import('element-plus/es')['ElOptiop']
     ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm']
     ElPopover: typeof import('element-plus/es')['ElPopover']
     ElRadio: typeof import('element-plus/es')['ElRadio']
@@ -65,6 +66,7 @@ declare module 'vue' {
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabPanel: typeof import('element-plus/es')['ElTabPanel']
     ElTabs: typeof import('element-plus/es')['ElTabs']
+    ElTextarea: typeof import('element-plus/es')['ElTextarea']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElTree: typeof import('element-plus/es')['ElTree']
     LocalImage: typeof import('./src/components/LocalImage/index.vue')['default']
@@ -119,6 +121,7 @@ declare global {
   const ElMenu: typeof import('element-plus/es')['ElMenu']
   const ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
   const ElOption: typeof import('element-plus/es')['ElOption']
+  const ElOptiop: typeof import('element-plus/es')['ElOptiop']
   const ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm']
   const ElPopover: typeof import('element-plus/es')['ElPopover']
   const ElRadio: typeof import('element-plus/es')['ElRadio']
@@ -136,6 +139,7 @@ declare global {
   const ElTabPane: typeof import('element-plus/es')['ElTabPane']
   const ElTabPanel: typeof import('element-plus/es')['ElTabPanel']
   const ElTabs: typeof import('element-plus/es')['ElTabs']
+  const ElTextarea: typeof import('element-plus/es')['ElTextarea']
   const ElTooltip: typeof import('element-plus/es')['ElTooltip']
   const ElTree: typeof import('element-plus/es')['ElTree']
   const LocalImage: typeof import('./src/components/LocalImage/index.vue')['default']

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

@@ -77,3 +77,72 @@ export const variableType = [
   { label: 'OBJECT', value: 'LV_OBJECT' },
   { label: 'BYTE_ARRAY', value: 'LV_BYTE_ARRAY' }
 ]
+
+/**
+ * 动画目标属性
+ */
+export const animationTargets = [
+  { label: '透明度', value: 'opacity' },
+  { label: 'X轴移动', value: 'translateX' },
+  { label: 'Y轴移动', value: 'translateY' },
+  { label: 'Z轴移动', value: 'translateZ' },
+  { label: '缩放', value: 'scale' },
+  { label: 'X轴缩放', value: 'scaleX' },
+  { label: 'Y轴缩放', value: 'scaleY' },
+  { label: 'Z轴缩放', value: 'scaleZ' },
+  { label: '旋转', value: 'rotate' },
+  { label: 'X轴旋转', value: 'rotateX' },
+  { label: 'Y轴旋转', value: 'rotateY' },
+  { label: 'Z轴旋转', value: 'rotateZ' },
+  { label: 'X轴倾斜', value: 'skewX' },
+  { label: 'Y轴倾斜', value: 'skewY' },
+  { label: '宽度', value: 'width' },
+  { label: '高度', value: 'height' },
+  { label: '背景颜色', value: 'backgroundColor' },
+  { label: '字体颜色', value: 'color' },
+  { label: '圆角', value: 'borderRadius' }
+]
+
+/**
+ * 动画缓动函数(Timing Function)
+ */
+export const timingFunctions = [
+  { label: '匀速 linear', value: 'linear' },
+  { label: '缓入 ease', value: 'ease' },
+  { label: '缓入 ease-in', value: 'ease-in' },
+  { label: '缓出 ease-out', value: 'ease-out' },
+  { label: '缓入缓出 ease-in-out', value: 'ease-in-out' },
+  { label: 'step-start', value: 'step-start' },
+  { label: 'step-end', value: 'step-end' },
+  { label: 'steps', value: 'steps' },
+  { label: '自定义贝塞尔 cubic-bezier', value: 'cubic-bezier' }
+]
+
+/**
+ * 动画次数
+ */
+export const iterationCounts = [
+  { label: '1 次', value: 1 },
+  { label: '2 次', value: 2 },
+  { label: '3 次', value: 3 },
+  { label: '4 次', value: 4 },
+  { label: '5 次', value: 5 },
+  { label: '无限循环', value: 'infinite' }
+]
+
+/**
+ * 预设多语言类型
+ */
+
+export const languagesMenu = [
+  { label: '中文(简体)', value: 'zh-CN' },
+  { label: '中文(繁体)', value: 'zh-TW' },
+  { label: '英文(美国)', value: 'en-US' },
+  { label: '英文(英国)', value: 'en-GB' },
+  { label: '日文', value: 'ja-JP' },
+  { label: '韩语', value: 'ko-KR' },
+  { label: '法语', value: 'fr-FR' },
+  { label: '德语', value: 'de-DE' },
+  { label: '西班牙语', value: 'es-ES' },
+  { label: '俄语', value: 'ru-RU' }
+]

+ 1 - 0
src/renderer/src/types/animation.d.ts

@@ -16,6 +16,7 @@ export type AnimationTimeline = {
 }
 
 export type Animation = {
+  id: string
   // 动画名称
   name: string
   // 动画时间线

+ 11 - 0
src/renderer/src/types/languages.d.ts

@@ -0,0 +1,11 @@
+export type languages = {
+  language: string
+  value: string
+  font: string
+}
+
+export type LanguagesGroup = {
+  id: string
+  key: string
+  values: languages[]
+}

+ 213 - 0
src/renderer/src/views/designer/config/AnimationConfig.vue

@@ -0,0 +1,213 @@
+<template>
+  <el-scrollbar :height="'calc(100vh - 198px)'" class="config pr-10px pl-10px">
+    <el-form label-position="top">
+      <div class="title flex justify-between items-center h-28px mb-10px">
+        <span class="text-14px">设置动画</span>
+        <el-icon class="cursor-pointer" @click.stop="addAnimation">
+          <Plus />
+        </el-icon>
+      </div>
+      <div v-for="item in data" :key="item.id">
+        <el-collapse v-model="activeNames">
+          <el-collapse-item :name="item.id">
+            <template #title>
+              <div class="collapse-title">
+                <el-icon class="arrow" :class="{ active: activeNames.includes(item.id) }">
+                  <ArrowRight />
+                </el-icon>
+
+                <span class="title-text">动画 - {{ item.name }}</span>
+
+                <el-icon @click.stop="handleAnimationRemove(item)">
+                  <Delete />
+                </el-icon>
+              </div>
+            </template>
+            <el-input v-model="item.name" placeholder="动画名称" class="mt-10px" />
+            <div v-for="(animationItem, index) in item.timeline" :key="index" class="mb-20px">
+              <div class="mt-10px mb-10px">动画属性</div>
+              <div
+                class="flex flex-wrap gap-10px mb-10px pb-20px"
+                style="border-bottom: 1px solid var(--el-border-color-lighter)"
+              >
+                <el-input-number
+                  v-model="animationItem.start"
+                  placeholder="开始值"
+                  :step="0.1"
+                  :min="0"
+                  style="flex: 0 0 calc(50% - 5px)"
+                />
+                <el-input-number
+                  v-model="animationItem.end"
+                  placeholder="结束值"
+                  :step="0.1"
+                  :min="0"
+                  style="flex: 0 0 calc(50% - 5px)"
+                />
+                <el-input-number
+                  v-model="animationItem.duration"
+                  placeholder="动画时间"
+                  :step="0.1"
+                  :min="0"
+                  style="flex: 0 0 calc(50% - 5px)"
+                />
+                <el-input-number
+                  v-model="animationItem.delay"
+                  placeholder="延迟时间"
+                  :step="0.1"
+                  :min="0"
+                  style="flex: 0 0 calc(50% - 5px)"
+                />
+                <el-select
+                  v-model="animationItem.timingFunction"
+                  placeholder="动画效果"
+                  style="flex: 0 0 calc(50% - 5px)"
+                >
+                  <el-option
+                    v-for="timing in timingFunctions"
+                    :key="timing.value"
+                    :value="timing.value"
+                    :label="timing.label"
+                  />
+                </el-select>
+                <el-select
+                  v-model="animationItem.iterationCount"
+                  placeholder="循环次数"
+                  style="flex: 0 0 calc(50% - 5px)"
+                >
+                  <el-option
+                    v-for="iteration in iterationCounts"
+                    :key="iteration.value"
+                    :value="iteration.value"
+                    :label="iteration.label"
+                  />
+                </el-select>
+              </div>
+              <div class="flex justify-between items-center gap-10px">
+                <el-select v-model="animationItem.target" placeholder="目标属性">
+                  <el-option
+                    v-for="target in animationTargets"
+                    :key="target.value"
+                    :value="target.value"
+                    :label="target.label"
+                  />
+                </el-select>
+                <el-button
+                  v-if="index !== item.timeline.length - 1"
+                  type="info"
+                  style="flex: 0 0 calc(50% - 5px)"
+                  @click="handletTimingFunction(item.timeline, 'delete', animationItem)"
+                  >删除</el-button
+                >
+                <el-button
+                  v-if="index === item.timeline.length - 1"
+                  type="primary"
+                  style="flex: 0 0 calc(50% - 5px)"
+                  @click="handletTimingFunction(item.timeline, 'add', '')"
+                  >添加</el-button
+                >
+              </div>
+            </div>
+            <el-button
+              v-if="!item.timeline.length"
+              type="primary"
+              style="width: 100%; margin-top: 10px"
+              @click="handletTimingFunction(item.timeline, 'add', '')"
+              >添加</el-button
+            >
+          </el-collapse-item>
+        </el-collapse>
+      </div>
+    </el-form>
+  </el-scrollbar>
+</template>
+
+<script setup lang="ts">
+import { ref, watch, defineEmits } from 'vue'
+import type { Animation } from '@/types/animation'
+import { ArrowRight, Plus, Delete } from '@element-plus/icons-vue'
+import { ElMessageBox } from 'element-plus'
+import { animationTargets, timingFunctions, iterationCounts } from '@/constants'
+import { v4 } from 'uuid'
+interface Emits {
+  (e: 'update:animation', val: Animation[]): void
+}
+const emit = defineEmits<Emits>()
+const props = defineProps<{
+  animation?: Animation[]
+}>()
+const activeNames = ref<string[]>([])
+const data = ref<Animation[]>(props.animation || ({} as Animation[]))
+watch(data, (val) => emit('update:animation', val))
+
+const addAnimation = () => {
+  data.value.push({
+    id: v4(),
+    name: '',
+    timeline: []
+  })
+}
+
+const handleAnimationRemove = (animation) => {
+  ElMessageBox.confirm('确定删除?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    const index = data.value.findIndex((item) => item.id === animation.id)
+    if (index !== -1) {
+      data.value.splice(index, 1)
+    }
+  })
+}
+
+const handletTimingFunction = (timeline, name, animationItem) => {
+  if (name === 'add') {
+    timeline.push({
+      target: '',
+      start: 0,
+      end: 0,
+      delay: 0,
+      duration: 0,
+      timingFunction: '',
+      iterationCount: 0
+    })
+  } else {
+    const index = timeline.findIndex((item) => item.id === animationItem.id)
+    if (index !== -1) {
+      timeline.splice(index, 1)
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+:deep(.el-form-item) {
+  margin-bottom: 5px;
+}
+:deep(.el-collapse-item__header) {
+  padding-right: 0px;
+}
+:deep(.el-collapse-item__arrow) {
+  display: none;
+}
+.collapse-title {
+  display: flex;
+  align-items: center;
+  width: 100%;
+}
+
+.arrow {
+  margin-right: 8px;
+  transition: transform 0.2s;
+}
+
+.arrow.active {
+  transform: rotate(90deg);
+}
+
+.title-text {
+  flex: 1;
+  font-weight: 500;
+}
+</style>

+ 140 - 0
src/renderer/src/views/designer/config/LanguagesConfig.vue

@@ -0,0 +1,140 @@
+<template>
+  <el-scrollbar :height="'calc(100vh - 198px)'" class="config pr-10px pl-10px">
+    <el-form label-position="top">
+      <div class="title flex justify-between items-center h-28px mb-10px">
+        <span class="text-14px">设置语言</span>
+        <el-icon class="cursor-pointer" @click="handleAdd">
+          <Plus />
+        </el-icon>
+      </div>
+      <div v-for="item in data" :key="item.id">
+        <el-collapse v-model="activeNames">
+          <el-collapse-item :name="item.id">
+            <template #title>
+              <div class="collapse-title">
+                <el-icon class="arrow" :class="{ active: activeNames.includes(item.id) }">
+                  <ArrowRight />
+                </el-icon>
+
+                <span class="title-text">{{ item.key }}</span>
+
+                <el-icon @click.stop="handleRemoveGroup(item)">
+                  <Delete />
+                </el-icon>
+              </div>
+            </template>
+            <el-input v-model="item.key" class="mt-10px mb-10px" placeholder="语言表示" />
+            <div v-for="(languagesItem, index) in item.values" :key="index" class="mb-10px">
+              <div class="flex flex-wrap gap-5px items-center">
+                <el-select v-model="languagesItem.language" style="flex: 1">
+                  <el-option
+                    v-for="menu in languagesMenu"
+                    :key="menu.value"
+                    :value="menu.value"
+                    :label="menu.label"
+                  />
+                </el-select>
+                <el-input v-model="languagesItem.value" style="flex: 1" />
+                <el-select v-model="languagesItem.font" style="flex: 1" placeholder="字体">
+                </el-select>
+                <el-icon
+                  class="cursor-pointer"
+                  @click.stop="handleRemoveItem(item.values, languagesItem)"
+                >
+                  <Delete />
+                </el-icon>
+              </div>
+            </div>
+            <el-icon class="cursor-pointer" @click="handleAddlanguagesValues(item.values)">
+              <Plus />
+            </el-icon>
+          </el-collapse-item>
+        </el-collapse>
+      </div>
+    </el-form>
+  </el-scrollbar>
+</template>
+
+<script setup lang="ts">
+import { ref, watch, defineEmits } from 'vue'
+import type { LanguagesGroup } from '@/types/languages'
+import { ArrowRight, Plus, Delete } from '@element-plus/icons-vue'
+import { ElMessageBox } from 'element-plus'
+import { languagesMenu } from '@/constants'
+import { v4 } from 'uuid'
+interface Emits {
+  (e: 'update:languages', val: LanguagesGroup[]): void
+}
+const emit = defineEmits<Emits>()
+const props = defineProps<{
+  languages?: LanguagesGroup[]
+}>()
+const activeNames = ref<string[]>([])
+const data = ref<LanguagesGroup[]>(props.languages || ({} as LanguagesGroup[]))
+watch(data, (val) => emit('update:languages', val))
+
+const handleAddlanguagesValues = (values) => {
+  values.push({
+    language: '',
+    value: '',
+    font: ''
+  })
+}
+
+const handleRemoveItem = (languages, languagesItem) => {
+  const index = languages.findIndex((item) => item.value === languagesItem.value)
+  if (index !== -1) {
+    languages.splice(index, 1)
+  }
+}
+
+const handleRemoveGroup = (languages) =>
+  ElMessageBox.confirm('确定删除?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    const index = data.value.findIndex((item) => item.id === languages.id)
+    if (index !== -1) {
+      data.value.splice(index, 1)
+    }
+  })
+const handleAdd = () => {
+  data.value.push({
+    id: v4(),
+    key: '',
+    values: []
+  })
+}
+</script>
+
+<style lang="less" scoped>
+:deep(.el-form-item) {
+  margin-bottom: 5px;
+}
+:deep(.el-collapse-item__header) {
+  padding-right: 0px;
+}
+:deep(.el-collapse-item__arrow) {
+  display: none;
+}
+.collapse-title {
+  display: flex;
+  align-items: center;
+  width: 100%;
+}
+
+.arrow {
+  margin-right: 8px;
+  transition: transform 0.2s;
+}
+
+.arrow.active {
+  transform: rotate(90deg);
+}
+
+.title-text {
+  flex: 1;
+  font-weight: 500;
+}
+</style>

+ 138 - 2
src/renderer/src/views/designer/config/VariableConfig.vue

@@ -1,18 +1,132 @@
 <template>
   <el-scrollbar :height="'calc(100vh - 198px)'" class="config pr-10px pl-10px">
-    <el-form label-position="top"> </el-form>
+    <el-form label-position="top">
+      <el-collapse v-for="(item, index) in data" :key="item.id" v-model="activeNames">
+        <el-button
+          v-if="index === 1 && !visibleGroupName"
+          type="primary"
+          class="mt-10px mb-10px"
+          @click="visibleGroupName = !visibleGroupName"
+        >
+          添加局部变量组
+        </el-button>
+        <el-input
+          v-if="index === 1 && visibleGroupName"
+          v-model="variableGroupName"
+          placeholder="请输入组名并回车创建"
+          class="mt-10px mb-10px"
+          @keyup.enter="handleGroup"
+        />
+        <el-collapse-item :name="item.name">
+          <template #title>
+            <div class="collapse-title">
+              <el-icon class="arrow" :class="{ active: activeNames.includes(item.name) }">
+                <ArrowRight />
+              </el-icon>
+
+              <span class="title-text">{{ item.name }}</span>
+
+              <el-icon class="mr-10px" @click.stop="addVariables(item.variables)">
+                <Plus />
+              </el-icon>
+              <el-icon @click.stop="removeVariables(item)">
+                <Delete />
+              </el-icon>
+            </div>
+          </template>
+          <div class="p-10px">
+            <!-- 头部描述 -->
+            <div v-for="(element, indexs) in item.variables" :key="element.id" class="mb-10px">
+              <div class="flex justify-between items-center mb-10px">
+                <span>变量 {{ indexs + 1 }}</span>
+                <el-icon
+                  class="cursor-pointer"
+                  @click="handleVariablesRemove(item.variables, element)"
+                >
+                  <Delete />
+                </el-icon>
+              </div>
+              <div class="flex gap-10px mb-10px">
+                <el-input v-model="element.name" placeholder="变量名称" />
+                <el-select v-model="element.type" placeholder="变量类型">
+                  <el-option
+                    v-for="type in variableType"
+                    :key="type.value"
+                    :label="type.label"
+                    :value="type.value"
+                  />
+                </el-select>
+              </div>
+              <el-input v-model="element.value" type="textarea" :rows="3" placeholder="初始值" />
+            </div>
+          </div>
+        </el-collapse-item>
+      </el-collapse>
+    </el-form>
   </el-scrollbar>
 </template>
 
 <script setup lang="ts">
-import { ref, watch, defineEmits, computed } from 'vue'
+import { ref, watch, defineEmits } from 'vue'
 import type { VariableGroup } from '@/types/variables'
+import { ArrowRight, Plus, Delete } from '@element-plus/icons-vue'
+import { ElMessageBox } from 'element-plus'
+import { variableType } from '@/constants'
+import { v4 } from 'uuid'
 interface Emits {
   (e: 'update:variables', val: VariableGroup[]): void
 }
+const emit = defineEmits<Emits>()
 const props = defineProps<{
   variables?: VariableGroup[]
 }>()
+const data = ref<VariableGroup[]>(props.variables || ({} as VariableGroup[]))
+watch(data, (val) => emit('update:variables', val))
+const activeNames = ref<string[]>([])
+// 输入的局部变量组名称
+const variableGroupName = ref('')
+const visibleGroupName = ref(false)
+
+watch(activeNames.value, (value) => console.log(value))
+
+const addVariables = (variables) => {
+  variables.push({
+    id: v4(),
+    name: '',
+    value: '',
+    type: ''
+  })
+}
+
+const handleVariablesRemove = (variables, element) => {
+  const index = variables.findIndex((item) => item.id === element.id)
+  if (index !== -1) {
+    variables.splice(index, 1)
+  }
+}
+
+const handleGroup = () => {
+  data.value.push({
+    id: v4(),
+    name: variableGroupName.value,
+    variables: []
+  })
+  visibleGroupName.value = !visibleGroupName.value
+  variableGroupName.value = ''
+}
+
+const removeVariables = (variables) => {
+  ElMessageBox.confirm('确定删除?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    const index = data.value.findIndex((item) => item.id === variables.id)
+    if (index !== -1) {
+      data.value.splice(index, 1)
+    }
+  })
+}
 </script>
 
 <style lang="less" scoped>
@@ -22,4 +136,26 @@ const props = defineProps<{
 :deep(.el-collapse-item__header) {
   padding-right: 0px;
 }
+:deep(.el-collapse-item__arrow) {
+  display: none;
+}
+.collapse-title {
+  display: flex;
+  align-items: center;
+  width: 100%;
+}
+
+.arrow {
+  margin-right: 8px;
+  transition: transform 0.2s;
+}
+
+.arrow.active {
+  transform: rotate(90deg);
+}
+
+.title-text {
+  flex: 1;
+  font-weight: 500;
+}
 </style>

+ 120 - 51
src/renderer/src/views/designer/config/index.vue

@@ -2,13 +2,17 @@
   <div>
     <el-tabs size="small">
       <el-tab-pane label="属性">
-        <property-config v-model:selected="data" />
+        <property-config v-model:selected="data.childer[0]" />
       </el-tab-pane>
       <el-tab-pane label="变量">
         <variable-config v-model:variables="data.variables" />
       </el-tab-pane>
-      <el-tab-pane label="动画"></el-tab-pane>
-      <el-tab-pane label="多语言"></el-tab-pane>
+      <el-tab-pane label="动画">
+        <animation-config v-model:animation="data.animation" />
+      </el-tab-pane>
+      <el-tab-pane label="多语言">
+        <languages-config v-model:languages="data.languages" />
+      </el-tab-pane>
       <el-tab-pane label="历史"></el-tab-pane>
     </el-tabs>
   </div>
@@ -18,56 +22,62 @@
 import { ref, watch } from 'vue'
 import PropertyConfig from './PropertyConfig.vue'
 import VariableConfig from './VariableConfig.vue'
+import AnimationConfig from './AnimationConfig.vue'
+import LanguagesConfig from './LanguagesConfig.vue'
 
 const data = ref({
-  name: '对象1',
-  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: {
-    border_radius: 0,
-    bg_color: '#ffffff',
-    bg_opa: 255,
-    gradient: '',
-    shade: 0,
-    tint: 0,
-    gradient_direction: 'none',
-    LV_PART_Image: '',
-    border_color: '#000000',
-    border_opa: 1,
-    border_width: 0,
-    border_style: 'solid',
-    box_shadow_spread: 0,
-    box_shadow: '',
-    box_shadow_blur: 0,
-    box_shadow_color: '#000000',
-    box_shadow_alpha: 1,
-    outline_color: '#ff0000',
-    outline_opa: 1,
-    outline_width: 0,
-    outline_style: 'solid',
-    box_shadow_x: 0,
-    box_shadow_y: 0,
-    boxShadow_color: '',
-    boxShadow_opa: 0,
-    boxShadow_x: 0,
-    boxShadow_y: 0,
-    boxShadow_blur: 0,
-    boxShadow_spread: 0,
-    padding_top: 0,
-    padding_bottom: 0,
-    padding_left: 0,
-    padding_right: 0
-  },
-  styleItems: {},
+  childer: [
+    {
+      name: '对象1',
+      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: {
+        border_radius: 0,
+        bg_color: '#ffffff',
+        bg_opa: 255,
+        gradient: '',
+        shade: 0,
+        tint: 0,
+        gradient_direction: 'none',
+        LV_PART_Image: '',
+        border_color: '#000000',
+        border_opa: 1,
+        border_width: 0,
+        border_style: 'solid',
+        box_shadow_spread: 0,
+        box_shadow: '',
+        box_shadow_blur: 0,
+        box_shadow_color: '#000000',
+        box_shadow_alpha: 1,
+        outline_color: '#ff0000',
+        outline_opa: 1,
+        outline_width: 0,
+        outline_style: 'solid',
+        box_shadow_x: 0,
+        box_shadow_y: 0,
+        boxShadow_color: '',
+        boxShadow_opa: 0,
+        boxShadow_x: 0,
+        boxShadow_y: 0,
+        boxShadow_blur: 0,
+        boxShadow_spread: 0,
+        padding_top: 0,
+        padding_bottom: 0,
+        padding_left: 0,
+        padding_right: 0
+      },
+      styleItems: {}
+    }
+  ],
   events: [
     {
       name: '点击',
@@ -76,6 +86,31 @@ const data = ref({
       type: ''
     }
   ],
+  animation: [
+    {
+      name: 'fade-move',
+      timeline: [
+        {
+          target: 'opacity',
+          start: 0,
+          end: 1,
+          delay: 0,
+          duration: 500,
+          timingFunction: 'ease',
+          iterationCount: 1
+        },
+        {
+          target: 'translateX',
+          start: -50,
+          end: 0,
+          delay: 0,
+          duration: 500,
+          timingFunction: 'ease-out',
+          iterationCount: 1
+        }
+      ]
+    }
+  ],
   variables: [
     // 全局变量组
     {
@@ -87,6 +122,12 @@ const data = ref({
           name: 'pageName',
           value: '',
           type: ''
+        },
+        {
+          id: '2',
+          name: 'pageName1',
+          value: '',
+          type: ''
         }
       ]
     },
@@ -102,6 +143,34 @@ const data = ref({
         }
       ]
     }
+  ],
+  languages: [
+    {
+      id: 'language_1',
+      // 语言表示
+      key: 'hello',
+      // 语言内容
+      values: [
+        {
+          language: 'zh-CN',
+          value: '你好',
+          font: 'font_1'
+        },
+        {
+          language: 'en-US',
+          value: 'hello',
+          font: 'font_1'
+        },
+        {
+          language: 'ja-JP',
+          value: 'こんにちは'
+        },
+        {
+          language: 'ko-KR',
+          value: '안녕하세요'
+        }
+      ]
+    }
   ]
 })