21 changed files with 2060 additions and 364 deletions
@ -0,0 +1,19 @@ |
|||
<template> |
|||
<div> |
|||
<router-view #="{ Component }"> |
|||
<component :is="Component" /> |
|||
</router-view> |
|||
</div> |
|||
</template> |
|||
|
|||
<script lang="ts"> |
|||
export default { |
|||
name: 'App' |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
body::-webkit-scrollbar { |
|||
width: 0; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,13 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<link rel="icon" href="/favicon.ico" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|||
<title>第二个页面</title> |
|||
</head> |
|||
<body> |
|||
<div id="app"></div> |
|||
<script type="module" src="./main.ts"></script> |
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,16 @@ |
|||
import { createApp } from 'vue' |
|||
import App from './App.vue' |
|||
|
|||
import router from './router' |
|||
|
|||
import '@/plugins/vant' |
|||
|
|||
const app = createApp(App) |
|||
|
|||
app.config.globalProperties.$$refs = {} |
|||
|
|||
// if (import.meta.env.DEV) {
|
|||
window.$$refs = app.config.globalProperties.$$refs |
|||
// }
|
|||
|
|||
app.use(router).mount('#app') |
|||
@ -0,0 +1,15 @@ |
|||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router' |
|||
|
|||
const routes: Array<RouteRecordRaw> = [ |
|||
{ |
|||
path: '/:pathMatch(.*)*', |
|||
component: () => import('./views/preview.vue') |
|||
} |
|||
] |
|||
|
|||
const router = createRouter({ |
|||
history: createWebHashHistory(), |
|||
routes |
|||
}) |
|||
|
|||
export default router |
|||
@ -0,0 +1,27 @@ |
|||
import { defineComponent } from 'vue' |
|||
|
|||
export default defineComponent({ |
|||
name: 'CompRender', |
|||
props: { |
|||
element: { |
|||
type: Object, |
|||
default: () => ({}) |
|||
}, |
|||
config: { |
|||
type: Object, |
|||
default: () => ({}) |
|||
} |
|||
}, |
|||
setup(props) { |
|||
return () => { |
|||
const component = props.config.componentMap[props.element.componentKey] |
|||
return component.render({ |
|||
size: {}, |
|||
props: props.element.props || {}, |
|||
model: {}, |
|||
block: props.element, |
|||
custom: {} |
|||
}) |
|||
} |
|||
} |
|||
}) |
|||
@ -0,0 +1,67 @@ |
|||
<template> |
|||
<template v-for="outItem in jsonData" :key="outItem._vid"> |
|||
<slot-item :element="outItem" :config="visualConfig" /> |
|||
</template> |
|||
</template> |
|||
|
|||
<script lang="tsx"> |
|||
import { defineComponent, PropType, reactive, toRefs } from 'vue' |
|||
import { visualConfig } from '@/visual.config' |
|||
import SlotItem from './slot-item.vue' |
|||
/** |
|||
* @name: preview |
|||
* @author: 卜启缘 |
|||
* @date: 2021/4/29 23:09 |
|||
* @description:preview |
|||
* @update: 2021/4/29 23:09 |
|||
*/ |
|||
export default defineComponent({ |
|||
name: 'Preview', |
|||
components: { |
|||
SlotItem |
|||
}, |
|||
emits: ['update:visible'], |
|||
setup(props) { |
|||
const state = reactive({ |
|||
jsonData: JSON.parse(sessionStorage.getItem('blocks') || '{}') |
|||
}) |
|||
|
|||
// 渲染组件 |
|||
const renderCom = (element) => { |
|||
if (Array.isArray(element)) { |
|||
return element.map((item) => renderCom(item)) |
|||
} |
|||
const component = props.config.componentMap[element.componentKey] |
|||
|
|||
return component.render({ |
|||
size: {}, |
|||
props: element.props || {}, |
|||
block: element, |
|||
model: {}, |
|||
custom: {} |
|||
}) |
|||
} |
|||
|
|||
return { |
|||
...toRefs(state), |
|||
visualConfig, |
|||
renderCom |
|||
} |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.h5-preview { |
|||
overflow: hidden; |
|||
.el-dialog__header { |
|||
display: none; |
|||
} |
|||
.simulator { |
|||
padding-right: 0; |
|||
&::-webkit-scrollbar { |
|||
width: 0; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -1,31 +0,0 @@ |
|||
import { NumberRange } from './number-range' |
|||
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils' |
|||
|
|||
export default { |
|||
key: 'number-range', |
|||
moduleName: 'baseWidgets', |
|||
label: '数字范围输入框', |
|||
resize: { |
|||
width: true |
|||
}, |
|||
preview: () => <NumberRange style={{ width: '100%' }} />, |
|||
render: ({ model, size }) => { |
|||
return ( |
|||
<NumberRange |
|||
style={{ |
|||
width: size.width ? `${size.width}px` : null |
|||
}} |
|||
{...{ |
|||
start: model.start.value, |
|||
'onUpdate:start': model.start.onChange, |
|||
end: model.end.value, |
|||
'onUpdate:end': model.end.onChange |
|||
}} |
|||
/> |
|||
) |
|||
}, |
|||
model: { |
|||
start: '起始绑定字段', |
|||
end: '截止绑定字段' |
|||
} |
|||
} as VisualEditorComponent |
|||
@ -1,24 +0,0 @@ |
|||
.number-range { |
|||
display: inline-flex; |
|||
width: 225px; |
|||
min-height: 40px; |
|||
align-items: stretch; |
|||
|
|||
& > div { |
|||
flex: 1; |
|||
|
|||
input { |
|||
width: 100%; |
|||
height: 100%; |
|||
margin: 0; |
|||
padding: 0; |
|||
box-sizing: border-box; |
|||
} |
|||
} |
|||
|
|||
span { |
|||
margin: 0 8px; |
|||
display: inline-flex; |
|||
align-items: center; |
|||
} |
|||
} |
|||
@ -1,30 +0,0 @@ |
|||
import { defineComponent } from 'vue' |
|||
import { useVModel } from '@vueuse/core' |
|||
import './number-range.scss' |
|||
|
|||
export const NumberRange = defineComponent({ |
|||
props: { |
|||
start: { type: String }, |
|||
end: { type: String } |
|||
}, |
|||
emits: { |
|||
'update:start': (_?: string) => true, |
|||
'update:end': (_?: string) => true |
|||
}, |
|||
setup(props) { |
|||
const startModel = useVModel(props, 'start') |
|||
const endModel = useVModel(props, 'end') |
|||
|
|||
return () => ( |
|||
<div class="number-range"> |
|||
<div> |
|||
<input type="text" v-model={startModel.value} /> |
|||
</div> |
|||
<span>~</span> |
|||
<div> |
|||
<input type="text" v-model={endModel.value} /> |
|||
</div> |
|||
</div> |
|||
) |
|||
} |
|||
}) |
|||
@ -1,37 +0,0 @@ |
|||
import { ElOption, ElSelect } from 'element-plus' |
|||
import { createEditorTableProp } from '@/visual-editor/visual-editor.props' |
|||
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils' |
|||
|
|||
export default { |
|||
key: 'select', |
|||
moduleName: 'baseWidgets', |
|||
label: '下拉框', |
|||
preview: () => <ElSelect />, |
|||
render: ({ props, model, custom }) => ( |
|||
<ElSelect |
|||
{...custom} |
|||
key={(props.options || []).map((opt: any) => opt.value).join(',')} |
|||
{...model.default} |
|||
> |
|||
{(props.options || []).map((opt: { label: string; value: string }, index: number) => ( |
|||
<ElOption label={opt.label} value={opt.value} key={index} /> |
|||
))} |
|||
</ElSelect> |
|||
), |
|||
props: { |
|||
options: createEditorTableProp({ |
|||
label: '下拉选项', |
|||
option: { |
|||
options: [ |
|||
{ label: '显示值', field: 'label' }, |
|||
{ label: '绑定值', field: 'value' }, |
|||
{ label: '备注', field: 'comments' } |
|||
], |
|||
showKey: 'label' |
|||
} |
|||
}) |
|||
}, |
|||
model: { |
|||
default: '绑定字段' |
|||
} |
|||
} as VisualEditorComponent |
|||
@ -0,0 +1,8 @@ |
|||
/** |
|||
* @name: index |
|||
* @author: 卜启缘 |
|||
* @date: 2021/5/6 0:04 |
|||
* @description:index |
|||
* @update: 2021/5/6 0:04 |
|||
*/ |
|||
export const BASE_URL = import.meta.env.BASE_URL |
|||
File diff suppressed because it is too large
Loading…
Reference in new issue