增加各种config组件

main
一杯沧海 1 year ago
parent f9b032a194
commit b7d451b5fb
  1. 353
      src/App.vue
  2. 4
      src/engineer/components/Canvas.vue
  3. 62
      src/engineer/configs/BackgroundConfig.vue
  4. 32
      src/engineer/configs/BooleanConfig.vue
  5. 4
      src/engineer/configs/ListConfig.vue
  6. 34
      src/engineer/configs/MarkConfig.vue
  7. 35
      src/engineer/configs/ObjectConfig.vue
  8. 3
      src/engineer/configs/TextConfig.vue
  9. 8
      src/engineer/configs/render.ts
  10. 21
      src/engineer/context.ts
  11. 2
      src/engineer/types.ts

@ -5,102 +5,107 @@ import DddBuilder, { hash } from './engineer'
let nextId = Date.now()
const blocks = ref<Block[]>([{
vid: hash(`${++nextId}`),
mid: '',
theme: {
radius: 24,
color: 'yellow',
},
children: {
type: 'text',
key: 'textName',
},
}, {
vid: hash(`${++nextId}`),
mid: '',
theme: {
color: 'pink',
margin: 12,
flexible: true,
},
children: {
type: 'image',
key: 'imageKey',
link: 'linkKey',
radius: 24,
},
}, {
vid: hash(`${++nextId}`),
mid: '',
theme: {
color: '#fafbfc',
margin: 12,
padding: 24,
mainAlign: 'center',
crossAlign: 'center',
flexible: true,
},
children: {
type: 'audio',
key: 'audioKey',
title: 'title',
},
}, {
vid: hash(`${++nextId}`),
mid: '',
theme: {
radius: 24,
color: 'teal',
},
children: [{
theme: {
flexible: true,
gap: 12,
crossAlign: 'center',
},
children: [{
theme: {
padding: 12,
margin: 12,
grow: 1,
},
children: {
vid: hash(`${++nextId}`),
theme: {
fontSize: 32,
},
children: 'left',
},
}, {
vid: hash(`${++nextId}`),
theme: {
width: 'auto',
padding: {
vertical: 4,
horizontal: 12,
},
color: 'pink',
radius: 16,
},
children: 'right222',
}, {
theme: {
width: 48,
},
}],
}],
}, ...Array.from(Array.from({length: 3})).map<Block>((_, i) => ({
vid: hash(`${++nextId}`),
mid: '',
children: [{
vid: hash(`${++nextId}`),
theme: {
fontSize: 22,
},
children: `测试${i}`,
}],
}))])
const blocks = ref<Block[]>([
// {
// vid: hash(`${++nextId}`),
// mid: '',
// theme: {
// radius: 24,
// color: 'yellow',
// },
// children: {
// type: 'text',
// key: 'textName',
// },
// }, {
// vid: hash(`${++nextId}`),
// mid: '',
// theme: {
// color: 'pink',
// margin: 12,
// flexible: true,
// },
// children: {
// type: 'image',
// key: 'imageKey',
// link: 'linkKey',
// radius: 24,
// },
// }, {
// vid: hash(`${++nextId}`),
// mid: '',
// theme: {
// color: '#fafbfc',
// margin: 12,
// padding: 24,
// mainAlign: 'center',
// crossAlign: 'center',
// flexible: true,
// },
// children: {
// type: 'audio',
// key: 'audioKey',
// title: 'title',
// },
// }, {
// vid: hash(`${++nextId}`),
// mid: '',
// theme: {
// radius: 24,
// color: 'teal',
// },
// children: [{
// theme: {
// flexible: true,
// gap: 12,
// crossAlign: 'center',
// },
// children: [{
// theme: {
// padding: 12,
// margin: 12,
// grow: 1,
// },
// children: {
// vid: hash(`${++nextId}`),
// theme: {
// fontSize: 32,
// },
// children: 'left',
// },
// }, {
// vid: hash(`${++nextId}`),
// theme: {
// width: 'auto',
// padding: {
// vertical: 4,
// horizontal: 12,
// },
// color: 'pink',
// radius: 16,
// },
// children: 'right222',
// }, {
// theme: {
// width: 48,
// },
// }
// ],
// }
// ],
// }, ...Array.from(Array.from({length: 3})).map<Block>((_, i) => ({
// vid: hash(`${++nextId}`),
// mid: '',
// children: [{
// vid: hash(`${++nextId}`),
// theme: {
// fontSize: 22,
// },
// children: `${i}`,
// }],
// }))
])
const categories = ref([{icon: 'trash', text: '媒体'}, {icon: 'trash', text: '图表'}, {icon: 'trash', text: '商品'}, {icon: 'trash', text: '功能'}, {icon: 'trash', text: '素材'}].map(c => ({
...c,
@ -134,66 +139,84 @@ categories.value.unshift({
maxReferenceCount: -1,
referenceCount: 0,
image: undefined,
configs: [{
type: 'list',
field: 'items',
label: '',
help: '最多可添加10张图片,建议宽度750px;鼠标拖拽左侧圆点可调整图片顺序',
addable: true,
configs: [{
type: 'image',
field: 'image',
//
inlines: [{
type: 'text',
field: 'title',
label: '标题',
help: '选填,不超过 4 个字',
}, {
type: 'text',
field: 'link',
label: '链接',
// help: '', // "${label}"
configs: [
{
type: 'list',
field: 'items',
label: '',
help: '最多可添加10张图片,建议宽度750px;鼠标拖拽左侧圆点可调整图片顺序',
addable: true,
configs: [{
type: 'image',
field: 'image',
//
inlines: [{
type: 'text',
field: 'title',
label: '标题',
help: '选填,不超过 4 个字',
}, {
type: 'text',
field: 'link',
label: '链接',
// help: '', // "${label}"
}],
label: '图片',
required: true,
}],
label: '图片',
required: true,
}],
}, {
type: 'object',
field: 'indicator',
label: '指示器',
configs: [{
type: 'mark',
field: 'style',
label: '指示器样式',
values: [{label: '圆形', value: 'circle'}, {label: '直线', value: 'line'}, {label: '数字', value: 'number'}],
}, {
type: 'mark',
field: 'position',
label: '指示器位置',
values: [{label: '居左', value: 'left'}, {label: '居中', value: 'center'}, {label: '居右', value: 'right'}],
}, {
type: 'color',
field: 'color',
label: '指示器颜色',
}],
}, {
type: 'object',
field: 'background',
label: '背景',
configs: [{
type: 'bool',
field: 'enabled',
label: '是否显示背景色',
}, {
type: 'background',
field: 'value',
// image
//
features: ['color', 'gradient'],
},
{
type: 'object',
field: 'indicator',
label: '指示器',
configs: [{
type: 'mark',
field: 'style',
label: '指示器样式',
values: [{label: '圆形', value: 'circle'}, {label: '直线', value: 'line'}, {label: '数字', value: 'number'}],
}, {
type: 'mark',
field: 'position',
label: '指示器位置',
values: [{label: '居左', value: 'left'}, {label: '居中', value: 'center'}, {label: '居右', value: 'right'}],
},
{
type: 'color',
field: 'color',
label: '指示器颜色',
}],
},
{
type: 'object',
field: 'background',
label: '背景',
configs: [{
type: 'boolean',
field: 'enabled',
label: '是否显示背景色',
}, {
type: 'background',
field: 'value',
// image
//
features: ['color', 'gradient'],
label: '背景',
}],
}],
}],
init: {
items: [
{
image: '',
// title: '',
// link: '',
}
],
indicator: {
style: 'circle',
color: '#000000',
position: 'left',
}
},
theme: {
height: 200,
padding: {
@ -210,7 +233,7 @@ categories.value.unshift({
radius: 12.0,
textAlign: 'center',
},
children: '内容',
children: '设置轮播图',
}],
},
{
@ -259,17 +282,17 @@ categories.value.unshift({
})
const data = ref<Record<string, Record<string, unknown>>>({
[blocks.value[0].vid]: {
textName: '测试 2222',
},
[blocks.value[1].vid]: {
imageKey: 'https://www.w3schools.com/css/paris.jpg',
linkKey: 'https://docs.taro.zone/canIUse/',
},
[blocks.value[2].vid]: {
audioKey: 'https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3',
title: '啊哈哈',
},
// [blocks.value[0].vid]: {
// textName: ' 2222',
// },
// [blocks.value[1].vid]: {
// imageKey: 'https://www.w3schools.com/css/paris.jpg',
// linkKey: 'https://docs.taro.zone/canIUse/',
// },
// [blocks.value[2].vid]: {
// audioKey: 'https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3',
// title: '',
// },
})
</script>

@ -1,7 +1,7 @@
<script lang="ts" setup>
import { computed, ref } from 'vue'
import Draggable from 'vuedraggable'
import { useContext } from '../context'
import { useContext, getModule } from '../context'
import { RenderBlock } from '../render'
import { DddView } from '../views'
@ -68,10 +68,12 @@ function handleDragEnd(): void {
function handleDragAdd(e: DraggableEvent): void {
const block = ctx.blocks[e.newDraggableIndex]
const module = getModule(ctx, block.mid)
ctx.activeViewId = block.vid
ctx.activeBlockId = block.vid
ctx.hoverViewId = '#canvas'
ctx.configurator = 'block'
ctx.sources[block.vid] = module.init ?? {}
key.value++
}

@ -0,0 +1,62 @@
<script lang="ts" setup>
import { computed } from "vue";
import { useSource } from "../context"
defineOptions({
name: "DddBackgroundConfig"
})
const props = defineProps<{
field: string
help?: string
features: string[]
label?: string
}>()
const tempString = useSource(props.field)
const typeList = computed(() => {
return props.features.map((item: any)=> {
return {
value: item,
label: formart(item)
}
})
})
function formart(str: string) {
const temp: Record<string, any> = {
color: '纯色',
gradient: '渐变',
}
return temp[str]
}
</script>
<template>
<div class="box">
<label>{{ label }}</label>
<div class="box-typeList">
<div v-for="(item,index) in typeList" :key="index" class="box-typeList-box">
<span>{{ item.label }}</span>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.box{
display: flex;
justify-content: space-between;
align-items: center;
&-typeList{
display: flex;
&-box{
display: flex;
color:#fff;
background-color: aqua;
width:50px;
height:20px;
font-size: 12px;
justify-content: center;
align-items: center;
}
}
}
</style>

@ -0,0 +1,32 @@
<script lang="ts" setup>
import { useSource } from '../context'
defineOptions({
name: "DddBooleanConfig"
})
const props = defineProps<{
field: string
label?: string
values?: any
}>()
const tempString = useSource<boolean>(props.field)
</script>
<template>
<div>
<label>
{{ label }}
</label>
<div>
<label></label>
<input type="radio" :value="true" v-model="tempString"><br>
<label></label>
<input type="radio" :value="false" v-model="tempString"><br>
</div>
</div>
</template>

@ -1,6 +1,5 @@
<script lang="ts" setup>
import { ModuleConfig, useContext, useSource } from '..';
import { setValue } from '../utils';
import { ModuleConfig, useSource } from '..';
import { RenderConfig } from './render';
@ -20,6 +19,7 @@ const props = defineProps<{
const list = useSource<any[]>(props.field)
const add = () => {
const item = props.configs.reduce<any>((res, cfg) => {
res[cfg.field] = undefined
return res

@ -0,0 +1,34 @@
<script lang="ts" setup>
import { useSource } from '../context'
defineOptions({
name: "DddMarkConfig"
})
const props = defineProps<{
field: string
label?: string
string?: string
values?: any
}>()
const tempString = useSource<string>(props.field)
function selectChange(e: any){
console.log(e.target.value)
}
</script>
<template>
<div>
<label>
{{ label }}
</label>
<div>
<select v-model="tempString" @change="selectChange">
<option value="none">不设置</option>
<option v-for="(opt,idx) in values" :key="idx" :value="opt.value">{{ opt.label }}</option>
</select>
</div>
</div>
</template>

@ -0,0 +1,35 @@
<script lang="ts" setup>
import { ModuleConfig } from "..";
import { useSource } from "../context"
import { RenderConfig } from './render';
defineOptions({
name: "DddObjectConfig"
})
defineProps<{
field: string
label?: string
help?: string
required?: boolean
configs: ModuleConfig[]
}>()
</script>
<template>
<div>
<label>
<span>{{ label }}设置</span>
</label>
<div v-for="(cfg, idx) in configs" :key="idx">
<RenderConfig
:type="cfg.type"
:props="{
...cfg,
field: `${field}.${cfg.field}`,
}"
/>
</div>
</div>
</template>

@ -7,14 +7,13 @@ defineOptions({
})
const props = defineProps<{
field: string // arr.0.text
field: string
label: string
help?: string
required?: boolean
}>()
const data = useSource<string>(props.field)
// const text = ref<string>(data.value ?? '')
</script>
<template>

@ -2,10 +2,18 @@ import type { Component } from "vue";
import { defineComponent, h } from 'vue'
import TextConfig from './TextConfig.vue'
import ListConfig from './ListConfig.vue'
import ObjectConfig from './ObjectConfig.vue'
import MarkConfig from "./MarkConfig.vue";
import BooleanConfig from "./BooleanConfig.vue"
import BackgroundConfig from "./BackgroundConfig.vue";
const configs: Record<string, Component> = {
text: TextConfig,
list: ListConfig,
object: ObjectConfig,
mark: MarkConfig,
boolean: BooleanConfig,
background:BackgroundConfig,
}
function render(type: string, props: Record<string, any>) {

@ -83,6 +83,17 @@ export function provideBlockId(id: string): void {
provide(blockIdKey, id)
}
export function getModule(ctx: UnwrapNestedRefs<EngineContext>, mid: string): Module | undefined {
for (const category of ctx.categories) {
for (const module of category.modules) {
if (module.mid === mid) {
return module
}
}
}
return undefined
}
export function useModule() {
const ctx = useContext()
@ -91,14 +102,10 @@ export function useModule() {
if (block.vid !== ctx.activeBlockId) {
continue
}
for (const category of ctx.categories) {
for (const module of category.modules) {
if (module.mid === block.mid) {
return module
}
}
const module = getModule(ctx, block.mid)
if (module != null) {
return module
}
break
}
return undefined
})

@ -397,6 +397,8 @@ export interface Module extends Block {
referenceCount?: number
/** 模块配置 */
configs: ModuleConfig[]
/** 初始化数据 */
init?: Record<string, any>
}
export type ModuleConfig =

Loading…
Cancel
Save