forked from tsai/vite-vue3-lowcode
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