fix: some bug
This commit is contained in:
parent
25b3d69041
commit
65493e128a
21
README.md
21
README.md
|
@ -32,6 +32,27 @@
|
||||||
目前在使用表单时,需要把相关的`表单控件`放到`表单容器`内部,并且需要将`按钮`放到`表单容器`内,
|
目前在使用表单时,需要把相关的`表单控件`放到`表单容器`内部,并且需要将`按钮`放到`表单容器`内,
|
||||||
然后再讲`按钮的type`设置为`表单提交按钮`这时候点击提交按钮才会自动收集表单容器内部的所有字段和值
|
然后再讲`按钮的type`设置为`表单提交按钮`这时候点击提交按钮才会自动收集表单容器内部的所有字段和值
|
||||||
|
|
||||||
|
### 快速生成组件属性
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 在vant文档中 chrome控制台输入以下代码,快速生成组件属性
|
||||||
|
let propObj = {
|
||||||
|
string: (config) => `createEditorInputProp(${JSON.stringify(config)})`,
|
||||||
|
number: (config) => `createEditorInputNumberProp(${JSON.stringify(config)})`,
|
||||||
|
boolean: (config) => `createEditorSwitchProp(${JSON.stringify(config)})`
|
||||||
|
}
|
||||||
|
|
||||||
|
$$('#props + table tr').reduce((prev, curr) => {
|
||||||
|
const children = curr.children
|
||||||
|
const key = children[0].textContent.replace(/-([a-z])/g, (all, i) => i.toUpperCase())
|
||||||
|
const value = (propObj[children[2].textContent] ?? propObj['string'])({
|
||||||
|
label: `'${children[1].textContent}'`
|
||||||
|
}).replaceAll('"', '')
|
||||||
|
prev[key] = value
|
||||||
|
return prev
|
||||||
|
}, {})
|
||||||
|
```
|
||||||
|
|
||||||
## 浏览器支持
|
## 浏览器支持
|
||||||
|
|
||||||
本地开发推荐使用`Chrome 80+` 浏览器
|
本地开发推荐使用`Chrome 80+` 浏览器
|
||||||
|
|
24
package.json
24
package.json
|
@ -20,20 +20,20 @@
|
||||||
"prepare": "husky install"
|
"prepare": "husky install"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vant/touch-emulator": "^1.2.0",
|
"@vant/touch-emulator": "^1.3.0",
|
||||||
"@vueuse/core": "^4.11.1",
|
"@vueuse/core": "^4.11.1",
|
||||||
"@vueuse/integrations": "^4.11.1",
|
"@vueuse/integrations": "^4.11.1",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"dayjs": "^1.10.4",
|
"dayjs": "^1.10.4",
|
||||||
"dexie": "^3.0.3",
|
"dexie": "^3.0.3",
|
||||||
"element-plus": "^1.0.2-beta.44",
|
"element-plus": "^1.0.2-beta.45",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"monaco-editor": "^0.24.0",
|
"monaco-editor": "^0.24.0",
|
||||||
"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.17",
|
"vant": "^3.0.17",
|
||||||
"vue": "^3.1.0-beta.4",
|
"vue": "3.0.11",
|
||||||
"vue-router": "^4.0.8",
|
"vue-router": "^4.0.8",
|
||||||
"vuedraggable": "^4.0.1",
|
"vuedraggable": "^4.0.1",
|
||||||
"vuex": "^4.0.1"
|
"vuex": "^4.0.1"
|
||||||
|
@ -41,13 +41,13 @@
|
||||||
"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": "^14.17.1",
|
"@types/node": "^15.6.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.25.0",
|
"@typescript-eslint/eslint-plugin": "^4.25.0",
|
||||||
"@typescript-eslint/parser": "^4.25.0",
|
"@typescript-eslint/parser": "^4.25.0",
|
||||||
"@vitejs/plugin-legacy": "^1.4.0",
|
"@vitejs/plugin-legacy": "^1.4.0",
|
||||||
"@vitejs/plugin-vue": "^1.2.2",
|
"@vitejs/plugin-vue": "^1.2.2",
|
||||||
"@vitejs/plugin-vue-jsx": "^1.1.4",
|
"@vitejs/plugin-vue-jsx": "^1.1.4",
|
||||||
"@vue/compiler-sfc": "^3.1.0-beta.4",
|
"@vue/compiler-sfc": "3.0.11",
|
||||||
"commitizen": "^4.2.4",
|
"commitizen": "^4.2.4",
|
||||||
"cz-conventional-changelog": "^3.3.0",
|
"cz-conventional-changelog": "^3.3.0",
|
||||||
"cz-customizable": "^6.3.0",
|
"cz-customizable": "^6.3.0",
|
||||||
|
@ -56,24 +56,24 @@
|
||||||
"eslint-plugin-import": "^2.23.3",
|
"eslint-plugin-import": "^2.23.3",
|
||||||
"eslint-plugin-prettier": "^3.4.0",
|
"eslint-plugin-prettier": "^3.4.0",
|
||||||
"eslint-plugin-vue": "^7.9.0",
|
"eslint-plugin-vue": "^7.9.0",
|
||||||
"gh-pages": "^3.1.0",
|
"gh-pages": "^3.2.0",
|
||||||
"husky": "^6.0.0",
|
"husky": "^6.0.0",
|
||||||
"lint-staged": "^10.5.4",
|
"lint-staged": "^11.0.0",
|
||||||
"prettier": "^2.3.0",
|
"prettier": "^2.3.0",
|
||||||
"pretty-quick": "^3.1.0",
|
"pretty-quick": "^3.1.0",
|
||||||
"sass": "1.32.13",
|
"sass": "1.34.0",
|
||||||
"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.2.4",
|
"typescript": "^4.3.2",
|
||||||
"vite": "2.3.4",
|
"vite": "2.3.4",
|
||||||
"vite-plugin-components": "^0.10.2",
|
"vite-plugin-components": "^0.10.3",
|
||||||
"vite-plugin-style-import": "^0.10.1",
|
"vite-plugin-style-import": "^0.10.1",
|
||||||
"vite-plugin-windicss": "^0.16.0",
|
"vite-plugin-windicss": "^0.16.7",
|
||||||
"vue-eslint-parser": "^7.6.0",
|
"vue-eslint-parser": "^7.6.0",
|
||||||
"vue-tsc": "^0.1.6",
|
"vue-tsc": "^0.1.6",
|
||||||
"windicss": "^2.5.14"
|
"windicss": "^3.0.12"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -3,10 +3,13 @@ import App from './App.vue'
|
||||||
|
|
||||||
import router from './router'
|
import router from './router'
|
||||||
|
|
||||||
import '@/plugins/vant'
|
import { setupVant } from '@/plugins/vant'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
|
// 安装vant插件
|
||||||
|
setupVant(app)
|
||||||
|
|
||||||
app.config.globalProperties.$$refs = {}
|
app.config.globalProperties.$$refs = {}
|
||||||
|
|
||||||
// if (import.meta.env.DEV) {
|
// if (import.meta.env.DEV) {
|
||||||
|
|
|
@ -44,26 +44,9 @@ export default defineComponent({
|
||||||
router.replace('/')
|
router.replace('/')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 渲染组件
|
|
||||||
const renderCom = (element) => {
|
|
||||||
if (Array.isArray(element)) {
|
|
||||||
return element.map((item) => renderCom(item))
|
|
||||||
}
|
|
||||||
const component = visualConfig.componentMap[element.componentKey]
|
|
||||||
|
|
||||||
return component.render({
|
|
||||||
size: {},
|
|
||||||
props: element.props || {},
|
|
||||||
block: element,
|
|
||||||
model: {},
|
|
||||||
custom: {}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...toRefs(state),
|
...toRefs(state),
|
||||||
visualConfig,
|
visualConfig
|
||||||
renderCom
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { createApp } from 'vue'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
|
||||||
import './plugins/element-plus'
|
import './plugins/element-plus'
|
||||||
import './plugins/vant'
|
import { setupVant } from './plugins/vant'
|
||||||
|
|
||||||
import 'normalize.css'
|
import 'normalize.css'
|
||||||
import 'virtual:windi.css'
|
import 'virtual:windi.css'
|
||||||
|
@ -13,6 +13,9 @@ import store from './store/'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
|
// 使用vant插件
|
||||||
|
setupVant(app)
|
||||||
|
|
||||||
app.config.globalProperties.$$refs = {}
|
app.config.globalProperties.$$refs = {}
|
||||||
|
|
||||||
// if (import.meta.env.DEV) {
|
// if (import.meta.env.DEV) {
|
||||||
|
|
|
@ -37,23 +37,23 @@ export default {
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '主要按钮',
|
label: '主要按钮',
|
||||||
val: 'primary'
|
value: 'primary'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '成功按钮',
|
label: '成功按钮',
|
||||||
val: 'success'
|
value: 'success'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '默认按钮',
|
label: '默认按钮',
|
||||||
val: 'default'
|
value: 'default'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '警告按钮',
|
label: '警告按钮',
|
||||||
val: 'warning'
|
value: 'warning'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '危险按钮',
|
label: '危险按钮',
|
||||||
val: 'danger'
|
value: 'danger'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'default'
|
defaultValue: 'default'
|
||||||
|
@ -63,19 +63,19 @@ export default {
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '大型',
|
label: '大型',
|
||||||
val: 'large'
|
value: 'large'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '普通',
|
label: '普通',
|
||||||
val: 'normal'
|
value: 'normal'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '小型',
|
label: '小型',
|
||||||
val: 'small'
|
value: 'small'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '迷你',
|
label: '迷你',
|
||||||
val: 'mini'
|
value: 'mini'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'normal'
|
defaultValue: 'normal'
|
||||||
|
@ -83,10 +83,10 @@ export default {
|
||||||
'native-type': createEditorSelectProp({
|
'native-type': createEditorSelectProp({
|
||||||
label: '原生button的type属性',
|
label: '原生button的type属性',
|
||||||
options: [
|
options: [
|
||||||
{ label: '普通button', val: 'button' },
|
{ label: '普通button', value: 'button' },
|
||||||
{
|
{
|
||||||
label: '表单提交按钮',
|
label: '表单提交按钮',
|
||||||
val: 'submit'
|
value: 'submit'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'button'
|
defaultValue: 'button'
|
||||||
|
@ -110,11 +110,11 @@ export default {
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '左侧',
|
label: '左侧',
|
||||||
val: 'left'
|
value: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '右侧',
|
label: '右侧',
|
||||||
val: 'right'
|
value: 'right'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
|
@ -128,8 +128,8 @@ export default {
|
||||||
'loading-type': createEditorSelectProp({
|
'loading-type': createEditorSelectProp({
|
||||||
label: '加载图标类型',
|
label: '加载图标类型',
|
||||||
options: [
|
options: [
|
||||||
{ label: 'circular', val: 'circular' },
|
{ label: 'circular', value: 'circular' },
|
||||||
{ label: 'spinner', val: 'spinner' }
|
{ label: 'spinner', value: 'spinner' }
|
||||||
],
|
],
|
||||||
defaultValue: 'circular'
|
defaultValue: 'circular'
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,15 +19,15 @@ export const createFieldProps = () => ({
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '左对齐',
|
label: '左对齐',
|
||||||
val: 'left'
|
value: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '居中',
|
label: '居中',
|
||||||
val: 'center'
|
value: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '右对齐',
|
label: '右对齐',
|
||||||
val: 'right'
|
value: 'right'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'left'
|
defaultValue: 'left'
|
||||||
|
|
|
@ -54,13 +54,13 @@ export default {
|
||||||
modelValue: createEditorSelectProp({
|
modelValue: createEditorSelectProp({
|
||||||
label: '默认值',
|
label: '默认值',
|
||||||
options: [
|
options: [
|
||||||
{ label: '萝卜', val: 'radish' },
|
{ label: '萝卜', value: 'radish' },
|
||||||
{ label: '青菜', val: 'greens' }
|
{ label: '青菜', value: 'greens' }
|
||||||
],
|
],
|
||||||
multiple: true,
|
multiple: true,
|
||||||
defaultValue: []
|
defaultValue: []
|
||||||
}),
|
}),
|
||||||
name: createEditorInputProp({ label: '名称,提交表单的标识符', defaultValue: 'checkbox' }),
|
name: createEditorInputProp({ label: '字段名', defaultValue: 'checkbox' }),
|
||||||
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '复选框' }),
|
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '复选框' }),
|
||||||
options: createEditorTableProp({
|
options: createEditorTableProp({
|
||||||
label: '默认选项',
|
label: '默认选项',
|
||||||
|
@ -82,11 +82,11 @@ export default {
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '水平',
|
label: '水平',
|
||||||
val: 'horizontal'
|
value: 'horizontal'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '垂直',
|
label: '垂直',
|
||||||
val: 'vertical'
|
value: 'vertical'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'horizontal'
|
defaultValue: 'horizontal'
|
||||||
|
|
|
@ -19,15 +19,15 @@ export const createFieldProps = () => ({
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '左对齐',
|
label: '左对齐',
|
||||||
val: 'left'
|
value: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '居中',
|
label: '居中',
|
||||||
val: 'center'
|
value: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '右对齐',
|
label: '右对齐',
|
||||||
val: 'right'
|
value: 'right'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'left'
|
defaultValue: 'left'
|
||||||
|
|
|
@ -12,6 +12,14 @@ import { reactive } from 'vue'
|
||||||
import { isDate } from '@/visual-editor/utils/is'
|
import { isDate } from '@/visual-editor/utils/is'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
|
const dateType = {
|
||||||
|
'month-day': 'MM-DD',
|
||||||
|
'year-month': 'YYYY-MM',
|
||||||
|
date: 'YYYY-MM-DD',
|
||||||
|
datehour: 'YYYY-MM-DD HH',
|
||||||
|
datetime: 'YYYY-MM-DD HH:mm:ss'
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
key: 'datetimePicker',
|
key: 'datetimePicker',
|
||||||
moduleName: 'baseWidgets',
|
moduleName: 'baseWidgets',
|
||||||
|
@ -21,11 +29,12 @@ export default {
|
||||||
const { registerRef } = useGlobalProperties()
|
const { registerRef } = useGlobalProperties()
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
showPicker: false,
|
showPicker: false,
|
||||||
text: ''
|
text: '',
|
||||||
|
currentDate: new Date()
|
||||||
})
|
})
|
||||||
|
|
||||||
const onConfirm = (value) => {
|
const onConfirm = (value) => {
|
||||||
const date = isDate(value) ? dayjs(value).format(props.format) : value
|
const date = isDate(value) ? dayjs(value).format(props.format || dateType[props.type]) : value
|
||||||
props.modelValue = date
|
props.modelValue = date
|
||||||
state.text = date
|
state.text = date
|
||||||
state.showPicker = false
|
state.showPicker = false
|
||||||
|
@ -56,6 +65,7 @@ export default {
|
||||||
<DatetimePicker
|
<DatetimePicker
|
||||||
ref={(el) => registerRef(el, block._vid)}
|
ref={(el) => registerRef(el, block._vid)}
|
||||||
{...props}
|
{...props}
|
||||||
|
v-model={state.currentDate}
|
||||||
onConfirm={onConfirm}
|
onConfirm={onConfirm}
|
||||||
onCancel={() => (state.showPicker = false)}
|
onCancel={() => (state.showPicker = false)}
|
||||||
/>
|
/>
|
||||||
|
@ -63,16 +73,12 @@ export default {
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return <PopupPicker />
|
||||||
<>
|
|
||||||
<PopupPicker />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: createEditorInputProp({ label: '默认值' }),
|
modelValue: createEditorInputProp({ label: '默认值' }),
|
||||||
name: createEditorInputProp({
|
name: createEditorInputProp({
|
||||||
label: '名称,提交表单的标识符',
|
label: '字段名',
|
||||||
defaultValue: 'datetimePicker'
|
defaultValue: 'datetimePicker'
|
||||||
}),
|
}),
|
||||||
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '时间选择器' }),
|
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '时间选择器' }),
|
||||||
|
@ -82,31 +88,31 @@ export default {
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: 'date',
|
label: 'date',
|
||||||
val: 'date'
|
value: 'date'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'time',
|
label: 'datetime',
|
||||||
val: 'time'
|
value: 'datetime'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'year-month',
|
label: 'year-month',
|
||||||
val: 'year-month'
|
value: 'year-month'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'month-day',
|
label: 'month-day',
|
||||||
val: 'month-day'
|
value: 'month-day'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'datehour',
|
label: 'datehour',
|
||||||
val: 'datehour'
|
value: 'datehour'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'time'
|
defaultValue: 'datetime'
|
||||||
}),
|
}),
|
||||||
format: createEditorInputProp({
|
format: createEditorInputProp({
|
||||||
label: '选择时间后格式化值',
|
label: '自定义日期格式化值',
|
||||||
tips: 'YYYY-MM-DD HH:mm:ss',
|
tips: 'YYYY-MM-DD HH:mm:ss',
|
||||||
defaultValue: 'YYYY-MM-DD HH:mm:ss'
|
defaultValue: ''
|
||||||
}),
|
}),
|
||||||
cancelButtonText: createEditorInputProp({ label: '取消按钮文字' }),
|
cancelButtonText: createEditorInputProp({ label: '取消按钮文字' }),
|
||||||
columnsOrder: createEditorInputProp({
|
columnsOrder: createEditorInputProp({
|
||||||
|
|
|
@ -27,9 +27,9 @@ export default {
|
||||||
'content-position': createEditorSelectProp({
|
'content-position': createEditorSelectProp({
|
||||||
label: '文本位置',
|
label: '文本位置',
|
||||||
options: [
|
options: [
|
||||||
{ label: '左边', val: 'left' },
|
{ label: '左边', value: 'left' },
|
||||||
{ label: '中间', val: 'center' },
|
{ label: '中间', value: 'center' },
|
||||||
{ label: '右边', val: 'right' }
|
{ label: '右边', value: 'right' }
|
||||||
],
|
],
|
||||||
defaultValue: 'center'
|
defaultValue: 'center'
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -29,45 +29,45 @@ export default {
|
||||||
label: '图片链接',
|
label: '图片链接',
|
||||||
defaultValue: 'https://img.yzcdn.cn/vant/cat.jpeg'
|
defaultValue: 'https://img.yzcdn.cn/vant/cat.jpeg'
|
||||||
}),
|
}),
|
||||||
width: createEditorInputProp({ label: '宽度,默认单位为 px', defaultValue: 100 }),
|
width: createEditorInputProp({ label: '宽度', defaultValue: 100 }),
|
||||||
height: createEditorInputProp({ label: '高度,默认单位为 px', defaultValue: 100 }),
|
height: createEditorInputProp({ label: '高度', defaultValue: 100 }),
|
||||||
'error-icon': createEditorInputProp({ label: '失败时提示的图标名称或图片链接' }),
|
errorIcon: createEditorInputProp({ label: '失败时提示的图标名称或图片链接' }),
|
||||||
fit: createEditorSelectProp({
|
fit: createEditorSelectProp({
|
||||||
label: '图片填充模式',
|
label: '图片填充模式',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '保持宽高缩放图片,使图片的长边能完全显示出来',
|
label: '保持宽高缩放图片,使图片的长边能完全显示出来',
|
||||||
val: 'contain'
|
value: 'contain'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '保持宽高缩放图片,使图片的短边能完全显示出来,裁剪长边',
|
label: '保持宽高缩放图片,使图片的短边能完全显示出来,裁剪长边',
|
||||||
val: 'cover'
|
value: 'cover'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '拉伸图片,使图片填满元素',
|
label: '拉伸图片,使图片填满元素',
|
||||||
val: 'fill'
|
value: 'fill'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '保持图片原有尺寸',
|
label: '保持图片原有尺寸',
|
||||||
val: 'none'
|
value: 'none'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '取 none 或 contain 中较小的一个',
|
label: '取 none 或 contain 中较小的一个',
|
||||||
val: 'scale-down'
|
value: 'scale-down'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'fill'
|
defaultValue: 'fill'
|
||||||
}),
|
}),
|
||||||
'icon-prefix': createEditorInputProp({
|
iconPrefix: createEditorInputProp({
|
||||||
label: '图标类名前缀',
|
label: '图标类名前缀',
|
||||||
tips: '图标类名前缀,同 Icon 组件的 class-prefix 属性'
|
tips: '图标类名前缀,同 Icon 组件的 class-prefix 属性'
|
||||||
}),
|
}),
|
||||||
'icon-size': createEditorInputProp({ label: '加载图标和失败图标的大小' }),
|
iconSize: createEditorInputProp({ label: '加载图标和失败图标的大小' }),
|
||||||
'lazy-load': createEditorSwitchProp({
|
lazyLoad: createEditorSwitchProp({
|
||||||
label: '是否开启图片懒加载',
|
label: '是否开启图片懒加载',
|
||||||
tips: '须配合 Lazyload 组件使用'
|
tips: '须配合 Lazyload 组件使用'
|
||||||
}),
|
}),
|
||||||
'loading-icon': createEditorInputProp({ label: '加载时提示的图标名称或图片链接' }),
|
loadingIcon: createEditorInputProp({ label: '加载时提示的图标名称或图片链接' }),
|
||||||
radius: createEditorInputProp({ label: '圆角大小', tips: '默认单位为 px' }),
|
radius: createEditorInputProp({ label: '圆角大小', tips: '默认单位为 px' }),
|
||||||
round: createEditorSwitchProp({ label: '是否显示为圆形' }),
|
round: createEditorSwitchProp({ label: '是否显示为圆形' }),
|
||||||
'show-error': createEditorSwitchProp({ label: '是否展示图片加载失败提示' }),
|
'show-error': createEditorSwitchProp({ label: '是否展示图片加载失败提示' }),
|
||||||
|
|
|
@ -16,17 +16,17 @@ export const createFieldProps = () => ({
|
||||||
label: '默认值',
|
label: '默认值',
|
||||||
defaultValue: ''
|
defaultValue: ''
|
||||||
}),
|
}),
|
||||||
name: createEditorInputProp({ label: '名称,提交表单的标识符', defaultValue: 'input' }),
|
name: createEditorInputProp({ label: '字段名', defaultValue: 'input' }),
|
||||||
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '输入框' }),
|
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '输入框' }),
|
||||||
type: createEditorSelectProp({
|
type: createEditorSelectProp({
|
||||||
label: '输入框类型',
|
label: '输入框类型',
|
||||||
options: [
|
options: [
|
||||||
{ label: '文本', val: 'text' },
|
{ label: '文本', value: 'text' },
|
||||||
{ label: '数字', val: 'number' },
|
{ label: '数字', value: 'number' },
|
||||||
{ label: '文本域', val: 'textarea' },
|
{ label: '文本域', value: 'textarea' },
|
||||||
{ label: '密码', val: 'password' },
|
{ label: '密码', value: 'password' },
|
||||||
{ label: '电话', val: 'tel' },
|
{ label: '电话', value: 'tel' },
|
||||||
{ label: '小数点', val: 'digit' }
|
{ label: '小数点', value: 'digit' }
|
||||||
],
|
],
|
||||||
defaultValue: 'text'
|
defaultValue: 'text'
|
||||||
}),
|
}),
|
||||||
|
@ -40,15 +40,15 @@ export const createFieldProps = () => ({
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '左对齐',
|
label: '左对齐',
|
||||||
val: 'left'
|
value: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '居中',
|
label: '居中',
|
||||||
val: 'center'
|
value: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '右对齐',
|
label: '右对齐',
|
||||||
val: 'right'
|
value: 'right'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'left'
|
defaultValue: 'left'
|
||||||
|
@ -66,8 +66,7 @@ export const createFieldProps = () => ({
|
||||||
autosize: createEditorSwitchProp({
|
autosize: createEditorSwitchProp({
|
||||||
label: '自适应内容高度',
|
label: '自适应内容高度',
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
tips:
|
tips: '是否自适应内容高度,只对 textarea 有效,可传入对象,如 { maxHeight: 100, minHeight: 50 },单位为px'
|
||||||
'是否自适应内容高度,只对 textarea 有效,可传入对象,如 { maxHeight: 100, minHeight: 50 },单位为px'
|
|
||||||
}),
|
}),
|
||||||
border: createEditorSwitchProp({ label: '是否显示内边框', defaultValue: true }),
|
border: createEditorSwitchProp({ label: '是否显示内边框', defaultValue: true }),
|
||||||
center: createEditorSwitchProp({ label: '内容垂直居中' }),
|
center: createEditorSwitchProp({ label: '内容垂直居中' }),
|
||||||
|
@ -78,8 +77,8 @@ export const createFieldProps = () => ({
|
||||||
'clear-trigger': createEditorSelectProp({
|
'clear-trigger': createEditorSelectProp({
|
||||||
label: '清除图标显示时机',
|
label: '清除图标显示时机',
|
||||||
options: [
|
options: [
|
||||||
{ label: '输入框不为空时展示', val: 'always' },
|
{ label: '输入框不为空时展示', value: 'always' },
|
||||||
{ label: '输入框聚焦且不为空时展示', val: 'focus' }
|
{ label: '输入框聚焦且不为空时展示', value: 'focus' }
|
||||||
],
|
],
|
||||||
defaultValue: 'always',
|
defaultValue: 'always',
|
||||||
tips: '显示清除图标的时机,always 表示输入框不为空时展示,focus 表示输入框聚焦且不为空时展示'
|
tips: '显示清除图标的时机,always 表示输入框不为空时展示,focus 表示输入框聚焦且不为空时展示'
|
||||||
|
@ -101,15 +100,15 @@ export const createFieldProps = () => ({
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '左对齐',
|
label: '左对齐',
|
||||||
val: 'left'
|
value: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '居中',
|
label: '居中',
|
||||||
val: 'center'
|
value: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '右对齐',
|
label: '右对齐',
|
||||||
val: 'right'
|
value: 'right'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'left'
|
defaultValue: 'left'
|
||||||
|
@ -119,15 +118,15 @@ export const createFieldProps = () => ({
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '左对齐',
|
label: '左对齐',
|
||||||
val: 'left'
|
value: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '居中',
|
label: '居中',
|
||||||
val: 'center'
|
value: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '右对齐',
|
label: '右对齐',
|
||||||
val: 'right'
|
value: 'right'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'left'
|
defaultValue: 'left'
|
||||||
|
|
|
@ -19,15 +19,15 @@ export const createFieldProps = () => ({
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '左对齐',
|
label: '左对齐',
|
||||||
val: 'left'
|
value: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '居中',
|
label: '居中',
|
||||||
val: 'center'
|
value: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '右对齐',
|
label: '右对齐',
|
||||||
val: 'right'
|
value: 'right'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'left'
|
defaultValue: 'left'
|
||||||
|
|
|
@ -39,7 +39,8 @@ export default {
|
||||||
style={{
|
style={{
|
||||||
width: size.width ? `${size.width}px` : null
|
width: size.width ? `${size.width}px` : null
|
||||||
}}
|
}}
|
||||||
v-slots={{
|
>
|
||||||
|
{{
|
||||||
input: () =>
|
input: () =>
|
||||||
state.text?.trim() == '' ? (
|
state.text?.trim() == '' ? (
|
||||||
<span class={'placeholder'}>{props.placeholder}</span>
|
<span class={'placeholder'}>{props.placeholder}</span>
|
||||||
|
@ -47,7 +48,7 @@ export default {
|
||||||
state.text
|
state.text
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
</Field>
|
||||||
<Popup v-model={[state.showPicker, 'show', ['modifier']]} position={'bottom'}>
|
<Popup v-model={[state.showPicker, 'show', ['modifier']]} position={'bottom'}>
|
||||||
<Picker
|
<Picker
|
||||||
ref={(el) => registerRef(el, block._vid)}
|
ref={(el) => registerRef(el, block._vid)}
|
||||||
|
@ -60,15 +61,11 @@ export default {
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return <PopupPicker />
|
||||||
<>
|
|
||||||
<PopupPicker />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: createEditorInputProp({ label: '默认值' }),
|
modelValue: createEditorInputProp({ label: '默认值' }),
|
||||||
name: createEditorInputProp({ label: '名称,提交表单的标识符', defaultValue: 'picker' }),
|
name: createEditorInputProp({ label: '字段名', defaultValue: 'picker' }),
|
||||||
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '选择器' }),
|
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '选择器' }),
|
||||||
columns: createEditorTableProp({
|
columns: createEditorTableProp({
|
||||||
label: '数据项',
|
label: '数据项',
|
||||||
|
|
|
@ -19,15 +19,15 @@ export const createFieldProps = () => ({
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '左对齐',
|
label: '左对齐',
|
||||||
val: 'left'
|
value: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '居中',
|
label: '居中',
|
||||||
val: 'center'
|
value: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '右对齐',
|
label: '右对齐',
|
||||||
val: 'right'
|
value: 'right'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'left'
|
defaultValue: 'left'
|
||||||
|
|
|
@ -48,7 +48,7 @@ export default {
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: createEditorInputProp({ label: '默认值', defaultValue: '' }),
|
modelValue: createEditorInputProp({ label: '默认值', defaultValue: '' }),
|
||||||
name: createEditorInputProp({ label: '名称,提交表单的标识符', defaultValue: 'radio' }),
|
name: createEditorInputProp({ label: '字段名', defaultValue: 'radio' }),
|
||||||
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '单选框' }),
|
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '单选框' }),
|
||||||
options: createEditorTableProp({
|
options: createEditorTableProp({
|
||||||
label: '默认选项',
|
label: '默认选项',
|
||||||
|
@ -70,11 +70,11 @@ export default {
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '水平',
|
label: '水平',
|
||||||
val: 'horizontal'
|
value: 'horizontal'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '垂直',
|
label: '垂直',
|
||||||
val: 'vertical'
|
value: 'vertical'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'horizontal'
|
defaultValue: 'horizontal'
|
||||||
|
|
|
@ -19,15 +19,15 @@ export const createFieldProps = () => ({
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '左对齐',
|
label: '左对齐',
|
||||||
val: 'left'
|
value: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '居中',
|
label: '居中',
|
||||||
val: 'center'
|
value: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '右对齐',
|
label: '右对齐',
|
||||||
val: 'right'
|
value: 'right'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'left'
|
defaultValue: 'left'
|
||||||
|
|
|
@ -44,7 +44,7 @@ export default {
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: createEditorInputNumberProp({ label: '默认值', defaultValue: 0 }),
|
modelValue: createEditorInputNumberProp({ label: '默认值', defaultValue: 0 }),
|
||||||
name: createEditorInputProp({ label: '名称,提交表单的标识符', defaultValue: 'rate' }),
|
name: createEditorInputProp({ label: '字段名', defaultValue: 'rate' }),
|
||||||
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '评分' }),
|
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '评分' }),
|
||||||
count: createEditorInputNumberProp({ label: '图标总数' }),
|
count: createEditorInputNumberProp({ label: '图标总数' }),
|
||||||
size: createEditorInputProp({ label: '图标大小' }),
|
size: createEditorInputProp({ label: '图标大小' }),
|
||||||
|
|
|
@ -19,15 +19,15 @@ export const createFieldProps = () => ({
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '左对齐',
|
label: '左对齐',
|
||||||
val: 'left'
|
value: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '居中',
|
label: '居中',
|
||||||
val: 'center'
|
value: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '右对齐',
|
label: '右对齐',
|
||||||
val: 'right'
|
value: 'right'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'left'
|
defaultValue: 'left'
|
||||||
|
|
|
@ -44,7 +44,7 @@ export default {
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: createEditorInputNumberProp({ label: '默认值', defaultValue: 0 }),
|
modelValue: createEditorInputNumberProp({ label: '默认值', defaultValue: 0 }),
|
||||||
name: createEditorInputProp({ label: '名称,提交表单的标识符', defaultValue: 'slider' }),
|
name: createEditorInputProp({ label: '字段名', defaultValue: 'slider' }),
|
||||||
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '滑块' }),
|
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '滑块' }),
|
||||||
min: createEditorInputNumberProp({ label: '最小值' }),
|
min: createEditorInputNumberProp({ label: '最小值' }),
|
||||||
max: createEditorInputNumberProp({ label: '最大值' }),
|
max: createEditorInputNumberProp({ label: '最大值' }),
|
||||||
|
|
|
@ -19,15 +19,15 @@ export const createFieldProps = () => ({
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '左对齐',
|
label: '左对齐',
|
||||||
val: 'left'
|
value: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '居中',
|
label: '居中',
|
||||||
val: 'center'
|
value: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '右对齐',
|
label: '右对齐',
|
||||||
val: 'right'
|
value: 'right'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'left'
|
defaultValue: 'left'
|
||||||
|
|
|
@ -43,7 +43,7 @@ export default {
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
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: '最小值' }),
|
||||||
max: createEditorInputNumberProp({ label: '最大值' }),
|
max: createEditorInputNumberProp({ label: '最大值' }),
|
||||||
|
|
|
@ -19,15 +19,15 @@ export const createFieldProps = () => ({
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '左对齐',
|
label: '左对齐',
|
||||||
val: 'left'
|
value: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '居中',
|
label: '居中',
|
||||||
val: 'center'
|
value: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '右对齐',
|
label: '右对齐',
|
||||||
val: 'right'
|
value: 'right'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultValue: 'left'
|
defaultValue: 'left'
|
||||||
|
|
|
@ -35,7 +35,7 @@ export default {
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
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: '打开时的背景色' }),
|
'active-color': createEditorInputProp({ label: '打开时的背景色' }),
|
||||||
'active-value': createEditorInputProp({ label: '打开时对应的值' }),
|
'active-value': createEditorInputProp({ label: '打开时对应的值' }),
|
||||||
|
|
|
@ -19,9 +19,9 @@ export default {
|
||||||
size: createEditorSelectProp({
|
size: createEditorSelectProp({
|
||||||
label: '字体大小',
|
label: '字体大小',
|
||||||
options: [
|
options: [
|
||||||
{ label: '14px', val: '14px' },
|
{ label: '14px', value: '14px' },
|
||||||
{ label: '18px', val: '18px' },
|
{ label: '18px', value: '18px' },
|
||||||
{ label: '24px', val: '24px' }
|
{ label: '24px', value: '24px' }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/**
|
||||||
|
* @name: createProps
|
||||||
|
* @author: 卜启缘
|
||||||
|
* @date: 2021/5/30 10:50
|
||||||
|
* @description:createProps
|
||||||
|
* @update: 2021/5/30 10:50
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
createEditorInputProp,
|
||||||
|
createEditorSelectProp,
|
||||||
|
createEditorSwitchProp,
|
||||||
|
createEditorTableProp
|
||||||
|
} from '@/visual-editor/visual-editor.props'
|
||||||
|
|
||||||
|
// 对齐方式
|
||||||
|
const alignOptions = [
|
||||||
|
{
|
||||||
|
label: '左对齐',
|
||||||
|
value: 'left'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '右对齐',
|
||||||
|
value: 'right'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '居中对齐',
|
||||||
|
value: 'center'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
export const compProps = {
|
||||||
|
'slots.default.children': createEditorTableProp({
|
||||||
|
label: '表单项',
|
||||||
|
option: {
|
||||||
|
options: [
|
||||||
|
{ label: '显示值', field: 'label' },
|
||||||
|
{ label: '绑定值', field: 'value' },
|
||||||
|
{ label: '备注', field: 'comments' }
|
||||||
|
],
|
||||||
|
showKey: 'label'
|
||||||
|
},
|
||||||
|
defaultValue: []
|
||||||
|
}),
|
||||||
|
colon: createEditorSwitchProp({ label: '是否在 label 后面添加冒号' }),
|
||||||
|
disabled: createEditorSwitchProp({ label: '是否禁用表单中的所有输入框' }),
|
||||||
|
errorMessageAlign: createEditorSelectProp({
|
||||||
|
label: '错误提示文案对齐方式',
|
||||||
|
defaultValue: 'left',
|
||||||
|
options: alignOptions
|
||||||
|
}),
|
||||||
|
inputAlign: createEditorSelectProp({
|
||||||
|
label: '输入框对齐方式',
|
||||||
|
defaultValue: 'left',
|
||||||
|
options: alignOptions
|
||||||
|
}),
|
||||||
|
labelAlign: createEditorSelectProp({
|
||||||
|
label: '表单项 label 对齐方式',
|
||||||
|
defaultValue: 'left',
|
||||||
|
options: alignOptions
|
||||||
|
}),
|
||||||
|
labelWidth: createEditorInputProp({ label: '表单项 label 宽度,默认单位为px' }),
|
||||||
|
readonly: createEditorSwitchProp({ label: '是否将表单中的所有输入框设置为只读状态' }),
|
||||||
|
scrollToError: createEditorSwitchProp({
|
||||||
|
label: '在提交表单且校验不通过时滚动至错误的表单项'
|
||||||
|
}),
|
||||||
|
showError: createEditorSwitchProp({ label: '是否在校验不通过时标红输入框' }),
|
||||||
|
showErrorMessage: createEditorSwitchProp({
|
||||||
|
label: '是否在校验不通过时在输入框下方展示错误提示'
|
||||||
|
}),
|
||||||
|
submitOnEnter: createEditorSwitchProp({ label: '是否在按下回车键时提交表单' }),
|
||||||
|
validateFirst: createEditorSwitchProp({ label: '是否在某一项校验不通过时停止校验' }),
|
||||||
|
validateTrigger: createEditorInputProp({
|
||||||
|
label: '表单校验触发时机,可选值为 onChange、onSubmit,详见下表'
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
import { Form, Field, Button } from 'vant'
|
import { Form, Field, Button } from 'vant'
|
||||||
import { renderSlot, getCurrentInstance } from 'vue'
|
import { renderSlot, getCurrentInstance } from 'vue'
|
||||||
import { createEditorTableProp } from '@/visual-editor/visual-editor.props'
|
|
||||||
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
import { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||||
|
import { compProps } from './compProps'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
key: 'form',
|
key: 'form',
|
||||||
|
@ -37,18 +37,5 @@ export default {
|
||||||
height: true,
|
height: true,
|
||||||
width: true
|
width: true
|
||||||
},
|
},
|
||||||
props: {
|
props: compProps
|
||||||
'slots.default.children': createEditorTableProp({
|
|
||||||
label: '表单项',
|
|
||||||
option: {
|
|
||||||
options: [
|
|
||||||
{ label: '显示值', field: 'label' },
|
|
||||||
{ label: '绑定值', field: 'value' },
|
|
||||||
{ label: '备注', field: 'comments' }
|
|
||||||
],
|
|
||||||
showKey: 'label'
|
|
||||||
},
|
|
||||||
defaultValue: []
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} as VisualEditorComponent
|
} as VisualEditorComponent
|
||||||
|
|
|
@ -85,32 +85,32 @@ export default {
|
||||||
slots: createEditorSelectProp({
|
slots: createEditorSelectProp({
|
||||||
label: '列比例',
|
label: '列比例',
|
||||||
options: [
|
options: [
|
||||||
{ label: '24', val: createSlots('24') },
|
{ label: '24', value: createSlots('24') },
|
||||||
{ label: '12:12', val: createSlots('12:12') },
|
{ label: '12:12', value: createSlots('12:12') },
|
||||||
{ label: '6:18', val: createSlots('6:18') },
|
{ label: '6:18', value: createSlots('6:18') },
|
||||||
{ label: '18:6', val: createSlots('18:6') },
|
{ label: '18:6', value: createSlots('18:6') },
|
||||||
{ label: '8:8:8', val: createSlots('8:8:8') },
|
{ label: '8:8:8', value: createSlots('8:8:8') },
|
||||||
{ label: '6:12:6', val: createSlots('6:12:6') },
|
{ label: '6:12:6', value: createSlots('6:12:6') },
|
||||||
{ label: '6:6:6:6', val: createSlots('6:6:6:6') }
|
{ label: '6:6:6:6', value: createSlots('6:6:6:6') }
|
||||||
],
|
],
|
||||||
defaultValue: createSlots('12:12')
|
defaultValue: createSlots('12:12')
|
||||||
}),
|
}),
|
||||||
justify: createEditorSelectProp({
|
justify: createEditorSelectProp({
|
||||||
label: '主轴对齐方式',
|
label: '主轴对齐方式',
|
||||||
options: [
|
options: [
|
||||||
{ label: '左对齐', val: 'start' },
|
{ label: '左对齐', value: 'start' },
|
||||||
{ label: '居中排列', val: 'center' },
|
{ label: '居中排列', value: 'center' },
|
||||||
{ label: '均匀对齐', val: 'space-around' },
|
{ label: '均匀对齐', value: 'space-around' },
|
||||||
{ label: '两端对齐', val: 'space-between' },
|
{ label: '两端对齐', value: 'space-between' },
|
||||||
{ label: '右对齐', val: 'end' }
|
{ label: '右对齐', value: 'end' }
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
align: createEditorSelectProp({
|
align: createEditorSelectProp({
|
||||||
label: '交叉轴对齐方式',
|
label: '交叉轴对齐方式',
|
||||||
options: [
|
options: [
|
||||||
{ label: '顶部对齐', val: 'top' },
|
{ label: '顶部对齐', value: 'top' },
|
||||||
{ label: '垂直居中', val: 'center' },
|
{ label: '垂直居中', value: 'center' },
|
||||||
{ label: '底部对齐', val: 'bottom' }
|
{ label: '底部对齐', value: 'bottom' }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,9 @@
|
||||||
|
import { App } from 'vue'
|
||||||
import '@vant/touch-emulator'
|
import '@vant/touch-emulator'
|
||||||
import 'vant/lib/index.css'
|
import 'vant/lib/index.css'
|
||||||
|
|
||||||
|
import { Lazyload } from 'vant'
|
||||||
|
|
||||||
|
export const setupVant = (app: App) => {
|
||||||
|
app.use(Lazyload)
|
||||||
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
>删除</el-dropdown-item
|
>删除</el-dropdown-item
|
||||||
>
|
>
|
||||||
<el-dropdown-item icon="el-icon-link" @click="setDefaultPage(data)"
|
<el-dropdown-item icon="el-icon-link" @click="setDefaultPage(data)"
|
||||||
>设为默认</el-dropdown-item
|
>设为首页</el-dropdown-item
|
||||||
>
|
>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
/**
|
||||||
|
* @name: index
|
||||||
|
* @author: 卜启缘
|
||||||
|
* @date: 2021/5/30 10:57
|
||||||
|
* @description:index
|
||||||
|
* @update: 2021/5/30 10:57
|
||||||
|
*/
|
||||||
|
export { TablePropEditor } from './table-prop-editor/table-prop-editor'
|
|
@ -1,8 +1,8 @@
|
||||||
import { defineComponent, PropType } from 'vue'
|
import { defineComponent, PropType, SetupContext } from 'vue'
|
||||||
import { VisualEditorProps } from '../../../../visual-editor.props'
|
import { VisualEditorProps } from '@/visual-editor/visual-editor.props'
|
||||||
import { useModel } from '../../../../hooks/useModel'
|
|
||||||
import { ElButton, ElTag } from 'element-plus'
|
import { ElButton, ElTag } from 'element-plus'
|
||||||
import { $$tablePropEditor } from './table-prop-edit.service'
|
import { $$tablePropEditor } from './table-prop-edit.service'
|
||||||
|
import { useVModel } from '@vueuse/core'
|
||||||
|
|
||||||
export const TablePropEditor = defineComponent({
|
export const TablePropEditor = defineComponent({
|
||||||
props: {
|
props: {
|
||||||
|
@ -10,11 +10,8 @@ export const TablePropEditor = defineComponent({
|
||||||
propConfig: { type: Object as PropType<VisualEditorProps>, required: true }
|
propConfig: { type: Object as PropType<VisualEditorProps>, required: true }
|
||||||
},
|
},
|
||||||
emits: ['update:modelValue'],
|
emits: ['update:modelValue'],
|
||||||
setup(props, ctx) {
|
setup(props, { emit }: SetupContext) {
|
||||||
const model = useModel(
|
const model = useVModel(props, 'modelValue', emit)
|
||||||
() => props.modelValue,
|
|
||||||
(val) => ctx.emit('update:modelValue', val)
|
|
||||||
)
|
|
||||||
|
|
||||||
const onClick = async () => {
|
const onClick = async () => {
|
||||||
const data = await $$tablePropEditor({
|
const data = await $$tablePropEditor({
|
||||||
|
|
|
@ -22,7 +22,7 @@ import {
|
||||||
ElPopover
|
ElPopover
|
||||||
} from 'element-plus'
|
} from 'element-plus'
|
||||||
import { VisualEditorProps, VisualEditorPropsType } from '@/visual-editor/visual-editor.props'
|
import { VisualEditorProps, VisualEditorPropsType } from '@/visual-editor/visual-editor.props'
|
||||||
import { TablePropEditor } from '@/visual-editor/components/right-attribute-panel/components/table-prop-editor/table-prop-editor'
|
import { TablePropEditor } from './components/'
|
||||||
import { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils'
|
import { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils'
|
||||||
import MonacoEditor from '../common/monaco-editor/MonacoEditor'
|
import MonacoEditor from '../common/monaco-editor/MonacoEditor'
|
||||||
import { useVModel } from '@vueuse/core'
|
import { useVModel } from '@vueuse/core'
|
||||||
|
@ -57,7 +57,7 @@ export default defineComponent({
|
||||||
<ElSelect v-model={propObj[prop]} valueKey={'value'} multiple={propConfig.multiple}>
|
<ElSelect v-model={propObj[prop]} valueKey={'value'} multiple={propConfig.multiple}>
|
||||||
{(() => {
|
{(() => {
|
||||||
return propConfig.options!.map((opt) => (
|
return propConfig.options!.map((opt) => (
|
||||||
<ElOption label={opt.label} value={opt.val} />
|
<ElOption label={opt.label} value={opt.value} />
|
||||||
))
|
))
|
||||||
})()}
|
})()}
|
||||||
</ElSelect>
|
</ElSelect>
|
||||||
|
@ -93,33 +93,30 @@ export default defineComponent({
|
||||||
width={200}
|
width={200}
|
||||||
trigger="hover"
|
trigger="hover"
|
||||||
content={`你可以利用该组件ID。对该组件进行获取和设置其属性,组件可用属性可在控制台输入:$$refs.${props.block._vid} 进行查看`}
|
content={`你可以利用该组件ID。对该组件进行获取和设置其属性,组件可用属性可在控制台输入:$$refs.${props.block._vid} 进行查看`}
|
||||||
v-slots={{
|
>
|
||||||
|
{{
|
||||||
reference: () => (
|
reference: () => (
|
||||||
<i style={{ marginLeft: '6px' }} class={'el-icon-warning-outline'}></i>
|
<i style={{ marginLeft: '6px' }} class={'el-icon-warning-outline'}></i>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
></ElPopover>
|
</ElPopover>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
)
|
)
|
||||||
if (!!component) {
|
if (!!component) {
|
||||||
if (!!component.props) {
|
if (!!component.props) {
|
||||||
content.push(
|
content.push(
|
||||||
<>
|
Object.entries(component.props || {}).map(([propName, propConfig]) => (
|
||||||
{Object.entries(component.props || {}).map(([propName, propConfig]) => (
|
|
||||||
<ElFormItem
|
<ElFormItem
|
||||||
key={propName}
|
key={props.block._vid + propName}
|
||||||
v-slots={{
|
v-slots={{
|
||||||
label: () =>
|
label: () =>
|
||||||
propConfig.tips ? (
|
propConfig.tips ? (
|
||||||
<>
|
<>
|
||||||
<ElPopover
|
<ElPopover width={200} trigger={'hover'} content={propConfig.tips}>
|
||||||
width={200}
|
{{
|
||||||
trigger={'hover'}
|
|
||||||
content={propConfig.tips}
|
|
||||||
v-slots={{
|
|
||||||
reference: () => <i class={'el-icon-warning-outline'}></i>
|
reference: () => <i class={'el-icon-warning-outline'}></i>
|
||||||
}}
|
}}
|
||||||
></ElPopover>
|
</ElPopover>
|
||||||
{propConfig.label}
|
{propConfig.label}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
@ -129,8 +126,7 @@ export default defineComponent({
|
||||||
>
|
>
|
||||||
{renderEditor(propName, propConfig)}
|
{renderEditor(propName, propConfig)}
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
))}
|
))
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,6 @@ export default defineComponent({
|
||||||
const { currentPage, visualConfig } = useVisualData()
|
const { currentPage, visualConfig } = useVisualData()
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
compRefs: [],
|
|
||||||
drag: false
|
drag: false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -188,37 +187,41 @@ export default defineComponent({
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.list-group-item {
|
.list-group-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
padding: 3px;
|
||||||
cursor: move;
|
cursor: move;
|
||||||
transform: translate(0);
|
transform: translate(0);
|
||||||
padding: 3px;
|
|
||||||
|
|
||||||
&.focus {
|
&.focus {
|
||||||
content: '';
|
content: '';
|
||||||
outline: 2px solid #006eff;
|
outline: 2px solid #006eff;
|
||||||
outline-offset: -2px;
|
outline-offset: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.drag::after {
|
&.drag::after {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.no-child {
|
&.no-child {
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
&.focusWithChild {
|
&.focusWithChild {
|
||||||
outline: 2px dashed #b0c1d7;
|
outline: 2px dashed #b0c1d7;
|
||||||
outline-offset: -2px;
|
outline-offset: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.focusWithChild::before {
|
&.focusWithChild::before {
|
||||||
content: attr(data-label);
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -3px;
|
|
||||||
top: 0;
|
top: 0;
|
||||||
transform: translate(-100%, 0);
|
left: -3px;
|
||||||
background-color: #006eff;
|
|
||||||
color: white;
|
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
color: white;
|
||||||
|
background-color: #006eff;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
content: attr(data-label);
|
||||||
|
transform: translate(-100%, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* @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, DeepReadonly } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import {
|
import {
|
||||||
VisualEditorModelValue,
|
VisualEditorModelValue,
|
||||||
VisualEditorBlockData,
|
VisualEditorBlockData,
|
||||||
|
@ -40,10 +40,7 @@ export interface VisualData {
|
||||||
setCurrentPage: (path: string) => void // 设置当前正在操作的页面
|
setCurrentPage: (path: string) => void // 设置当前正在操作的页面
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initVisualData = (): VisualData => {
|
const defaultValue: VisualEditorModelValue = {
|
||||||
const jsonData: VisualEditorModelValue = JSON.parse(
|
|
||||||
sessionStorage.getItem(localKey) as string
|
|
||||||
) || {
|
|
||||||
container: {
|
container: {
|
||||||
width: 360,
|
width: 360,
|
||||||
height: 960
|
height: 960
|
||||||
|
@ -57,7 +54,14 @@ export const initVisualData = (): VisualData => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const initVisualData = (): VisualData => {
|
||||||
|
const localData = JSON.parse(sessionStorage.getItem(localKey) as string)
|
||||||
|
const jsonData: VisualEditorModelValue = Object.keys(localData?.pages || {}).length
|
||||||
|
? localData
|
||||||
|
: defaultValue
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
console.log('jsonData:', jsonData)
|
console.log('jsonData:', jsonData)
|
||||||
// 所有页面的path都必须以 / 开发
|
// 所有页面的path都必须以 / 开发
|
||||||
|
@ -65,8 +69,20 @@ export const initVisualData = (): VisualData => {
|
||||||
|
|
||||||
const state: IState = reactive({
|
const state: IState = reactive({
|
||||||
jsonData,
|
jsonData,
|
||||||
currentPage: jsonData.pages[route.path] ?? jsonData.pages['/']
|
currentPage: jsonData.pages[route.path]
|
||||||
})
|
})
|
||||||
|
const paths = Object.keys(jsonData.pages)
|
||||||
|
|
||||||
|
const isExistPath = paths.some((path) => route.path == path)
|
||||||
|
// 当前页面是否存在
|
||||||
|
if (!isExistPath) {
|
||||||
|
router.replace(paths[0] || '/')
|
||||||
|
state.currentPage = jsonData.pages[paths[0]] ?? defaultValue.pages['/']
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(jsonData.pages, 'jsonData.pages')
|
||||||
|
console.log(route.path, 'route.path')
|
||||||
|
console.log(state.currentPage, '哈哈哈')
|
||||||
|
|
||||||
// 路由变化时更新当前操作的页面
|
// 路由变化时更新当前操作的页面
|
||||||
watch(
|
watch(
|
||||||
|
@ -88,7 +104,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 ?? { title: '新页面', path, blocks: [] }
|
||||||
}
|
}
|
||||||
// 删除page
|
// 删除page
|
||||||
const deletePage = (path = '', redirectPath = '') => {
|
const deletePage = (path = '', redirectPath = '') => {
|
||||||
|
@ -100,6 +116,10 @@ export const initVisualData = (): VisualData => {
|
||||||
// 设置当前页面
|
// 设置当前页面
|
||||||
const setCurrentPage = (path = '/') => {
|
const setCurrentPage = (path = '/') => {
|
||||||
state.currentPage = jsonData.pages[path]
|
state.currentPage = jsonData.pages[path]
|
||||||
|
if (!state.currentPage) {
|
||||||
|
state.currentPage = jsonData.pages['/']
|
||||||
|
router.replace('/')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新pages下面的blocks
|
// 更新pages下面的blocks
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
/**
|
||||||
|
* @name: index.d
|
||||||
|
* @author: 卜启缘
|
||||||
|
* @date: 2021/5/30 10:40
|
||||||
|
* @description:index.d
|
||||||
|
* @update: 2021/5/30 10:40
|
||||||
|
*/
|
||||||
|
declare type LabelValueOptions = {
|
||||||
|
label: string
|
||||||
|
value: any
|
||||||
|
}[]
|
|
@ -18,22 +18,7 @@ export type VisualEditorProps = {
|
||||||
} & {
|
} & {
|
||||||
table?: VisualEditorTableOption
|
table?: VisualEditorTableOption
|
||||||
}
|
}
|
||||||
// 控制台输入以下代码,快速生成组件属性
|
|
||||||
// let propObj = {
|
|
||||||
// string: (config) => `createEditorInputProp(${JSON.stringify(config)})`,
|
|
||||||
// number: (config) => `createEditorInputNumberProp(${JSON.stringify(config)})`,
|
|
||||||
// boolean: (config) => `createEditorSwitchProp(${JSON.stringify(config)})`
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// $$('#props + table tr').reduce((prev, curr) => {
|
|
||||||
// const children = curr.children
|
|
||||||
// const key = children[0].textContent.replace(/-([a-z])/g, (all, i) => i.toUpperCase())
|
|
||||||
// const value = (propObj[children[2].textContent ?? propObj['string'])({
|
|
||||||
// label: children[1].textContent
|
|
||||||
// }).replaceAll('"', '')
|
|
||||||
// prev[key] = value
|
|
||||||
// return prev
|
|
||||||
// }, {})
|
|
||||||
/*---------------------------------------switch-------------------------------------------*/
|
/*---------------------------------------switch-------------------------------------------*/
|
||||||
interface EditorSwitchProp {
|
interface EditorSwitchProp {
|
||||||
label: string
|
label: string
|
||||||
|
|
|
@ -1,232 +1,232 @@
|
||||||
import { useCommander } from './plugins/command.plugin'
|
// import { useCommander } from './plugins/command.plugin'
|
||||||
import { VisualEditorBlockData, VisualEditorModelValue } from './visual-editor.utils'
|
// import { VisualEditorBlockData, VisualEditorModelValue } from './visual-editor.utils'
|
||||||
import { cloneDeep } from 'lodash'
|
// import { cloneDeep } from 'lodash'
|
||||||
|
//
|
||||||
export function useVisualCommand({
|
// export function useVisualCommand({
|
||||||
focusData,
|
// focusData,
|
||||||
updateBlocks,
|
// updateBlocks,
|
||||||
dataModel,
|
// dataModel,
|
||||||
dragstart,
|
// dragstart,
|
||||||
dragend
|
// dragend
|
||||||
}: {
|
// }: {
|
||||||
focusData: { value: { focus: VisualEditorBlockData[]; unFocus: VisualEditorBlockData[] } }
|
// focusData: { value: { focus: VisualEditorBlockData[]; unFocus: VisualEditorBlockData[] } }
|
||||||
updateBlocks: (blocks?: VisualEditorBlockData[]) => void
|
// updateBlocks: (blocks?: VisualEditorBlockData[]) => void
|
||||||
dataModel: { value: VisualEditorModelValue }
|
// dataModel: { value: VisualEditorModelValue }
|
||||||
dragstart: { on: (cb: () => void) => void; off: (cb: () => void) => void }
|
// dragstart: { on: (cb: () => void) => void; off: (cb: () => void) => void }
|
||||||
dragend: { on: (cb: () => void) => void; off: (cb: () => void) => void }
|
// dragend: { on: (cb: () => void) => void; off: (cb: () => void) => void }
|
||||||
}) {
|
// }) {
|
||||||
const commander = useCommander()
|
// const commander = useCommander()
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 删除命令
|
// * 删除命令
|
||||||
* @author 卜启缘
|
// * @author 卜启缘
|
||||||
* @date 2021/4/22 11:37 下午
|
// * @date 2021/4/22 11:37 下午
|
||||||
*/
|
// */
|
||||||
commander.registry({
|
// commander.registry({
|
||||||
name: 'delete',
|
// name: 'delete',
|
||||||
keyboard: ['backspace', 'delete', 'ctrl+d'],
|
// keyboard: ['backspace', 'delete', 'ctrl+d'],
|
||||||
execute: () => {
|
// execute: () => {
|
||||||
// console.log('执行删除命令')
|
// // console.log('执行删除命令')
|
||||||
const data = {
|
// const data = {
|
||||||
before: dataModel.value.blocks,
|
// before: dataModel.value.blocks,
|
||||||
after: focusData.value.unFocus
|
// after: focusData.value.unFocus
|
||||||
}
|
// }
|
||||||
return {
|
// return {
|
||||||
redo: () => {
|
// redo: () => {
|
||||||
// console.log('重做删除命令')
|
// // console.log('重做删除命令')
|
||||||
updateBlocks(cloneDeep(data.after))
|
// updateBlocks(cloneDeep(data.after))
|
||||||
},
|
// },
|
||||||
undo: () => {
|
// undo: () => {
|
||||||
// console.log('撤回删除命令')
|
// // console.log('撤回删除命令')
|
||||||
updateBlocks(cloneDeep(data.before))
|
// updateBlocks(cloneDeep(data.before))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 拖拽命令,适用于三种情况:
|
// * 拖拽命令,适用于三种情况:
|
||||||
* - 从菜单拖拽组件到容器画布;
|
// * - 从菜单拖拽组件到容器画布;
|
||||||
* - 在容器中拖拽组件调整位置
|
// * - 在容器中拖拽组件调整位置
|
||||||
* - 拖拽调整组件的宽度和高度;
|
// * - 拖拽调整组件的宽度和高度;
|
||||||
* @author 卜启缘
|
// * @author 卜启缘
|
||||||
* @date 2021/4/22 11:38 下午
|
// * @date 2021/4/22 11:38 下午
|
||||||
*/
|
// */
|
||||||
commander.registry({
|
// commander.registry({
|
||||||
name: 'drag',
|
// name: 'drag',
|
||||||
init() {
|
// init() {
|
||||||
this.data = { before: null as null | VisualEditorBlockData[] }
|
// this.data = { before: null as null | VisualEditorBlockData[] }
|
||||||
const handler = {
|
// const handler = {
|
||||||
dragstart: () => (this.data.before = cloneDeep(dataModel.value.blocks)),
|
// dragstart: () => (this.data.before = cloneDeep(dataModel.value.blocks)),
|
||||||
dragend: () => commander.state.commands.drag()
|
// dragend: () => commander.state.commands.drag()
|
||||||
}
|
// }
|
||||||
dragstart.on(handler.dragstart)
|
// dragstart.on(handler.dragstart)
|
||||||
dragend.on(handler.dragend)
|
// dragend.on(handler.dragend)
|
||||||
return () => {
|
// return () => {
|
||||||
dragstart.off(handler.dragstart)
|
// dragstart.off(handler.dragstart)
|
||||||
dragend.off(handler.dragend)
|
// dragend.off(handler.dragend)
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
execute() {
|
// execute() {
|
||||||
const before = cloneDeep(this.data.before)
|
// const before = cloneDeep(this.data.before)
|
||||||
const after = cloneDeep(dataModel.value.blocks)
|
// const after = cloneDeep(dataModel.value.blocks)
|
||||||
return {
|
// return {
|
||||||
redo: () => {
|
// redo: () => {
|
||||||
updateBlocks(cloneDeep(after))
|
// updateBlocks(cloneDeep(after))
|
||||||
},
|
// },
|
||||||
undo: () => {
|
// undo: () => {
|
||||||
updateBlocks(cloneDeep(before))
|
// updateBlocks(cloneDeep(before))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
//
|
||||||
commander.registry({
|
// commander.registry({
|
||||||
name: 'clear',
|
// name: 'clear',
|
||||||
execute: () => {
|
// execute: () => {
|
||||||
const data = {
|
// const data = {
|
||||||
before: cloneDeep(dataModel.value.blocks),
|
// before: cloneDeep(dataModel.value.blocks),
|
||||||
after: cloneDeep([])
|
// after: cloneDeep([])
|
||||||
}
|
// }
|
||||||
return {
|
// return {
|
||||||
redo: () => {
|
// redo: () => {
|
||||||
updateBlocks(cloneDeep(data.after))
|
// updateBlocks(cloneDeep(data.after))
|
||||||
},
|
// },
|
||||||
undo: () => {
|
// undo: () => {
|
||||||
updateBlocks(cloneDeep(data.before))
|
// updateBlocks(cloneDeep(data.before))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
//
|
||||||
commander.registry({
|
// commander.registry({
|
||||||
name: 'placeTop',
|
// name: 'placeTop',
|
||||||
keyboard: 'ctrl+up',
|
// keyboard: 'ctrl+up',
|
||||||
execute: () => {
|
// execute: () => {
|
||||||
const data = {
|
// const data = {
|
||||||
before: cloneDeep(dataModel.value.blocks),
|
// before: cloneDeep(dataModel.value.blocks),
|
||||||
after: cloneDeep(
|
// after: cloneDeep(
|
||||||
(() => {
|
// (() => {
|
||||||
const { focus, unFocus } = focusData.value
|
// const { focus, unFocus } = focusData.value
|
||||||
const maxZIndex =
|
// const maxZIndex =
|
||||||
unFocus.reduce((prev, block) => Math.max(prev, block.zIndex), -Infinity) + 1
|
// unFocus.reduce((prev, block) => Math.max(prev, block.zIndex), -Infinity) + 1
|
||||||
focus.forEach((block) => (block.zIndex = maxZIndex))
|
// focus.forEach((block) => (block.zIndex = maxZIndex))
|
||||||
return cloneDeep(dataModel.value.blocks)
|
// return cloneDeep(dataModel.value.blocks)
|
||||||
})()
|
// })()
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
return {
|
// return {
|
||||||
redo: () => {
|
// redo: () => {
|
||||||
updateBlocks(cloneDeep(data.after))
|
// updateBlocks(cloneDeep(data.after))
|
||||||
},
|
// },
|
||||||
undo: () => {
|
// undo: () => {
|
||||||
updateBlocks(cloneDeep(data.before))
|
// updateBlocks(cloneDeep(data.before))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
//
|
||||||
commander.registry({
|
// commander.registry({
|
||||||
name: 'placeBottom',
|
// name: 'placeBottom',
|
||||||
keyboard: 'ctrl+down',
|
// keyboard: 'ctrl+down',
|
||||||
execute: () => {
|
// execute: () => {
|
||||||
const data = {
|
// const data = {
|
||||||
before: cloneDeep(dataModel.value.blocks),
|
// before: cloneDeep(dataModel.value.blocks),
|
||||||
after: cloneDeep(
|
// after: cloneDeep(
|
||||||
(() => {
|
// (() => {
|
||||||
const { focus, unFocus } = focusData.value
|
// const { focus, unFocus } = focusData.value
|
||||||
let minZIndex =
|
// let minZIndex =
|
||||||
unFocus.reduce((prev, block) => Math.min(prev, block.zIndex), Infinity) - 1
|
// unFocus.reduce((prev, block) => Math.min(prev, block.zIndex), Infinity) - 1
|
||||||
if (minZIndex < 0) {
|
// if (minZIndex < 0) {
|
||||||
const dur = Math.abs(minZIndex)
|
// const dur = Math.abs(minZIndex)
|
||||||
unFocus.forEach((block) => (block.zIndex += dur))
|
// unFocus.forEach((block) => (block.zIndex += dur))
|
||||||
minZIndex = 0
|
// minZIndex = 0
|
||||||
}
|
// }
|
||||||
focus.forEach((block) => (block.zIndex = minZIndex))
|
// focus.forEach((block) => (block.zIndex = minZIndex))
|
||||||
return cloneDeep(dataModel.value.blocks)
|
// return cloneDeep(dataModel.value.blocks)
|
||||||
})()
|
// })()
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
return {
|
// return {
|
||||||
redo: () => {
|
// redo: () => {
|
||||||
updateBlocks(cloneDeep(data.after))
|
// updateBlocks(cloneDeep(data.after))
|
||||||
},
|
// },
|
||||||
undo: () => {
|
// undo: () => {
|
||||||
updateBlocks(cloneDeep(data.before))
|
// updateBlocks(cloneDeep(data.before))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
//
|
||||||
commander.registry({
|
// commander.registry({
|
||||||
name: 'updateBlock',
|
// name: 'updateBlock',
|
||||||
execute: (newBlock: VisualEditorBlockData, oldBlock: VisualEditorBlockData) => {
|
// execute: (newBlock: VisualEditorBlockData, oldBlock: VisualEditorBlockData) => {
|
||||||
let blocks = cloneDeep(dataModel.value.blocks || [])
|
// let blocks = cloneDeep(dataModel.value.blocks || [])
|
||||||
const data = {
|
// const data = {
|
||||||
before: blocks,
|
// before: blocks,
|
||||||
after: (() => {
|
// after: (() => {
|
||||||
blocks = [...blocks]
|
// blocks = [...blocks]
|
||||||
const index = dataModel.value.blocks!.indexOf(oldBlock)
|
// const index = dataModel.value.blocks!.indexOf(oldBlock)
|
||||||
if (index > -1) {
|
// if (index > -1) {
|
||||||
blocks.splice(index, 1, newBlock)
|
// blocks.splice(index, 1, newBlock)
|
||||||
}
|
// }
|
||||||
return cloneDeep(blocks)
|
// return cloneDeep(blocks)
|
||||||
})()
|
// })()
|
||||||
}
|
// }
|
||||||
return {
|
// return {
|
||||||
redo: () => {
|
// redo: () => {
|
||||||
updateBlocks(cloneDeep(data.after))
|
// updateBlocks(cloneDeep(data.after))
|
||||||
},
|
// },
|
||||||
undo: () => {
|
// undo: () => {
|
||||||
updateBlocks(cloneDeep(data.before))
|
// updateBlocks(cloneDeep(data.before))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
//
|
||||||
commander.registry({
|
// commander.registry({
|
||||||
name: 'updateModelValue',
|
// name: 'updateModelValue',
|
||||||
execute: (val: VisualEditorModelValue) => {
|
// execute: (val: VisualEditorModelValue) => {
|
||||||
const data = {
|
// const data = {
|
||||||
before: cloneDeep(dataModel.value),
|
// before: cloneDeep(dataModel.value),
|
||||||
after: cloneDeep(val)
|
// after: cloneDeep(val)
|
||||||
}
|
// }
|
||||||
return {
|
// return {
|
||||||
redo: () => {
|
// redo: () => {
|
||||||
dataModel.value = data.after
|
// dataModel.value = data.after
|
||||||
},
|
// },
|
||||||
undo: () => {
|
// undo: () => {
|
||||||
dataModel.value = data.before
|
// dataModel.value = data.before
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
//
|
||||||
commander.registry({
|
// commander.registry({
|
||||||
name: 'selectAll',
|
// name: 'selectAll',
|
||||||
followQueue: false,
|
// followQueue: false,
|
||||||
keyboard: 'ctrl+a',
|
// keyboard: 'ctrl+a',
|
||||||
execute: () => {
|
// execute: () => {
|
||||||
return {
|
// return {
|
||||||
redo: () => {
|
// redo: () => {
|
||||||
;(dataModel.value.blocks || []).forEach((block) => (block.focus = true))
|
// ;(dataModel.value.blocks || []).forEach((block) => (block.focus = true))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
//
|
||||||
commander.init()
|
// commander.init()
|
||||||
|
//
|
||||||
return {
|
// return {
|
||||||
undo: () => commander.state.commands.undo(),
|
// undo: () => commander.state.commands.undo(),
|
||||||
redo: () => commander.state.commands.redo(),
|
// redo: () => commander.state.commands.redo(),
|
||||||
delete: () => commander.state.commands.delete(),
|
// delete: () => commander.state.commands.delete(),
|
||||||
clear: () => commander.state.commands.clear(),
|
// clear: () => commander.state.commands.clear(),
|
||||||
placeTop: () => commander.state.commands.placeTop(),
|
// placeTop: () => commander.state.commands.placeTop(),
|
||||||
placeBottom: () => commander.state.commands.placeBottom(),
|
// placeBottom: () => commander.state.commands.placeBottom(),
|
||||||
updateBlock: (newBlock: VisualEditorBlockData, oldBlock: VisualEditorBlockData) =>
|
// updateBlock: (newBlock: VisualEditorBlockData, oldBlock: VisualEditorBlockData) =>
|
||||||
commander.state.commands.updateBlock(newBlock, oldBlock),
|
// commander.state.commands.updateBlock(newBlock, oldBlock),
|
||||||
updateModelValue: (val: VisualEditorModelValue) =>
|
// updateModelValue: (val: VisualEditorModelValue) =>
|
||||||
commander.state.commands.updateModelValue(val)
|
// commander.state.commands.updateModelValue(val)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
Loading…
Reference in New Issue