diff --git a/src/App.vue b/src/App.vue
index bc85f84..161fbfe 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -132,382 +132,409 @@ const categories = ref([{ icon: 'trash', text: '媒体' }, { icon: 'trash', text
categories.value.unshift({
icon: 'trash',
text: '基础',
- modules: [{
- vid: hash(`${++nextId}`),
- mid: hash(`${++nextId}`),
- title: '轮播图',
- maxReferenceCount: -1,
- referenceCount: 0,
- image: undefined,
- configs: [
- {
- type: 'list',
- field: 'items',
- label: '轮播图设置',
- help: '最多可添加10张图片,建议宽度750px;鼠标拖拽左侧圆点可调整图片顺序',
- addable: true,
- configs: [{
- type: 'image',
- field: 'image',
- label: '图片',
- required: true,
- // 表示内联数据
- inlines: [{
- type: 'text',
- field: 'title',
- label: '标题',
- help: '选填,不超过 4 个字',
+ modules: [
+ {
+ vid: hash(`${++nextId}`),
+ mid: hash(`${++nextId}`),
+ title: '轮播图',
+ maxReferenceCount: -1,
+ referenceCount: 0,
+ image: undefined,
+ configs: [
+ {
+ type: 'list',
+ field: 'items',
+ label: '轮播图设置',
+ help: '最多可添加10张图片,建议宽度750px;鼠标拖拽左侧圆点可调整图片顺序',
+ addable: true,
+ configs: [{
+ type: 'image',
+ field: 'image',
+ label: '图片',
+ required: true,
+ // 表示内联数据
+ inlines: [{
+ type: 'text',
+ field: 'title',
+ label: '标题',
+ help: '选填,不超过 4 个字',
+ }, {
+ type: 'text',
+ field: 'link',
+ label: '链接',
+ help: '请输入链接', // 自动生成:"请输入${label}"
+ }],
+ }],
+ },
+ {
+ type: 'object',
+ field: 'indicator',
+ label: '指示器',
+ configs: [{
+ type: 'mark',
+ field: 'style',
+ label: '指示器样式',
+ values: [
+ { label: '圆形', value: '#circle' },
+ { label: '直线', value: '#line' },
+ { label: '数字', value: '#number' },
+ ],
}, {
- type: 'text',
- field: 'link',
- label: '链接',
- help: '请输入链接', // 自动生成:"请输入${label}"
+ type: 'mark',
+ field: 'position',
+ label: '指示器位置',
+ values: [
+ { label: '居左', value: 'start' },
+ { label: '居中', value: 'center' },
+ { label: '居右', value: 'end' },
+ ],
+ },
+ {
+ type: 'color',
+ field: 'color',
+ label: '指示器颜色',
}],
- }],
- },
- {
- 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: 'start' },
- { label: '居中', value: 'center' },
- { label: '居右', value: 'end' },
- ],
},
{
- type: 'color',
- field: 'color',
- label: '指示器颜色',
- }],
- },
- {
- type: 'object',
- field: 'background',
- label: '背景',
- configs: [{
- type: 'boolean',
- field: 'enabled',
- label: '是否显示背景色',
- }, {
- type: 'background',
- field: 'value',
- // 背景的不同实现方式,可以在里面添加 image 选项来支持图片
- // 这里只能支持颜色和渐变,
- features: ['color', 'gradient'],
+ type: 'object',
+ field: 'background',
label: '背景',
- }],
- }
- ],
- init: {
- items: [
- {
- image: '',
- title: '123',
- link: '123',
+ configs: [{
+ type: 'boolean',
+ field: 'enabled',
+ label: '是否显示背景色',
+ }, {
+ type: 'background',
+ field: 'value',
+ // 背景的不同实现方式,可以在里面添加 image 选项来支持图片
+ // 这里只能支持颜色和渐变,
+ features: ['color', 'gradient'],
+ label: '背景',
+ }],
}
],
- indicator: {
- style: '#circle',
- color: 'green',
- position: 'start',
- },
- background: {
- enabled: true,
- value: "#ffffff",
- },
- theme: {
- color: 'white',
- radius: 24
- }
- },
- templates: {
- '#circle': {
- theme: {
- gap: 20,
- },
- children: {
- type: 'each',
- key: 'items',
- handle: {
- theme: {
- width: 20,
- height: 20,
- radius: 10,
- color: '@@indicator.color',
- },
+ init: {
+ items: [
+ {
+ image: '',
+ title: '123',
+ link: '123',
}
+ ],
+ indicator: {
+ style: '#circle',
+ color: 'green',
+ position: 'start',
+ },
+ background: {
+ enabled: true,
+ value: "#ffffff",
+ },
+ theme: {
+ color: 'white',
+ radius: 24
}
},
- '#line': {
- theme: {
- gap: 20,
+ templates: {
+ '#circle': {
+ theme: {
+ gap: 20,
+ },
+ children: {
+ type: 'each',
+ key: 'items',
+ handle: {
+ theme: {
+ width: 20,
+ height: 20,
+ radius: 10,
+ color: '@@indicator.color',
+ },
+ }
+ }
},
- children: {
- type: 'each',
- key: 'items',
- handle: {
- theme: {
- width: 40,
- height: 20,
- color: '@@indicator.color',
- },
+ '#line': {
+ theme: {
+ gap: 20,
+ },
+ children: {
+ type: 'each',
+ key: 'items',
+ handle: {
+ theme: {
+ width: 40,
+ height: 20,
+ color: '@@indicator.color',
+ },
+ }
}
+ },
+ "#number": {
+ theme: {
+ color: 'rgba(0,0,0,0.4)',
+ textColor: '#fff'
+ },
+ children: '1/len(items)'
}
},
- "#number": {
- theme: {
- color: 'rgba(0,0,0,0.4)',
- textColor: '#fff'
+ theme: {
+ position: 'relative',
+ height: 200,
+ padding: {
+ horizontal: 12.0,
+ vertical: 12,
},
- children: '1/len(items)'
- }
- },
- theme: {
- position: 'relative',
- height: 200,
- padding: {
- horizontal: 12.0,
- vertical: 12,
+ color: 'cyan',
},
- color: 'cyan',
+ children: [
+ {
+ vid: hash(`${++nextId}`),
+ theme: {
+ width: '100%',
+ height: '100%',
+ color: '@@theme.color',
+ radius: "@@theme.radius",
+ textAlign: 'center',
+ },
+ children: '设置轮播图',
+ },
+ {
+ theme: {
+ position: 'absolute',
+ flexible: true,
+ mainAlign: '@@indicator.position',
+ bottom: 20,
+ left: 20,
+ right: 20,
+ height: 20,
+ color: 'red',
+ },
+ children: {
+ type: 'template',
+ key: 'indicator.style'
+ }
+ }],
},
- children: [{
+ {
+ title: '产品组',
vid: hash(`${++nextId}`),
- theme: {
- width: '100%',
- height: '100%',
- color: '@@theme.color',
- radius: "@@theme.radius",
- textAlign: 'center',
- },
- children: '设置轮播图',
- }, {
- theme: {
- position: 'absolute',
- flexible: true,
- mainAlign: '@@indicator.position',
- bottom: 20,
- left: 20,
- right: 20,
- height: 20,
- color: 'red',
- },
- // children: {
- // type: 'each',
- // key: 'indicator.position',
- // handle: {
- // theme: {
- // width: 20,
- // height: 20,
- // radius: 10,
- // color: 'black',
- // }
- // },
- // }
- children: {
- type: 'template',
- key: 'indicator.style'
- }
- }],
- },
- {
- vid: hash(`${++nextId}`),
- mid: hash(`${++nextId}`),
- title: '产品组',
- maxReferenceCount: -1,
- referenceCount: 0,
- image: undefined,
- configs: [
- {
- type: 'object',
- field: 'titleAndDesc',
- label: '产品标题及说明',
- configs: [
- {
- type: 'text',
- label: '产品标题',
- field: 'mainTitle'
- },
- {
- type: 'text',
- label: '说明',
- field: 'content',
- },
- ]
- },
- {
- help: '最多可添加10张图片,建议宽度750px;鼠标拖拽左侧圆点可调整图片顺序',
- addable: true,
- type: 'list',
- field: 'groups',
- label: '产品组列表',
- configs: [
- {
- type: 'image',
- label: '产品图片',
- field: 'productPhoto',
- // 表示内联数据
- inlines: [{
+ mid: hash(`${++nextId}`),
+ maxReferenceCount: -1,
+ referenceCount: 0,
+ image: undefined,
+ configs: [
+ {
+ type: 'object',
+ field: 'titleAndDesc',
+ label: '产品标题及说明',
+ configs: [
+ {
type: 'text',
- field: 'link',
- label: '链接',
- help: '请输入链接', // 自动生成:"请输入${label}"
+ label: '产品标题',
+ field: 'mainTitle'
},
{
type: 'text',
- label: '自定义标题',
- field: 'productTitle',
+ label: '说明',
+ field: 'content',
},
{
type: 'text',
- label: '自定义说明',
- field: 'productDesc',
+ label: '提示',
+ field: 'more',
},
- ]
- },
-
- ]
- },
- ],
- init: {
- titleAndDesc: {
- mainTitle: '标题',
- content: '说明',
- },
- groups: [
+ ]
+ },
{
+ help: '帮助',
+ addable: true,
+ type: 'list',
+ field: 'groups',
+ label: '产品组列表',
+ configs: [
+ {
+ type: 'image',
+ label: '产品图片',
+ field: 'productPhoto',
+ // 表示内联数据
+ inlines: [{
+ type: 'text',
+ field: 'link',
+ label: '链接',
+ help: '请输入链接', // 自动生成:"请输入${label}"
+ },
+ {
+ type: 'text',
+ label: '自定义标题',
+ field: 'productTitle',
+ },
+ {
+ type: 'text',
+ label: '自定义说明',
+ field: 'productDesc',
+ },
+ ]
+ },
- productTitle: '111',
- }
+ ]
+ },
],
-
- },
- theme: {
- height: 200,
- padding: {
- horizontal: 12.0,
+ init: {
+ titleAndDesc: {
+ mainTitle: '标题123',
+ content: '说明123',
+ more: '查看更多',
+ },
+ groups: [
+ {
+ productTitle: '111',
+ }
+ ],
+ theme: {
+ color: 'blue',
+ },
+ children:{
+ theme: {
+ radius: 12
+ },
+ }
},
- color: 'pink',
- },
- children: {
- vid: hash(`${++nextId}`),
theme: {
- width: '100%',
- height: '100%',
- color: 'white',
- radius: 12.0,
- textAlign: 'center',
+ height: 200,
+ padding: 12,
+ color: '@@theme.color',
},
- children: [
- {
- theme: {
- flexible: true,
- gap: 12,
- crossAlign: 'center',
- },
- children: [
- {
- theme: {
- padding: {
- horizontal: 5
- },
- },
- children: [
- {
- theme: {
- flexible: true,
- gap: 5,
- crossAlign: 'center',
+ children: {
+ vid: hash(`${++nextId}`),
+ theme: {
+ width: '100%',
+ height: '100%',
+ color: 'white',
+ clip: 'hidden',
+ radius: '@@children.theme.radius',
+ textAlign: 'center',
+ },
+ children: [
+ {
+ theme: {
+ flexible: true,
+ gap: 12,
+ crossAlign: 'center',
+ },
+ children: [
+ {
+ theme: {
+ padding: {
+ horizontal: 5
},
- children: [
- {
- theme: {
- fontSize: 16,
- },
- children: '左侧标题',
+ },
+ children: [
+ {
+ theme: {
+ flexible: true,
+ gap: 5,
+ crossAlign: 'center',
},
- {
- theme: {
- fontSize: 16,
+ children: [
+ {
+ theme: {
+ fontSize: 16,
+ },
+ children: {
+ type: 'text',
+ key: 'titleAndDesc.mainTitle'
+ },
},
- children: '左侧说明',
- }
- ]
- },
- ]
- },
- {
- theme: {
- grow: 1,
- }
- },
- {
- vid: hash(`${++nextId}`),
- theme: {
- width: 'auto',
- margin: {
- horizontal: 5,
+ {
+ theme: {
+ fontSize: 16,
+ },
+ children: {
+ type: 'text',
+ key: 'titleAndDesc.content'
+ },
+ }
+ ]
+ },
+ ]
+ },
+ {
+ theme: {
+ grow: 1,
+ }
+ },
+ {
+ vid: hash(`${++nextId}`),
+ theme: {
+ width: 'auto',
+ margin: {
+ horizontal: 5,
+ },
+ fontSize: 12,
+ padding: {
+ vertical: 1,
+ horizontal: 5,
+ },
+ color: '@@children.children.children.children.children.2.color',
+ textColor: '#fff',
+ radius: 16,
},
- fontSize: 12,
- padding: {
- vertical: 1,
- horizontal: 5,
+ children: {
+ type: 'text',
+ key: 'titleAndDesc.more'
},
- color: 'pink',
- radius: 16,
},
- children: '查看更多',
- },
- ],
- },
- {
- vid: hash(`${++nextId}`),
- theme: {
- width: "94%",
- height: "70%",
- color: 'pink',
- radius: 12.0,
- margin: {
- top: '1%',
- left: '3%',
- right: '3%',
- bottom: '2%',
- },
- padding: {
- horizontal: 3,
- }
+ ],
},
- children: [{
+ {
+ vid: hash(`${++nextId}`),
theme: {
- width: '35%',
- height: '100%',
- mainAlign: "center",
- color: '#fff',
- crossAlign: "center"
-
+ width: "94%",
+ height: "70%",
+ color: 'pink',
+ radius: 12.0,
+ margin: {
+ top: '1%',
+ left: '3%',
+ right: '3%',
+ bottom: '2%',
+ },
+ padding: {
+ horizontal: 3,
+ },
+ gap: 3,
+ clip: 'autoX',
},
- children: '产品'
+ children:
+ {
+ type: 'each',
+ key: 'groups',
+ handle: {
+ theme: {
+ width: '100px',
+ height: '100%',
+ radius: 10,
+ color: '#fff',
+ },
+ }
+ },
+ // [{
+ // theme: {
+ // width: '35%',
+ // height: '100%',
+ // mainAlign: "center",
+ // color: '#fff',
+ // crossAlign: "center"
+ //
+ // },
+ // children: { }
+ // },
+ // ]
},
- ]
- },
- ]
+ ]
+ }
}
- }
],
})
diff --git a/src/engineer/components/ConfigCurrentView.vue b/src/engineer/components/ConfigCurrentView.vue
index b025cdc..2e672fc 100644
--- a/src/engineer/components/ConfigCurrentView.vue
+++ b/src/engineer/components/ConfigCurrentView.vue
@@ -3,6 +3,7 @@ import type { View } from '../types';
import { computed } from 'vue';
import { useContext } from '../context';
import ColorConfig from '../configs/ColorConfig.vue';
+import NumberStyle from '../styles/NumberStyle.vue'
defineOptions({
name: 'ConfigCurrentView',
@@ -17,17 +18,30 @@ const styles = computed(() => {
return undefined
}
return Object.entries(view.value.theme).filter(([, value]) => {
- return typeof value === 'string' && value.startsWith('@@theme.')
+ return typeof value === 'string' && value.startsWith('@@')
}) as Array<[string, string]>
})
+const label = computed(()=>{
+ if(!view.value?.title) {
+ return undefined
+ }
+ return view.value.title
+})
+
+
{{ ctx.activeViewId }}
+
-
-
- {{ key }}:{{ value }}
-
-{{ view }}
+
+
diff --git a/src/engineer/context.ts b/src/engineer/context.ts
index bb7c459..a0f8207 100644
--- a/src/engineer/context.ts
+++ b/src/engineer/context.ts
@@ -51,7 +51,7 @@ export interface EngineContextBase {
nextId: number
/** 数据源 */
sources: Record>
- /** 到处数据 */
+ /** 导出数据 */
export: () => Exported
/** 获取动态数据 */
value: (blockId: string, key: string) => T | undefined
@@ -62,7 +62,7 @@ export type EngineContext = UnwrapNestedRefs
export const contextKey: InjectionKey = Symbol.for('ddd:engine')
const must = (v: T | undefined, error: string): T => {
- if (v == null) {
+ if(v==null){
throw new Error(error)
}
return v
@@ -74,8 +74,8 @@ export function useContext(): EngineContext {
export const parentViewIdKey: InjectionKey = Symbol.for('ddd:view:parent:id')
-export function useParentViewId(): string | undefined {
- return inject(parentViewIdKey)
+export function useParentViewId(): string {
+ return must(inject(parentViewIdKey), 'no parentViewId no found')
}
export function provideParentViewId(id: string | undefined): void {
@@ -86,7 +86,7 @@ export function provideParentViewId(id: string | undefined): void {
const blockIdKey: InjectionKey = Symbol.for('ddd:block:id')
-export function useBlockId(): string {
+export const useBlockId = (): string => {
return must(inject(blockIdKey), "no block found")
}
@@ -94,8 +94,9 @@ export function provideBlockId(id: string): void {
provide(blockIdKey, id)
}
-export const currentViewDOMRectKey: InjectionKey>> = Symbol.for('ddd:view:current:domrect')
-export const parentViewDOMRectKey: InjectionKey>> = Symbol.for('ddd:view:parent:domrect')
+type ReactingDomRect = InjectionKey>>
+export const currentViewDOMRectKey: ReactingDomRect = Symbol.for('ddd:view:current:domrect')
+export const parentViewDOMRectKey: ReactingDomRect = Symbol.for('ddd:view:parent:domrect')
export function useCurrentViewDOMRect(): UnwrapNestedRefs> {
return must(inject(currentViewDOMRectKey), 'no DOMReact found')
@@ -106,9 +107,9 @@ export function useParentViewDOMRect(): UnwrapNestedRefs> {
}
export function getModule(ctx: UnwrapNestedRefs, mid: string): Module | undefined {
- for (const category of ctx.categories) {
- for (const module of category.modules) {
- if (module.mid === mid) {
+ for(const category of ctx.categories){
+ for(const module of category.modules){
+ if(module.mid === mid) {
return module
}
}
@@ -116,15 +117,15 @@ export function getModule(ctx: UnwrapNestedRefs, mid: string)
return undefined
}
-export function useModule() {
+export function useModule(){
const ctx = useContext()
return computed((): Module | undefined => {
- for (const block of ctx.blocks) {
- if (block.vid !== ctx.activeBlockId) {
+ for(const block of ctx.blocks){
+ if(block.vid !== ctx.activeBlockId){
continue
}
- const module = getModule(ctx, block.mid)
+ const module = getModule(ctx,block.mid)
if (module != null) {
return module
}
@@ -163,7 +164,9 @@ export interface TreeData {
value: any
}
-const treeDataKey: InjectionKey|WritableComputedRef | null> = Symbol.for('ddd:view:tree:data')
+type RefTreeData = InjectionKey|WritableComputedRef|null>
+
+const treeDataKey: RefTreeData = Symbol.for('ddd:view:tree:data')
export function provideTreeData(data: UnwrapNestedRefs | WritableComputedRef | null) {
provide(treeDataKey, data)
@@ -175,7 +178,9 @@ export function useSource(source: string | undefined, fallback?: T)
const blockId = useBlockId()
return computed({
+
get(): T | undefined {
+ console.log('get',source,'source',blockId || ctx.activeBlockId,'id')
if (!source) {
return fallback
}
@@ -193,6 +198,7 @@ export function useSource(source: string | undefined, fallback?: T)
return valueOf(ctx.sources[id], source) ?? fallback
},
set(value: T | undefined) {
+ console.log('set',value,'value',source,'source',blockId || ctx.activeBlockId,'id')
if (!source || source.startsWith("$")) {
return
}
diff --git a/src/engineer/styles/NumberStyle.vue b/src/engineer/styles/NumberStyle.vue
new file mode 100644
index 0000000..483bc18
--- /dev/null
+++ b/src/engineer/styles/NumberStyle.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/src/engineer/types.ts b/src/engineer/types.ts
index bdf4d40..8f57685 100644
--- a/src/engineer/types.ts
+++ b/src/engineer/types.ts
@@ -274,7 +274,7 @@ export type ClipBehavior =
| 'visible'
| 'auto'
| 'autoX' // overflow-x: auto; overflow-y: hidden
- | 'autoY' // overflow-x: hidden; overflow-y: auto
+ | 'autoY' // overflow-y: hidden; overflow-y: auto
/**
* 视图数据
@@ -405,6 +405,7 @@ export interface View {
*/
// theme?: Theme | Widget
theme?: DynamicTheme
+ title?: string
/**
* 关联数据源
*/
diff --git a/src/engineer/views/RenderTemplate.vue b/src/engineer/views/RenderTemplate.vue
index 4e51616..8221b45 100644
--- a/src/engineer/views/RenderTemplate.vue
+++ b/src/engineer/views/RenderTemplate.vue
@@ -9,11 +9,12 @@ const props = defineProps<{
const mod = useModule()
const name = useSource(props.source)
-const view = computed(() => {
+const view = computed(()=>{
const ts = mod.value?.templates
const key = name.value
return ts && key ? ts[key] : undefined
})
+
diff --git a/src/engineer/views/TextView.vue b/src/engineer/views/TextView.vue
index e62259c..567687e 100644
--- a/src/engineer/views/TextView.vue
+++ b/src/engineer/views/TextView.vue
@@ -1,6 +1,5 @@