Vue 3版本初次提交,继续测试中。

This commit is contained in:
vdpAdmin
2021-12-25 19:36:55 +08:00
commit d3c60c5b8a
294 changed files with 22068 additions and 0 deletions

View File

@ -0,0 +1,23 @@
import {
addContainerWidgetSchema,
addBasicFieldSchema,
addAdvancedFieldSchema,
addCustomWidgetSchema
} from '@/components/form-designer/widget-panel/widgetsConfig'
import {
registerCommonProperty,
registerAdvancedProperty,
registerEventProperty
} from '@/components/form-designer/setting-panel/propertyRegister'
export default {
addContainerWidgetSchema,
addBasicFieldSchema,
addAdvancedFieldSchema,
addCustomWidgetSchema,
registerCommonProperty,
registerAdvancedProperty,
registerEventProperty,
}

View File

@ -0,0 +1,112 @@
//import { vfApp } from '@/utils/create-app'
import {
addContainerWidgetSchema,
addCustomWidgetSchema
} from '@/components/form-designer/widget-panel/widgetsConfig'
import * as PERegister from '@/components/form-designer/setting-panel/propertyRegister'
import * as PEFactory from '@/components/form-designer/setting-panel/property-editor-factory.jsx'
import {cardSchema} from "@/extension/samples/extension-schema"
import CardWidget from '@/extension/samples/card/card-widget'
import CardItem from '@/extension/samples/card/card-item'
import {registerCWGenerator} from '@/utils/sfc-generator'
import {cardTemplateGenerator} from '@/extension/samples/extension-sfc-generator'
import {alertSchema} from "@/extension/samples/extension-schema"
import AlertWidget from '@/extension/samples/alert/alert-widget'
import {registerFWGenerator} from '@/utils/sfc-generator'
import {alertTemplateGenerator} from '@/extension/samples/extension-sfc-generator'
export const loadExtension = function (app) {
/**
* 加载容器组件步骤:
* 1. 加载组件Json Schema;
* 2. 全局注册容器组件,容器组件有两种状态——设计期和运行期,故需要注册两个组件;
* 3. 全局注册属性编辑器组件(基本属性、高级属性、事件属性);
* 4. 注册容器组件的代码生成器;
* 5. 加载完毕。
*/
addContainerWidgetSchema(cardSchema) //加载组件Json Schema
/* -------------------------------------------------- */
app.component(CardWidget.name, CardWidget) //注册设计期的容器组件
app.component(CardItem.name, CardItem) //注册运行期的容器组件
/* -------------------------------------------------- */
PERegister.registerCPEditor(app, 'card-folded', 'card-folded-editor',
PEFactory.createBooleanEditor('folded', 'extension.setting.cardFolded'))
PERegister.registerCPEditor(app, 'card-showFold', 'card-showFold-editor',
PEFactory.createBooleanEditor('showFold', 'extension.setting.cardShowFold'))
PERegister.registerCPEditor(app, 'card-cardWidth', 'card-cardWidth-editor',
PEFactory.createInputTextEditor('cardWidth', 'extension.setting.cardWidth'))
let shadowOptions = [
{label: 'never', value: 'never'},
{label: 'hover', value: 'hover'},
{label: 'always', value: 'always'},
]
PERegister.registerCPEditor(app, 'card-shadow', 'card-shadow-editor',
PEFactory.createSelectEditor('shadow', 'extension.setting.cardShadow',
{optionItems: shadowOptions}))
/* -------------------------------------------------- */
registerCWGenerator('card', cardTemplateGenerator) //注册容器组件的代码生成器
/* -------------------------------------------------- */
/* 容器组件加载完毕 end */
/**
* 加载字段组件步骤:
* 1. 加载组件Json Schema;
* 2. 全局注册字段组件,字段组件设计期和运行期共用,故仅需注册一个组件;
* 3. 全局注册属性编辑器组件(基本属性、高级属性、事件属性);
* 4. 注册字段组件的代码生成器;
* 5. 加载完毕。
*/
addCustomWidgetSchema(alertSchema) //加载组件Json Schema
/* -------------------------------------------------- */
app.component(AlertWidget.name, AlertWidget) //注册组件
/* -------------------------------------------------- */
PERegister.registerCPEditor(app, 'alert-title', 'alert-title-editor',
PEFactory.createInputTextEditor('title', 'extension.setting.alertTitle'))
let typeOptions = [
{label: 'success', value: 'success'},
{label: 'warning', value: 'warning'},
{label: 'info', value: 'info'},
{label: 'error', value: 'error'},
]
PERegister.registerCPEditor(app, 'alert-type', 'alert-type-editor',
PEFactory.createSelectEditor('type', 'extension.setting.alertType',
{optionItems: typeOptions}))
PERegister.registerCPEditor(app, 'alert-description', 'alert-description-editor',
PEFactory.createInputTextEditor('description', 'extension.setting.description'))
PERegister.registerCPEditor(app, 'alert-closable', 'alert-closable-editor',
PEFactory.createBooleanEditor('closable', 'extension.setting.closable'))
PERegister.registerCPEditor(app, 'alert-closeText', 'alert-closeText-editor',
PEFactory.createInputTextEditor('closeText', 'extension.setting.closeText'))
PERegister.registerCPEditor(app, 'alert-center', 'alert-center-editor',
PEFactory.createBooleanEditor('center', 'extension.setting.center'))
PERegister.registerCPEditor(app, 'alert-showIcon', 'alert-showIcon-editor',
PEFactory.createBooleanEditor('showIcon', 'extension.setting.showIcon'))
let effectOptions = [
{label: 'light', value: 'light'},
{label: 'dark', value: 'dark'},
]
PERegister.registerCPEditor(app, 'alert-effect', 'alert-effect-editor',
PEFactory.createRadioButtonGroupEditor('effect', 'extension.setting.effect',
{optionItems: effectOptions}))
PERegister.registerEPEditor(app, 'alert-onClose', 'alert-onClose-editor',
PEFactory.createEventHandlerEditor('onClose', []))
/* -------------------------------------------------- */
registerFWGenerator('alert', alertTemplateGenerator) //注册字段组件的代码生成器
/* -------------------------------------------------- */
/* 字段组件加载完毕 end */
}

View File

@ -0,0 +1,72 @@
<template>
<static-content-wrapper :designer="designer" :field="field" :design-state="designState"
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
<el-alert ref="fieldEditor" :title="field.options.title" :type="field.options.type"
:description="field.options.description" :closable="field.options.closable"
:center="field.options.center" :close-text="field.options.closeText"
:show-icon="field.options.showIcon" :effect="field.options.effect" @close="handelCloseCustomEvent"></el-alert>
</static-content-wrapper>
</template>
<script>
import StaticContentWrapper from '@/components/form-designer/form-widget/field-widget/static-content-wrapper'
import emitter from '@/utils/emitter'
import i18n from "@/utils/i18n"
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin"
export default {
name: "alert-widget",
componentName: 'FieldWidget', //必须固定为FieldWidget用于接收父级组件的broadcast事件
mixins: [emitter, fieldMixin, i18n],
props: {
field: Object,
parentWidget: Object,
parentList: Array,
indexOfParentList: Number,
designer: Object,
designState: {
type: Boolean,
default: false
},
subFormRowIndex: { /* 子表单组件行索引从0开始计数 */
type: Number,
default: -1
},
subFormColIndex: { /* 子表单组件列索引从0开始计数 */
type: Number,
default: -1
},
subFormRowId: { /* 子表单组件行Id唯一id且不可变 */
type: String,
default: ''
},
},
components: {
StaticContentWrapper,
},
created() {
this.registerToRefList()
this.initEventHandler()
},
beforeUnmount() {
this.unregisterFromRefList()
},
methods: {
handelCloseCustomEvent() {
if (!!this.field.options.onClose) {
let changeFn = new Function(this.field.options.onClose)
changeFn.call(this)
}
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,102 @@
<template>
<container-item-wrapper :widget="widget">
<el-card :key="widget.id" class="card-container" :class="[!!widget.options.folded ? 'folded' : '', customClass]"
:shadow="widget.options.shadow" :style="{width: widget.options.cardWidth + '!important' || ''}"
:ref="widget.id" v-show="!widget.options.hidden">
<template #header>
<div class="clear-fix">
<span>{{widget.options.label}}</span>
<i v-if="widget.options.showFold" class="float-right"
:class="[!widget.options.folded ? 'el-icon-arrow-down' : 'el-icon-arrow-up']" @click="toggleCard"></i>
</div>
</template>
<template v-if="!!widget.widgetList && (widget.widgetList.length > 0)">
<template v-for="(subWidget, swIdx) in widget.widgetList">
<template v-if="'container' === subWidget.category">
<component :is="subWidget.type + '-item'" :widget="subWidget" :key="swIdx" :parent-list="widget.widgetList"
:index-of-parent-list="swIdx" :parent-widget="widget">
<!-- 递归传递插槽 -->
<template v-for="slot in Object.keys($slots)" v-slot:[slot]="scope">
<slot :name="slot" v-bind="scope"/>
</template>
</component>
</template>
<template v-else>
<component :is="subWidget.type + '-widget'" :field="subWidget" :designer="null" :key="swIdx" :parent-list="widget.widgetList"
:index-of-parent-list="swIdx" :parent-widget="widget">
<!-- 递归传递插槽 -->
<template v-for="slot in Object.keys($slots)" v-slot:[slot]="scope">
<slot :name="slot" v-bind="scope"/>
</template>
</component>
</template>
</template>
</template>
</el-card>
</container-item-wrapper>
</template>
<script>
import emitter from '@/utils/emitter'
import i18n from "@/utils/i18n"
import refMixin from "@/components/form-render/refMixin"
import ContainerItemWrapper from '@/components/form-render/container-item/container-item-wrapper'
import containerItemMixin from "@/components/form-render/container-item/containerItemMixin"
import FieldComponents from '@/components/form-designer/form-widget/field-widget/index'
export default {
name: "card-item",
componentName: 'ContainerItem',
mixins: [emitter, i18n, refMixin, containerItemMixin],
components: {
ContainerItemWrapper,
...FieldComponents,
},
props: {
widget: Object,
},
inject: ['refList', 'sfRefList', 'globalModel'],
computed: {
customClass() {
return this.widget.options.customClass || ''
},
},
created() {
this.initRefList()
},
beforeUnmount() {
this.unregisterFromRefList()
},
methods: {
toggleCard() {
this.widget.options.folded = !this.widget.options.folded
},
},
}
</script>
<style lang="scss" scoped>
:deep(.el-card__header) {
padding: 10px 12px;
}
.folded :deep(.el-card__body) {
display: none;
}
.clear-fix:before, .clear-fix:after {
display: table;
content: "";
}
.clear-fix:after {
clear: both;
}
.float-right {
float: right;
}
</style>

View File

@ -0,0 +1,121 @@
<template>
<container-wrapper :designer="designer" :widget="widget" :parent-widget="parentWidget" :parent-list="parentList"
:index-of-parent-list="indexOfParentList">
<el-card :key="widget.id" class="card-container" @click.stop="selectWidget(widget)"
:shadow="widget.options.shadow" :style="{width: widget.options.cardWidth + '!important' || ''}"
:class="[selected ? 'selected' : '', !!widget.options.folded ? 'folded' : '', customClass]">
<template #header>
<div class="clear-fix">
<span>{{widget.options.label}}</span>
<i v-if="widget.options.showFold" class="float-right"
:class="[!widget.options.folded ? 'el-icon-arrow-down' : 'el-icon-arrow-up']"
@click="toggleCard"></i>
</div>
</template>
<draggable :list="widget.widgetList" item-key="id" v-bind="{group:'dragGroup', ghostClass: 'ghost',animation: 200}"
handle=".drag-handler" tag="transition-group" :component-data="{name: 'fade'}"
@add="(evt) => onContainerDragAdd(evt, widget.widgetList)"
@update="onContainerDragUpdate" :move="checkContainerMove">
<template #item="{ element: subWidget, index: swIdx }">
<div class="form-widget-list">
<template v-if="'container' === subWidget.category">
<component :is="subWidget.type + '-widget'" :widget="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
:index-of-parent-list="swIdx" :parent-widget="widget"></component>
</template>
<template v-else>
<component :is="subWidget.type + '-widget'" :field="subWidget" :designer="designer" :key="subWidget.id" :parent-list="widget.widgetList"
:index-of-parent-list="swIdx" :parent-widget="widget" :design-state="true"></component>
</template>
</div>
</template>
</draggable>
</el-card>
</container-wrapper>
</template>
<script>
import i18n from "@/utils/i18n"
import containerMixin from "@/components/form-designer/form-widget/container-widget/containerMixin"
import Draggable from 'vuedraggable'
import ContainerWrapper from "@/components/form-designer/form-widget/container-widget/container-wrapper"
import FieldComponents from '@/components/form-designer/form-widget/field-widget/index'
export default {
name: "card-widget",
componentName: 'ContainerWidget',
mixins: [i18n, containerMixin],
components: {
Draggable,
ContainerWrapper,
...FieldComponents,
},
props: {
widget: Object,
parentWidget: Object,
parentList: Array,
indexOfParentList: Number,
designer: Object,
},
computed: {
selected() {
return this.widget.id === this.designer.selectedId
},
customClass() {
return this.widget.options.customClass || ''
},
},
methods: {
/**
* 检查接收哪些组件拖放如不接受某些组件拖放则根据组件类型判断后返回false
* @param evt
* @returns {boolean}
*/
checkContainerMove(evt) {
return true
},
toggleCard() {
this.widget.options.folded = !this.widget.options.folded
},
/**
* 设置折叠/打开状态
* @param folded
*/
setFolded(folded) {
this.widget.options.folded = !!folded
}
}
}
</script>
<style lang="scss" scoped>
.card-container.selected {
outline: 2px solid $--color-primary !important;
}
:deep(.el-card__header) {
padding: 10px 12px;
}
.folded :deep(.el-card__body) {
display: none;
}
.clear-fix:before, .clear-fix:after {
display: table;
content: "";
}
.clear-fix:after {
clear: both;
}
.float-right {
float: right;
}
</style>

View File

@ -0,0 +1,36 @@
export const cardSchema = {
type: 'card',
category: 'container',
icon: 'card',
widgetList: [],
options: {
name: '',
label: 'card',
hidden: false,
folded: false,
showFold: true,
cardWidth: '100%',
shadow: 'never',
customClass: '',
}
}
export const alertSchema = {
type: 'alert',
icon: 'alert',
formItemFlag: false,
options: {
name: '',
title: 'Good things are coming...',
type: 'info',
description: '',
closable: true,
closeText: '',
center: true,
showIcon: false,
effect: 'light',
hidden: false,
onClose: '',
customClass: '',
}
}

View File

@ -0,0 +1,52 @@
import {buildClassAttr, buildContainerWidget, buildFieldWidget} from '@/utils/sfc-generator'
export const cardTemplateGenerator = function (cw, formConfig) {
const wop = cw.options
//const headerAttr = `header="${wop.label}"`
const classAttr = buildClassAttr(cw)
const styleAttr = !!wop.cardWidth ? `style="{width: ${wop.cardWidth} !important}"` : ''
const shadowAttr = `shadow="${wop.shadow}"`
const vShowAttr = !!wop.hidden ? `v-show="false"` : ''
const cardTemplate =
`<div class="card-container">
<el-card ${classAttr} ${styleAttr} ${shadowAttr} ${vShowAttr}>
<template #header>
<div class="clear-fix">
<span>${wop.label}</span>
${!!wop.showFold ? `<i class="float-right el-icon-arrow-down"></i>` : ''}
</div>
</template>
${
cw.widgetList.map(wItem => {
if (wItem.category === 'container') {
return buildContainerWidget(wItem, formConfig)
} else {
return buildFieldWidget(wItem, formConfig)
}
}).join('')
}
</el-card>
</div>`
return cardTemplate
}
export const alertTemplateGenerator = function(fw, formConfig) {
const wop = fw.options
const titleAttr = `title="${wop.title}"`
const typeAttr = `type=${wop.type}`
const descriptionAttr = !!wop.description ? `description="${wop.description}"` : ''
const closableAttr = `:closable="${wop.closable}"`
const closeTextAttr = !!wop.closeText ? `close-text="${wop.closeText}"` : ''
const centerAttr = `:center="${wop.center}"`
const showIconAttr = `:show-icon="${wop.showIcon}"`
const effectAttr = `effect="${wop.effect}"`
const alertTemplate =
`<el-alert ${titleAttr} ${typeAttr} ${descriptionAttr} ${closableAttr} ${closeTextAttr} ${centerAttr}
${showIconAttr} ${effectAttr}>
</el-alert>`
return alertTemplate
}