diff --git a/packages/ui-vue/components/designer-canvas/src/components/maps.ts b/packages/ui-vue/components/designer-canvas/src/components/maps.ts index 9e4de777f9fb77082760bc72be59b4af35100efb..bc6f087de8381e2ff5dd645228a24633b6a0ed30 100644 --- a/packages/ui-vue/components/designer-canvas/src/components/maps.ts +++ b/packages/ui-vue/components/designer-canvas/src/components/maps.ts @@ -57,6 +57,7 @@ import FTreeGrid from '@farris/ui-vue/components/tree-grid'; import FFieldset from '@farris/ui-vue/components/fieldset'; import FDrawer from '@farris/ui-vue/components/drawer'; import FHtmlTemplate from '@farris/ui-vue/components/html-template'; +import FDesignerHiddenArea from '@farris/ui-vue/components/designer-hidden-area'; const componentMap: Record = {}; const componentPropsConverter: Record = {}; @@ -130,6 +131,7 @@ function loadDesignerRegister() { FFieldset.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); FDrawer.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); FHtmlTemplate.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); + FDesignerHiddenArea.registerDesigner(componentMap, componentPropsConverter, componentPropertyConfigConverter); } } diff --git a/packages/ui-vue/components/designer-canvas/src/composition/dg-control.ts b/packages/ui-vue/components/designer-canvas/src/composition/dg-control.ts index 853950e642606731f8f98e19973d6e67df3da882..816e428eff26057d20d874f04ce54f2835581bb6 100644 --- a/packages/ui-vue/components/designer-canvas/src/composition/dg-control.ts +++ b/packages/ui-vue/components/designer-canvas/src/composition/dg-control.ts @@ -83,5 +83,8 @@ export const DgControl = { 'external-container': { type: 'external-container', name: '外部容器', icon: 'content-container' }, - 'list-nav': { type: 'list-nav', name: '列表导航' } + 'list-nav': { type: 'list-nav', name: '列表导航' }, + + 'hidden-component': { type: 'hidden-component', name: '隐藏组件' } + }; diff --git a/packages/ui-vue/components/designer-canvas/src/designer-canvas.component.tsx b/packages/ui-vue/components/designer-canvas/src/designer-canvas.component.tsx index f51372a3c5f3b28f16375cc9fee1a6aa03cdec69..d92ebf1a1f732516055beed5386f28e03d8e2111 100644 --- a/packages/ui-vue/components/designer-canvas/src/designer-canvas.component.tsx +++ b/packages/ui-vue/components/designer-canvas/src/designer-canvas.component.tsx @@ -11,6 +11,7 @@ import './composition/class/control.css'; import { loadDesignerRegister } from './components/maps'; import { F_MODAL_SERVICE_TOKEN } from '../../modal'; import { canvasKey, refreshCanvas } from './composition/update-cancas'; +import { FDesignerHiddenArea } from '@farris/ui-vue/components/designer-hidden-area'; export default defineComponent({ name: 'FDesignerCanvas', @@ -99,6 +100,17 @@ export default defineComponent({ setPositionOfButtonGroupInContainer(designerCanvasContainerElementRef.value); }); } + + /** + * 选择HiddenComponent后,触发属性面板更新 + * @param schemaValue + * @param componentInstance + */ + function onSelectHiddenComponent(schemaValue: ComponentSchema, componentInstance) { + const schemaType = schemaValue.type; + context.emit('selectionChange', schemaType, schemaValue, '', componentInstance); + } + onMounted(() => { if (designerCanvasElementRef.value) { useDragulaComposition.initializeDragula(designerCanvasElementRef.value); @@ -123,6 +135,7 @@ export default defineComponent({
{schema.value && } + {/* {schema.value && } */}
diff --git a/packages/ui-vue/components/designer-hidden-area/designer-hidden-area.css b/packages/ui-vue/components/designer-hidden-area/designer-hidden-area.css new file mode 100644 index 0000000000000000000000000000000000000000..0061975a69657dfafe6aa163529ebd5cba57017f --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/designer-hidden-area.css @@ -0,0 +1,127 @@ +/* 主内容 */ +.f-designer-hidden-area-container { + z-index: 999; +} + +.f-designer-hidden-area-main-content { + display: flex; + height: 400px; + background: #F8FAFC; + border-radius: 10px 10px 0px 0px; + box-shadow: 0px -10px 10px -10px rgba(215, 223, 244, 1); +} + +.f-designer-hidden-area-top-bar-container { + display: flex; + justify-content: flex-end; + margin-right: 30px; +} + +/* 右侧模板 */ +.f-designer-hidden-area-template-container { + background: white; + margin: 10px 10px 10px 0px; + width: 15%; + display: flex; + flex-direction: column; + align-items: center; + border-radius: 6px; +} + +.f-designer-hidden-area-usual-template-text { + width: 65px; + height: 26px; + background: #F0F3F9; + border-radius: 0px 0px 12px 12px; + text-align: center; + color: #8DA3CE; +} + +.f-designer-hidden-area-template-box-container { + width: 140px; + height: 140px; + border: 1px solid #EBEBEB; + border-radius: 4px; + margin-top: 10px; +} + +.f-designer-hidden-area-template-img-container { + width: 138px; + height: 109px; +} + +.f-designer-hidden-area-template-text-container { + height: 28px; + box-shadow: rgb(215, 223, 244) 0px -10px 10px -10px; + background: rgb(248, 250, 251); + display: flex; + align-items: center; + padding-left: 5px; +} + +/* 左侧HiddenComponent */ +.f-designer-hidden-area-component { + display: inline-block; + margin: 10px 0px 0px 10px; +} + +.f-designer-hidden-area-component-container { + display: flex; + margin: 10px; + width: 85%; + border-radius: 6px; +} + +.f-designer-hidden-area-component-list-container { + display: flex; + flex: 1; + border-radius: 6px; + box-shadow: rgba(91, 163, 255, 0.1) 0px 0px 8px 0px; + flex-wrap: wrap; + overflow: auto; +} + +.f-designer-hidden-area-component-white-background { + background-color: white; +} + +.hidden-area-drag-over:not(.no-drop) { + background-color: #f3f8ff !important; + border: 0.8px dashed #388fff !important; +} + +.f-designer-hidden-area-form-box-container { + width: 140px; + height: 140px; + border: 1px solid #EBEBEB; + border-radius: 4px; +} + +.f-designer-hidden-area-form-box-selected { + border: 2px solid #388fff !important; +} + +.f-designer-hidden-area-empty-container { + display: flex; + flex: 1; + box-shadow: rgba(91, 163, 255, 0.1) 0px 0px 8px 0px; + border-radius: 6px; + display: flex; + justify-content: center; + align-items: center; +} + +.f-designer-hidden-area-empty-container-border { + border: 0.8px dashed rgb(143, 157, 176); +} + +.f-designer-hidden-area-empty-drap-text { + width: 140px; + height: 20px; + opacity: 0.55; + font-family: PingFangSC-Regular; + font-size: 14px; + color: #3F4764; + text-align: center; + font-weight: 400; +} \ No newline at end of file diff --git a/packages/ui-vue/components/designer-hidden-area/index.ts b/packages/ui-vue/components/designer-hidden-area/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..e7e98c71655e2f693bb7e68d3e6507e42dc055e0 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/index.ts @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import type { App } from 'vue'; +import FDesignerHiddenArea from './src/designer-hidden-area.component'; +import FHiddenComponent from './src/components/hidden-component/hidden-component.component'; +import { propsResolver } from './src/components/hidden-component/hidden-component.props'; + +export { FDesignerHiddenArea }; + +export default { + install(app: App): void { + app.component(FDesignerHiddenArea.name as string, FDesignerHiddenArea); + }, + registerDesigner(componentMap: Record, propsResolverMap: Record, configResolverMap: Record): void { + componentMap['hidden-component'] = FHiddenComponent; + propsResolverMap['hidden-component'] = propsResolver; + } +}; diff --git a/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component-selector/hidden-component-selector.component.tsx b/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component-selector/hidden-component-selector.component.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2658935ef9e5c73ffe1918ff17b47074e9171ab3 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component-selector/hidden-component-selector.component.tsx @@ -0,0 +1,78 @@ +import { computed, defineComponent, Ref, ref } from "vue"; +import { FNotifyService } from "@farris/ui-vue/components/notify"; +import { FSchemaSelector, SchemaItem } from "@farris/ui-vue/components/schema-selector"; +import { FormSchemaRepositorySymbol } from '../../../../common'; +import { hiddenComponentSelectorProps, HiddenComponentSelectorProps } from "./hidden-component-selector.props"; +import { LookupSchemaRepositoryToken } from "@farris/ui-vue/components/lookup"; + +export default defineComponent({ + name: 'FHiddenComponentSelector', + props: hiddenComponentSelectorProps, + emits: ['close', 'submit'], + setup(props: HiddenComponentSelectorProps, context) { + const selectedComponent: Ref = ref(); + const { hiddenComponentType, designerHostService } = props; + const notifyService = new FNotifyService(); + notifyService.globalConfig = { position: 'top-center' }; + + const formBasicInfo = designerHostService.formSchemaUtils.getFormMetadataBasicInfo(); + const editorParams = { formBasicInfo }; + const viewOptions = [ + { id: 'recommend', title: '推荐', type: 'Card', dataSource: 'Recommand', pagination: false }, + { id: 'total', title: '全部', type: 'Card', dataSource: 'Total', pagination: false } + ]; + const injectSymbolToken = computed(() => { + return hiddenComponentType === 'Popup' ? FormSchemaRepositorySymbol : LookupSchemaRepositoryToken; + }) + + /** + * 选择HiddenComponent + * @param $event + */ + function onSelectionChange($event) { + if (hiddenComponentType === 'Help') { + selectedComponent.value = $event[0].data; + } else { + selectedComponent.value = $event[0]; + } + } + + /** + * 校验HiddenComponent + * @returns + */ + async function validate() { + if (!selectedComponent.value) { + notifyService.warning('请选择表单'); + return false; + } + return true; + } + + function onSubmit() { + context.emit('submit', selectedComponent.value); + } + + function onCancel() { + context.emit('close'); + } + + return () => { + return ( + + + ) + } + } + +}) diff --git a/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component-selector/hidden-component-selector.props.ts b/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component-selector/hidden-component-selector.props.ts new file mode 100644 index 0000000000000000000000000000000000000000..69af9e460e1d4e4c42ca9894e1e13b613abaebc6 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component-selector/hidden-component-selector.props.ts @@ -0,0 +1,13 @@ +import { ExtractPropTypes, PropType } from "vue"; +import { HiddenComponentType } from "../../composition/types"; + +export const hiddenComponentSelectorProps = { + id: { type: String, default: '' }, + modelValue: { type: Object }, + designerHostService: { type: String, Object: {} }, + hiddenComponentType: { type: String as PropType, default: 'Popup' }, + +} as Record; + +export type HiddenComponentSelectorProps = ExtractPropTypes; + diff --git a/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component-template/hidden-component-template.component.tsx b/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component-template/hidden-component-template.component.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a06b30e34aea23000319a67b4cac8e40cb40161e --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component-template/hidden-component-template.component.tsx @@ -0,0 +1,44 @@ +import { ref } from "vue"; + +export default function () { + const templates = ref([ + { + code: 'Popup', + name: '弹窗', + imagePath: './image/弹窗.png', + + }, { + code: 'Help', + name: '帮助', + imagePath: './image/帮助.png', + }, + ]); + + function renderTemplate(template: { code: string, name: string, imagePath: string }) { + const { code, name, imagePath } = template; + return ( +
+
+
+ +
+
+
{name}
+
+
+
+ ); + } + + return () => { + return ( +
+
常用模板
+
+ {templates.value.map(renderTemplate)} +
+
+ ) + } +} diff --git a/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component/hidden-component-container.component.tsx b/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component/hidden-component-container.component.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0daf3db2824fc2ce6d5b9ffe0bb9ccedf27bd300 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component/hidden-component-container.component.tsx @@ -0,0 +1,107 @@ +import { computed, inject, onMounted, Ref, ref, SetupContext } from "vue"; +import { useHiddenAreaDragula } from "../../composition/use-hidden-area-dragula"; +import { DesignerHiddenAreaProps } from "../../designer-hidden-area.props"; +import { DesignerHostService } from "@farris/ui-vue/components/designer-canvas"; +import FHiddenComponent from './hidden-component.component'; +import useHiddenComponent from "../../composition/use-hidden-component"; +import { HiddenComponentSchema } from "../../composition/types"; + +export default function ( + props: DesignerHiddenAreaProps, + context: SetupContext, +) { + /** HiddenComponent的容器 */ + const componentContainerRef = ref(); + /** 选中组件的内码 */ + const selectedComponentId: Ref = ref(); + const designerHostService = inject('designer-host-service') as DesignerHostService; + const hiddenComponentComposition = useHiddenComponent(designerHostService); + /** 拖拽相关方法 */ + const { initDragula, attachToDragulaContainer } = useHiddenAreaDragula(designerHostService, hiddenComponentComposition); + + const module = designerHostService.formSchemaUtils.getModule(); + module.hiddenComponents ??= []; + const hiddenComponents = ref(module.hiddenComponents); + /** 存在HiddenComponents */ + const hasHiddenComponents = computed(() => { + return hiddenComponents.value.length > 0; + }) + /** HiddenComponent是否选中 */ + const isSelected = computed(() => { + return (hiddenComponentSchema: HiddenComponentSchema) => hiddenComponentSchema.id === selectedComponentId.value; + }) + + /** + * 点击HiddenComponent + * @param selectedComponent + * @param componentInstance + */ + function onClick(selectedComponent: HiddenComponentSchema, componentInstance: any) { + selectedComponentId.value = selectedComponent.id; + context.emit('selectionChange', selectedComponent, componentInstance); + } + + /** + * 删除HiddenComponent + * @param component + */ + function onDelete(hiddenComponentSchema: HiddenComponentSchema) { + hiddenComponentComposition.deleteComponent(hiddenComponentSchema); + } + + onMounted(() => { + initDragula(componentContainerRef.value); + attachToDragulaContainer(); + }) + + /** + * 渲染HiddenComponent + * @returns + */ + function renderComponent(hiddenComponentSchema: HiddenComponentSchema) { + return ( + + + ) + } + + /** + * 渲染HiddenComponent所在的容器 + * @returns + */ + function renderComponentContainer() { + return ( +
+ {hiddenComponents.value.map(renderComponent)} +
+ ) + } + + /** + * 渲染空容器 + * @returns + */ + function renderEmptyContainer() { + return ( +
+
+ 从右侧拖拽模版到这里 +
+
+ ) + } + + return () => { + return ( +
+ {hasHiddenComponents.value ? renderComponentContainer() : renderEmptyContainer()} +
+ ) + } + +} diff --git a/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component/hidden-component.component.tsx b/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component/hidden-component.component.tsx new file mode 100644 index 0000000000000000000000000000000000000000..dffda2cedcf5e219bfecc6d04a3c86f92dc01711 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component/hidden-component.component.tsx @@ -0,0 +1,105 @@ +import { computed, defineComponent, inject, onMounted, ref, watch } from "vue"; +import { FNotifyService } from "@farris/ui-vue/components/notify"; +import { DesignerHostService, useDesignerComponent } from "@farris/ui-vue/components/designer-canvas"; +import { hiddenComponentProps, HiddenComponentProps } from "./hidden-component.props"; +import { useDesignerRules } from "../../composition/use-designer-rules"; +import { HiddenComponentSchema } from "../../composition/types"; + +export default defineComponent({ + name: 'FHiddenComponent', + props: hiddenComponentProps, + emits: ['click', 'delete'] as (string[] & ThisType) | undefined, + setup(props: HiddenComponentProps, context) { + const elementRef = ref(); + const notifyService = new FNotifyService(); + notifyService.globalConfig = { position: 'top-center' }; + /** HiddenComponent的Schema */ + const hiddenComponentSchema: HiddenComponentSchema = props.modelValue; + const { name, componentType } = hiddenComponentSchema; + /** 当前组件是否选中 */ + const isSelected = ref(props.isSelected); + + const designerHostService = inject('designer-host-service') as DesignerHostService; + const designerRulesComposition = useDesignerRules(hiddenComponentSchema, designerHostService); + const componentInstance = useDesignerComponent(elementRef, undefined, designerRulesComposition); + + /** 删除按钮的样式 */ + const deleteButtonStyle = computed(() => { + return isSelected.value ? 'display: flex;position:relative' : 'display: none'; + }) + /** 图片路径 */ + const imagePath = computed(() => { + return componentType === 'Popup' ? './image/弹窗.png' : './image/弹窗.png'; + }) + + /** + * 点击HiddenComponent + */ + function onClick() { + context.emit('click', hiddenComponentSchema, componentInstance.value); + } + + /** + * 删除HiddenComponent + */ + function onDelete() { + context.emit('delete', hiddenComponentSchema); + } + + onMounted(() => { + elementRef.value.componentInstance = componentInstance; + }); + + watch( + () => props.isSelected, + () => { + isSelected.value = props.isSelected; + } + ); + + context.expose(componentInstance.value); + + function renderDeleteButton() { + return ( +
+
+ +
+
+ ); + } + + function renderHidenComponent() { + return ( +
+
+
+ +
+
+
{name}
+
+
+
+ ); + } + + return () => { + return ( +
+ {renderDeleteButton()} + {renderHidenComponent()} +
+ ); + } + } + +}) diff --git a/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component/hidden-component.props.ts b/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component/hidden-component.props.ts new file mode 100644 index 0000000000000000000000000000000000000000..95d7bf5ba8463e04e84a54c022c1460c8d4a4f1e --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/components/hidden-component/hidden-component.props.ts @@ -0,0 +1,16 @@ +import { ExtractPropTypes } from "vue"; +import { createPropsResolver } from '../../../../dynamic-resolver'; +import { schemaMapper } from '../../schema/schema-mapper'; +import { schemaResolver } from '../../schema/schema-resolver'; +import hiddenComponentSchema from '../../schema/hidden-component.schema.json'; + +export const hiddenComponentProps = { + id: { type: String, default: '' }, + modelValue: { type: Object, default: {} }, + isSelected: { type: Boolean, default: false }, + +} as Record; + +export type HiddenComponentProps = ExtractPropTypes; + +export const propsResolver = createPropsResolver(hiddenComponentProps, hiddenComponentSchema, schemaMapper, schemaResolver); diff --git a/packages/ui-vue/components/designer-hidden-area/src/composition/drag-resolve.tsx b/packages/ui-vue/components/designer-hidden-area/src/composition/drag-resolve.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f23f3eeaeaf40639c844ce5d0ff8856cd6dd3b69 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/composition/drag-resolve.tsx @@ -0,0 +1,85 @@ +import { DesignerHostService } from "@farris/ui-vue/components/designer-canvas"; +import { ModalFunctions } from "@farris/ui-vue/components/modal/src/composition/type"; +import FHiddenAreaFormSelector from '../components/hidden-component-selector/hidden-component-selector.component'; +import { DesignerHTMLElement } from "@farris/ui-vue/components/designer-canvas/src/composition/types"; +import { HiddenComponentType, UseHiddenComponent } from "./types"; +import { SchemaItem } from "@farris/ui-vue/components/schema-selector"; + +export function dragResolveService(designerHostService: DesignerHostService, hiddenComponentComposition: UseHiddenComponent) { + let modalEditor: ModalFunctions; + + /** + * 关闭模态框 + */ + function closeModal() { + const closeFunction = modalEditor?.modalRef?.value.close; + if (closeFunction) { + closeFunction(); + } + } + + /** + * 确定选择HiddenComponent + * @param selectedComponent + * @param hiddenComponentType + * @returns + */ + function onSubmit(selectedComponent: SchemaItem, hiddenComponentType: HiddenComponentType) { + hiddenComponentComposition.addComponent(selectedComponent, hiddenComponentType); + closeModal(); + } + + /** + * 渲染HiddenComponent选择器 + * @param hiddenComponentType + * @returns + */ + function renderComponentSelector(hiddenComponentType: HiddenComponentType) { + return () => { + return ( + { onSubmit(selectedComponent, hiddenComponentType) }} + onClose={closeModal} hiddenComponentType={hiddenComponentType}> + ) + } + } + + /** + * 弹出HiddenComponent选择器 + * @param element + * @returns + */ + function showModel(element: DesignerHTMLElement) { + const hiddenComponentType = element.getAttribute('data-code') as HiddenComponentType; + if (!hiddenComponentType) { + console.error('HiddenComponentType is null'); + return; + } + const title = hiddenComponentType === 'Help' ? '选择帮助' : '选择表单'; + modalEditor = designerHostService.modalService.open({ + title: title, + width: 950, + height: 600, + fitContent: false, + showButtons: false, + render: renderComponentSelector(hiddenComponentType), + enableEsc: true, + draggable: true + }); + } + + /** + * 拖拽落下事件 + * @param element + * @param target + * @param source + * @param sibling + * @returns + */ + function onDrop(element: DesignerHTMLElement, target: DesignerHTMLElement, source: DesignerHTMLElement, sibling: DesignerHTMLElement) { + showModel(element); + } + + return { + onDrop + }; +} diff --git a/packages/ui-vue/components/designer-hidden-area/src/composition/types.ts b/packages/ui-vue/components/designer-hidden-area/src/composition/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..1bfdd277938223c15c96e4da9009d73743c6bc53 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/composition/types.ts @@ -0,0 +1,16 @@ +import { SchemaItem } from "@farris/ui-vue/components/schema-selector"; + +export type HiddenComponentType = 'Popup' | 'Help'; + +export interface HiddenComponentSchema { + id: string; + type: 'hidden-component'; + name: string; + componentType: HiddenComponentType; + component: SchemaItem; +} + +export interface UseHiddenComponent { + addComponent: (component: SchemaItem, hiddenComponentType: HiddenComponentType) => void; + deleteComponent: (hiddenComponentSchema: HiddenComponentSchema) => void; +} \ No newline at end of file diff --git a/packages/ui-vue/components/designer-hidden-area/src/composition/use-designer-rules.ts b/packages/ui-vue/components/designer-hidden-area/src/composition/use-designer-rules.ts new file mode 100644 index 0000000000000000000000000000000000000000..3a46d3621c687ecff2b385f16ebed8a5f4068109 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/composition/use-designer-rules.ts @@ -0,0 +1,36 @@ +import { DesignerHostService, UseDesignerRules } from "../../../designer-canvas/src/composition/types"; +import { ComponentSchema } from "../../../designer-canvas/src/types"; +import { HiddenComponentProperty } from "../property-config/hidden-component.property-config"; + +export function useDesignerRules(schema: ComponentSchema, designerHostService: DesignerHostService): UseDesignerRules { + + function canAccepts(): boolean { + return false; + } + + function checkCanDeleteComponent() { + return false; + } + + function checkCanMoveComponent() { + return false; + } + + function hideNestedPaddingInDesginerView() { + return false; + } + function getStyles(): string { + return ''; + } + + /** + * 构造属性配置方法 + * @param componentId + * @returns + */ + function getPropsConfig(componentId: string) { + const properties = new HiddenComponentProperty(componentId, designerHostService); + return properties.getPropertyConfig(schema); + } + return { canAccepts, checkCanDeleteComponent, checkCanMoveComponent, hideNestedPaddingInDesginerView, getStyles, getPropsConfig }; +} diff --git a/packages/ui-vue/components/designer-hidden-area/src/composition/use-hidden-area-dragula.ts b/packages/ui-vue/components/designer-hidden-area/src/composition/use-hidden-area-dragula.ts new file mode 100644 index 0000000000000000000000000000000000000000..e6a39e6877e25f2b7fba5de40679db9f63b9dab4 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/composition/use-hidden-area-dragula.ts @@ -0,0 +1,69 @@ +import dragula from '@farris/designer-dragula'; +import { DesignerHTMLElement } from '../../../designer-canvas/src/composition/types'; +import { dragResolveService } from './drag-resolve'; +import { DesignerHostService } from "@farris/ui-vue/components/designer-canvas"; +import { UseHiddenComponent } from './types'; + +export function useHiddenAreaDragula(designerHostService: DesignerHostService, hiddenComponentComposition: UseHiddenComponent) { + + let dragulaInstance: any; + /** 拖拽所需的服务 */ + const dragResolveUtil = dragResolveService(designerHostService, hiddenComponentComposition); + + const COMPONENT_CONTAINER_CLASS = "f-designer-hidden-area-component-container"; + const TEMPLATE_BOX_CLASS = "f-designer-hidden-area-template-box-container"; + + /** + * 初始化拖拽 + */ + function initDragula(containerElement: DesignerHTMLElement) { + if (dragulaInstance) { + dragulaInstance.destroy(); + } + if (!dragula || !containerElement) { + return; + } + + dragulaInstance = dragula([containerElement], { + direction: 'horizontal', + revertOnSpill: true, + moves(element: DesignerHTMLElement): boolean { + return !element.classList.contains('no-drag'); + }, + getMirrorText(element: DesignerHTMLElement): string { + return element.innerText; + }, + accepts(element: HTMLElement, target: DesignerHTMLElement, source: HTMLElement, sibling: DesignerHTMLElement): boolean { + const canAccept = target.className.includes(COMPONENT_CONTAINER_CLASS); + return canAccept; + } + }).on('over', (element: DesignerHTMLElement, container: DesignerHTMLElement) => { + if (container.className.includes(COMPONENT_CONTAINER_CLASS)) { + container.className += ' hidden-area-drag-over'; + } + }).on('out', (el: DesignerHTMLElement, container: DesignerHTMLElement) => { + container.className = container.className.replace('hidden-area-drag-over', '').replace(' ', ''); + }).on('drop', (element: DesignerHTMLElement, target: DesignerHTMLElement, source: DesignerHTMLElement, sibling: DesignerHTMLElement + ) => dragResolveUtil.onDrop(element, target, source, sibling)); + + } + + /** + * 把右侧模板添加到可拖拽容器中 + * @returns + */ + function attachToDragulaContainer() { + if (!dragulaInstance) { + return; + } + const templateBoxs = document.getElementsByClassName(TEMPLATE_BOX_CLASS); + const formContainer = document.getElementsByClassName(COMPONENT_CONTAINER_CLASS); + dragulaInstance.containers = [...templateBoxs, ...formContainer]; + } + + + return { + initDragula, + attachToDragulaContainer + }; +} diff --git a/packages/ui-vue/components/designer-hidden-area/src/composition/use-hidden-component.ts b/packages/ui-vue/components/designer-hidden-area/src/composition/use-hidden-component.ts new file mode 100644 index 0000000000000000000000000000000000000000..a6ddc0f05c17fddb46806910ca2a495c95bf054e --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/composition/use-hidden-component.ts @@ -0,0 +1,52 @@ +import { Ref, ref } from "vue"; +import { HiddenComponentSchema, HiddenComponentType, UseHiddenComponent } from "./types"; +import { FNotifyService } from "@farris/ui-vue/components/notify"; +import { DesignerHostService } from "@farris/ui-vue/components/designer-canvas"; +import { useGuid } from "@farris/ui-vue/components/common"; +import { SchemaItem } from "@farris/ui-vue/components/schema-selector"; + +export default function (designerHostService: DesignerHostService): UseHiddenComponent { + + const notifyService = new FNotifyService(); + notifyService.globalConfig = { position: 'top-center' }; + + const module = designerHostService.formSchemaUtils.getModule(); + module.hiddenComponents ??= []; + const hiddenComponents: Ref = ref(module.hiddenComponents); + + /** + * 添加HiddenComponent + * @param component + * @param hiddenComponentType + */ + function addComponent(component: SchemaItem, hiddenComponentType: HiddenComponentType) { + const { uuid } = useGuid(); + const id = `hidden-component-${uuid(4)}`; + const hiddenComponentSchema: HiddenComponentSchema = { + id, + type: 'hidden-component', + name: component.name, + componentType: hiddenComponentType, + component + } + + hiddenComponents.value.push(hiddenComponentSchema); + } + + /** + * 删除HiddenComponent + * @param hiddenComponentSchema + */ + function deleteComponent(hiddenComponentSchema: HiddenComponentSchema) { + const componentIndex = hiddenComponents.value.findIndex(component => component.id === hiddenComponentSchema.id); + if (componentIndex > -1) { + hiddenComponents.value.splice(componentIndex, 1); + } + } + + + return { + addComponent, + deleteComponent, + } +} diff --git a/packages/ui-vue/components/designer-hidden-area/src/designer-hidden-area.component.tsx b/packages/ui-vue/components/designer-hidden-area/src/designer-hidden-area.component.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e1a767fdee010f6cef112be3ab0663e0e66fa1d2 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/designer-hidden-area.component.tsx @@ -0,0 +1,55 @@ +import { defineComponent, ref, } from 'vue'; +import { DesignerHiddenAreaProps, designerHiddenAreaProps } from './designer-hidden-area.props'; +import getHiddenComponentTemplateRender from './components/hidden-component-template/hidden-component-template.component'; +import getHiddenComponentContainerRender from './components/hidden-component/hidden-component-container.component'; + +import '../designer-hidden-area.css' + +export default defineComponent({ + name: 'FDesignerHiddenArea', + props: designerHiddenAreaProps, + emits: ['selectionChange'] as (string[] & ThisType) | undefined, + setup(props: DesignerHiddenAreaProps, context) { + const showHiddenArea = ref(false); + /** 渲染HiddenComponent的容器 */ + const renderHiddenComponentContainer = getHiddenComponentContainerRender(props, context); + /** 渲染HiddenComponent的模板 */ + const renderHiddenComponentTemplate = getHiddenComponentTemplateRender(); + + /** + * 点击顶部按钮 + */ + function onClickTopBar() { + showHiddenArea.value = !showHiddenArea.value; + } + + function renderTopBar() { + return ( +
+ + + + {showHiddenArea.value ? '隐藏区域' : '收起面板'} + + +
+ ) + } + + return () => { + return ( +
+ {renderTopBar()} + +
+ ); + } + } + +}); + diff --git a/packages/ui-vue/components/designer-hidden-area/src/designer-hidden-area.props.ts b/packages/ui-vue/components/designer-hidden-area/src/designer-hidden-area.props.ts new file mode 100644 index 0000000000000000000000000000000000000000..c72f5faeb136a48c7f75cd6c47be5c615766361c --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/designer-hidden-area.props.ts @@ -0,0 +1,8 @@ +import { ExtractPropTypes } from "vue"; + +export const designerHiddenAreaProps = { + id: { type: String, default: '' }, + modelValue: { type: Object }, +} as Record; + +export type DesignerHiddenAreaProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/designer-hidden-area/src/property-config/hidden-component.property-config.ts b/packages/ui-vue/components/designer-hidden-area/src/property-config/hidden-component.property-config.ts new file mode 100644 index 0000000000000000000000000000000000000000..24c4ecd9d377db3778384e39352a148d4ccadc83 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/property-config/hidden-component.property-config.ts @@ -0,0 +1,16 @@ +import { ComponentSchema, DesignerHostService } from "@farris/ui-vue/components/designer-canvas"; +import { BaseControlProperty } from "@farris/ui-vue/components/property-panel"; + +export class HiddenComponentProperty extends BaseControlProperty { + + constructor(componentId: string, designerHostService: DesignerHostService) { + super(componentId, designerHostService); + } + public getPropertyConfig(propertyData: ComponentSchema) { + // 基本信息 + this.propertyConfig.categories['basic'] = this.getBasicPropConfig(propertyData); + + return this.propertyConfig; + } + +} diff --git a/packages/ui-vue/components/designer-hidden-area/src/schema/hidden-component.schema.json b/packages/ui-vue/components/designer-hidden-area/src/schema/hidden-component.schema.json new file mode 100644 index 0000000000000000000000000000000000000000..0293e5d71b4f91ad0e21a3f4de422c6bf6e1eb42 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/schema/hidden-component.schema.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://farris-design.gitee.io/hidden-component.schema.json", + "title": "hidden-component", + "description": "A Farris Visual Component", + "type": "object", + "properties": { + "id": { + "description": "The unique identifier for a hidden-component", + "type": "string" + }, + "type": { + "description": "The type string of hidden-component", + "type": "string", + "default": "hidden-component" + }, + "componentType": { + "type": "string", + "default": "" + }, + "component": { + "type": "ojbect", + "default": {} + } + }, + "required": [ + "id", + "type", + "componentType", + "component" + ] +} \ No newline at end of file diff --git a/packages/ui-vue/components/designer-hidden-area/src/schema/schema-mapper.ts b/packages/ui-vue/components/designer-hidden-area/src/schema/schema-mapper.ts new file mode 100644 index 0000000000000000000000000000000000000000..e7bbde5239e60e023845779228cfed23b626ac4a --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/schema/schema-mapper.ts @@ -0,0 +1,4 @@ +import { resolveAppearance, MapperFunction } from '../../../dynamic-resolver'; + +export const schemaMapper = new Map([ +]); diff --git a/packages/ui-vue/components/designer-hidden-area/src/schema/schema-resolver.ts b/packages/ui-vue/components/designer-hidden-area/src/schema/schema-resolver.ts new file mode 100644 index 0000000000000000000000000000000000000000..75fe61bbed0338e4861bbdd5bec45b23a373a2c8 --- /dev/null +++ b/packages/ui-vue/components/designer-hidden-area/src/schema/schema-resolver.ts @@ -0,0 +1,6 @@ +import { DesignerComponentInstance, DesignerHostService, DgControl } from "../../../designer-canvas"; +import { DynamicResolver } from "../../../dynamic-resolver"; + +export function schemaResolver(resolver: DynamicResolver, schema: Record, context: Record, designerHostService?: DesignerHostService): Record { + return schema; +} \ No newline at end of file diff --git a/packages/ui-vue/components/designer.ts b/packages/ui-vue/components/designer.ts index b8aabcb5d13652f718de7901a55435d27b2a81f5..45ca914df5c130e40ea17934953e76880ec26c24 100644 --- a/packages/ui-vue/components/designer.ts +++ b/packages/ui-vue/components/designer.ts @@ -10,4 +10,5 @@ export * from './schema-selector'; export * from './dynamic-resolver'; export * from './field-selector'; export { resolverMap } from './dynamic-view'; +export { FDesignerHiddenArea} from './designer-hidden-area'; diff --git a/packages/ui-vue/components/property-editor/src/composition/use-state-machine.ts b/packages/ui-vue/components/property-editor/src/composition/use-state-machine.ts index d96ccaa36db304fb9a97d20316fa4e422176fe2a..671f78ca35a949cb3ddb8578584f0e263aa4f79d 100644 --- a/packages/ui-vue/components/property-editor/src/composition/use-state-machine.ts +++ b/packages/ui-vue/components/property-editor/src/composition/use-state-machine.ts @@ -29,9 +29,10 @@ export function useStateMachine( } // 3、转化为新的格式 + const status = matchResult[1] === '!' ? false : true; const newStateMachineFormat: StateMachineValue = { type: 'StateMachine', - status: matchResult[1], + status, field: matchResult[2] }