feat(component): pageSetting

pull/15/head
bqy_fe 3 years ago
parent 5f99924474
commit f387fa8993
  1. 9
      .github/workflows/deploy.yml
  2. 29
      components.d.ts
  3. 47
      package.json
  4. 10
      preview/views/comp-render.tsx
  5. 43
      preview/views/preview.vue
  6. 12
      src/packages/base-widgets/divider/index.tsx
  7. 8
      src/packages/base-widgets/nav-bar/index.tsx
  8. 16
      src/packages/base-widgets/process/index.tsx
  9. 49
      src/packages/base-widgets/stepper/index.tsx
  10. 6
      src/packages/base-widgets/swipe/createFieldProps.ts
  11. 4
      src/packages/base-widgets/swipe/index.tsx
  12. 25
      src/packages/base-widgets/switch/index.tsx
  13. 23
      src/packages/base-widgets/text/index.tsx
  14. 62
      src/visual-editor/components/common/simulator.vue
  15. 22
      src/visual-editor/components/left-aside/components/base-widgets/index.tsx
  16. 4
      src/visual-editor/components/left-aside/components/page-tree/index.vue
  17. 2
      src/visual-editor/components/left-aside/index.vue
  18. 6
      src/visual-editor/components/right-attribute-panel/components/attr-editor/AttrEditor.tsx
  19. 3
      src/visual-editor/components/right-attribute-panel/components/index.ts
  20. 43
      src/visual-editor/components/right-attribute-panel/components/page-setting/pageSetting.tsx
  21. 20
      src/visual-editor/components/right-attribute-panel/components/page-setting/styles.module.scss
  22. 7
      src/visual-editor/components/right-attribute-panel/index.tsx
  23. 8
      src/visual-editor/components/simulator-editor/comp-render.tsx
  24. 24
      src/visual-editor/components/simulator-editor/draggable-transition-group.vue
  25. 141
      src/visual-editor/components/simulator-editor/simulator-editor.vue
  26. 34
      src/visual-editor/hooks/useVisualData.ts
  27. 5
      src/visual-editor/index.vue
  28. 7
      src/visual-editor/visual-editor.props.tsx
  29. 19
      src/visual-editor/visual-editor.utils.ts
  30. 3
      vite.config.ts
  31. 630
      yarn.lock

@ -1,5 +1,10 @@
name: deploy 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: on:
push: push:
branches: [main] branches: [main]
@ -16,10 +21,10 @@ jobs:
node-version: '14.x' node-version: '14.x'
- name: Install - name: Install
run: npm install run: yarn install --frozen-lockfile
- name: Build - name: Build
run: npm run build run: yarn build
- name: Deploy - name: Deploy
uses: peaceiris/actions-gh-pages@v3 uses: peaceiris/actions-gh-pages@v3

29
components.d.ts vendored

@ -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 {}

@ -4,8 +4,8 @@
"private": false, "private": false,
"description": "A Vite2.x + Vue3 + TypeScript LowCode", "description": "A Vite2.x + Vue3 + TypeScript LowCode",
"scripts": { "scripts": {
"dev": "vite", "dev": "cross-env --max_old_space_size=4096 vite",
"build": "vite build", "build": "cross-env vite build",
"build-tsc": "vue-tsc --noEmit && vite build", "build-tsc": "vue-tsc --noEmit && vite build",
"serve": "vite preview", "serve": "vite preview",
"deploy": "gh-pages -d dist", "deploy": "gh-pages -d dist",
@ -27,53 +27,54 @@
"axios": "^0.21.1", "axios": "^0.21.1",
"dayjs": "^1.10.5", "dayjs": "^1.10.5",
"dexie": "^3.0.3", "dexie": "^3.0.3",
"element-plus": "^1.0.2-beta.48", "element-plus": "1.0.2-beta.51",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"monaco-editor": "^0.25.0", "monaco-editor": "^0.25.2",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"nprogress": "^1.0.0-1", "nprogress": "^1.0.0-1",
"qrcode": "^1.4.4", "qrcode": "^1.4.4",
"vant": "^3.0.18", "vant": "^3.1.0",
"vue": "3.1.1", "vue": "3.1.2",
"vue-router": "^4.0.8", "vue-router": "^4.0.10",
"vuedraggable": "^4.0.3", "vuedraggable": "^4.0.3",
"vuex": "^4.0.1" "vuex": "^4.0.2"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^12.1.4", "@commitlint/cli": "^12.1.4",
"@commitlint/config-conventional": "^12.1.4", "@commitlint/config-conventional": "^12.1.4",
"@types/node": "^15.12.2", "@types/node": "^15.12.4",
"@typescript-eslint/eslint-plugin": "^4.27.0", "@typescript-eslint/eslint-plugin": "^4.28.0",
"@typescript-eslint/parser": "^4.27.0", "@typescript-eslint/parser": "^4.28.0",
"@vitejs/plugin-legacy": "^1.4.1", "@vitejs/plugin-legacy": "^1.4.2",
"@vitejs/plugin-vue": "^1.2.3", "@vitejs/plugin-vue": "^1.2.3",
"@vitejs/plugin-vue-jsx": "^1.1.5", "@vitejs/plugin-vue-jsx": "^1.1.5",
"@vue/compiler-sfc": "3.1.1", "@vue/compiler-sfc": "3.1.2",
"commitizen": "^4.2.4", "commitizen": "^4.2.4",
"cross-env": "^7.0.3",
"cz-conventional-changelog": "^3.3.0", "cz-conventional-changelog": "^3.3.0",
"cz-customizable": "^6.3.0", "cz-customizable": "^6.3.0",
"eslint": "^7.28.0", "eslint": "^7.29.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.23.4", "eslint-plugin-import": "^2.23.4",
"eslint-plugin-prettier": "^3.4.0", "eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-vue": "^7.11.1", "eslint-plugin-vue": "^7.11.1",
"gh-pages": "^3.2.1", "gh-pages": "^3.2.3",
"husky": "^6.0.0", "husky": "^6.0.0",
"lint-staged": "^11.0.0", "lint-staged": "^11.0.0",
"prettier": "^2.3.1", "prettier": "^2.3.1",
"pretty-quick": "^3.1.0", "pretty-quick": "^3.1.1",
"sass": "1.35.0", "sass": "1.35.1",
"stylelint": "^13.13.1", "stylelint": "^13.13.1",
"stylelint-config-prettier": "^8.0.2", "stylelint-config-prettier": "^8.0.2",
"stylelint-config-standard": "^22.0.0", "stylelint-config-standard": "^22.0.0",
"stylelint-order": "^4.1.0", "stylelint-order": "^4.1.0",
"typescript": "^4.3.2", "typescript": "^4.3.4",
"vite": "2.3.7", "vite": "2.3.8",
"vite-plugin-components": "^0.11.1", "vite-plugin-components": "^0.11.2",
"vite-plugin-style-import": "^0.10.1", "vite-plugin-style-import": "^1.0.0",
"vite-plugin-windicss": "^1.0.3", "vite-plugin-windicss": "^1.1.1",
"vue-eslint-parser": "^7.6.0", "vue-eslint-parser": "^7.6.0",
"vue-tsc": "^0.1.7", "vue-tsc": "^0.2.0",
"windicss": "^3.1.3" "windicss": "^3.1.3"
}, },
"repository": { "repository": {

@ -1,10 +1,10 @@
/* /*
* @Author: * @Author:
* @Date: 2021-05-04 05:36:58 * @Date: 2021-05-04 05:36:58
* @LastEditTime: 2021-06-14 10:03:06 * @LastEditTime: 2021-06-24 00:36:24
* @LastEditors: * @LastEditors:
* @Description: * @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 { defineComponent, PropType } from 'vue'
import { VisualEditorBlockData, VisualEditorConfig } from '@/visual-editor/visual-editor.utils' import { VisualEditorBlockData, VisualEditorConfig } from '@/visual-editor/visual-editor.utils'
@ -22,15 +22,13 @@ export default defineComponent({
} }
}, },
setup(props) { setup(props) {
return () => { return () =>
const component = props.config.componentMap[props.element.componentKey] props.config.componentMap[props.element.componentKey].render({
return component.render({
size: {}, size: {},
props: props.element.props || {}, props: props.element.props || {},
model: {}, model: {},
block: props.element, block: props.element,
custom: {} 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>
<template v-for="outItem in currentPage" :key="outItem._vid"> <template v-for="outItem in blocks" :key="outItem._vid">
<slot-item :element="outItem" :config="visualConfig" /> <slot-item :element="outItem" :config="visualConfig" />
</template> </template>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, reactive, toRefs } from 'vue' import { defineComponent, reactive, toRefs, onMounted } from 'vue'
import { Toast } from 'vant' import { Toast } from 'vant'
import { visualConfig } from '@/visual.config' import { visualConfig } from '@/visual.config'
import { CacheEnum } from '@/enums' import { CacheEnum } from '@/enums'
@ -36,14 +44,24 @@ export default defineComponent({
const route = router.currentRoute const route = router.currentRoute
const currentPage = jsonData.pages[route.value.path]
console.log('currentPage:', currentPage)
const state = reactive({ const state = reactive({
currentPage: jsonData.pages[route.value.path]?.blocks blocks: currentPage?.blocks
}) })
// //
if (!state.currentPage) { if (!state.blocks) {
router.replace('/') router.replace('/')
} }
onMounted(() => {
const { bgImage, bgColor } = currentPage.config
document.body.style.setProperty('--image', `url(${bgImage})`)
document.body.style.setProperty('--bg-color', bgColor)
})
return { return {
...toRefs(state), ...toRefs(state),
visualConfig visualConfig
@ -53,19 +71,8 @@ export default defineComponent({
</script> </script>
<style lang="scss"> <style lang="scss">
.h5-preview { body {
overflow: hidden; background-color: var(--bg-color);
background-image: var(--image);
.el-dialog__header {
display: none;
}
.simulator {
padding-right: 0;
&::-webkit-scrollbar {
width: 0;
}
}
} }
</style> </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 { Divider } from 'vant'
import { import {
createEditorColorProp, createEditorColorProp,
@ -41,7 +49,7 @@ export default {
defaultValue: 'center' defaultValue: 'center'
}), }),
dashed: createEditorSwitchProp({ label: '是否为虚线' }), dashed: createEditorSwitchProp({ label: '是否为虚线' }),
'text-color': createEditorColorProp('文本颜色'), 'text-color': createEditorColorProp({ label: '文本颜色' }),
'divider-color': createEditorColorProp('分割线颜色') 'divider-color': createEditorColorProp({ label: '分割线颜色' })
} }
} as VisualEditorComponent } 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 { NavBar } from 'vant'
import 'vant/lib/nav-bar/index.css' import 'vant/lib/nav-bar/index.css'
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils' 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 { Progress } from 'vant'
import { import {
createEditorColorProp, createEditorColorProp,
@ -21,11 +29,11 @@ export default {
percentage: createEditorInputNumberProp({ label: '进度百分比', defaultValue: 50 }), percentage: createEditorInputNumberProp({ label: '进度百分比', defaultValue: 50 }),
strokeWidth: createEditorInputNumberProp({ label: '线条粗细', defaultValue: 5 }), strokeWidth: createEditorInputNumberProp({ label: '线条粗细', defaultValue: 5 }),
inactive: createEditorSwitchProp({ label: '是否置灰', defaultValue: false }), inactive: createEditorSwitchProp({ label: '是否置灰', defaultValue: false }),
color: createEditorColorProp('进度条颜色', '#1989fa'), color: createEditorColorProp({ label: '进度条颜色', defaultValue: '#1989fa' }),
trackColor: createEditorColorProp('轨道颜色', '#e5e5e5'), trackColor: createEditorColorProp({ label: '轨道颜色', defaultValue: '#e5e5e5' }),
pivotText: createEditorInputProp({ label: '进度文字内容' }), pivotText: createEditorInputProp({ label: '进度文字内容' }),
pivotColor: createEditorColorProp('进度文字背景色', '#1989fa'), pivotColor: createEditorColorProp({ label: '进度文字背景色', defaultValue: '#1989fa' }),
textColor: createEditorColorProp('进度文字颜色', '#ffffff'), textColor: createEditorColorProp({ label: '进度文字颜色', defaultValue: '#ffffff' }),
showPivot: createEditorSwitchProp({ label: '是否显示进度文字', defaultValue: true }) showPivot: createEditorSwitchProp({ label: '是否显示进度文字', defaultValue: true })
} }
} as VisualEditorComponent } 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 { Field, Stepper } from 'vant'
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils' import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
import { createFieldProps } from './createFieldProps' import { createFieldProps } from './createFieldProps'
import { useGlobalProperties } from '@/hooks/useGlobalProperties' import { useGlobalProperties } from '@/hooks/useGlobalProperties'
import { import {
createEditorInputNumberProp, createEditorInputNumberProp,
createEditorInputProp createEditorInputProp,
createEditorSwitchProp,
createEditorSelectProp
} from '@/visual-editor/visual-editor.props' } from '@/visual-editor/visual-editor.props'
export default { export default {
@ -45,9 +55,42 @@ export default {
modelValue: createEditorInputNumberProp({ label: '默认值', defaultValue: 0 }), modelValue: createEditorInputNumberProp({ label: '默认值', defaultValue: 0 }),
name: createEditorInputProp({ label: '字段名', defaultValue: 'stepper' }), name: createEditorInputProp({ label: '字段名', defaultValue: 'stepper' }),
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '步进器' }), label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '步进器' }),
min: createEditorInputNumberProp({ label: '最小值' }), min: createEditorInputNumberProp({ label: '最小值', defaultValue: 0 }),
max: createEditorInputNumberProp({ label: '最大值' }), 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: { resize: {
width: true width: true

@ -1,7 +1,7 @@
/* /*
* @Author: * @Author:
* @Date: 2021-06-14 12:24:12 * @Date: 2021-06-14 12:24:12
* @LastEditTime: 2021-06-14 18:43:21 * @LastEditTime: 2021-06-21 23:04:42
* @LastEditors: * @LastEditors:
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\swipe\createFieldProps.ts * @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\swipe\createFieldProps.ts
@ -18,9 +18,9 @@ export const createFieldProps = () => ({
labelPosition: 'top', labelPosition: 'top',
defaultValue: ['https://img.yzcdn.cn/vant/apple-1.jpg', 'https://img.yzcdn.cn/vant/apple-2.jpg'] 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' }), height: createEditorInputProp({ label: '滑块高度,单位为 px', defaultValue: '200' }),
autoplay: createEditorInputProp({ label: '自动轮播间隔,单位为 ms', defaultValue: '' }), autoplay: createEditorInputProp({ label: '自动轮播间隔,单位为 ms', defaultValue: '3000' }),
duration: createEditorInputProp({ label: '动画时长,单位为 ms', defaultValue: '500' }), duration: createEditorInputProp({ label: '动画时长,单位为 ms', defaultValue: '500' }),
indicatorColor: createEditorInputProp({ label: '指示器颜色', defaultValue: '#1989fa' }), indicatorColor: createEditorInputProp({ label: '指示器颜色', defaultValue: '#1989fa' }),
initialSwipe: createEditorInputProp({ label: '初始位置索引值', defaultValue: '0' }), initialSwipe: createEditorInputProp({ label: '初始位置索引值', defaultValue: '0' }),

@ -1,7 +1,7 @@
/* /*
* @Author: * @Author:
* @Date: 2021-06-14 12:24:12 * @Date: 2021-06-14 12:24:12
* @LastEditTime: 2021-06-14 21:19:28 * @LastEditTime: 2021-06-21 23:06:36
* @LastEditors: * @LastEditors:
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\swipe\index.tsx * @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\swipe\index.tsx
@ -41,7 +41,7 @@ export default {
{props.images?.map((item) => ( {props.images?.map((item) => (
<> <>
<SwipeItem key={item}> <SwipeItem key={item}>
<img src={item} /> <img style={{ width: '100%' }} src={item} />
</SwipeItem> </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 { Field, Switch } from 'vant'
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils' import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
import { createFieldProps } from './createFieldProps' import { createFieldProps } from './createFieldProps'
import { useGlobalProperties } from '@/hooks/useGlobalProperties' 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 { export default {
key: 'switch', key: 'switch',
@ -27,7 +39,6 @@ export default {
ref={(el) => registerRef(el, block._vid)} ref={(el) => registerRef(el, block._vid)}
{...props} {...props}
v-model={props.modelValue} v-model={props.modelValue}
size={20}
/> />
) )
}} }}
@ -38,13 +49,13 @@ export default {
modelValue: createEditorInputProp({ label: '默认值', defaultValue: 'false' }), modelValue: createEditorInputProp({ label: '默认值', defaultValue: 'false' }),
name: createEditorInputProp({ label: '字段名', defaultValue: 'switch' }), name: createEditorInputProp({ label: '字段名', defaultValue: 'switch' }),
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '开关' }), label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '开关' }),
'active-color': createEditorInputProp({ label: '打开时的背景色' }), activeColor: createEditorColorProp({ label: '打开时的背景色' }),
'active-value': createEditorInputProp({ label: '打开时对应的值' }), activeValue: createEditorInputProp({ label: '打开时对应的值', defaultValue: 'true' }),
inactiveColor: createEditorColorProp({ label: '关闭时的背景色' }),
inactiveValue: createEditorInputProp({ label: '关闭时对应的值', defaultValue: 'false' }),
disabled: createEditorSwitchProp({ label: '是否为禁用状态' }), disabled: createEditorSwitchProp({ label: '是否为禁用状态' }),
'inactive-color': createEditorInputProp({ label: '关闭时的背景色' }),
'inactive-value': createEditorInputProp({ label: '关闭时对应的值' }),
loading: createEditorSwitchProp({ label: '是否为加载状态' }), loading: createEditorSwitchProp({ label: '是否为加载状态' }),
size: createEditorInputProp({ label: '开关尺寸' }), size: createEditorInputProp({ label: '开关尺寸', defaultValue: '20px' }),
...createFieldProps() ...createFieldProps()
}, },
resize: { resize: {

@ -1,16 +1,17 @@
/* /*
* @Author: * @Author:
* @Date: 2021-06-01 09:45:21 * @Date: 2021-06-01 09:45:21
* @LastEditTime: 2021-06-14 10:17:54 * @LastEditTime: 2021-06-22 23:14:46
* @LastEditors: * @LastEditors:
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\text\index.tsx * @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\text\index.tsx
*/ */
import { useGlobalProperties } from '@/hooks/useGlobalProperties' import { useGlobalProperties } from '@/hooks/useGlobalProperties'
import { import {
createEditorColorProp, createEditorColorProp,
createEditorInputProp, createEditorInputProp,
createEditorSelectProp createEditorSelectProp,
createEditorInputNumberProp
} from '@/visual-editor/visual-editor.props' } from '@/visual-editor/visual-editor.props'
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils' import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
import { fontArr } from './fontArr' import { fontArr } from './fontArr'
@ -26,7 +27,11 @@ export default {
return ( return (
<div <div
ref={(el) => registerRef(el, block._vid)} 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 || '默认文本'} {props.text || '默认文本'}
</div> </div>
@ -35,14 +40,10 @@ export default {
props: { props: {
text: createEditorInputProp({ label: '显示文本' }), text: createEditorInputProp({ label: '显示文本' }),
font: createEditorSelectProp({ label: '字体设置', options: fontArr }), font: createEditorSelectProp({ label: '字体设置', options: fontArr }),
color: createEditorColorProp('字体颜色'), color: createEditorColorProp({ label: '字体颜色' }),
size: createEditorSelectProp({ size: createEditorInputNumberProp({
label: '字体大小', label: '字体大小',
options: [ defaultValue: 16
{ label: '14px', value: '14px' },
{ label: '18px', value: '18px' },
{ label: '24px', value: '24px' }
]
}) })
} }
} as VisualEditorComponent } 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: * @Author:
* @Date: 2021-06-01 13:22:14 * @Date: 2021-06-01 13:22:14
* @LastEditTime: 2021-06-12 14:39:38 * @LastEditTime: 2021-06-23 11:40:10
* @LastEditors: * @LastEditors:
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\base-widgets\index.tsx * @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 { cloneDeep } from 'lodash'
import { visualConfig } from '@/visual.config' import { visualConfig } from '@/visual.config'
import Draggable from 'vuedraggable'
import styles from './index.module.scss' import styles from './index.module.scss'
import { createNewBlock } from '@/visual-editor/visual-editor.utils' import { createNewBlock } from '@/visual-editor/visual-editor.utils'
import DraggableTransitionGroup from '@/visual-editor/components/simulator-editor/draggable-transition-group.vue'
export default defineComponent({ export default defineComponent({
name: 'BaseWidgets', name: 'BaseWidgets',
setup() { setup() {
const baseWidgets = ref(visualConfig.componentModules.baseWidgets)
const log = (evt) => { const log = (evt) => {
window.console.log(evt) window.console.log('onChange:', evt)
} }
// 克隆组件 // 克隆组件
const cloneDog = (comp) => { const cloneDog = (comp) => {
@ -29,15 +31,13 @@ export default defineComponent({
return () => ( return () => (
<> <>
<Draggable <DraggableTransitionGroup
class={styles.listGroup} class={styles.listGroup}
sort={false} v-model={baseWidgets.value}
forceFallback={false}
list={visualConfig.componentModules.baseWidgets}
group={{ name: 'components', pull: 'clone', put: false }} group={{ name: 'components', pull: 'clone', put: false }}
clone={cloneDog} clone={cloneDog}
item-key="_vid"
onChange={log} onChange={log}
itemKey={'key'}
> >
{{ {{
item: ({ element }) => ( item: ({ element }) => (
@ -46,7 +46,7 @@ export default defineComponent({
</div> </div>
) )
}} }}
</Draggable> </DraggableTransitionGroup>
</> </>
) )
} }

@ -66,7 +66,7 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, reactive, computed, toRefs } from 'vue' 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 { useRouter, useRoute } from 'vue-router'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
@ -146,7 +146,7 @@ export default defineComponent({
await router.replace(path) await router.replace(path)
state.currentNodeKey = path state.currentNodeKey = path
} else { } else {
incrementPage(path, { title, blocks: [] }) incrementPage(path, createNewPage({ title }))
} }
state.dialogFormVisible = false state.dialogFormVisible = false
} }

@ -51,10 +51,12 @@ export default defineComponent({
::v-deep(.el-tabs__item) { ::v-deep(.el-tabs__item) {
height: 80px; height: 80px;
padding: 20px 16px; padding: 20px 16px;
[class^='el-icon-'] { [class^='el-icon-'] {
font-size: 20px; font-size: 20px;
} }
} }
::v-deep(.el-tabs__content) { ::v-deep(.el-tabs__content) {
height: 100%; height: 100%;
overflow-y: auto; overflow-y: auto;

@ -1,7 +1,7 @@
/* /*
* @Author: * @Author:
* @Date: 2021-06-10 16:23:06 * @Date: 2021-06-10 16:23:06
* @LastEditTime: 2021-06-14 17:22:11 * @LastEditTime: 2021-06-21 10:00:54
* @LastEditors: * @LastEditors:
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\attr-editor\AttrEditor.tsx * @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 renderEditor = (propName: string, propConfig: VisualEditorProps) => {
const { propObj, prop } = useDotProp(currentBlock.value.props, propName) const { propObj, prop } = useDotProp(currentBlock.value.props, propName)
propObj[prop] ??= propConfig.defaultValue
return { return {
[VisualEditorPropsType.input]: () => ( [VisualEditorPropsType.input]: () => (
<ElInput v-model={propObj[prop]} placeholder={propConfig.tips || propConfig.label} /> <ElInput v-model={propObj[prop]} placeholder={propConfig.tips || propConfig.label} />
@ -43,7 +45,7 @@ export const AttrEditor = defineComponent({
[VisualEditorPropsType.select]: () => ( [VisualEditorPropsType.select]: () => (
<ElSelect v-model={propObj[prop]} valueKey={'value'} multiple={propConfig.multiple}> <ElSelect v-model={propObj[prop]} valueKey={'value'} multiple={propConfig.multiple}>
{propConfig.options?.map((opt) => ( {propConfig.options?.map((opt) => (
<ElOption label={opt.label} value={opt.value} /> <ElOption label={opt.label} style={{ fontFamily: opt.value }} value={opt.value} />
))} ))}
</ElSelect> </ElSelect>
), ),

@ -1,7 +1,7 @@
/* /*
* @Author: * @Author:
* @Date: 2021-06-12 22:18:48 * @Date: 2021-06-12 22:18:48
* @LastEditTime: 2021-06-14 18:53:02 * @LastEditTime: 2021-06-23 22:17:38
* @LastEditors: * @LastEditors:
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\index.ts * @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 { AttrEditor } from './attr-editor/AttrEditor'
export { Animate } from './animate/Animate' export { Animate } from './animate/Animate'
export { CrossSortableOptionsEditor } from './cross-sortable-options-editor/cross-sortable-options-editor' export { CrossSortableOptionsEditor } from './cross-sortable-options-editor/cross-sortable-options-editor'
export { PageSetting } from './page-setting/pageSetting'

@ -1,8 +1,49 @@
/* /*
* @Author: * @Author:
* @Date: 2021-06-13 22:07:29 * @Date: 2021-06-13 22:07:29
* @LastEditTime: 2021-06-14 18:18:51 * @LastEditTime: 2021-06-24 00:23:39
* @LastEditors: * @LastEditors:
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\page-setting\pageSetting.tsx * @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: * @Author:
* @Date: 2021-06-01 13:22:14 * @Date: 2021-06-01 13:22:14
* @LastEditTime: 2021-06-13 21:26:49 * @LastEditTime: 2021-06-23 22:18:34
* @LastEditors: * @LastEditors:
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\index.tsx * @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 { ElTabPane, ElTabs } from 'element-plus'
import MonacoEditor from '../common/monaco-editor/MonacoEditor' import MonacoEditor from '../common/monaco-editor/MonacoEditor'
import { useVisualData } from '@/visual-editor/hooks/useVisualData' import { useVisualData } from '@/visual-editor/hooks/useVisualData'
import { AttrEditor, Animate } from './components' import { AttrEditor, Animate, PageSetting } from './components'
export default defineComponent({ export default defineComponent({
name: 'RightAttributePanel', name: 'RightAttributePanel',
@ -57,6 +57,9 @@ export default defineComponent({
title="" title=""
/> />
</ElTabPane> </ElTabPane>
<ElTabPane label="页面设置" name="page-setting">
<PageSetting />
</ElTabPane>
</ElTabs> </ElTabs>
</div> </div>
</div> </div>

@ -1,7 +1,7 @@
/* /*
* @Author: * @Author:
* @Date: 2021-05-04 05:36:58 * @Date: 2021-05-04 05:36:58
* @LastEditTime: 2021-06-14 10:02:47 * @LastEditTime: 2021-06-24 00:36:24
* @LastEditors: * @LastEditors:
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\simulator-editor\comp-render.tsx * @FilePath: \vite-vue3-lowcode\src\visual-editor\components\simulator-editor\comp-render.tsx
@ -22,15 +22,13 @@ export default defineComponent({
} }
}, },
setup(props) { setup(props) {
return () => { return () =>
const component = props.config.componentMap[props.element.componentKey] props.config.componentMap[props.element.componentKey].render({
return component.render({
size: {}, size: {},
props: props.element.props || {}, props: props.element.props || {},
model: {}, model: {},
block: props.element, block: props.element,
custom: {} custom: {}
}) })
}
} }
}) })

@ -9,11 +9,11 @@
type: 'transition-group', type: 'transition-group',
name: !isDrag ? 'flip-list' : null name: !isDrag ? 'flip-list' : null
}" }"
item-key="_vid" :group="group"
v-bind="dragOptions" v-bind="{ ...dragOptions, $attrs }"
:item-key="itemKey"
@start="isDrag = true" @start="isDrag = true"
@end="isDrag = false" @end="isDrag = false"
@change="log"
> >
<template #item="item"> <template #item="item">
<div> <div>
@ -46,7 +46,16 @@ export default defineComponent({
drag: { drag: {
type: Boolean, type: Boolean,
default: false default: false
} },
itemKey: {
type: String,
default: '_vid'
},
group: {
type: Object,
default: () => ({ name: 'components' })
},
fallbackClass: String
}, },
emits: ['update:moduleValue', 'update:drag'], emits: ['update:moduleValue', 'update:drag'],
setup(props, { emit }: SetupContext) { setup(props, { emit }: SetupContext) {
@ -57,17 +66,12 @@ export default defineComponent({
const dragOptions = computed(() => ({ const dragOptions = computed(() => ({
animation: 200, animation: 200,
group: 'components',
disabled: false, disabled: false,
ghostClass: 'ghost' ghostClass: 'ghost'
})) }))
const log = () => {
// console.log('', evt)
// console.log('', state.VMBlocks)
}
return { return {
...toRefs(state), ...toRefs(state),
log,
dragOptions dragOptions
} }
} }

@ -1,49 +1,59 @@
<template> <template>
<DraggableTransitionGroup <div class="simulator-container">
v-model:drag="drag" <div class="simulator-editor">
v-model="currentPage.blocks" <div class="simulator-editor-content" :style="pageStyle">
style="min-height: 500px" <DraggableTransitionGroup
> v-model:drag="drag"
<template #item="{ element: outElement }"> v-model="currentPage.blocks"
<div style="min-height: 500px"
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]> <template #item="{ element: outElement }">
<SlotItem <div
v-model:children="value.children" class="list-group-item"
v-model:drag="drag" :data-label="outElement.label"
:slot-key="slotKey" :class="{
:config="visualConfig" focus: outElement.focus,
:on-contextmenu-block="onContextmenuBlock" focusWithChild: outElement.focusWithChild,
:select-comp="selectComp" drag,
:delete-comp="deleteComp" ['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> </template>
</comp-render> </DraggableTransitionGroup>
</div> </div>
</template> </div>
</DraggableTransitionGroup> </div>
</template> </template>
<script lang="tsx"> <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 { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils'
import DraggableTransitionGroup from './draggable-transition-group.vue' import DraggableTransitionGroup from './draggable-transition-group.vue'
import { $$dropdown, DropdownOption } from '@/visual-editor/utils/dropdown-service' import { $$dropdown, DropdownOption } from '@/visual-editor/utils/dropdown-service'
@ -62,14 +72,22 @@ export default defineComponent({
}, },
emits: ['on-selected'], emits: ['on-selected'],
setup() { setup() {
const { globalProperties } = useGlobalProperties()
const { currentPage, visualConfig, setCurrentBlock } = useVisualData() const { currentPage, visualConfig, setCurrentBlock } = useVisualData()
const { globalProperties } = useGlobalProperties()
const state = reactive({ const state = reactive({
drag: false drag: false
}) })
const pageStyle = computed(() => {
const { bgImage, bgColor } = currentPage.value.config
return {
backgroundImage: `url(${bgImage})`,
backgroundColor: bgColor
}
})
// //
//@leafId id //@leafId id
//@nodes Json //@nodes Json
@ -196,6 +214,7 @@ export default defineComponent({
...toRefs(state), ...toRefs(state),
currentPage, currentPage,
visualConfig, visualConfig,
pageStyle,
deleteComp, deleteComp,
selectComp, selectComp,
onContextmenuBlock onContextmenuBlock
@ -206,12 +225,52 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
@import './func.scss'; @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 { .list-group-item {
position: relative; position: relative;
padding: 3px; padding: 3px;
cursor: move; cursor: move;
transform: translate(0); transform: translate(0);
> div {
position: relative;
}
&.focus { &.focus {
content: ''; content: '';
outline: 2px solid #006eff; outline: 2px solid #006eff;

@ -5,7 +5,16 @@
* @descriptionuseVisualData * @descriptionuseVisualData
* @update: 2021/5/6 11:59 * @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 { useRoute, useRouter } from 'vue-router'
import { import {
VisualEditorModelValue, VisualEditorModelValue,
@ -21,7 +30,7 @@ import { CacheEnum } from '@/enums'
export const localKey = CacheEnum.PAGE_DATA_KEY export const localKey = CacheEnum.PAGE_DATA_KEY
// 注入jsonData的key // 注入jsonData的key
export const injectKey = Symbol('injectKey') export const injectKey: InjectionKey<string> = Symbol()
interface IState { interface IState {
currentBlock: VisualEditorBlockData // 当前正在操作的组件 currentBlock: VisualEditorBlockData // 当前正在操作的组件
@ -43,17 +52,26 @@ export interface VisualData {
setCurrentBlock: (block: VisualEditorBlockData) => void // 设置当前正在操作的组件 setCurrentBlock: (block: VisualEditorBlockData) => void // 设置当前正在操作的组件
} }
/**
* @description
*/
export const createNewPage = ({ title = '新页面', path = '/' }) => ({
title,
path,
config: {
bgColor: '',
bgImage: ''
},
blocks: []
})
const defaultValue: VisualEditorModelValue = { const defaultValue: VisualEditorModelValue = {
container: { container: {
width: 360, width: 360,
height: 960 height: 960
}, },
pages: { pages: {
'/': { '/': createNewPage({ title: '首页' })
title: '首页',
path: '/',
blocks: []
}
} }
} }
@ -106,7 +124,7 @@ export const initVisualData = (): VisualData => {
} }
// 添加page // 添加page
const incrementPage = (path = '', page: VisualEditorPage) => { const incrementPage = (path = '', page: VisualEditorPage) => {
state.jsonData.pages[getPrefixPath(path)] ??= page ?? { title: '新页面', path, blocks: [] } state.jsonData.pages[getPrefixPath(path)] ??= page ?? createNewPage({ path })
} }
// 删除page // 删除page
const deletePage = (path = '', redirectPath = '') => { const deletePage = (path = '', redirectPath = '') => {

@ -13,9 +13,7 @@
</el-aside> </el-aside>
<el-main> <el-main>
<!-- 中间编辑区域start --> <!-- 中间编辑区域start -->
<Simulator> <simulator-editor />
<simulator-editor />
</Simulator>
<!-- 中间编辑区域end --> <!-- 中间编辑区域end -->
<!-- 右侧属性面板start --> <!-- 右侧属性面板start -->
@ -31,7 +29,6 @@ import Header from './components/header/index.vue'
import LeftAside from './components/left-aside/index.vue' import LeftAside from './components/left-aside/index.vue'
import RightAttributePanel from './components/right-attribute-panel' import RightAttributePanel from './components/right-attribute-panel'
import SimulatorEditor from './components/simulator-editor/simulator-editor.vue' import SimulatorEditor from './components/simulator-editor/simulator-editor.vue'
import Simulator from './components/common/simulator.vue'
</script> </script>
<style lang="scss"> <style lang="scss">

@ -84,7 +84,12 @@ export function createEditorInputNumberProp({
/*---------------------------------------color-------------------------------------------*/ /*---------------------------------------color-------------------------------------------*/
export function createEditorColorProp(label: string, defaultValue?: string): VisualEditorProps { interface EditorColorProp {
label: string
defaultValue?: string
}
export function createEditorColorProp({ label, defaultValue }: EditorColorProp): VisualEditorProps {
return { return {
type: VisualEditorPropsType.color, type: VisualEditorPropsType.color,
label, label,

@ -2,6 +2,9 @@ import { VisualEditorProps } from './visual-editor.props'
import { inject, provide } from 'vue' import { inject, provide } from 'vue'
import { useDotProp } from '@/visual-editor/hooks/useDotProp' import { useDotProp } from '@/visual-editor/hooks/useDotProp'
/**
* @description
*/
export interface VisualEditorBlockData { export interface VisualEditorBlockData {
_vid: string // 组件id 时间戳 _vid: string // 组件id 时间戳
moduleName: keyof ComponentModules // 组件所属的模块(基础组件、容器组件) moduleName: keyof ComponentModules // 组件所属的模块(基础组件、容器组件)
@ -21,14 +24,26 @@ export interface VisualEditorBlockData {
animations?: Animation[] // 动画集 animations?: Animation[] // 动画集
[prop: string]: any [prop: string]: any
} }
/**
* @description
*/
export interface PageConfig {
bgImage: string // 背景图片
bgColor: string // 背景颜色
}
/**
* @description
*/
export interface VisualEditorPage { export interface VisualEditorPage {
title: string // 页面标题 title: string // 页面标题
path: string // 页面路径 path: string // 页面路径
isDefault?: boolean // 404是重定向到默认页面 isDefault?: boolean // 404是重定向到默认页面
config: PageConfig // 页面配置
blocks: VisualEditorBlockData[] // 当前页面的所有组件 blocks: VisualEditorBlockData[] // 当前页面的所有组件
} }
/**
* @description =>
*/
export interface VisualEditorPages { export interface VisualEditorPages {
[path: string]: VisualEditorPage [path: string]: VisualEditorPage
} }

@ -29,9 +29,10 @@ export default ({ mode }: ConfigEnv): UserConfig => {
targets: ['defaults', 'not IE 11'] targets: ['defaults', 'not IE 11']
}), }),
ViteComponents({ ViteComponents({
globalComponentsDeclaration: true,
// 自动导入组件(还不够完善,可能会有样式丢失) // 自动导入组件(还不够完善,可能会有样式丢失)
// valid file extensions for components. // valid file extensions for components.
extensions: ['vue', 'tsx'], extensions: ['vue', 'tsx', 'js'],
customComponentResolvers: [ElementPlusResolver(), VantResolver()] customComponentResolvers: [ElementPlusResolver(), VantResolver()]
}), }),
styleImport({ styleImport({

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save