parent
25b3d69041
commit
65493e128a
@ -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,2 +1,9 @@ |
||||
import { App } from 'vue' |
||||
import '@vant/touch-emulator' |
||||
import 'vant/lib/index.css' |
||||
|
||||
import { Lazyload } from 'vant' |
||||
|
||||
export const setupVant = (app: App) => { |
||||
app.use(Lazyload) |
||||
} |
||||
|
@ -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' |
@ -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 |
||||
}[] |
@ -1,232 +1,232 @@ |
||||
import { useCommander } from './plugins/command.plugin' |
||||
import { VisualEditorBlockData, VisualEditorModelValue } from './visual-editor.utils' |
||||
import { cloneDeep } from 'lodash' |
||||
|
||||
export function useVisualCommand({ |
||||
focusData, |
||||
updateBlocks, |
||||
dataModel, |
||||
dragstart, |
||||
dragend |
||||
}: { |
||||
focusData: { value: { focus: VisualEditorBlockData[]; unFocus: VisualEditorBlockData[] } } |
||||
updateBlocks: (blocks?: VisualEditorBlockData[]) => void |
||||
dataModel: { value: VisualEditorModelValue } |
||||
dragstart: { on: (cb: () => void) => void; off: (cb: () => void) => void } |
||||
dragend: { on: (cb: () => void) => void; off: (cb: () => void) => void } |
||||
}) { |
||||
const commander = useCommander() |
||||
|
||||
/** |
||||
* 删除命令 |
||||
* @author 卜启缘 |
||||
* @date 2021/4/22 11:37 下午 |
||||
*/ |
||||
commander.registry({ |
||||
name: 'delete', |
||||
keyboard: ['backspace', 'delete', 'ctrl+d'], |
||||
execute: () => { |
||||
// console.log('执行删除命令')
|
||||
const data = { |
||||
before: dataModel.value.blocks, |
||||
after: focusData.value.unFocus |
||||
} |
||||
return { |
||||
redo: () => { |
||||
// console.log('重做删除命令')
|
||||
updateBlocks(cloneDeep(data.after)) |
||||
}, |
||||
undo: () => { |
||||
// console.log('撤回删除命令')
|
||||
updateBlocks(cloneDeep(data.before)) |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
|
||||
/** |
||||
* 拖拽命令,适用于三种情况: |
||||
* - 从菜单拖拽组件到容器画布; |
||||
* - 在容器中拖拽组件调整位置 |
||||
* - 拖拽调整组件的宽度和高度; |
||||
* @author 卜启缘 |
||||
* @date 2021/4/22 11:38 下午 |
||||
*/ |
||||
commander.registry({ |
||||
name: 'drag', |
||||
init() { |
||||
this.data = { before: null as null | VisualEditorBlockData[] } |
||||
const handler = { |
||||
dragstart: () => (this.data.before = cloneDeep(dataModel.value.blocks)), |
||||
dragend: () => commander.state.commands.drag() |
||||
} |
||||
dragstart.on(handler.dragstart) |
||||
dragend.on(handler.dragend) |
||||
return () => { |
||||
dragstart.off(handler.dragstart) |
||||
dragend.off(handler.dragend) |
||||
} |
||||
}, |
||||
execute() { |
||||
const before = cloneDeep(this.data.before) |
||||
const after = cloneDeep(dataModel.value.blocks) |
||||
return { |
||||
redo: () => { |
||||
updateBlocks(cloneDeep(after)) |
||||
}, |
||||
undo: () => { |
||||
updateBlocks(cloneDeep(before)) |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
|
||||
commander.registry({ |
||||
name: 'clear', |
||||
execute: () => { |
||||
const data = { |
||||
before: cloneDeep(dataModel.value.blocks), |
||||
after: cloneDeep([]) |
||||
} |
||||
return { |
||||
redo: () => { |
||||
updateBlocks(cloneDeep(data.after)) |
||||
}, |
||||
undo: () => { |
||||
updateBlocks(cloneDeep(data.before)) |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
|
||||
commander.registry({ |
||||
name: 'placeTop', |
||||
keyboard: 'ctrl+up', |
||||
execute: () => { |
||||
const data = { |
||||
before: cloneDeep(dataModel.value.blocks), |
||||
after: cloneDeep( |
||||
(() => { |
||||
const { focus, unFocus } = focusData.value |
||||
const maxZIndex = |
||||
unFocus.reduce((prev, block) => Math.max(prev, block.zIndex), -Infinity) + 1 |
||||
focus.forEach((block) => (block.zIndex = maxZIndex)) |
||||
return cloneDeep(dataModel.value.blocks) |
||||
})() |
||||
) |
||||
} |
||||
return { |
||||
redo: () => { |
||||
updateBlocks(cloneDeep(data.after)) |
||||
}, |
||||
undo: () => { |
||||
updateBlocks(cloneDeep(data.before)) |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
|
||||
commander.registry({ |
||||
name: 'placeBottom', |
||||
keyboard: 'ctrl+down', |
||||
execute: () => { |
||||
const data = { |
||||
before: cloneDeep(dataModel.value.blocks), |
||||
after: cloneDeep( |
||||
(() => { |
||||
const { focus, unFocus } = focusData.value |
||||
let minZIndex = |
||||
unFocus.reduce((prev, block) => Math.min(prev, block.zIndex), Infinity) - 1 |
||||
if (minZIndex < 0) { |
||||
const dur = Math.abs(minZIndex) |
||||
unFocus.forEach((block) => (block.zIndex += dur)) |
||||
minZIndex = 0 |
||||
} |
||||
focus.forEach((block) => (block.zIndex = minZIndex)) |
||||
return cloneDeep(dataModel.value.blocks) |
||||
})() |
||||
) |
||||
} |
||||
return { |
||||
redo: () => { |
||||
updateBlocks(cloneDeep(data.after)) |
||||
}, |
||||
undo: () => { |
||||
updateBlocks(cloneDeep(data.before)) |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
|
||||
commander.registry({ |
||||
name: 'updateBlock', |
||||
execute: (newBlock: VisualEditorBlockData, oldBlock: VisualEditorBlockData) => { |
||||
let blocks = cloneDeep(dataModel.value.blocks || []) |
||||
const data = { |
||||
before: blocks, |
||||
after: (() => { |
||||
blocks = [...blocks] |
||||
const index = dataModel.value.blocks!.indexOf(oldBlock) |
||||
if (index > -1) { |
||||
blocks.splice(index, 1, newBlock) |
||||
} |
||||
return cloneDeep(blocks) |
||||
})() |
||||
} |
||||
return { |
||||
redo: () => { |
||||
updateBlocks(cloneDeep(data.after)) |
||||
}, |
||||
undo: () => { |
||||
updateBlocks(cloneDeep(data.before)) |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
|
||||
commander.registry({ |
||||
name: 'updateModelValue', |
||||
execute: (val: VisualEditorModelValue) => { |
||||
const data = { |
||||
before: cloneDeep(dataModel.value), |
||||
after: cloneDeep(val) |
||||
} |
||||
return { |
||||
redo: () => { |
||||
dataModel.value = data.after |
||||
}, |
||||
undo: () => { |
||||
dataModel.value = data.before |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
|
||||
commander.registry({ |
||||
name: 'selectAll', |
||||
followQueue: false, |
||||
keyboard: 'ctrl+a', |
||||
execute: () => { |
||||
return { |
||||
redo: () => { |
||||
;(dataModel.value.blocks || []).forEach((block) => (block.focus = true)) |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
|
||||
commander.init() |
||||
|
||||
return { |
||||
undo: () => commander.state.commands.undo(), |
||||
redo: () => commander.state.commands.redo(), |
||||
delete: () => commander.state.commands.delete(), |
||||
clear: () => commander.state.commands.clear(), |
||||
placeTop: () => commander.state.commands.placeTop(), |
||||
placeBottom: () => commander.state.commands.placeBottom(), |
||||
updateBlock: (newBlock: VisualEditorBlockData, oldBlock: VisualEditorBlockData) => |
||||
commander.state.commands.updateBlock(newBlock, oldBlock), |
||||
updateModelValue: (val: VisualEditorModelValue) => |
||||
commander.state.commands.updateModelValue(val) |
||||
} |
||||
} |
||||
// import { useCommander } from './plugins/command.plugin'
|
||||
// import { VisualEditorBlockData, VisualEditorModelValue } from './visual-editor.utils'
|
||||
// import { cloneDeep } from 'lodash'
|
||||
//
|
||||
// export function useVisualCommand({
|
||||
// focusData,
|
||||
// updateBlocks,
|
||||
// dataModel,
|
||||
// dragstart,
|
||||
// dragend
|
||||
// }: {
|
||||
// focusData: { value: { focus: VisualEditorBlockData[]; unFocus: VisualEditorBlockData[] } }
|
||||
// updateBlocks: (blocks?: VisualEditorBlockData[]) => void
|
||||
// dataModel: { value: VisualEditorModelValue }
|
||||
// dragstart: { on: (cb: () => void) => void; off: (cb: () => void) => void }
|
||||
// dragend: { on: (cb: () => void) => void; off: (cb: () => void) => void }
|
||||
// }) {
|
||||
// const commander = useCommander()
|
||||
//
|
||||
// /**
|
||||
// * 删除命令
|
||||
// * @author 卜启缘
|
||||
// * @date 2021/4/22 11:37 下午
|
||||
// */
|
||||
// commander.registry({
|
||||
// name: 'delete',
|
||||
// keyboard: ['backspace', 'delete', 'ctrl+d'],
|
||||
// execute: () => {
|
||||
// // console.log('执行删除命令')
|
||||
// const data = {
|
||||
// before: dataModel.value.blocks,
|
||||
// after: focusData.value.unFocus
|
||||
// }
|
||||
// return {
|
||||
// redo: () => {
|
||||
// // console.log('重做删除命令')
|
||||
// updateBlocks(cloneDeep(data.after))
|
||||
// },
|
||||
// undo: () => {
|
||||
// // console.log('撤回删除命令')
|
||||
// updateBlocks(cloneDeep(data.before))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// /**
|
||||
// * 拖拽命令,适用于三种情况:
|
||||
// * - 从菜单拖拽组件到容器画布;
|
||||
// * - 在容器中拖拽组件调整位置
|
||||
// * - 拖拽调整组件的宽度和高度;
|
||||
// * @author 卜启缘
|
||||
// * @date 2021/4/22 11:38 下午
|
||||
// */
|
||||
// commander.registry({
|
||||
// name: 'drag',
|
||||
// init() {
|
||||
// this.data = { before: null as null | VisualEditorBlockData[] }
|
||||
// const handler = {
|
||||
// dragstart: () => (this.data.before = cloneDeep(dataModel.value.blocks)),
|
||||
// dragend: () => commander.state.commands.drag()
|
||||
// }
|
||||
// dragstart.on(handler.dragstart)
|
||||
// dragend.on(handler.dragend)
|
||||
// return () => {
|
||||
// dragstart.off(handler.dragstart)
|
||||
// dragend.off(handler.dragend)
|
||||
// }
|
||||
// },
|
||||
// execute() {
|
||||
// const before = cloneDeep(this.data.before)
|
||||
// const after = cloneDeep(dataModel.value.blocks)
|
||||
// return {
|
||||
// redo: () => {
|
||||
// updateBlocks(cloneDeep(after))
|
||||
// },
|
||||
// undo: () => {
|
||||
// updateBlocks(cloneDeep(before))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// commander.registry({
|
||||
// name: 'clear',
|
||||
// execute: () => {
|
||||
// const data = {
|
||||
// before: cloneDeep(dataModel.value.blocks),
|
||||
// after: cloneDeep([])
|
||||
// }
|
||||
// return {
|
||||
// redo: () => {
|
||||
// updateBlocks(cloneDeep(data.after))
|
||||
// },
|
||||
// undo: () => {
|
||||
// updateBlocks(cloneDeep(data.before))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// commander.registry({
|
||||
// name: 'placeTop',
|
||||
// keyboard: 'ctrl+up',
|
||||
// execute: () => {
|
||||
// const data = {
|
||||
// before: cloneDeep(dataModel.value.blocks),
|
||||
// after: cloneDeep(
|
||||
// (() => {
|
||||
// const { focus, unFocus } = focusData.value
|
||||
// const maxZIndex =
|
||||
// unFocus.reduce((prev, block) => Math.max(prev, block.zIndex), -Infinity) + 1
|
||||
// focus.forEach((block) => (block.zIndex = maxZIndex))
|
||||
// return cloneDeep(dataModel.value.blocks)
|
||||
// })()
|
||||
// )
|
||||
// }
|
||||
// return {
|
||||
// redo: () => {
|
||||
// updateBlocks(cloneDeep(data.after))
|
||||
// },
|
||||
// undo: () => {
|
||||
// updateBlocks(cloneDeep(data.before))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// commander.registry({
|
||||
// name: 'placeBottom',
|
||||
// keyboard: 'ctrl+down',
|
||||
// execute: () => {
|
||||
// const data = {
|
||||
// before: cloneDeep(dataModel.value.blocks),
|
||||
// after: cloneDeep(
|
||||
// (() => {
|
||||
// const { focus, unFocus } = focusData.value
|
||||
// let minZIndex =
|
||||
// unFocus.reduce((prev, block) => Math.min(prev, block.zIndex), Infinity) - 1
|
||||
// if (minZIndex < 0) {
|
||||
// const dur = Math.abs(minZIndex)
|
||||
// unFocus.forEach((block) => (block.zIndex += dur))
|
||||
// minZIndex = 0
|
||||
// }
|
||||
// focus.forEach((block) => (block.zIndex = minZIndex))
|
||||
// return cloneDeep(dataModel.value.blocks)
|
||||
// })()
|
||||
// )
|
||||
// }
|
||||
// return {
|
||||
// redo: () => {
|
||||
// updateBlocks(cloneDeep(data.after))
|
||||
// },
|
||||
// undo: () => {
|
||||
// updateBlocks(cloneDeep(data.before))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// commander.registry({
|
||||
// name: 'updateBlock',
|
||||
// execute: (newBlock: VisualEditorBlockData, oldBlock: VisualEditorBlockData) => {
|
||||
// let blocks = cloneDeep(dataModel.value.blocks || [])
|
||||
// const data = {
|
||||
// before: blocks,
|
||||
// after: (() => {
|
||||
// blocks = [...blocks]
|
||||
// const index = dataModel.value.blocks!.indexOf(oldBlock)
|
||||
// if (index > -1) {
|
||||
// blocks.splice(index, 1, newBlock)
|
||||
// }
|
||||
// return cloneDeep(blocks)
|
||||
// })()
|
||||
// }
|
||||
// return {
|
||||
// redo: () => {
|
||||
// updateBlocks(cloneDeep(data.after))
|
||||
// },
|
||||
// undo: () => {
|
||||
// updateBlocks(cloneDeep(data.before))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// commander.registry({
|
||||
// name: 'updateModelValue',
|
||||
// execute: (val: VisualEditorModelValue) => {
|
||||
// const data = {
|
||||
// before: cloneDeep(dataModel.value),
|
||||
// after: cloneDeep(val)
|
||||
// }
|
||||
// return {
|
||||
// redo: () => {
|
||||
// dataModel.value = data.after
|
||||
// },
|
||||
// undo: () => {
|
||||
// dataModel.value = data.before
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// commander.registry({
|
||||
// name: 'selectAll',
|
||||
// followQueue: false,
|
||||
// keyboard: 'ctrl+a',
|
||||
// execute: () => {
|
||||
// return {
|
||||
// redo: () => {
|
||||
// ;(dataModel.value.blocks || []).forEach((block) => (block.focus = true))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// commander.init()
|
||||
//
|
||||
// return {
|
||||
// undo: () => commander.state.commands.undo(),
|
||||
// redo: () => commander.state.commands.redo(),
|
||||
// delete: () => commander.state.commands.delete(),
|
||||
// clear: () => commander.state.commands.clear(),
|
||||
// placeTop: () => commander.state.commands.placeTop(),
|
||||
// placeBottom: () => commander.state.commands.placeBottom(),
|
||||
// updateBlock: (newBlock: VisualEditorBlockData, oldBlock: VisualEditorBlockData) =>
|
||||
// commander.state.commands.updateBlock(newBlock, oldBlock),
|
||||
// updateModelValue: (val: VisualEditorModelValue) =>
|
||||
// commander.state.commands.updateModelValue(val)
|
||||
// }
|
||||
// }
|
||||
|
Loading…
Reference in new issue