feat(component): pageSetting
This commit is contained in:
parent
5f99924474
commit
f387fa8993
|
@ -1,5 +1,10 @@
|
|||
name: deploy
|
||||
|
||||
env:
|
||||
# 7 GiB by default on GitHub, setting to 6 GiB
|
||||
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
|
||||
NODE_OPTIONS: --max-old-space-size=6144
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
@ -16,10 +21,10 @@ jobs:
|
|||
node-version: '14.x'
|
||||
|
||||
- name: Install
|
||||
run: npm install
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
run: yarn build
|
||||
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// generated by vite-plugin-components
|
||||
// read more https://github.com/vuejs/vue-next/pull/3399
|
||||
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
ElHeader: typeof import('element-plus/es/el-header')['default']
|
||||
ElAside: typeof import('element-plus/es/el-aside')['default']
|
||||
ElMain: typeof import('element-plus/es/el-main')['default']
|
||||
ElContainer: typeof import('element-plus/es/el-container')['default']
|
||||
ElCol: typeof import('element-plus/es/el-col')['default']
|
||||
ElButton: typeof import('element-plus/es/el-button')['default']
|
||||
ElTooltip: typeof import('element-plus/es/el-tooltip')['default']
|
||||
ElRow: typeof import('element-plus/es/el-row')['default']
|
||||
ElPopover: typeof import('element-plus/es/el-popover')['default']
|
||||
ElTabPane: typeof import('element-plus/es/el-tab-pane')['default']
|
||||
ElTabs: typeof import('element-plus/es/el-tabs')['default']
|
||||
ElDialog: typeof import('element-plus/es/el-dialog')['default']
|
||||
ElTag: typeof import('element-plus/es/el-tag')['default']
|
||||
ElDropdownItem: typeof import('element-plus/es/el-dropdown-item')['default']
|
||||
ElDropdownMenu: typeof import('element-plus/es/el-dropdown-menu')['default']
|
||||
ElDropdown: typeof import('element-plus/es/el-dropdown')['default']
|
||||
ElTree: typeof import('element-plus/es/el-tree')['default']
|
||||
ElInput: typeof import('element-plus/es/el-input')['default']
|
||||
ElFormItem: typeof import('element-plus/es/el-form-item')['default']
|
||||
ElForm: typeof import('element-plus/es/el-form')['default']
|
||||
}
|
||||
}
|
||||
|
||||
export {}
|
47
package.json
47
package.json
|
@ -4,8 +4,8 @@
|
|||
"private": false,
|
||||
"description": "A Vite2.x + Vue3 + TypeScript LowCode",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"dev": "cross-env --max_old_space_size=4096 vite",
|
||||
"build": "cross-env vite build",
|
||||
"build-tsc": "vue-tsc --noEmit && vite build",
|
||||
"serve": "vite preview",
|
||||
"deploy": "gh-pages -d dist",
|
||||
|
@ -27,53 +27,54 @@
|
|||
"axios": "^0.21.1",
|
||||
"dayjs": "^1.10.5",
|
||||
"dexie": "^3.0.3",
|
||||
"element-plus": "^1.0.2-beta.48",
|
||||
"element-plus": "1.0.2-beta.51",
|
||||
"lodash": "^4.17.21",
|
||||
"monaco-editor": "^0.25.0",
|
||||
"monaco-editor": "^0.25.2",
|
||||
"normalize.css": "^8.0.1",
|
||||
"nprogress": "^1.0.0-1",
|
||||
"qrcode": "^1.4.4",
|
||||
"vant": "^3.0.18",
|
||||
"vue": "3.1.1",
|
||||
"vue-router": "^4.0.8",
|
||||
"vant": "^3.1.0",
|
||||
"vue": "3.1.2",
|
||||
"vue-router": "^4.0.10",
|
||||
"vuedraggable": "^4.0.3",
|
||||
"vuex": "^4.0.1"
|
||||
"vuex": "^4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^12.1.4",
|
||||
"@commitlint/config-conventional": "^12.1.4",
|
||||
"@types/node": "^15.12.2",
|
||||
"@typescript-eslint/eslint-plugin": "^4.27.0",
|
||||
"@typescript-eslint/parser": "^4.27.0",
|
||||
"@vitejs/plugin-legacy": "^1.4.1",
|
||||
"@types/node": "^15.12.4",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.0",
|
||||
"@typescript-eslint/parser": "^4.28.0",
|
||||
"@vitejs/plugin-legacy": "^1.4.2",
|
||||
"@vitejs/plugin-vue": "^1.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^1.1.5",
|
||||
"@vue/compiler-sfc": "3.1.1",
|
||||
"@vue/compiler-sfc": "3.1.2",
|
||||
"commitizen": "^4.2.4",
|
||||
"cross-env": "^7.0.3",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"cz-customizable": "^6.3.0",
|
||||
"eslint": "^7.28.0",
|
||||
"eslint": "^7.29.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-import": "^2.23.4",
|
||||
"eslint-plugin-prettier": "^3.4.0",
|
||||
"eslint-plugin-vue": "^7.11.1",
|
||||
"gh-pages": "^3.2.1",
|
||||
"gh-pages": "^3.2.3",
|
||||
"husky": "^6.0.0",
|
||||
"lint-staged": "^11.0.0",
|
||||
"prettier": "^2.3.1",
|
||||
"pretty-quick": "^3.1.0",
|
||||
"sass": "1.35.0",
|
||||
"pretty-quick": "^3.1.1",
|
||||
"sass": "1.35.1",
|
||||
"stylelint": "^13.13.1",
|
||||
"stylelint-config-prettier": "^8.0.2",
|
||||
"stylelint-config-standard": "^22.0.0",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"typescript": "^4.3.2",
|
||||
"vite": "2.3.7",
|
||||
"vite-plugin-components": "^0.11.1",
|
||||
"vite-plugin-style-import": "^0.10.1",
|
||||
"vite-plugin-windicss": "^1.0.3",
|
||||
"typescript": "^4.3.4",
|
||||
"vite": "2.3.8",
|
||||
"vite-plugin-components": "^0.11.2",
|
||||
"vite-plugin-style-import": "^1.0.0",
|
||||
"vite-plugin-windicss": "^1.1.1",
|
||||
"vue-eslint-parser": "^7.6.0",
|
||||
"vue-tsc": "^0.1.7",
|
||||
"vue-tsc": "^0.2.0",
|
||||
"windicss": "^3.1.3"
|
||||
},
|
||||
"repository": {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-05-04 05:36:58
|
||||
* @LastEditTime: 2021-06-14 10:03:06
|
||||
* @LastEditTime: 2021-06-24 00:36:24
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description:
|
||||
* @FilePath: \vite-vue3-lowcode\preview\views\comp-render.tsx
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\simulator-editor\comp-render.tsx
|
||||
*/
|
||||
import { defineComponent, PropType } from 'vue'
|
||||
import { VisualEditorBlockData, VisualEditorConfig } from '@/visual-editor/visual-editor.utils'
|
||||
|
@ -22,15 +22,13 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
setup(props) {
|
||||
return () => {
|
||||
const component = props.config.componentMap[props.element.componentKey]
|
||||
return component.render({
|
||||
return () =>
|
||||
props.config.componentMap[props.element.componentKey].render({
|
||||
size: {},
|
||||
props: props.element.props || {},
|
||||
model: {},
|
||||
block: props.element,
|
||||
custom: {}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
<!--
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-01 09:45:21
|
||||
* @LastEditTime: 2021-06-24 00:19:14
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description:
|
||||
* @FilePath: \vite-vue3-lowcode\preview\views\preview.vue
|
||||
-->
|
||||
<template>
|
||||
<template v-for="outItem in currentPage" :key="outItem._vid">
|
||||
<template v-for="outItem in blocks" :key="outItem._vid">
|
||||
<slot-item :element="outItem" :config="visualConfig" />
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, toRefs } from 'vue'
|
||||
import { defineComponent, reactive, toRefs, onMounted } from 'vue'
|
||||
import { Toast } from 'vant'
|
||||
import { visualConfig } from '@/visual.config'
|
||||
import { CacheEnum } from '@/enums'
|
||||
|
@ -36,14 +44,24 @@ export default defineComponent({
|
|||
|
||||
const route = router.currentRoute
|
||||
|
||||
const currentPage = jsonData.pages[route.value.path]
|
||||
console.log('currentPage:', currentPage)
|
||||
|
||||
const state = reactive({
|
||||
currentPage: jsonData.pages[route.value.path]?.blocks
|
||||
blocks: currentPage?.blocks
|
||||
})
|
||||
|
||||
// 如果当前页面路由匹配不到,则重定向到首页
|
||||
if (!state.currentPage) {
|
||||
if (!state.blocks) {
|
||||
router.replace('/')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const { bgImage, bgColor } = currentPage.config
|
||||
document.body.style.setProperty('--image', `url(${bgImage})`)
|
||||
document.body.style.setProperty('--bg-color', bgColor)
|
||||
})
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
visualConfig
|
||||
|
@ -53,19 +71,8 @@ export default defineComponent({
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.h5-preview {
|
||||
overflow: hidden;
|
||||
|
||||
.el-dialog__header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.simulator {
|
||||
padding-right: 0;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
body {
|
||||
background-color: var(--bg-color);
|
||||
background-image: var(--image);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-01 09:45:21
|
||||
* @LastEditTime: 2021-06-22 23:13:09
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 分割线
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\divider\index.tsx
|
||||
*/
|
||||
import { Divider } from 'vant'
|
||||
import {
|
||||
createEditorColorProp,
|
||||
|
@ -41,7 +49,7 @@ export default {
|
|||
defaultValue: 'center'
|
||||
}),
|
||||
dashed: createEditorSwitchProp({ label: '是否为虚线' }),
|
||||
'text-color': createEditorColorProp('文本颜色'),
|
||||
'divider-color': createEditorColorProp('分割线颜色')
|
||||
'text-color': createEditorColorProp({ label: '文本颜色' }),
|
||||
'divider-color': createEditorColorProp({ label: '分割线颜色' })
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-05-04 05:36:58
|
||||
* @LastEditTime: 2021-06-22 22:51:42
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 导航栏
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\nav-bar\index.tsx
|
||||
*/
|
||||
import { NavBar } from 'vant'
|
||||
import 'vant/lib/nav-bar/index.css'
|
||||
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-12 22:18:48
|
||||
* @LastEditTime: 2021-06-22 23:14:22
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 进度条
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\process\index.tsx
|
||||
*/
|
||||
import { Progress } from 'vant'
|
||||
import {
|
||||
createEditorColorProp,
|
||||
|
@ -21,11 +29,11 @@ export default {
|
|||
percentage: createEditorInputNumberProp({ label: '进度百分比', defaultValue: 50 }),
|
||||
strokeWidth: createEditorInputNumberProp({ label: '线条粗细', defaultValue: 5 }),
|
||||
inactive: createEditorSwitchProp({ label: '是否置灰', defaultValue: false }),
|
||||
color: createEditorColorProp('进度条颜色', '#1989fa'),
|
||||
trackColor: createEditorColorProp('轨道颜色', '#e5e5e5'),
|
||||
color: createEditorColorProp({ label: '进度条颜色', defaultValue: '#1989fa' }),
|
||||
trackColor: createEditorColorProp({ label: '轨道颜色', defaultValue: '#e5e5e5' }),
|
||||
pivotText: createEditorInputProp({ label: '进度文字内容' }),
|
||||
pivotColor: createEditorColorProp('进度文字背景色', '#1989fa'),
|
||||
textColor: createEditorColorProp('进度文字颜色', '#ffffff'),
|
||||
pivotColor: createEditorColorProp({ label: '进度文字背景色', defaultValue: '#1989fa' }),
|
||||
textColor: createEditorColorProp({ label: '进度文字颜色', defaultValue: '#ffffff' }),
|
||||
showPivot: createEditorSwitchProp({ label: '是否显示进度文字', defaultValue: true })
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-01 09:45:21
|
||||
* @LastEditTime: 2021-06-22 23:08:50
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: '表单项类型 - 步进器
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\stepper\index.tsx
|
||||
*/
|
||||
import { Field, Stepper } from 'vant'
|
||||
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { createFieldProps } from './createFieldProps'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import {
|
||||
createEditorInputNumberProp,
|
||||
createEditorInputProp
|
||||
createEditorInputProp,
|
||||
createEditorSwitchProp,
|
||||
createEditorSelectProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
|
||||
export default {
|
||||
|
@ -45,9 +55,42 @@ export default {
|
|||
modelValue: createEditorInputNumberProp({ label: '默认值', defaultValue: 0 }),
|
||||
name: createEditorInputProp({ label: '字段名', defaultValue: 'stepper' }),
|
||||
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '步进器' }),
|
||||
min: createEditorInputNumberProp({ label: '最小值' }),
|
||||
min: createEditorInputNumberProp({ label: '最小值', defaultValue: 0 }),
|
||||
max: createEditorInputNumberProp({ label: '最大值' }),
|
||||
...createFieldProps()
|
||||
...createFieldProps(),
|
||||
allowEmpty: createEditorSwitchProp({ label: '是否允许输入的值为空', defaultValue: false }),
|
||||
buttonSize: createEditorInputProp({
|
||||
label: '按钮大小以及输入框高度,默认单位为 px',
|
||||
defaultValue: '28px'
|
||||
}),
|
||||
decimalLength: createEditorInputProp({ label: '固定显示的小数位数', defaultValue: '' }),
|
||||
defaultValue: createEditorInputProp({
|
||||
label: '初始值,当 v-model 为空时生效',
|
||||
defaultValue: '1'
|
||||
}),
|
||||
disableInput: createEditorSwitchProp({ label: '是否禁用输入框', defaultValue: false }),
|
||||
disableMinus: createEditorSwitchProp({ label: '是否禁用减少按钮', defaultValue: false }),
|
||||
disablePlus: createEditorSwitchProp({ label: '是否禁用增加按钮', defaultValue: false }),
|
||||
disabled: createEditorSwitchProp({ label: '是否禁用步进器', defaultValue: false }),
|
||||
inputWidth: createEditorInputProp({ label: '输入框宽度,默认单位为 px', defaultValue: '32px' }),
|
||||
integer: createEditorSwitchProp({ label: '是否只允许输入整数', defaultValue: false }),
|
||||
longPress: createEditorSwitchProp({ label: '是否开启长按手势', defaultValue: true }),
|
||||
placeholder: createEditorInputProp({ label: '输入框占位提示文字', defaultValue: '' }),
|
||||
showInput: createEditorSwitchProp({ label: '是否显示输入框', defaultValue: true }),
|
||||
showMinus: createEditorSwitchProp({ label: '是否显示减少按钮', defaultValue: true }),
|
||||
showPlus: createEditorSwitchProp({ label: '是否显示增加按钮', defaultValue: true }),
|
||||
step: createEditorInputProp({ label: '步长,每次点击时改变的值', defaultValue: '1' }),
|
||||
theme: createEditorSelectProp({
|
||||
label: '样式风格',
|
||||
options: [
|
||||
{
|
||||
label: '默认',
|
||||
value: ''
|
||||
},
|
||||
{ label: '圆角风格', value: 'round' }
|
||||
],
|
||||
defaultValue: ''
|
||||
})
|
||||
},
|
||||
resize: {
|
||||
width: true
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-14 12:24:12
|
||||
* @LastEditTime: 2021-06-14 18:43:21
|
||||
* @LastEditTime: 2021-06-21 23:04:42
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description:
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\swipe\createFieldProps.ts
|
||||
|
@ -18,9 +18,9 @@ export const createFieldProps = () => ({
|
|||
labelPosition: 'top',
|
||||
defaultValue: ['https://img.yzcdn.cn/vant/apple-1.jpg', 'https://img.yzcdn.cn/vant/apple-2.jpg']
|
||||
}),
|
||||
width: createEditorInputProp({ label: '滑块宽度,单位为 px', defaultValue: 'auto' }),
|
||||
// width: createEditorInputProp({ label: '滑块宽度,单位为 px', defaultValue: 'auto' }),
|
||||
height: createEditorInputProp({ label: '滑块高度,单位为 px', defaultValue: '200' }),
|
||||
autoplay: createEditorInputProp({ label: '自动轮播间隔,单位为 ms', defaultValue: '' }),
|
||||
autoplay: createEditorInputProp({ label: '自动轮播间隔,单位为 ms', defaultValue: '3000' }),
|
||||
duration: createEditorInputProp({ label: '动画时长,单位为 ms', defaultValue: '500' }),
|
||||
indicatorColor: createEditorInputProp({ label: '指示器颜色', defaultValue: '#1989fa' }),
|
||||
initialSwipe: createEditorInputProp({ label: '初始位置索引值', defaultValue: '0' }),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-14 12:24:12
|
||||
* @LastEditTime: 2021-06-14 21:19:28
|
||||
* @LastEditTime: 2021-06-21 23:06:36
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 轮播图组件
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\swipe\index.tsx
|
||||
|
@ -41,7 +41,7 @@ export default {
|
|||
{props.images?.map((item) => (
|
||||
<>
|
||||
<SwipeItem key={item}>
|
||||
<img src={item} />
|
||||
<img style={{ width: '100%' }} src={item} />
|
||||
</SwipeItem>
|
||||
</>
|
||||
))}
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-01 09:45:21
|
||||
* @LastEditTime: 2021-06-23 10:16:32
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 表单项类型 - 开关
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\switch\index.tsx
|
||||
*/
|
||||
import { Field, Switch } from 'vant'
|
||||
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { createFieldProps } from './createFieldProps'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { createEditorInputProp, createEditorSwitchProp } from '@/visual-editor/visual-editor.props'
|
||||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSwitchProp,
|
||||
createEditorColorProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
|
||||
export default {
|
||||
key: 'switch',
|
||||
|
@ -27,7 +39,6 @@ export default {
|
|||
ref={(el) => registerRef(el, block._vid)}
|
||||
{...props}
|
||||
v-model={props.modelValue}
|
||||
size={20}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
|
@ -38,13 +49,13 @@ export default {
|
|||
modelValue: createEditorInputProp({ label: '默认值', defaultValue: 'false' }),
|
||||
name: createEditorInputProp({ label: '字段名', defaultValue: 'switch' }),
|
||||
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '开关' }),
|
||||
'active-color': createEditorInputProp({ label: '打开时的背景色' }),
|
||||
'active-value': createEditorInputProp({ label: '打开时对应的值' }),
|
||||
activeColor: createEditorColorProp({ label: '打开时的背景色' }),
|
||||
activeValue: createEditorInputProp({ label: '打开时对应的值', defaultValue: 'true' }),
|
||||
inactiveColor: createEditorColorProp({ label: '关闭时的背景色' }),
|
||||
inactiveValue: createEditorInputProp({ label: '关闭时对应的值', defaultValue: 'false' }),
|
||||
disabled: createEditorSwitchProp({ label: '是否为禁用状态' }),
|
||||
'inactive-color': createEditorInputProp({ label: '关闭时的背景色' }),
|
||||
'inactive-value': createEditorInputProp({ label: '关闭时对应的值' }),
|
||||
loading: createEditorSwitchProp({ label: '是否为加载状态' }),
|
||||
size: createEditorInputProp({ label: '开关尺寸' }),
|
||||
size: createEditorInputProp({ label: '开关尺寸', defaultValue: '20px' }),
|
||||
...createFieldProps()
|
||||
},
|
||||
resize: {
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-01 09:45:21
|
||||
* @LastEditTime: 2021-06-14 10:17:54
|
||||
* @LastEditTime: 2021-06-22 23:14:46
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description:
|
||||
* @Description: 文本
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\text\index.tsx
|
||||
*/
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import {
|
||||
createEditorColorProp,
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp
|
||||
createEditorSelectProp,
|
||||
createEditorInputNumberProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { fontArr } from './fontArr'
|
||||
|
@ -26,7 +27,11 @@ export default {
|
|||
return (
|
||||
<div
|
||||
ref={(el) => registerRef(el, block._vid)}
|
||||
style={{ color: props.color, fontSize: props.size, fontFamily: props.font }}
|
||||
style={{
|
||||
color: props.color,
|
||||
fontSize: `${parseFloat(props.size)}px`,
|
||||
fontFamily: props.font
|
||||
}}
|
||||
>
|
||||
{props.text || '默认文本'}
|
||||
</div>
|
||||
|
@ -35,14 +40,10 @@ export default {
|
|||
props: {
|
||||
text: createEditorInputProp({ label: '显示文本' }),
|
||||
font: createEditorSelectProp({ label: '字体设置', options: fontArr }),
|
||||
color: createEditorColorProp('字体颜色'),
|
||||
size: createEditorSelectProp({
|
||||
color: createEditorColorProp({ label: '字体颜色' }),
|
||||
size: createEditorInputNumberProp({
|
||||
label: '字体大小',
|
||||
options: [
|
||||
{ label: '14px', value: '14px' },
|
||||
{ label: '18px', value: '18px' },
|
||||
{ label: '24px', value: '24px' }
|
||||
]
|
||||
defaultValue: 16
|
||||
})
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
<!--
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-01 13:30:22
|
||||
* @LastEditTime: 2021-06-14 00:21:31
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 手机模拟器
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\common\simulator.vue
|
||||
-->
|
||||
<template>
|
||||
<div class="simulator-container">
|
||||
<div class="simulator-editor">
|
||||
<div class="simulator-editor-content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="tsx">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Simulator'
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.simulator-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-right: 240px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@media (max-width: 1314px) {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.simulator-editor {
|
||||
width: 560px;
|
||||
height: 640px;
|
||||
min-width: 560px;
|
||||
padding: 10px 100px;
|
||||
overflow: hidden auto;
|
||||
background: #fafafa;
|
||||
border-radius: 5px;
|
||||
transform: translate(0);
|
||||
box-sizing: border-box;
|
||||
background-clip: content-box;
|
||||
contain: layout;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
&-content {
|
||||
min-height: 100%;
|
||||
box-shadow: 0 8px 12px #ebedf0;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,23 +1,25 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-01 13:22:14
|
||||
* @LastEditTime: 2021-06-12 14:39:38
|
||||
* @LastEditTime: 2021-06-23 11:40:10
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description:
|
||||
* @Description: 基础组件
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\base-widgets\index.tsx
|
||||
*/
|
||||
import { defineComponent } from 'vue'
|
||||
import { defineComponent, ref } from 'vue'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { visualConfig } from '@/visual.config'
|
||||
import Draggable from 'vuedraggable'
|
||||
import styles from './index.module.scss'
|
||||
import { createNewBlock } from '@/visual-editor/visual-editor.utils'
|
||||
import DraggableTransitionGroup from '@/visual-editor/components/simulator-editor/draggable-transition-group.vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BaseWidgets',
|
||||
setup() {
|
||||
const baseWidgets = ref(visualConfig.componentModules.baseWidgets)
|
||||
|
||||
const log = (evt) => {
|
||||
window.console.log(evt)
|
||||
window.console.log('onChange:', evt)
|
||||
}
|
||||
// 克隆组件
|
||||
const cloneDog = (comp) => {
|
||||
|
@ -29,15 +31,13 @@ export default defineComponent({
|
|||
|
||||
return () => (
|
||||
<>
|
||||
<Draggable
|
||||
<DraggableTransitionGroup
|
||||
class={styles.listGroup}
|
||||
sort={false}
|
||||
forceFallback={false}
|
||||
list={visualConfig.componentModules.baseWidgets}
|
||||
v-model={baseWidgets.value}
|
||||
group={{ name: 'components', pull: 'clone', put: false }}
|
||||
clone={cloneDog}
|
||||
item-key="_vid"
|
||||
onChange={log}
|
||||
itemKey={'key'}
|
||||
>
|
||||
{{
|
||||
item: ({ element }) => (
|
||||
|
@ -46,7 +46,7 @@ export default defineComponent({
|
|||
</div>
|
||||
)
|
||||
}}
|
||||
</Draggable>
|
||||
</DraggableTransitionGroup>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, computed, toRefs } from 'vue'
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData'
|
||||
import { useVisualData, createNewPage } from '@/visual-editor/hooks/useVisualData'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
|
@ -146,7 +146,7 @@ export default defineComponent({
|
|||
await router.replace(path)
|
||||
state.currentNodeKey = path
|
||||
} else {
|
||||
incrementPage(path, { title, blocks: [] })
|
||||
incrementPage(path, createNewPage({ title }))
|
||||
}
|
||||
state.dialogFormVisible = false
|
||||
}
|
||||
|
|
|
@ -51,10 +51,12 @@ export default defineComponent({
|
|||
::v-deep(.el-tabs__item) {
|
||||
height: 80px;
|
||||
padding: 20px 16px;
|
||||
|
||||
[class^='el-icon-'] {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep(.el-tabs__content) {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-10 16:23:06
|
||||
* @LastEditTime: 2021-06-14 17:22:11
|
||||
* @LastEditTime: 2021-06-21 10:00:54
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 组件属性编辑器
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\attr-editor\AttrEditor.tsx
|
||||
|
@ -30,6 +30,8 @@ export const AttrEditor = defineComponent({
|
|||
const renderEditor = (propName: string, propConfig: VisualEditorProps) => {
|
||||
const { propObj, prop } = useDotProp(currentBlock.value.props, propName)
|
||||
|
||||
propObj[prop] ??= propConfig.defaultValue
|
||||
|
||||
return {
|
||||
[VisualEditorPropsType.input]: () => (
|
||||
<ElInput v-model={propObj[prop]} placeholder={propConfig.tips || propConfig.label} />
|
||||
|
@ -43,7 +45,7 @@ export const AttrEditor = defineComponent({
|
|||
[VisualEditorPropsType.select]: () => (
|
||||
<ElSelect v-model={propObj[prop]} valueKey={'value'} multiple={propConfig.multiple}>
|
||||
{propConfig.options?.map((opt) => (
|
||||
<ElOption label={opt.label} value={opt.value} />
|
||||
<ElOption label={opt.label} style={{ fontFamily: opt.value }} value={opt.value} />
|
||||
))}
|
||||
</ElSelect>
|
||||
),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-12 22:18:48
|
||||
* @LastEditTime: 2021-06-14 18:53:02
|
||||
* @LastEditTime: 2021-06-23 22:17:38
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description:
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\index.ts
|
||||
|
@ -11,3 +11,4 @@ export { TablePropEditor } from './table-prop-editor/table-prop-editor'
|
|||
export { AttrEditor } from './attr-editor/AttrEditor'
|
||||
export { Animate } from './animate/Animate'
|
||||
export { CrossSortableOptionsEditor } from './cross-sortable-options-editor/cross-sortable-options-editor'
|
||||
export { PageSetting } from './page-setting/pageSetting'
|
||||
|
|
|
@ -1,8 +1,49 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-13 22:07:29
|
||||
* @LastEditTime: 2021-06-14 18:18:51
|
||||
* @LastEditTime: 2021-06-24 00:23:39
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 当前页面配置
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\page-setting\pageSetting.tsx
|
||||
*/
|
||||
import { defineComponent } from 'vue'
|
||||
import { ElForm, ElFormItem, ElInput, ElUpload, ElColorPicker } from 'element-plus'
|
||||
import styles from './styles.module.scss'
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData'
|
||||
|
||||
export const PageSetting = defineComponent({
|
||||
setup() {
|
||||
const { currentPage } = useVisualData()
|
||||
|
||||
const pageConfig = currentPage.value.config
|
||||
|
||||
const beforeUpload = (file: File) => {
|
||||
console.log(file, '要上传的文件')
|
||||
const fileReader = new FileReader()
|
||||
fileReader.onload = (event) => {
|
||||
pageConfig.bgImage = event.target?.result as string
|
||||
}
|
||||
fileReader.readAsDataURL(file)
|
||||
}
|
||||
|
||||
return () => (
|
||||
<>
|
||||
<ElForm>
|
||||
<ElFormItem label="背景颜色">
|
||||
<ElColorPicker v-model={pageConfig.bgColor} />
|
||||
</ElFormItem>
|
||||
<ElFormItem label="背景图片">
|
||||
<ElInput v-model={pageConfig.bgImage} placeholder={'图片地址'} />
|
||||
</ElFormItem>
|
||||
<ElUpload action={''} beforeUpload={beforeUpload} class={styles.upload}>
|
||||
{pageConfig.bgImage ? (
|
||||
<img src={pageConfig.bgImage} />
|
||||
) : (
|
||||
<i class="el-icon-plus uploader-icon"></i>
|
||||
)}
|
||||
</ElUpload>
|
||||
</ElForm>
|
||||
</>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
.upload {
|
||||
:global {
|
||||
.el-upload {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.uploader-icon {
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
font-size: 28px;
|
||||
line-height: 178px;
|
||||
color: #8c939d;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-01 13:22:14
|
||||
* @LastEditTime: 2021-06-13 21:26:49
|
||||
* @LastEditTime: 2021-06-23 22:18:34
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 属性编辑器
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\index.tsx
|
||||
|
@ -13,7 +13,7 @@ import styles from './index.module.scss'
|
|||
import { ElTabPane, ElTabs } from 'element-plus'
|
||||
import MonacoEditor from '../common/monaco-editor/MonacoEditor'
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData'
|
||||
import { AttrEditor, Animate } from './components'
|
||||
import { AttrEditor, Animate, PageSetting } from './components'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RightAttributePanel',
|
||||
|
@ -57,6 +57,9 @@ export default defineComponent({
|
|||
title=""
|
||||
/>
|
||||
</ElTabPane>
|
||||
<ElTabPane label="页面设置" name="page-setting">
|
||||
<PageSetting />
|
||||
</ElTabPane>
|
||||
</ElTabs>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-05-04 05:36:58
|
||||
* @LastEditTime: 2021-06-14 10:02:47
|
||||
* @LastEditTime: 2021-06-24 00:36:24
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description:
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\simulator-editor\comp-render.tsx
|
||||
|
@ -22,15 +22,13 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
setup(props) {
|
||||
return () => {
|
||||
const component = props.config.componentMap[props.element.componentKey]
|
||||
return component.render({
|
||||
return () =>
|
||||
props.config.componentMap[props.element.componentKey].render({
|
||||
size: {},
|
||||
props: props.element.props || {},
|
||||
model: {},
|
||||
block: props.element,
|
||||
custom: {}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
type: 'transition-group',
|
||||
name: !isDrag ? 'flip-list' : null
|
||||
}"
|
||||
item-key="_vid"
|
||||
v-bind="dragOptions"
|
||||
:group="group"
|
||||
v-bind="{ ...dragOptions, $attrs }"
|
||||
:item-key="itemKey"
|
||||
@start="isDrag = true"
|
||||
@end="isDrag = false"
|
||||
@change="log"
|
||||
>
|
||||
<template #item="item">
|
||||
<div>
|
||||
|
@ -46,7 +46,16 @@ export default defineComponent({
|
|||
drag: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
itemKey: {
|
||||
type: String,
|
||||
default: '_vid'
|
||||
},
|
||||
group: {
|
||||
type: Object,
|
||||
default: () => ({ name: 'components' })
|
||||
},
|
||||
fallbackClass: String
|
||||
},
|
||||
emits: ['update:moduleValue', 'update:drag'],
|
||||
setup(props, { emit }: SetupContext) {
|
||||
|
@ -57,17 +66,12 @@ export default defineComponent({
|
|||
|
||||
const dragOptions = computed(() => ({
|
||||
animation: 200,
|
||||
group: 'components',
|
||||
disabled: false,
|
||||
ghostClass: 'ghost'
|
||||
}))
|
||||
const log = () => {
|
||||
// console.log('接收的组件:', evt)
|
||||
// console.log('全部组件:', state.VMBlocks)
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
log,
|
||||
dragOptions
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,49 +1,59 @@
|
|||
<template>
|
||||
<DraggableTransitionGroup
|
||||
v-model:drag="drag"
|
||||
v-model="currentPage.blocks"
|
||||
style="min-height: 500px"
|
||||
>
|
||||
<template #item="{ element: outElement }">
|
||||
<div
|
||||
class="list-group-item"
|
||||
:data-label="outElement.label"
|
||||
:class="{
|
||||
focus: outElement.focus,
|
||||
focusWithChild: outElement.focusWithChild,
|
||||
drag,
|
||||
['has-slot']: !!Object.keys(outElement.props.slots || {}).length
|
||||
}"
|
||||
@contextmenu.stop.prevent="onContextmenuBlock($event, outElement)"
|
||||
@mousedown="selectComp(outElement)"
|
||||
>
|
||||
<comp-render
|
||||
:key="outElement._vid"
|
||||
:config="visualConfig"
|
||||
:element="outElement"
|
||||
:style="{
|
||||
pointerEvents: Object.keys(outElement.props?.slots || {}).length ? 'auto' : 'none'
|
||||
}"
|
||||
<div class="simulator-container">
|
||||
<div class="simulator-editor">
|
||||
<div class="simulator-editor-content" :style="pageStyle">
|
||||
<DraggableTransitionGroup
|
||||
v-model:drag="drag"
|
||||
v-model="currentPage.blocks"
|
||||
style="min-height: 500px"
|
||||
>
|
||||
<template v-for="(value, slotKey) in outElement.props?.slots" :key="slotKey" #[slotKey]>
|
||||
<SlotItem
|
||||
v-model:children="value.children"
|
||||
v-model:drag="drag"
|
||||
:slot-key="slotKey"
|
||||
:config="visualConfig"
|
||||
:on-contextmenu-block="onContextmenuBlock"
|
||||
:select-comp="selectComp"
|
||||
:delete-comp="deleteComp"
|
||||
/>
|
||||
<template #item="{ element: outElement }">
|
||||
<div
|
||||
class="list-group-item"
|
||||
:data-label="outElement.label"
|
||||
:class="{
|
||||
focus: outElement.focus,
|
||||
focusWithChild: outElement.focusWithChild,
|
||||
drag,
|
||||
['has-slot']: !!Object.keys(outElement.props.slots || {}).length
|
||||
}"
|
||||
@contextmenu.stop.prevent="onContextmenuBlock($event, outElement)"
|
||||
@mousedown="selectComp(outElement)"
|
||||
>
|
||||
<comp-render
|
||||
:key="outElement._vid"
|
||||
:config="visualConfig"
|
||||
:element="outElement"
|
||||
:style="{
|
||||
pointerEvents: Object.keys(outElement.props?.slots || {}).length ? 'auto' : 'none'
|
||||
}"
|
||||
>
|
||||
<template
|
||||
v-for="(value, slotKey) in outElement.props?.slots"
|
||||
:key="slotKey"
|
||||
#[slotKey]
|
||||
>
|
||||
<SlotItem
|
||||
v-model:children="value.children"
|
||||
v-model:drag="drag"
|
||||
:slot-key="slotKey"
|
||||
:config="visualConfig"
|
||||
:on-contextmenu-block="onContextmenuBlock"
|
||||
:select-comp="selectComp"
|
||||
:delete-comp="deleteComp"
|
||||
/>
|
||||
</template>
|
||||
</comp-render>
|
||||
</div>
|
||||
</template>
|
||||
</comp-render>
|
||||
</DraggableTransitionGroup>
|
||||
</div>
|
||||
</template>
|
||||
</DraggableTransitionGroup>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="tsx">
|
||||
import { defineComponent, reactive, toRefs } from 'vue'
|
||||
import { defineComponent, reactive, computed, toRefs } from 'vue'
|
||||
import { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils'
|
||||
import DraggableTransitionGroup from './draggable-transition-group.vue'
|
||||
import { $$dropdown, DropdownOption } from '@/visual-editor/utils/dropdown-service'
|
||||
|
@ -62,14 +72,22 @@ export default defineComponent({
|
|||
},
|
||||
emits: ['on-selected'],
|
||||
setup() {
|
||||
const { globalProperties } = useGlobalProperties()
|
||||
|
||||
const { currentPage, visualConfig, setCurrentBlock } = useVisualData()
|
||||
|
||||
const { globalProperties } = useGlobalProperties()
|
||||
|
||||
const state = reactive({
|
||||
drag: false
|
||||
})
|
||||
|
||||
const pageStyle = computed(() => {
|
||||
const { bgImage, bgColor } = currentPage.value.config
|
||||
return {
|
||||
backgroundImage: `url(${bgImage})`,
|
||||
backgroundColor: bgColor
|
||||
}
|
||||
})
|
||||
|
||||
//递归实现
|
||||
//@leafId 为你要查找的id,
|
||||
//@nodes 为原始Json数据
|
||||
|
@ -196,6 +214,7 @@ export default defineComponent({
|
|||
...toRefs(state),
|
||||
currentPage,
|
||||
visualConfig,
|
||||
pageStyle,
|
||||
deleteComp,
|
||||
selectComp,
|
||||
onContextmenuBlock
|
||||
|
@ -206,12 +225,52 @@ export default defineComponent({
|
|||
<style lang="scss" scoped>
|
||||
@import './func.scss';
|
||||
|
||||
.simulator-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-right: 240px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@media (max-width: 1314px) {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.simulator-editor {
|
||||
width: 560px;
|
||||
height: 640px;
|
||||
min-width: 560px;
|
||||
padding: 10px 100px;
|
||||
overflow: hidden auto;
|
||||
background: #fafafa;
|
||||
border-radius: 5px;
|
||||
transform: translate(0);
|
||||
box-sizing: border-box;
|
||||
background-clip: content-box;
|
||||
contain: layout;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
&-content {
|
||||
min-height: 100%;
|
||||
box-shadow: 0 8px 12px #ebedf0;
|
||||
}
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
position: relative;
|
||||
padding: 3px;
|
||||
cursor: move;
|
||||
transform: translate(0);
|
||||
|
||||
> div {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&.focus {
|
||||
content: '';
|
||||
outline: 2px solid #006eff;
|
||||
|
|
|
@ -5,7 +5,16 @@
|
|||
* @description:useVisualData
|
||||
* @update: 2021/5/6 11:59
|
||||
*/
|
||||
import { reactive, inject, readonly, computed, watch, ComputedRef, DeepReadonly } from 'vue'
|
||||
import {
|
||||
reactive,
|
||||
inject,
|
||||
readonly,
|
||||
computed,
|
||||
watch,
|
||||
ComputedRef,
|
||||
InjectionKey,
|
||||
DeepReadonly
|
||||
} from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import {
|
||||
VisualEditorModelValue,
|
||||
|
@ -21,7 +30,7 @@ import { CacheEnum } from '@/enums'
|
|||
export const localKey = CacheEnum.PAGE_DATA_KEY
|
||||
|
||||
// 注入jsonData的key
|
||||
export const injectKey = Symbol('injectKey')
|
||||
export const injectKey: InjectionKey<string> = Symbol()
|
||||
|
||||
interface IState {
|
||||
currentBlock: VisualEditorBlockData // 当前正在操作的组件
|
||||
|
@ -43,17 +52,26 @@ export interface VisualData {
|
|||
setCurrentBlock: (block: VisualEditorBlockData) => void // 设置当前正在操作的组件
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 创建空的新页面
|
||||
*/
|
||||
export const createNewPage = ({ title = '新页面', path = '/' }) => ({
|
||||
title,
|
||||
path,
|
||||
config: {
|
||||
bgColor: '',
|
||||
bgImage: ''
|
||||
},
|
||||
blocks: []
|
||||
})
|
||||
|
||||
const defaultValue: VisualEditorModelValue = {
|
||||
container: {
|
||||
width: 360,
|
||||
height: 960
|
||||
},
|
||||
pages: {
|
||||
'/': {
|
||||
title: '首页',
|
||||
path: '/',
|
||||
blocks: []
|
||||
}
|
||||
'/': createNewPage({ title: '首页' })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +124,7 @@ export const initVisualData = (): VisualData => {
|
|||
}
|
||||
// 添加page
|
||||
const incrementPage = (path = '', page: VisualEditorPage) => {
|
||||
state.jsonData.pages[getPrefixPath(path)] ??= page ?? { title: '新页面', path, blocks: [] }
|
||||
state.jsonData.pages[getPrefixPath(path)] ??= page ?? createNewPage({ path })
|
||||
}
|
||||
// 删除page
|
||||
const deletePage = (path = '', redirectPath = '') => {
|
||||
|
|
|
@ -13,9 +13,7 @@
|
|||
</el-aside>
|
||||
<el-main>
|
||||
<!-- 中间编辑区域start -->
|
||||
<Simulator>
|
||||
<simulator-editor />
|
||||
</Simulator>
|
||||
<simulator-editor />
|
||||
<!-- 中间编辑区域end -->
|
||||
|
||||
<!-- 右侧属性面板start -->
|
||||
|
@ -31,7 +29,6 @@ import Header from './components/header/index.vue'
|
|||
import LeftAside from './components/left-aside/index.vue'
|
||||
import RightAttributePanel from './components/right-attribute-panel'
|
||||
import SimulatorEditor from './components/simulator-editor/simulator-editor.vue'
|
||||
import Simulator from './components/common/simulator.vue'
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
@ -84,7 +84,12 @@ export function createEditorInputNumberProp({
|
|||
|
||||
/*---------------------------------------color-------------------------------------------*/
|
||||
|
||||
export function createEditorColorProp(label: string, defaultValue?: string): VisualEditorProps {
|
||||
interface EditorColorProp {
|
||||
label: string
|
||||
defaultValue?: string
|
||||
}
|
||||
|
||||
export function createEditorColorProp({ label, defaultValue }: EditorColorProp): VisualEditorProps {
|
||||
return {
|
||||
type: VisualEditorPropsType.color,
|
||||
label,
|
||||
|
|
|
@ -2,6 +2,9 @@ import { VisualEditorProps } from './visual-editor.props'
|
|||
import { inject, provide } from 'vue'
|
||||
import { useDotProp } from '@/visual-editor/hooks/useDotProp'
|
||||
|
||||
/**
|
||||
* @description 组件属性
|
||||
*/
|
||||
export interface VisualEditorBlockData {
|
||||
_vid: string // 组件id 时间戳
|
||||
moduleName: keyof ComponentModules // 组件所属的模块(基础组件、容器组件)
|
||||
|
@ -21,14 +24,26 @@ export interface VisualEditorBlockData {
|
|||
animations?: Animation[] // 动画集
|
||||
[prop: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 页面配置
|
||||
*/
|
||||
export interface PageConfig {
|
||||
bgImage: string // 背景图片
|
||||
bgColor: string // 背景颜色
|
||||
}
|
||||
/**
|
||||
* @description 页面对象
|
||||
*/
|
||||
export interface VisualEditorPage {
|
||||
title: string // 页面标题
|
||||
path: string // 页面路径
|
||||
isDefault?: boolean // 404是重定向到默认页面
|
||||
config: PageConfig // 页面配置
|
||||
blocks: VisualEditorBlockData[] // 当前页面的所有组件
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 可以认为是 路由=>页面
|
||||
*/
|
||||
export interface VisualEditorPages {
|
||||
[path: string]: VisualEditorPage
|
||||
}
|
||||
|
|
|
@ -29,9 +29,10 @@ export default ({ mode }: ConfigEnv): UserConfig => {
|
|||
targets: ['defaults', 'not IE 11']
|
||||
}),
|
||||
ViteComponents({
|
||||
globalComponentsDeclaration: true,
|
||||
// 自动导入组件(还不够完善,可能会有样式丢失)
|
||||
// valid file extensions for components.
|
||||
extensions: ['vue', 'tsx'],
|
||||
extensions: ['vue', 'tsx', 'js'],
|
||||
customComponentResolvers: [ElementPlusResolver(), VantResolver()]
|
||||
}),
|
||||
styleImport({
|
||||
|
|
Loading…
Reference in New Issue