jiaxing.liao недель назад: 3
Родитель
Сommit
a00526188d

+ 2 - 1
src/renderer/src/locales/en_US.json

@@ -101,5 +101,6 @@
   "tileview": "Tileview",
   "table": "Table",
   "list": "List",
-  "layout": "Layout"
+  "layout": "Layout",
+  "messageBox": "MsgBox"
 }

+ 2 - 1
src/renderer/src/locales/zh_CN.json

@@ -101,5 +101,6 @@
   "tileview": "平铺视图",
   "table": "表格",
   "list": "列表",
-  "layout": "布局"
+  "layout": "布局",
+  "messageBox": "消息框"
 }

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

@@ -16,6 +16,7 @@ import Tabview from './tabview/index'
 import Tileview from './tileview/index'
 import Table from './table/index'
 import List from './list/index'
+import MessageBox from './message/index'
 
 import Page from './page'
 import { IComponentModelConfig } from './type'
@@ -40,7 +41,8 @@ export const ComponentArray = [
   Tabview,
   Tileview,
   Table,
-  List
+  List,
+  MessageBox
 ]
 
 const componentMap: { [key: string]: IComponentModelConfig } = ComponentArray.reduce((acc, cur) => {

+ 64 - 0
src/renderer/src/lvgl-widgets/message/Config.vue

@@ -0,0 +1,64 @@
+<template>
+  <el-card class="mb-12px" body-class="p-8px!">
+    <template #header>
+      <div class="flex items-center justify-between">
+        <span>按钮组</span>
+        <LuPlus class="cursor-pointer" size="16px" @click="handleAddRow" />
+      </div>
+    </template>
+    <el-scrollbar max-height="120px">
+      <div
+        class="flex items-center gap-4px box-border pr-12px mb-4px"
+        v-for="(_, index) in children || []"
+        :key="index"
+      >
+        <div class="w-full flex items-center gap-4px relative group/item">
+          <el-input spellcheck="false" v-model="children[index].text" />
+          <div class="cursor-pointer" @click="handleDeleteItem(index)">
+            <LuTrash2 size="14px" />
+          </div>
+        </div>
+      </div>
+    </el-scrollbar>
+  </el-card>
+</template>
+
+<script setup lang="ts">
+import { computed, type Ref } from 'vue'
+import { LuPlus, LuTrash2 } from 'vue-icons-plus/lu'
+
+const props = defineProps<{
+  values: Ref<{ text: string }[]>
+}>()
+
+// 子项
+const children = computed({
+  get() {
+    return props.values?.value || []
+  },
+  set(list: any[]) {
+    if (props.values?.value) {
+      props.values.value = list
+    }
+  }
+})
+
+/**
+ * 删除一项
+ * @param index 索引
+ */
+const handleDeleteItem = (index: number) => {
+  children.value.splice(index, 1)
+}
+
+/**
+ * 添加一项
+ */
+const handleAddRow = () => {
+  children.value?.push({
+    text: 'title'
+  })
+}
+</script>
+
+<style scoped></style>

+ 49 - 0
src/renderer/src/lvgl-widgets/message/MessageBox.vue

@@ -0,0 +1,49 @@
+<template>
+  <div :style="styleMap?.mainStyle" class="overflow-hidden box-broder">
+    <div :style="styleMap?.titleStyle" class="flex items-center justify-between box-broder p-10px">
+      <span>{{ title }}</span>
+      <span
+        class="bg-#2195f6 shadow-[0_4px_0_#cccccc] text-white w-40px h-30px rounded-10px grid place-items-center"
+      >
+        <LuX size="14px" />
+      </span>
+    </div>
+    <div :style="styleMap?.contentStyle" class="box-broder p-10px">{{ content }}</div>
+    <div class="flex items-center justify-around">
+      <div
+        :style="{ ...styleMap?.btnsStyle, width: btnWidth + 'px', height: btnHeight + 'px' }"
+        v-for="(btn, index) in btns"
+        :key="index"
+        class="grid place-items-center shadow-[0_4px_0_#cccccc]"
+      >
+        {{ btn.text }}
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useWidgetStyle } from '../hooks/useWidgetStyle'
+import { LuX } from 'vue-icons-plus/lu'
+
+const props = defineProps<{
+  width: number
+  height: number
+  styles: any
+  state: string
+  part: string
+  title: string
+  content: string
+  closeBtn: boolean
+  btnWidth: number
+  btnHeight: number
+  btns: { text: string }[]
+}>()
+
+const styleMap = useWidgetStyle({
+  widget: 'lv_msgbox',
+  props
+})
+</script>
+
+<style scoped></style>

+ 345 - 0
src/renderer/src/lvgl-widgets/message/index.tsx

@@ -0,0 +1,345 @@
+import MessageBox from './MessageBox.vue'
+import icon from '../assets/icon/icon_17message.svg'
+import { flagOptions } from '@/constants'
+import type { IComponentModelConfig } from '../type'
+import i18n from '@/locales'
+import defaultStyle from './style.json'
+import Config from './Config.vue'
+
+export default {
+  label: i18n.global.t('messageBox'),
+  icon,
+  component: MessageBox,
+  key: 'lv_msgbox',
+  group: i18n.global.t('layout'),
+  sort: 1,
+  hasChildren: false,
+  defaultStyle,
+  parts: [
+    {
+      name: 'main',
+      stateList: ['default']
+    },
+    {
+      name: 'title',
+      stateList: ['default']
+    },
+    {
+      name: 'content',
+      stateList: ['default']
+    },
+    {
+      name: 'btns',
+      stateList: ['default']
+    }
+  ],
+  defaultSchema: {
+    name: 'msgbox',
+    props: {
+      x: 0,
+      y: 0,
+      width: 260,
+      height: 140,
+      addFlags: [],
+      removeFlags: [],
+      title: 'Title',
+      content: 'Content',
+      closeBtn: true,
+      btnWidth: 60,
+      btnHeight: 30,
+      btns: [{ text: 'Apply' }, { text: 'Close' }]
+    },
+    styles: [
+      {
+        part: {
+          name: 'main',
+          state: 'default'
+        },
+        background: {
+          color: '#ffffffff'
+        },
+        border: {
+          color: '#ffffff64',
+          width: 0,
+          radius: 4,
+          side: ['all']
+        },
+        shadow: {
+          color: '#2092f5ff',
+          x: 0,
+          y: 0,
+          spread: 0,
+          width: 0
+        }
+      },
+      {
+        part: {
+          name: 'title',
+          state: 'default'
+        },
+        background: {
+          color: '#ffffffff'
+        },
+        text: {
+          color: '#35383cff',
+          size: 12,
+          weight: 'normal',
+          family: 'xx'
+        },
+        spacer: {
+          letterSpacing: 0,
+          lineHeight: 15
+        }
+      },
+      {
+        part: {
+          name: 'content',
+          state: 'default'
+        },
+        text: {
+          color: '#35383cff',
+          size: 12,
+          weight: 'normal',
+          family: 'xx'
+        },
+        spacer: {
+          letterSpacing: 0,
+          lineHeight: 10
+        }
+      },
+      {
+        part: {
+          name: 'btns',
+          state: 'default'
+        },
+        background: {
+          color: '#e6e6e6ff'
+        },
+        text: {
+          color: '#35383cff',
+          size: 12,
+          weight: 'normal',
+          family: 'xx'
+        },
+        border: {
+          color: '#2092f5ff',
+          width: 0,
+          radius: 10,
+          side: ['all']
+        }
+      }
+    ]
+  },
+  config: {
+    // 组件属性
+    props: [
+      {
+        label: '名称',
+        field: 'name',
+        valueType: 'text',
+        componentProps: {
+          placeholder: '请输入名称'
+        }
+      },
+      {
+        label: '位置/大小',
+        valueType: 'group',
+        children: [
+          {
+            field: 'props.x',
+            valueType: 'number',
+            componentProps: {
+              span: 12
+            },
+            slots: { prefix: 'X' }
+          },
+          {
+            field: 'props.y',
+            valueType: 'number',
+            componentProps: {
+              span: 12
+            },
+            slots: { prefix: 'Y' }
+          },
+          {
+            field: 'props.width',
+            valueType: 'number',
+            componentProps: {
+              span: 12
+            },
+            slots: { prefix: 'W' }
+          },
+          {
+            field: 'props.height',
+            valueType: 'number',
+            componentProps: {
+              span: 12
+            },
+            slots: { prefix: 'H' }
+          }
+        ]
+      },
+      {
+        label: '添加标识',
+        field: 'props.addFlags',
+        valueType: 'checkbox',
+        componentProps: {
+          options: flagOptions,
+          defaultCollapsed: true
+        }
+      },
+      {
+        label: '删除标识',
+        field: 'props.removeFlags',
+        valueType: 'checkbox',
+        componentProps: {
+          options: flagOptions,
+          defaultCollapsed: true
+        }
+      }
+    ],
+    coreProps: [
+      {
+        label: '标题',
+        field: 'props.title',
+        valueType: 'text'
+      },
+      {
+        label: '关闭按钮',
+        field: 'props.closeBtn',
+        valueType: 'switch'
+      },
+      {
+        label: '按钮尺寸',
+        valueType: 'group',
+        children: [
+          {
+            field: 'props.btnWidth',
+            valueType: 'number',
+            componentProps: {
+              span: 12,
+              min: 0,
+              max: 200
+            },
+            slots: { prefix: 'W' }
+          },
+          {
+            field: 'props.btnHeight',
+            valueType: 'number',
+            componentProps: {
+              span: 12,
+              min: 0,
+              max: 200
+            },
+            slots: { prefix: 'Y' }
+          }
+        ]
+      },
+      {
+        label: '按钮组',
+        field: 'props.btns',
+        render: (val) => {
+          return <Config values={val} />
+        }
+      }
+    ],
+    // 组件样式
+    styles: [
+      {
+        label: '模块状态',
+        field: 'part',
+        valueType: 'part'
+      },
+      {
+        valueType: 'dependency',
+        name: ['part'],
+        dependency: ({ part }) => {
+          return part?.name === 'main'
+            ? [
+                {
+                  label: '背景',
+                  field: 'background',
+                  valueType: 'background',
+                  componentProps: {
+                    onlyColor: true
+                  }
+                },
+                {
+                  label: '边框',
+                  field: 'border',
+                  valueType: 'border'
+                },
+                {
+                  label: '阴影',
+                  field: 'shadow',
+                  valueType: 'shadow'
+                }
+              ]
+            : part?.name === 'title'
+              ? [
+                  {
+                    label: '背景',
+                    field: 'background',
+                    valueType: 'background',
+                    componentProps: {
+                      onlyColor: true
+                    }
+                  },
+                  {
+                    label: '字体',
+                    field: 'text',
+                    valueType: 'font',
+                    componentProps: {
+                      hideAlign: true
+                    }
+                  },
+                  {
+                    label: '间距',
+                    field: 'spacer',
+                    valueType: 'spacer'
+                  }
+                ]
+              : part?.name === 'content'
+                ? [
+                    {
+                      label: '字体',
+                      field: 'text',
+                      valueType: 'font',
+                      componentProps: {
+                        hideAlign: true
+                      }
+                    },
+                    {
+                      label: '间距',
+                      field: 'spacer',
+                      valueType: 'spacer'
+                    }
+                  ]
+                : [
+                    {
+                      label: '背景',
+                      field: 'background',
+                      valueType: 'background',
+                      componentProps: {
+                        onlyColor: true
+                      }
+                    },
+                    {
+                      label: '字体',
+                      field: 'text',
+                      valueType: 'font',
+                      componentProps: {
+                        hideAlign: true
+                      }
+                    },
+                    {
+                      label: '边框',
+                      field: 'border',
+                      valueType: 'border'
+                    }
+                  ]
+        }
+      }
+    ]
+  }
+} as IComponentModelConfig

+ 100 - 0
src/renderer/src/lvgl-widgets/message/style.json

@@ -0,0 +1,100 @@
+{
+  "widget": "lv_msgbox",
+  "styleName": "defualt",
+  "part": [
+    {
+      "partName": "main",
+      "state": [
+        {
+          "state": "default",
+          "style": {
+            "background": {
+              "color": "#ffffffff"
+            },
+            "border": {
+              "color": "#ffffff64",
+              "width": 0,
+              "radius": 4,
+              "side": ["all"]
+            },
+            "shadow": {
+              "color": "#2092f5ff",
+              "x": 0,
+              "y": 0,
+              "spread": 0,
+              "width": 0
+            }
+          }
+        }
+      ]
+    },
+    {
+      "partName": "title",
+      "state": [
+        {
+          "state": "default",
+          "style": {
+            "background": {
+              "color": "#ffffffff"
+            },
+            "text": {
+              "color": "#35383cff",
+              "size": 12,
+              "weight": "normal",
+              "family": "xx"
+            },
+            "spacer": {
+              "letterSpacing": 0,
+              "lineHeight": 15
+            }
+          }
+        }
+      ]
+    },
+    {
+      "partName": "content",
+      "state": [
+        {
+          "state": "default",
+          "style": {
+            "text": {
+              "color": "#35383cff",
+              "size": 12,
+              "weight": "normal",
+              "family": "xx"
+            },
+            "spacer": {
+              "letterSpacing": 0,
+              "lineHeight": 10
+            }
+          }
+        }
+      ]
+    },
+    {
+      "partName": "btns",
+      "state": [
+        {
+          "state": "default",
+          "style": {
+            "background": {
+              "color": "#e6e6e6ff"
+            },
+            "text": {
+              "color": "#35383cff",
+              "size": 12,
+              "weight": "normal",
+              "family": "xx"
+            },
+            "border": {
+              "color": "#2092f5ff",
+              "width": 0,
+              "radius": 10,
+              "side": ["all"]
+            }
+          }
+        }
+      ]
+    }
+  ]
+}