From 9438ae8cc8dc9f304f3f5ab1ba0e17dad0d5a1b4 Mon Sep 17 00:00:00 2001 From: biaogebusy <349255833@qq.com> Date: Thu, 2 Jan 2025 14:16:50 +0800 Subject: [PATCH 01/35] refact: common toolbar --- .../layout-builder.component.html | 2 +- .../builder-list/builder-list.component.html | 2 +- .../builder-list/builder-list.component.scss | 24 ++++++++++- .../dynamic-component.component.html | 40 ++++++++++--------- .../dynamic-component.component.ts | 20 ++++------ src/theme/component/_builder.scss | 19 --------- .../component/builder/_builder-list.scss | 8 ++-- 7 files changed, 59 insertions(+), 56 deletions(-) diff --git a/src/app/modules/builder/layout-builder/layout-builder.component.html b/src/app/modules/builder/layout-builder/layout-builder.component.html index 69a0d2c22..bf24c78ae 100644 --- a/src/app/modules/builder/layout-builder/layout-builder.component.html +++ b/src/app/modules/builder/layout-builder/layout-builder.component.html @@ -95,7 +95,7 @@ /> } - + } diff --git a/src/app/modules/builder/main/builder-list/builder-list.component.html b/src/app/modules/builder/main/builder-list/builder-list.component.html index 4f7ae6b41..f4eb099ff 100644 --- a/src/app/modules/builder/main/builder-list/builder-list.component.html +++ b/src/app/modules/builder/main/builder-list/builder-list.component.html @@ -25,7 +25,7 @@ @if (item) { @if (builderConfig$ | async; as builderConfig) { diff --git a/src/app/modules/builder/main/builder-list/builder-list.component.scss b/src/app/modules/builder/main/builder-list/builder-list.component.scss index 6b96dd510..2a2c9e8bc 100644 --- a/src/app/modules/builder/main/builder-list/builder-list.component.scss +++ b/src/app/modules/builder/main/builder-list/builder-list.component.scss @@ -30,11 +30,33 @@ transform: translateX(-50%); } &:hover { - outline-offset: -1px; .add-new-section { display: flex; } } + ::ng-deep { + .active-toolbar { + position: relative; + display: block; + box-sizing: content-box; + padding: 2px; + &:hover { + z-index: 10; + outline-offset: -1px; + > .component-toolbar { + display: block !important; + } + } + > .component-toolbar { + position: absolute; + left: 0; + top: 0px; + width: 100%; + z-index: 999; + line-height: 1; + } + } + } } .actions { diff --git a/src/app/uiux/widgets/builder/dynamic-component/dynamic-component.component.html b/src/app/uiux/widgets/builder/dynamic-component/dynamic-component.component.html index 41bdbdf55..bb06a6ae2 100644 --- a/src/app/uiux/widgets/builder/dynamic-component/dynamic-component.component.html +++ b/src/app/uiux/widgets/builder/dynamic-component/dynamic-component.component.html @@ -1,23 +1,25 @@ -@if (showToolbar) { - -} -@let content = inputs.type ? inputs : inputs.content; -
- @if (content?.id) { - - } - @if (content?.spacer) { - - } - @if (content?.bg) { - +
+ @if (showToolbar()) { + } + @let content = inputs.type ? inputs : inputs.content; +
+ @if (content?.id) { + + } + @if (content?.spacer) { + + } + @if (content?.bg) { + + } -
- -
+
+ +
- @if (content?.spacer) { - - } + @if (content?.spacer) { + + } +
diff --git a/src/app/uiux/widgets/builder/dynamic-component/dynamic-component.component.ts b/src/app/uiux/widgets/builder/dynamic-component/dynamic-component.component.ts index 69d9f1eda..d0d742570 100644 --- a/src/app/uiux/widgets/builder/dynamic-component/dynamic-component.component.ts +++ b/src/app/uiux/widgets/builder/dynamic-component/dynamic-component.component.ts @@ -20,6 +20,7 @@ import { ViewRef, createComponent, inject, + signal, } from '@angular/core'; import { Observable } from 'rxjs'; import { BuilderState } from '@core/state/BuilderState'; @@ -39,11 +40,10 @@ export class DynamicComponentComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy, AfterContentInit { @Input() inputs: IDynamicInputs; - @Input() index: number; - @HostBinding('class.active-toolbar') activeToolbarClass: boolean; + @Input() index: number; // just for order @ViewChild('componentContainer', { read: ViewContainerRef, static: true }) container: ViewContainerRef; - showToolbar: boolean; + showToolbar = signal(false); ele = inject(ElementRef); cd = inject(ChangeDetectorRef); @@ -60,11 +60,7 @@ export class DynamicComponentComponent @Inject(IS_BUILDER_MODE) public isBuilderMode$: Observable ) {} - ngOnInit(): void { - if (this.screenService.isPlatformBrowser()) { - this.showToolbar = !!this.coreConfig.builder?.enable && this.inputs?.showToolbar; - } - } + ngOnInit(): void {} ngOnChanges(changes: SimpleChanges): void { if (!changes.inputs.firstChange) { @@ -74,11 +70,11 @@ export class DynamicComponentComponent ngAfterContentInit(): void { this.isBuilderMode$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(state => { - if (!this.inputs?.showToolbar) { - this.activeToolbarClass = false; - return; + if (state) { + this.showToolbar.set(true); + } else { + this.showToolbar.set(false); } - this.activeToolbarClass = state; }); } diff --git a/src/theme/component/_builder.scss b/src/theme/component/_builder.scss index 16f91e88a..6607f40be 100644 --- a/src/theme/component/_builder.scss +++ b/src/theme/component/_builder.scss @@ -146,25 +146,6 @@ $dark-theme: mat.m2-define-dark-theme( } } - // for dynamic-component host class - .active-toolbar { - position: relative; - display: block; - box-sizing: content-box; - &:hover { - > .component-toolbar { - display: block !important; - } - } - > .component-toolbar { - position: absolute; - left: 0; - top: 0px; - width: 100%; - z-index: 999; - line-height: 1; - } - } .drawer-right { .builder-list { min-width: 85vw; diff --git a/src/theme/component/builder/_builder-list.scss b/src/theme/component/builder/_builder-list.scss index 7656824ac..87130a488 100644 --- a/src/theme/component/builder/_builder-list.scss +++ b/src/theme/component/builder/_builder-list.scss @@ -2,9 +2,11 @@ @mixin builder-list($background, $foreground, $primary, $warn) { background-color: mat.m2-get-color-from-palette($background, card); .component-item { - &:hover { - outline: 1px dashed mat.m2-get-color-from-palette($primary); - z-index: 10; + // for dynamic-component host class + .active-toolbar { + &:hover { + outline: 1px dashed mat.m2-get-color-from-palette($primary); + } } .animate-warn { &::after { From 8d3fdde7dee66ef23e43f139cd7f19dbc5f4b6f6 Mon Sep 17 00:00:00 2001 From: biaogebusy <349255833@qq.com> Date: Thu, 2 Jan 2025 14:59:00 +0800 Subject: [PATCH 02/35] refact: common updown component --- src/app/core/state/BuilderState.ts | 24 ++++++++++++++----- .../component-toolbar.component.html | 11 ++++++--- .../component-toolbar.component.ts | 10 ++++---- .../dynamic-component.component.ts | 22 +++++++---------- 4 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/app/core/state/BuilderState.ts b/src/app/core/state/BuilderState.ts index de19bc051..237634ee7 100644 --- a/src/app/core/state/BuilderState.ts +++ b/src/app/core/state/BuilderState.ts @@ -153,14 +153,25 @@ export class BuilderState { this.storage.store(this.versionKey, Object.assign([], this.version)); } - upDownComponent(index: number, direction: string): void { + getObjectByPath(path: string, body: any[]): any[] { + if (path.includes('.')) { + const after = path.slice(0, path.lastIndexOf('.')); + return get(body, after); + } else { + // 一级组件 + return body; + } + } + + upDownComponent(index: number, direction: string, path: string): void { const { body } = this.currentPage; + let arrs = this.getObjectByPath(path, body); if (direction === 'up') { - [body[index - 1], body[index]] = [body[index], body[index - 1]]; + [arrs[index - 1], arrs[index]] = [arrs[index], arrs[index - 1]]; } - if (direction === 'down' && index < body.length - 1) { - [body[index], body[index + 1]] = [body[index + 1], body[index]]; + if (direction === 'down' && index < arrs.length - 1) { + [arrs[index], arrs[index + 1]] = [arrs[index + 1], arrs[index]]; } this.closeRightDrawer$.next(true); this.saveLocalVersions(); @@ -176,9 +187,10 @@ export class BuilderState { } } - deleteComponent(index: number): void { + deleteComponent(index: number, path: string): void { const { body } = this.currentPage; - body.splice(index, 1); + const arrs = this.getObjectByPath(path, body); + arrs.splice(index, 1); this.updatePage(); } diff --git a/src/app/uiux/widgets/builder/component-toolbar/component-toolbar.component.html b/src/app/uiux/widgets/builder/component-toolbar/component-toolbar.component.html index 5d592e430..2297d000a 100644 --- a/src/app/uiux/widgets/builder/component-toolbar/component-toolbar.component.html +++ b/src/app/uiux/widgets/builder/component-toolbar/component-toolbar.component.html @@ -3,7 +3,7 @@ @if (index > 0) {
@@ -19,7 +19,7 @@ }
@@ -54,7 +54,12 @@ />
} -
+
+ @if (isBuilderMode$ | async) { - }
diff --git a/src/app/modules/builder/layout-builder/layout-builder.component.scss b/src/app/modules/builder/layout-builder/layout-builder.component.scss index 82938c3c1..32b56d2fa 100644 --- a/src/app/modules/builder/layout-builder/layout-builder.component.scss +++ b/src/app/modules/builder/layout-builder/layout-builder.component.scss @@ -14,10 +14,28 @@ &.item-layout-builder { @apply w-full; } - > .toolbar { + ::ng-deep { + .component-toolbar { + .actions { + top: auto; + bottom: 100%; + border-radius: 4px 4px 0 0; + } + } + } + .block-toolbar { + position: absolute; left: 50%; - bottom: 100%; + bottom: -34px; transform: translateX(-50%); + z-index: 99; + display: none; + white-space: nowrap; + } + &:hover { + .block-toolbar { + display: block; + } } } } diff --git a/src/stories/Changelog.mdx b/src/stories/Changelog.mdx index f1fe8b01c..b37dd1011 100644 --- a/src/stories/Changelog.mdx +++ b/src/stories/Changelog.mdx @@ -4,7 +4,7 @@ import { Meta } from '@storybook/blocks'; # 更新日志 -## 9.0.2(2025-01-01) +## 9.0.2(2025-01-02) - 新增了账户更新组件; - 重构了复合组件和基组件个Formly配置; @@ -25,6 +25,7 @@ import { Meta } from '@storybook/blocks'; - 修改了媒体库svg的显示问题; - 按钮组件Icon支持左右两侧位置; - 可视化box、card、card1v1基组件配置; +- 重构了component toolbar,移除了block toolbar; ## 9.0.1(2024-12-03) From 21221991d53d5602d6718dc0dbc7f56e585687ff Mon Sep 17 00:00:00 2001 From: biaogebusy <349255833@qq.com> Date: Thu, 2 Jan 2025 23:24:36 +0800 Subject: [PATCH 04/35] refact: toolbar --- .../core/directive/contentedit.directive.ts | 2 +- src/app/core/interface/IBuilder.ts | 8 +- src/app/core/service/builder.service.ts | 34 +- src/app/core/state/BuilderState.ts | 3 + src/app/core/token/token-providers.ts | 4 +- .../builder/data/widgets-for-builder.ts | 2327 +++++++++-------- .../block-toolbar/block-toolbar.component.ts | 2 +- .../builder-list/builder-list.component.html | 4 + .../builder-list/builder-list.component.scss | 10 + .../widget-picker.component.html | 102 +- .../widget-picker.component.scss | 4 - .../widget-picker/widget-picker.component.ts | 22 +- .../component/builder/_builder-list.scss | 4 + 13 files changed, 1297 insertions(+), 1229 deletions(-) diff --git a/src/app/core/directive/contentedit.directive.ts b/src/app/core/directive/contentedit.directive.ts index 3750c6e92..e6955fa39 100644 --- a/src/app/core/directive/contentedit.directive.ts +++ b/src/app/core/directive/contentedit.directive.ts @@ -93,7 +93,7 @@ export class ContenteditDirective implements AfterViewInit, OnInit { }, }; this.builder.rightContent$.next({ - mode: 'push', + mode: 'over', hasBackdrop: false, style: { 'width': '260px', diff --git a/src/app/core/interface/IBuilder.ts b/src/app/core/interface/IBuilder.ts index 38abb3461..1d71d7e68 100644 --- a/src/app/core/interface/IBuilder.ts +++ b/src/app/core/interface/IBuilder.ts @@ -134,11 +134,17 @@ export interface ILayoutSetting { export interface IWidgetPicker { type: 'widget-picker'; - addType: 'widget' | 'layout'; + addType: string; path: string; content: any; } +export interface IWidgets { + label: string; + icon: IIcon; + elements: any[]; +} + export interface IMetaEdit { type: string; data: any; diff --git a/src/app/core/service/builder.service.ts b/src/app/core/service/builder.service.ts index 786ee51e1..55292554c 100644 --- a/src/app/core/service/builder.service.ts +++ b/src/app/core/service/builder.service.ts @@ -503,21 +503,27 @@ export class BuilderService extends ApiService { } addBlock(addType: string, content: any, path: string): void { - this.builder.rightContent$.next({ - mode: 'over', - hasBackdrop: false, - style: { - width: '308px', - }, - elements: [ - { - type: 'widget-picker', - addType, - path, - content, - }, - ], + this.builder.wigetsPicker$.next({ + type: 'widget-picker', + addType, + path, + content, }); + // this.builder.rightContent$.next({ + // mode: 'over', + // hasBackdrop: false, + // style: { + // width: '308px', + // }, + // elements: [ + // { + // type: 'widget-picker', + // addType, + // path, + // content, + // }, + // ], + // }); } initExtraBody(body: any[], isTemplate?: boolean): any[] { diff --git a/src/app/core/state/BuilderState.ts b/src/app/core/state/BuilderState.ts index 237634ee7..6a9934334 100644 --- a/src/app/core/state/BuilderState.ts +++ b/src/app/core/state/BuilderState.ts @@ -6,6 +6,8 @@ import { IBuilderDynamicContent, IBuilderShowcase, ILayoutSetting, + IWidgetPicker, + IWidgets, } from '@core/interface/IBuilder'; import { ICard1v1 } from '@core/interface/widgets/ICard'; import { UtilitiesService } from '@core/service/utilities.service'; @@ -28,6 +30,7 @@ export class BuilderState { public showcase$ = new Subject(); public themeMode = new BehaviorSubject<'light' | 'dark'>('light'); public rightContent$ = new Subject(); + public wigetsPicker$ = new Subject(); public closeRightDrawer$ = new Subject(); public fixedChange$ = new Subject(); public animateDisable$ = new Subject(); diff --git a/src/app/core/token/token-providers.ts b/src/app/core/token/token-providers.ts index a01828de8..9a45e37b1 100644 --- a/src/app/core/token/token-providers.ts +++ b/src/app/core/token/token-providers.ts @@ -4,7 +4,7 @@ import { IUser } from '@core/interface/IUser'; import { Observable } from 'rxjs'; import { IBranding } from '../interface/branding/IBranding'; import { INotify } from '@core/interface/widgets/IWidgets'; -import { IBuilderConfig, IUiux } from '@core/interface/IBuilder'; +import { IBuilderConfig, IUiux, IWidgets } from '@core/interface/IBuilder'; import { IThemePreview } from '@core/interface/combs/IThemePreview'; import { ILanguage } from '@core/interface/IEnvironment'; import { IManageAssets } from '@core/interface/manage/IManage'; @@ -29,4 +29,4 @@ export const BUILDER_FULL_SCREEN = new InjectionToken>('buil export const UIUX = new InjectionToken('builder uiux data'); export const IS_BUILDER_MODE = new InjectionToken>('is builder mode'); -export const WIDGETS = new InjectionToken('builder widgets for popup select'); +export const WIDGETS = new InjectionToken('builder widgets for popup select'); diff --git a/src/app/modules/builder/data/widgets-for-builder.ts b/src/app/modules/builder/data/widgets-for-builder.ts index a02cb3889..07028802f 100644 --- a/src/app/modules/builder/data/widgets-for-builder.ts +++ b/src/app/modules/builder/data/widgets-for-builder.ts @@ -1,286 +1,989 @@ export const widgets = [ { - label: 'Layout', - icon: { - svg: 'view-dashboard-outline', - }, - preview: '/assets/images/builder/widgets/layout.png', - content: { - gap: { - xs: 0, - sm: 0, - md: 0, - lg: 0, + label: '基础', + elements: [ + { + label: '标题', + icon: { + svg: 'format-header-2', + }, + content: { + type: 'title', + label: '欢迎使用Web Builder构建页面', + classes: 'mat-headline-3 bold', + style: 'style-v4', + }, }, - wrapperClass: '', - spacer: 'none', - type: 'layout-builder', - fullWidth: false, - bg: { - classes: 'bg-fill-width', + { + label: '富文本', + icon: { + svg: 'format-text', + }, + content: { + type: 'text', + spacer: 'none', + body: '信使UI是基于 Material 的 Angular 前端框架,丰富的组件可提供优秀的数字创新体验,使用 Web Builder 可以通过拖拽快速构建响应式、多主题的 Web 页面。', + }, }, - elements: [ - { + { + label: '链接', + icon: { + svg: 'link', + }, + content: { + type: 'link', + label: '更多', classes: '', - row: { - xs: 12, - sm: 12, - md: 6, - lg: 6, + href: '/', + }, + }, + { + label: '按钮', + icon: { + svg: 'button-cursor', + }, + content: { + type: 'btn', + href: '/node/1', + target: '_blank', + label: '了解更多', + mode: 'raised', + color: 'primary', + }, + }, + { + label: '间距', + icon: { + svg: 'minus-thick', + }, + content: { + type: 'spacer', + size: 'sm', + }, + }, + { + label: '分割线', + icon: { + svg: 'border-horizontal', + }, + content: { + type: 'divider', + }, + }, + { + label: 'JSON', + icon: { + svg: 'code-json', + }, + content: { + type: 'json', + name: 'sample', + spacer: { + x: 'none', + y: 'none', }, - elements: [], }, - { - classes: '', - row: { - xs: 12, - sm: 12, - md: 6, - lg: 6, + }, + { + label: '表格', + icon: { + svg: 'table', + }, + preview: '/assets/images/builder/widgets/table.png', + content: { + type: 'dynamic-table', + header: [ + { + label: '模块', + key: 'module', + }, + { + label: '描述', + key: 'info', + }, + { + label: '安装量', + key: 'tatol', + }, + { + label: '备注', + key: 'remarks', + dialog: { + shorten: 5, + label: '更多', + }, + }, + ], + elements: [ + { + module: 'Slick Carousel', + tatol: 2992, + info: 'Slick 轮播,强大响应式且性能优异的图片轮播解决方案,有非常丰富的配置选项,slick 官网自己调侃这是你最后使用的图片轮播', + remarks: '查看', + }, + { + module: 'Views Slideshow', + tatol: 5501, + info: '视图轮播模块,该模块是最受欢迎的幻灯片模块,可放任何内容,高度定制\t', + remarks: '查看', + }, + { + module: 'Colorbox', + tatol: 4438, + info: '轻量级高可定制幻灯片模块,高度集成在 Drupal 中,可放图片,Iframed 或者在线内容等等\t', + remarks: '查看', + }, + { + module: 'Flex Slider', + tatol: 8930, + info: '响应式、可调整大小、适配浏览器和移动设备,支持移动设备手势滑动\t', + remarks: '查看', + }, + { + module: 'Owl Carousel', + tatol: 1000, + info: '提供视图样式,字段格式化和管理 UI,支持响应式、移动手势、高定制幻灯片,CSS3 动画,JSON,有可用的回调,自定义事件等\t', + remarks: '查看', + }, + ], + }, + }, + { + label: '联系我们', + icon: { + svg: 'account-box-outline', + }, + preview: '/assets/images/builder/widgets/contact.png', + content: { + type: 'contact-us', + params: { + webform_id: 'contact', + }, + bg: { + classes: 'bg-fill-width', + icon: 'wave', + }, + action: { + label: '提交表单', }, - elements: [], + formOrder: '1', + contact: [ + { + title: { + label: '地址', + }, + icon: { + name: 'location_on', + }, + style: 'style-v7 small-box', + content: '创客城2栋', + }, + { + title: { + label: '电话号码', + }, + style: 'style-v7 small-box', + icon: { + name: 'phone', + }, + content: '+086 0771xxxx', + }, + { + title: { + label: '邮件', + }, + style: 'style-v7 small-box', + icon: { + name: 'mail', + }, + content: 'service@example.com', + }, + { + title: { + label: '微信', + }, + style: 'style-v7 small-box', + icon: { + name: 'chat_bubble', + }, + content: 'biaogebusy', + }, + ], + form: [ + { + type: 'input', + key: 'name', + className: 'w-full', + props: { + label: '姓名', + appearance: 'outline', + required: true, + }, + }, + { + type: 'input', + key: 'email', + className: 'w-full', + props: { + label: '邮箱', + appearance: 'outline', + required: true, + }, + }, + { + type: 'input', + key: 'subject', + className: 'w-full', + props: { + label: '主题', + appearance: 'outline', + }, + }, + { + type: 'textarea', + key: 'message', + className: 'w-full', + props: { + label: '内容', + placeholder: 'Message', + appearance: 'fill', + rows: 5, + }, + }, + ], }, - ], - }, - }, - { - label: 'Tailwind', - icon: { - svg: 'code-json', - }, - preview: '/assets/images/builder/widgets/tailwind-v1.png', - content: { - type: 'custom-template', - json: { - title: 'web builder', - subTitle: '是一款通过拖拽组件构建页面的低代码', - img: '/assets/images/avatar/05.jpeg', - content: - '信使UI是一款开源的前端框架,基于Angular Material UI,支持SSR,多应用,后端可根据实际情况自由配置,可自定义开发、新增组件库。', }, - html: '
\n \n
\n

\n “{{content}}”\n

\n
\n
\n {{title}}\n
\n
\n {{subTitle}}\n
\n
\n
\n
', - }, - }, - { - label: 'API', - icon: { - svg: 'api', - }, - preview: '/assets/images/builder/widgets/tailwind-v2.png', - content: { - type: 'custom-template', - isAPI: true, - api: '/api/v1/content', - html: '
\n {{#rows }}\n
\n
\n \n {{#img}}\n \n {{/img}}\n {{^img}}\n \n {{/img}}\n
\n {{title}}\n
{{body}}
\n \n
\n
\n
\n {{/rows}}\n
', - }, - }, - { - label: 'JSON', - icon: { - svg: 'code-json', - }, - content: { - type: 'json', - name: 'sample', - spacer: { - x: 'none', - y: 'none', + { + label: '折叠面板', + icon: { + svg: 'format-line-weight', + }, + content: { + type: 'panel', + elements: [ + { + title: '组件驱动开发', + icon: 'person', + params: { + expanded: true, + }, + elements: [ + { + type: 'text', + spacer: 'none', + body: 'Storybook采用了组件驱动开发的方法,即将UI组件作为开发的核心单元。开发人员可以在Storybook中为每个UI组件创建"stories",描述组件在不同状态和交互方式下的行为和外观。这种方法能够提高组件的可重用性和可测试性。', + }, + ], + }, + { + title: '组件展示和测试', + icon: 'faviores', + elements: [ + { + type: 'text', + spacer: 'none', + body: 'Storybook提供了一个交互式的界面,用于展示和测试UI组件。开发人员可以在浏览器中浏览和交互组件,以便检查其外观和行为,并确保它们在各种条件下正常工作。这有助于加快开发迭代周期,提高组件的质量。', + }, + ], + }, + { + title: '文档化', + icon: 'faviores', + elements: [ + { + type: 'text', + spacer: 'none', + body: 'Storybook不仅可以展示和测试组件,还可以自动生成组件的文档。开发人员可以使用Markdown或其他文档格式编写组件文档,并将其与组件关联。这使得团队成员可以更好地理解和使用组件,减少了沟通成本。', + }, + ], + }, + { + title: '插件和工具生态系统', + icon: 'faviores', + elements: [ + { + type: 'text', + spacer: 'none', + body: 'Storybook拥有丰富的插件和工具生态系统,可以扩展其功能。这些插件可以用于模拟数据、测试组件的不同状态和交互,并生成自动化测试报告。这样,开发人员可以根据自己的需求定制和扩展Storybook。', + }, + ], + }, + ], + }, }, - }, + ], }, { - label: '标题', - icon: { - svg: 'format-header-2', - }, - content: { - type: 'title', - label: '欢迎使用Web Builder构建页面', - classes: 'mat-headline-3 bold', - style: 'style-v4', - }, - }, - { - label: '富文本', - icon: { - svg: 'format-text', - }, - content: { - type: 'text', - spacer: 'none', - body: '信使UI是基于 Material 的 Angular 前端框架,丰富的组件可提供优秀的数字创新体验,使用 Web Builder 可以通过拖拽快速构建响应式、多主题的 Web 页面。', - }, - }, - { - label: '图片', - icon: { - svg: 'image-outline', - }, - content: { - type: 'img', - hostClasses: 'text-center', - classes: 'object-contain', - src: '/assets/images/illustration/08.png', - alt: 'alt', - width: 400, - height: 300, - }, - }, - { - label: '视频', - icon: { - svg: 'play-circle-outline', - }, - content: { - type: 'video', - options: { - controls: true, - aspectRatio: '1:1', - poster: '/assets/video/poster01.png', - sources: [ - { - src: '/assets/video/storybook.mp4', - type: 'video/mp4', - }, - ], + label: '自定义', + elements: [ + { + label: 'Layout', + icon: { + svg: 'view-dashboard-outline', + }, + preview: '/assets/images/builder/widgets/layout.png', + content: { + gap: { + xs: 0, + sm: 0, + md: 0, + lg: 0, + }, + wrapperClass: '', + spacer: 'none', + type: 'layout-builder', + fullWidth: false, + bg: { + classes: 'bg-fill-width', + }, + elements: [ + { + classes: '', + row: { + xs: 12, + sm: 12, + md: 6, + lg: 6, + }, + elements: [], + }, + { + classes: '', + row: { + xs: 12, + sm: 12, + md: 6, + lg: 6, + }, + elements: [], + }, + ], + }, }, - }, - }, - { - label: '链接', - icon: { - svg: 'link', - }, - content: { - type: 'link', - label: '更多', - classes: '', - href: '/', - }, - }, - { - label: '按钮', - icon: { - svg: 'button-cursor', - }, - content: { - type: 'btn', - href: '/node/1', - target: '_blank', - label: '了解更多', - mode: 'raised', - color: 'primary', - }, - }, - { - label: '间距', - icon: { - svg: 'minus-thick', - }, - content: { - type: 'spacer', - size: 'sm', - }, - }, - { - label: '分割线', - icon: { - svg: 'border-horizontal', - }, - content: { - type: 'divider', - }, - }, - { - label: '图标', - icon: { - svg: 'svg', - }, - content: { - type: 'icon', - color: 'primary', - svg: 'border-color', - }, + { + label: 'Tailwind', + icon: { + svg: 'code-json', + }, + preview: '/assets/images/builder/widgets/tailwind-v1.png', + content: { + type: 'custom-template', + json: { + title: 'web builder', + subTitle: '是一款通过拖拽组件构建页面的低代码', + img: '/assets/images/avatar/05.jpeg', + content: + '信使UI是一款开源的前端框架,基于Angular Material UI,支持SSR,多应用,后端可根据实际情况自由配置,可自定义开发、新增组件库。', + }, + html: '
\n \n
\n

\n “{{content}}”\n

\n
\n
\n {{title}}\n
\n
\n {{subTitle}}\n
\n
\n
\n
', + }, + }, + { + label: 'API', + icon: { + svg: 'api', + }, + preview: '/assets/images/builder/widgets/tailwind-v2.png', + content: { + type: 'custom-template', + isAPI: true, + api: '/api/v1/content', + html: '
\n {{#rows }}\n
\n
\n \n {{#img}}\n \n {{/img}}\n {{^img}}\n \n {{/img}}\n
\n {{title}}\n
{{body}}
\n \n
\n
\n
\n {{/rows}}\n
', + }, + }, + ], }, { - label: '幻灯片', - icon: { - svg: 'view-array-outline', - }, - preview: '/assets/images/builder/widgets/swiper.png', - content: { - type: 'swiper', - params: { - navigation: false, - breakpoints: { - '600': { - slidesPerView: 3, - spaceBetween: 20, - }, - '960': { - slidesPerView: 3, - spaceBetween: 50, + label: '媒体', + elements: [ + { + label: '图片', + icon: { + svg: 'image-outline', + }, + content: { + type: 'img', + hostClasses: 'text-center', + classes: 'object-contain', + src: '/assets/images/illustration/08.png', + alt: 'alt', + width: 400, + height: 300, + }, + }, + { + label: '视频', + icon: { + svg: 'play-circle-outline', + }, + content: { + type: 'video', + options: { + controls: true, + aspectRatio: '1:1', + poster: '/assets/video/poster01.png', + sources: [ + { + src: '/assets/video/storybook.mp4', + type: 'video/mp4', + }, + ], }, }, }, - classes: '', - elements: [ - { - type: 'card', - title: '高性能', - subTitle: 'High Performance', - classes: 'card-no-shadow', - body: '默认情况下,Drupal 运行速度很快,您可以优化部署,使其运行得更快;', - feature: { - fullIcon: 'fullscreen', - openIcon: 'open_in_new', - link: '#', - ratios: 'media-4-3', - img: { - classes: 'object-fit', - src: '/assets/images/cases/porto1.jpg', - alt: 'alt', + { + label: '播放按钮', + icon: { + svg: 'play-circle-outline', + }, + content: { + type: 'btn-video', + color: 'primary', + video: { + type: 'video', + options: { + controls: true, + aspectRatio: '16:9', + poster: '/assets/video/poster01.png', + sources: [ + { + src: '/assets/video/storybook.mp4', + type: 'video/mp4', + }, + ], }, }, }, - { - type: 'card', - feature: { - fullIcon: 'fullscreen', - openIcon: 'open_in_new', - link: '#', - ratios: 'media-4-3', - img: { - classes: 'object-fit', - src: '/assets/images/cases/porto7.jpg', - alt: 'alt', + }, + { + label: '图标', + icon: { + svg: 'svg', + }, + content: { + type: 'icon', + color: 'primary', + svg: 'border-color', + }, + }, + { + label: '幻灯片', + icon: { + svg: 'view-array-outline', + }, + preview: '/assets/images/builder/widgets/swiper.png', + content: { + type: 'swiper', + params: { + navigation: false, + breakpoints: { + '600': { + slidesPerView: 3, + spaceBetween: 20, + }, + '960': { + slidesPerView: 3, + spaceBetween: 50, + }, }, }, - title: '易用的编辑器', - subTitle: 'Simplicity for Editors', - classes: 'card-no-shadow', - body: '通过友好的预览、拖放媒体提高内容编辑的易用性,高效的工作;', + classes: '', + elements: [ + { + type: 'card', + title: '高性能', + subTitle: 'High Performance', + classes: 'card-no-shadow', + body: '默认情况下,Drupal 运行速度很快,您可以优化部署,使其运行得更快;', + feature: { + fullIcon: 'fullscreen', + openIcon: 'open_in_new', + link: '#', + ratios: 'media-4-3', + img: { + classes: 'object-fit', + src: '/assets/images/cases/porto1.jpg', + alt: 'alt', + }, + }, + }, + { + type: 'card', + feature: { + fullIcon: 'fullscreen', + openIcon: 'open_in_new', + link: '#', + ratios: 'media-4-3', + img: { + classes: 'object-fit', + src: '/assets/images/cases/porto7.jpg', + alt: 'alt', + }, + }, + title: '易用的编辑器', + subTitle: 'Simplicity for Editors', + classes: 'card-no-shadow', + body: '通过友好的预览、拖放媒体提高内容编辑的易用性,高效的工作;', + }, + { + type: 'card', + feature: { + fullIcon: 'fullscreen', + openIcon: 'open_in_new', + link: '#', + ratios: 'media-4-3', + img: { + classes: 'object-fit', + src: '/assets/images/cases/porto2.jpg', + alt: 'alt', + }, + }, + title: '多语言', + subTitle: 'Leader in Multilingual', + classes: 'card-no-shadow', + body: 'Drupal 100多种语言提供了无以伦比的支持和翻译工作流程;', + }, + { + type: 'card', + feature: { + fullIcon: 'fullscreen', + openIcon: 'open_in_new', + link: '#', + ratios: 'media-4-3', + img: { + classes: 'object-fit', + src: '/assets/images/cases/porto3.jpg', + alt: 'alt', + }, + }, + title: '更有弹性', + subTitle: 'Flexibility', + classes: 'card-no-shadow', + body: '无论是一个还是多个站点,Drupal 总是可以游刃有余的构建;', + }, + { + type: 'card', + feature: { + fullIcon: 'fullscreen', + openIcon: 'open_in_new', + link: '#', + ratios: 'media-4-3', + img: { + classes: 'object-fit', + src: '/assets/images/cases/porto4.jpg', + alt: 'alt', + }, + }, + title: '安全性', + subTitle: 'Rigorous Security', + classes: 'card-no-shadow', + body: '为了抵御安全漏洞,将有一组团队解决并发布安全修补程序,超过45000名贡献者使该平台成为市场上最安全、最稳定的平台之一;', + }, + ], }, - { - type: 'card', - feature: { - fullIcon: 'fullscreen', - openIcon: 'open_in_new', - link: '#', - ratios: 'media-4-3', - img: { - classes: 'object-fit', - src: '/assets/images/cases/porto2.jpg', - alt: 'alt', + }, + { + label: 'Lightbox', + icon: { + svg: 'view-carousel-outline', + }, + content: { + type: 'inline-lightbox', + label: ['查看图片', 'Word 下载', 'PDF 预览'], + elements: [ + { + src: '/assets/images/cases/porto1.jpg', + }, + { + src: '/assets/images/cases/porto2.pdf', + }, + { + src: '/assets/images/cases/porto3.pdf', + }, + ], + }, + }, + ], + }, + { + label: 'Box', + elements: [ + { + label: 'Box', + icon: { + svg: 'box', + }, + content: { + type: 'box', + img: { + src: '/assets/images/svg/Asset187.svg', + alt: 'browser', + }, + style: 'style-v3 use-image', + title: { + href: '#', + label: '高性能', + }, + content: '默认情况下,Drupal 运行速度很快,您可以优化部署,使其运行得更快;', + }, + }, + { + label: 'Box v1', + icon: { + svg: 'box', + }, + content: { + type: 'box', + style: 'style-v1', + icon: { + name: 'fingerprint', + }, + title: { + href: '/', + label: '组件编辑', + }, + content: '通过简单的管理界面对复杂的可视化编辑', + more: { + href: '#', + label: '更多', + }, + }, + }, + { + label: 'Box v2', + icon: { + svg: 'box', + }, + content: { + type: 'box', + style: 'style-v2', + icon: { + name: 'verified_user', + }, + title: { + href: '/', + label: '组件编辑', + }, + content: '通过简单的管理界面对复杂的可视化编辑', + more: { + href: '#', + label: '更多', + }, + }, + }, + { + label: 'Box v3', + icon: { + svg: 'box', + }, + content: { + type: 'box', + style: 'style-v3', + icon: { + name: 'verified_user', + }, + title: { + href: '/', + label: '组件编辑', + }, + content: '通过简单的管理界面对复杂的可视化编辑', + more: { + href: '#', + label: '更多', + }, + }, + }, + { + label: 'Box v4', + icon: { + svg: 'box', + }, + content: { + type: 'box', + style: 'style-v4', + icon: { + name: 'verified_user', + }, + title: { + href: '/', + label: '组件编辑', + }, + content: '通过简单的管理界面对复杂的可视化编辑', + more: { + href: '#', + label: '更多', + }, + }, + }, + { + label: 'Box v5', + icon: { + svg: 'box', + }, + content: { + type: 'box', + style: 'style-v5', + icon: { + name: 'verified_user', + }, + title: { + href: '/', + label: '组件编辑', + }, + content: '通过简单的管理界面对复杂的可视化编辑', + more: { + href: '#', + label: '更多', + }, + }, + }, + { + label: 'Box v6', + icon: { + svg: 'box', + }, + content: { + type: 'box', + style: 'style-v6', + icon: { + name: 'verified_user', + }, + title: { + href: '/', + label: '组件编辑', + }, + content: '通过简单的管理界面对复杂的可视化编辑', + more: { + href: '#', + label: '更多', + }, + }, + }, + { + label: 'Box v7', + icon: { + svg: 'box', + }, + content: { + type: 'box', + style: 'style-v7', + icon: { + name: 'verified_user', + }, + title: { + href: '/', + label: '组件编辑', + }, + content: '通过简单的管理界面对复杂的可视化编辑', + more: { + href: '#', + label: '更多', + }, + }, + }, + { + label: 'Box v9', + icon: { + svg: 'box', + }, + content: { + type: 'box', + style: 'style-v9', + icon: { + name: 'fingerprint', + }, + title: { + href: '/', + label: '组件编辑', + }, + content: '通过简单的管理界面对复杂的可视化编辑', + more: { + href: '#', + label: '更多', + }, + }, + }, + { + label: 'Box v10', + icon: { + svg: 'box', + }, + content: { + type: 'box', + style: 'style-v10', + icon: { + name: 'fingerprint', + }, + title: { + href: '/', + label: '组件编辑', + }, + content: '通过简单的管理界面对复杂的可视化编辑', + more: { + href: '#', + label: '更多', + }, + }, + }, + ], + }, + { + label: '图表', + elements: [ + { + label: '柱状图', + icon: { + svg: 'chart-bar', + }, + preview: '/assets/images/builder/widgets/bar.png', + content: { + type: 'chart', + title: { + text: '年度活动金额预算', + subtext: '南宁', + }, + legend: { + bottom: '10px', + }, + tooltip: { + trigger: 'axis', + }, + dataset: { + source: [ + ['红包预算', '2020', '2021', '2022'], + ['第一季度', 4180, 9056, 7942], + ['第二季度', 7908, 9032, 8471], + ['第三季度', 4785, 7987, 4172], + ], + }, + xAxis: { + type: 'category', + }, + yAxis: {}, + series: [ + { + type: 'bar', + }, + { + type: 'bar', + }, + { + type: 'bar', + }, + ], + }, + }, + { + label: '折线图', + icon: { + svg: 'chart-line', + }, + preview: '/assets/images/builder/widgets/line.png', + content: { + type: 'chart', + title: { + text: '年度活动金额预算', + subtext: '南宁', + }, + legend: { + bottom: '10px', + }, + tooltip: { + trigger: 'axis', + }, + dataset: { + source: [ + ['红包预算', '2020', '2021', '2022'], + ['第一季度', 4180, 9056, 7942], + ['第二季度', 7908, 9032, 8471], + ['第三季度', 4785, 7987, 4172], + ], + }, + xAxis: { + type: 'category', + }, + yAxis: {}, + series: [ + { + type: 'line', + }, + { + type: 'line', + }, + { + type: 'line', }, + ], + }, + }, + { + label: '饼图', + icon: { + svg: 'chart-pie', + }, + preview: '/assets/images/builder/widgets/pie.png', + content: { + type: 'chart', + title: { + text: '金额预算占比', + subtext: '2022年9月', + left: 'center', }, - title: '多语言', - subTitle: 'Leader in Multilingual', - classes: 'card-no-shadow', - body: 'Drupal 100多种语言提供了无以伦比的支持和翻译工作流程;', + tooltip: { + trigger: 'item', + }, + legend: { + orient: 'vertical', + left: 'left', + }, + xAxis: { + type: 'category', + }, + yAxis: {}, + dataset: { + source: [ + ['预算', '费用'], + ['大额红包总金额', 398], + ['小额红包总金额', 916], + ['提成总额', 370], + ], + }, + series: [ + { + name: 'Access From', + type: 'pie', + radius: '50%', + label: { + formatter: '{b}: {d}%', + }, + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)', + }, + }, + }, + ], + }, + }, + ], + }, + { + label: '卡片', + elements: [ + { + label: '卡片', + icon: { + svg: 'card-outline', }, - { + preview: '/assets/images/builder/widgets/card.png', + content: { type: 'card', + title: '高性能', + subTitle: 'High Performance', + classes: 'card-no-shadow', + body: '默认情况下,Drupal 运行速度很快,您可以优化部署,使其运行得更快;', feature: { fullIcon: 'fullscreen', openIcon: 'open_in_new', @@ -292,13 +995,22 @@ export const widgets = [ alt: 'alt', }, }, - title: '更有弹性', - subTitle: 'Flexibility', - classes: 'card-no-shadow', - body: '无论是一个还是多个站点,Drupal 总是可以游刃有余的构建;', }, - { - type: 'card', + }, + { + label: '卡片1v1', + icon: { + svg: 'numeric-1', + }, + preview: '/assets/images/builder/widgets/card-1v1.png', + content: { + type: 'card-1v1', + link: { + href: '#', + label: 'Drupal 100多种语言提供了无以伦比的支持和翻译工作流程', + }, + user: '表歌', + time: '2022/09/27', feature: { fullIcon: 'fullscreen', openIcon: 'open_in_new', @@ -306,944 +1018,267 @@ export const widgets = [ ratios: 'media-4-3', img: { classes: 'object-fit', - src: '/assets/images/cases/porto4.jpg', + src: '/assets/images/cases/porto3.jpg', alt: 'alt', }, }, - title: '安全性', - subTitle: 'Rigorous Security', - classes: 'card-no-shadow', - body: '为了抵御安全漏洞,将有一组团队解决并发布安全修补程序,超过45000名贡献者使该平台成为市场上最安全、最稳定的平台之一;', + moreLabel: '查看更多', }, - ], - }, - }, - { - label: '联系我们', - icon: { - svg: 'account-box-outline', - }, - preview: '/assets/images/builder/widgets/contact.png', - content: { - type: 'contact-us', - params: { - webform_id: 'contact', }, - bg: { - classes: 'bg-fill-width', - icon: 'wave', - }, - action: { - label: '提交表单', - }, - formOrder: '1', - contact: [ - { - title: { - label: '地址', - }, - icon: { - name: 'location_on', - }, - style: 'style-v7 small-box', - content: '创客城2栋', + { + label: '卡片2v2', + icon: { + svg: 'numeric-2', }, - { - title: { - label: '电话号码', - }, - style: 'style-v7 small-box', - icon: { - name: 'phone', + preview: '/assets/images/builder/widgets/card-1v2.png', + content: { + type: 'card-1v2', + link: { + href: '#', + label: 'Drupal 100多种语言提供了无以伦比的支持和翻译工作流程', }, - content: '+086 0771xxxx', - }, - { - title: { - label: '邮件', + subTitle: '多语言', + img: { + href: '#', + src: '/assets/images/cases/porto3.jpg', + alt: 'alt', }, - style: 'style-v7 small-box', - icon: { - name: 'mail', + bg: { + classes: 'object-fit', + img: { + hostClasses: '', + src: '/assets/images/showcase/pattern-01.png', + }, }, - content: 'service@example.com', }, - { - title: { - label: '微信', - }, - style: 'style-v7 small-box', - icon: { - name: 'chat_bubble', - }, - content: 'biaogebusy', - }, - ], - form: [ - { - type: 'input', - key: 'name', - className: 'w-full', - props: { - label: '姓名', - appearance: 'outline', - required: true, - }, - }, - { - type: 'input', - key: 'email', - className: 'w-full', - props: { - label: '邮箱', - appearance: 'outline', - required: true, - }, - }, - { - type: 'input', - key: 'subject', - className: 'w-full', - props: { - label: '主题', - appearance: 'outline', - }, - }, - { - type: 'textarea', - key: 'message', - className: 'w-full', - props: { - label: '内容', - placeholder: 'Message', - appearance: 'fill', - rows: 5, - }, - }, - ], - }, - }, - { - label: '柱状图', - icon: { - svg: 'chart-bar', - }, - preview: '/assets/images/builder/widgets/bar.png', - content: { - type: 'chart', - title: { - text: '年度活动金额预算', - subtext: '南宁', - }, - legend: { - bottom: '10px', - }, - tooltip: { - trigger: 'axis', }, - dataset: { - source: [ - ['红包预算', '2020', '2021', '2022'], - ['第一季度', 4180, 9056, 7942], - ['第二季度', 7908, 9032, 8471], - ['第三季度', 4785, 7987, 4172], - ], - }, - xAxis: { - type: 'category', - }, - yAxis: {}, - series: [ - { - type: 'bar', - }, - { - type: 'bar', + { + label: '卡片1v4', + icon: { + svg: 'numeric-4', }, - { - type: 'bar', + content: { + type: 'card-1v4', + img: { + classes: 'w-full h-full object-cover', + src: '/assets/images/avatar/01.jpeg', + }, + star: 5, + title: '- Johnson', + subTitle: '前端开发', + body: '信使是一个灵活可扩展性高的前端Anuglar框架,动态组件可以使得组件之间变得更加灵活,但是依赖循环也变得复杂。', }, - ], - }, - }, - { - label: '折线图', - icon: { - svg: 'chart-line', - }, - preview: '/assets/images/builder/widgets/line.png', - content: { - type: 'chart', - title: { - text: '年度活动金额预算', - subtext: '南宁', }, - legend: { - bottom: '10px', - }, - tooltip: { - trigger: 'axis', - }, - dataset: { - source: [ - ['红包预算', '2020', '2021', '2022'], - ['第一季度', 4180, 9056, 7942], - ['第二季度', 7908, 9032, 8471], - ['第三季度', 4785, 7987, 4172], - ], - }, - xAxis: { - type: 'category', - }, - yAxis: {}, - series: [ - { - type: 'line', - }, - { - type: 'line', + { + label: '卡片1v5', + icon: { + svg: 'numeric-5', }, - { - type: 'line', + content: { + type: 'card-1v5', + title: '讨论 Builder 架构', + body: '讨论未来的发展方向和基础架构,是否可以融入 AI 生成相应的内容,为用户提供优秀的数字创新体验。', + more: { + href: '/node/1', + target: '_blank', + label: '查看更多', + }, + footer: { + label: 'Step 01.', + icon: { + svg: 'chevron-double-right', + }, + }, }, - ], - }, - }, - { - label: '饼图', - icon: { - svg: 'chart-pie', - }, - preview: '/assets/images/builder/widgets/pie.png', - content: { - type: 'chart', - title: { - text: '金额预算占比', - subtext: '2022年9月', - left: 'center', - }, - tooltip: { - trigger: 'item', }, - legend: { - orient: 'vertical', - left: 'left', - }, - xAxis: { - type: 'category', - }, - yAxis: {}, - dataset: { - source: [ - ['预算', '费用'], - ['大额红包总金额', 398], - ['小额红包总金额', 916], - ['提成总额', 370], - ], - }, - series: [ - { - name: 'Access From', - type: 'pie', - radius: '50%', - label: { - formatter: '{b}: {d}%', - }, - emphasis: { - itemStyle: { - shadowBlur: 10, - shadowOffsetX: 0, - shadowColor: 'rgba(0, 0, 0, 0.5)', - }, + { + label: '卡片1v6', + icon: { + svg: 'numeric-6', + }, + content: { + title: { + classes: 'text-primary', + label: '免费', }, + type: 'card-1v6', + prefix: '¥', + number: '79', + suffix: '/月', + body: '
  • 完全开放
  • 安全检测机制
  • 高质量交付源码文件
  • 免费一个域名绑定
  • 二十四小时免费技术支持
', + classes: '', + actionsAlign: 'start', + actions: [ + { + href: '#', + label: '开始', + type: 'btn', + color: 'primary', + mode: 'raised', + }, + { + type: 'btn', + label: '立即购买', + href: '#', + mode: 'raised', + color: 'primary', + }, + ], }, - ], - }, + }, + ], }, { - label: '折叠面板', - icon: { - svg: 'format-line-weight', - }, - content: { - type: 'panel', - elements: [ - { - title: '组件驱动开发', - icon: 'person', + label: '其他', + elements: [ + { + label: '进步器', + icon: { + svg: 'debug-step-over', + }, + content: { + type: 'stepper', params: { - expanded: true, + mode: 'horizontal', + labelPosition: 'bottom', + linear: true, }, - elements: [ + steps: [ { - type: 'text', - spacer: 'none', - body: 'Storybook采用了组件驱动开发的方法,即将UI组件作为开发的核心单元。开发人员可以在Storybook中为每个UI组件创建"stories",描述组件在不同状态和交互方式下的行为和外观。这种方法能够提高组件的可重用性和可测试性。', + label: '指派中', }, - ], - }, - { - title: '组件展示和测试', - icon: 'faviores', - elements: [ { - type: 'text', - spacer: 'none', - body: 'Storybook提供了一个交互式的界面,用于展示和测试UI组件。开发人员可以在浏览器中浏览和交互组件,以便检查其外观和行为,并确保它们在各种条件下正常工作。这有助于加快开发迭代周期,提高组件的质量。', + label: '接受', + completed: true, }, - ], - }, - { - title: '文档化', - icon: 'faviores', - elements: [ { - type: 'text', - spacer: 'none', - body: 'Storybook不仅可以展示和测试组件,还可以自动生成组件的文档。开发人员可以使用Markdown或其他文档格式编写组件文档,并将其与组件关联。这使得团队成员可以更好地理解和使用组件,减少了沟通成本。', + label: '停止', }, - ], - }, - { - title: '插件和工具生态系统', - icon: 'faviores', - elements: [ { - type: 'text', - spacer: 'none', - body: 'Storybook拥有丰富的插件和工具生态系统,可以扩展其功能。这些插件可以用于模拟数据、测试组件的不同状态和交互,并生成自动化测试报告。这样,开发人员可以根据自己的需求定制和扩展Storybook。', + label: '转移', }, - ], - }, - ], - }, - }, - { - label: '表格', - icon: { - svg: 'table', - }, - preview: '/assets/images/builder/widgets/table.png', - content: { - type: 'dynamic-table', - header: [ - { - label: '模块', - key: 'module', - }, - { - label: '描述', - key: 'info', - }, - { - label: '安装量', - key: 'tatol', - }, - { - label: '备注', - key: 'remarks', - dialog: { - shorten: 5, - label: '更多', - }, - }, - ], - elements: [ - { - module: 'Slick Carousel', - tatol: 2992, - info: 'Slick 轮播,强大响应式且性能优异的图片轮播解决方案,有非常丰富的配置选项,slick 官网自己调侃这是你最后使用的图片轮播', - remarks: '查看', - }, - { - module: 'Views Slideshow', - tatol: 5501, - info: '视图轮播模块,该模块是最受欢迎的幻灯片模块,可放任何内容,高度定制\t', - remarks: '查看', - }, - { - module: 'Colorbox', - tatol: 4438, - info: '轻量级高可定制幻灯片模块,高度集成在 Drupal 中,可放图片,Iframed 或者在线内容等等\t', - remarks: '查看', - }, - { - module: 'Flex Slider', - tatol: 8930, - info: '响应式、可调整大小、适配浏览器和移动设备,支持移动设备手势滑动\t', - remarks: '查看', - }, - { - module: 'Owl Carousel', - tatol: 1000, - info: '提供视图样式,字段格式化和管理 UI,支持响应式、移动手势、高定制幻灯片,CSS3 动画,JSON,有可用的回调,自定义事件等\t', - remarks: '查看', - }, - ], - }, - }, - { - label: '播放按钮', - icon: { - svg: 'play-circle-outline', - }, - content: { - type: 'btn-video', - color: 'primary', - video: { - type: 'video', - options: { - controls: true, - aspectRatio: '16:9', - poster: '/assets/video/poster01.png', - sources: [ { - src: '/assets/video/storybook.mp4', - type: 'video/mp4', + label: '已完成', }, ], }, }, - }, - }, - { - label: 'Box', - icon: { - svg: 'box', - }, - content: { - type: 'box', - img: { - src: '/assets/images/svg/Asset187.svg', - alt: 'browser', - }, - style: 'style-v3 use-image', - title: { - href: '#', - label: '高性能', - }, - content: '默认情况下,Drupal 运行速度很快,您可以优化部署,使其运行得更快;', - }, - }, - { - label: 'Box v1', - icon: { - svg: 'box', - }, - content: { - type: 'box', - style: 'style-v1', - icon: { - name: 'fingerprint', - }, - title: { - href: '/', - label: '组件编辑', - }, - content: '通过简单的管理界面对复杂的可视化编辑', - more: { - href: '#', - label: '更多', - }, - }, - }, - { - label: 'Box v2', - icon: { - svg: 'box', - }, - content: { - type: 'box', - style: 'style-v2', - icon: { - name: 'verified_user', - }, - title: { - href: '/', - label: '组件编辑', - }, - content: '通过简单的管理界面对复杂的可视化编辑', - more: { - href: '#', - label: '更多', - }, - }, - }, - { - label: 'Box v3', - icon: { - svg: 'box', - }, - content: { - type: 'box', - style: 'style-v3', - icon: { - name: 'verified_user', - }, - title: { - href: '/', - label: '组件编辑', - }, - content: '通过简单的管理界面对复杂的可视化编辑', - more: { - href: '#', - label: '更多', - }, - }, - }, - { - label: 'Box v4', - icon: { - svg: 'box', - }, - content: { - type: 'box', - style: 'style-v4', - icon: { - name: 'verified_user', - }, - title: { - href: '/', - label: '组件编辑', - }, - content: '通过简单的管理界面对复杂的可视化编辑', - more: { - href: '#', - label: '更多', - }, - }, - }, - { - label: 'Box v5', - icon: { - svg: 'box', - }, - content: { - type: 'box', - style: 'style-v5', - icon: { - name: 'verified_user', - }, - title: { - href: '/', - label: '组件编辑', - }, - content: '通过简单的管理界面对复杂的可视化编辑', - more: { - href: '#', - label: '更多', - }, - }, - }, - { - label: 'Box v6', - icon: { - svg: 'box', - }, - content: { - type: 'box', - style: 'style-v6', - icon: { - name: 'verified_user', - }, - title: { - href: '/', - label: '组件编辑', - }, - content: '通过简单的管理界面对复杂的可视化编辑', - more: { - href: '#', - label: '更多', - }, - }, - }, - { - label: 'Box v7', - icon: { - svg: 'box', - }, - content: { - type: 'box', - style: 'style-v7', - icon: { - name: 'verified_user', - }, - title: { - href: '/', - label: '组件编辑', - }, - content: '通过简单的管理界面对复杂的可视化编辑', - more: { - href: '#', - label: '更多', - }, - }, - }, - { - label: 'Box v9', - icon: { - svg: 'box', - }, - content: { - type: 'box', - style: 'style-v9', - icon: { - name: 'fingerprint', - }, - title: { - href: '/', - label: '组件编辑', - }, - content: '通过简单的管理界面对复杂的可视化编辑', - more: { - href: '#', - label: '更多', - }, - }, - }, - { - label: 'Box v10', - icon: { - svg: 'box', - }, - content: { - type: 'box', - style: 'style-v10', - icon: { - name: 'fingerprint', - }, - title: { - href: '/', - label: '组件编辑', - }, - content: '通过简单的管理界面对复杂的可视化编辑', - more: { - href: '#', - label: '更多', - }, - }, - }, - { - label: '卡片', - icon: { - svg: 'card-outline', - }, - preview: '/assets/images/builder/widgets/card.png', - content: { - type: 'card', - title: '高性能', - subTitle: 'High Performance', - classes: 'card-no-shadow', - body: '默认情况下,Drupal 运行速度很快,您可以优化部署,使其运行得更快;', - feature: { - fullIcon: 'fullscreen', - openIcon: 'open_in_new', - link: '#', - ratios: 'media-4-3', - img: { - classes: 'object-fit', - src: '/assets/images/cases/porto3.jpg', - alt: 'alt', - }, - }, - }, - }, - { - label: '卡片1v1', - icon: { - svg: 'numeric-1', - }, - preview: '/assets/images/builder/widgets/card-1v1.png', - content: { - type: 'card-1v1', - link: { - href: '#', - label: 'Drupal 100多种语言提供了无以伦比的支持和翻译工作流程', - }, - user: '表歌', - time: '2022/09/27', - feature: { - fullIcon: 'fullscreen', - openIcon: 'open_in_new', - link: '#', - ratios: 'media-4-3', - img: { - classes: 'object-fit', - src: '/assets/images/cases/porto3.jpg', - alt: 'alt', + { + label: '进度组', + icon: { + svg: 'format-list-group', }, - }, - moreLabel: '查看更多', - }, - }, - { - label: '卡片2v2', - icon: { - svg: 'numeric-2', - }, - preview: '/assets/images/builder/widgets/card-1v2.png', - content: { - type: 'card-1v2', - link: { - href: '#', - label: 'Drupal 100多种语言提供了无以伦比的支持和翻译工作流程', - }, - subTitle: '多语言', - img: { - href: '#', - src: '/assets/images/cases/porto3.jpg', - alt: 'alt', - }, - bg: { - classes: 'object-fit', - img: { - hostClasses: '', - src: '/assets/images/showcase/pattern-01.png', + content: { + type: 'progress-group', + elements: [ + { + label: 'HTML/CSS', + value: 95, + }, + { + label: 'Angular/JavaScript', + value: 79, + }, + { + label: 'Drupal', + value: 60, + }, + ], }, }, - }, - }, - { - label: '卡片1v4', - icon: { - svg: 'numeric-4', - }, - content: { - type: 'card-1v4', - img: { - classes: 'w-full h-full object-cover', - src: '/assets/images/avatar/01.jpeg', - }, - star: 5, - title: '- Johnson', - subTitle: '前端开发', - body: '信使是一个灵活可扩展性高的前端Anuglar框架,动态组件可以使得组件之间变得更加灵活,但是依赖循环也变得复杂。', - }, - }, - { - label: '卡片1v5', - icon: { - svg: 'numeric-5', - }, - content: { - type: 'card-1v5', - title: '讨论 Builder 架构', - body: '讨论未来的发展方向和基础架构,是否可以融入 AI 生成相应的内容,为用户提供优秀的数字创新体验。', - more: { - href: '/node/1', - target: '_blank', - label: '查看更多', - }, - footer: { - label: 'Step 01.', + { + label: '列表', icon: { - svg: 'chevron-double-right', - }, - }, - }, - }, - { - label: '卡片1v6', - icon: { - svg: 'numeric-6', - }, - content: { - title: { - classes: 'text-primary', - label: '免费', - }, - type: 'card-1v6', - prefix: '¥', - number: '79', - suffix: '/月', - body: '
  • 完全开放
  • 安全检测机制
  • 高质量交付源码文件
  • 免费一个域名绑定
  • 二十四小时免费技术支持
', - classes: '', - actionsAlign: 'start', - actions: [ - { - href: '#', - label: '开始', - type: 'btn', - color: 'primary', - mode: 'raised', + svg: 'format-list-checkbox', }, - { - type: 'btn', - label: '立即购买', - href: '#', - mode: 'raised', - color: 'primary', + content: { + type: 'media-list', + title: '热门文章', + elements: [ + { + link: { + label: '使用 DevTools 对 Angular 前端应用性能分析优化', + href: '/node/417', + }, + img: { + src: '../assets/images/showcase/blog1-large.jpeg', + alt: '', + }, + changed: '2024-07-16', + }, + { + link: { + label: '使用 takeUntil 操作符管理 Angular 组件的订阅', + href: '/node/415', + }, + img: { + src: '../assets/images/showcase/blog2-large.jpeg', + alt: '', + }, + changed: '2024-07-16', + }, + { + link: { + label: '你应该了解的 Angular 最佳实践', + href: '2024-07-16', + }, + img: { + src: '../assets/images/showcase/blog3-large.jpeg', + alt: '', + }, + changed: '2024-07-16', + }, + { + link: { + label: 'Angular 5 rxjs 5.5.2 多个 http 并行 forkJoin 请求', + href: '2024-07-16', + }, + img: { + src: '../assets/images/showcase/blog4-large.jpeg', + alt: '', + }, + changed: '2024-07-16', + }, + ], }, - ], - }, - }, - { - label: '进步器', - icon: { - svg: 'debug-step-over', - }, - content: { - type: 'stepper', - params: { - mode: 'horizontal', - labelPosition: 'bottom', - linear: true, }, - steps: [ - { - label: '指派中', - }, - { - label: '接受', - completed: true, - }, - { - label: '停止', - }, - { - label: '转移', - }, - { - label: '已完成', - }, - ], - }, - }, - { - label: '进度组', - icon: { - svg: 'format-list-group', - }, - content: { - type: 'progress-group', - elements: [ - { - label: 'HTML/CSS', - value: 95, - }, - { - label: 'Angular/JavaScript', - value: 79, - }, - { - label: 'Drupal', - value: 60, - }, - ], - }, - }, - { - label: '列表', - icon: { - svg: 'format-list-checkbox', - }, - content: { - type: 'media-list', - title: '热门文章', - elements: [ - { - link: { - label: '使用 DevTools 对 Angular 前端应用性能分析优化', - href: '/node/417', - }, - img: { - src: '../assets/images/showcase/blog1-large.jpeg', - alt: '', - }, - changed: '2024-07-16', + { + label: '对象', + icon: { + svg: 'format-list-bulleted-type', }, - { - link: { - label: '使用 takeUntil 操作符管理 Angular 组件的订阅', - href: '/node/415', - }, + content: { + type: 'media-object', img: { - src: '../assets/images/showcase/blog2-large.jpeg', - alt: '', + src: '/assets/images/avatar/01.jpeg', + width: 45, + height: 45, + alt: 'logo', }, - changed: '2024-07-16', + meta: '2024-07', + title: '前端开发工程师', + subTitle: 'Davyin', + content: + '专注于 Drupal 前端主题开发,目前主要从事于 Angular 前端开发,终身学习体验者,热衷于健身,希望明天比今天好一点。', }, - { - link: { - label: '你应该了解的 Angular 最佳实践', - href: '2024-07-16', - }, - img: { - src: '../assets/images/showcase/blog3-large.jpeg', - alt: '', - }, - changed: '2024-07-16', + }, + { + label: '感言', + icon: { + svg: 'format-wrap-square', }, - { - link: { - label: 'Angular 5 rxjs 5.5.2 多个 http 并行 forkJoin 请求', - href: '2024-07-16', - }, + content: { + type: 'testimonial', + style: 'style-v2', + title: 'Johnson', + subTitle: 'FrontEnd', img: { - src: '../assets/images/showcase/blog4-large.jpeg', + src: '/assets/images/avatar/01.jpeg', alt: '', }, - changed: '2024-07-16', + body: '作为一名非专业的Web开发者,我曾经因为缺乏编码和设计技能而感到十分困惑。然而自从我开始使用Builder构建页面后,我的许多顾虑就消失了。', }, - ], - }, - }, - { - label: '对象', - icon: { - svg: 'format-list-bulleted-type', - }, - content: { - type: 'media-object', - img: { - src: '/assets/images/avatar/01.jpeg', - width: 45, - height: 45, - alt: 'logo', - }, - meta: '2024-07', - title: '前端开发工程师', - subTitle: 'Davyin', - content: - '专注于 Drupal 前端主题开发,目前主要从事于 Angular 前端开发,终身学习体验者,热衷于健身,希望明天比今天好一点。', - }, - }, - { - label: '感言', - icon: { - svg: 'format-wrap-square', - }, - content: { - type: 'testimonial', - style: 'style-v2', - title: 'Johnson', - subTitle: 'FrontEnd', - img: { - src: '/assets/images/avatar/01.jpeg', - alt: '', }, - body: '作为一名非专业的Web开发者,我曾经因为缺乏编码和设计技能而感到十分困惑。然而自从我开始使用Builder构建页面后,我的许多顾虑就消失了。', - }, - }, - { - label: 'Lightbox', - icon: { - svg: 'view-carousel-outline', - }, - content: { - type: 'inline-lightbox', - label: ['查看图片', 'Word 下载', 'PDF 预览'], - elements: [ - { - src: '/assets/images/cases/porto1.jpg', - }, - { - src: '/assets/images/cases/porto2.pdf', - }, - { - src: '/assets/images/cases/porto3.pdf', - }, - ], - }, + ], }, ]; diff --git a/src/app/modules/builder/layout-builder/block-toolbar/block-toolbar.component.ts b/src/app/modules/builder/layout-builder/block-toolbar/block-toolbar.component.ts index b32592cd1..e4bc69b80 100644 --- a/src/app/modules/builder/layout-builder/block-toolbar/block-toolbar.component.ts +++ b/src/app/modules/builder/layout-builder/block-toolbar/block-toolbar.component.ts @@ -42,7 +42,7 @@ export class BlockToolbarComponent { } addBlock(addType: string, content: any, target: any): void { - this.builderSerivce.addBlock(addType, content, this.util.generatePath(target)); + // this.builderSerivce.addBlock(addType, content, this.util.generatePath(target)); } onCopy(widget: any): any { diff --git a/src/app/modules/builder/main/builder-list/builder-list.component.html b/src/app/modules/builder/main/builder-list/builder-list.component.html index f4eb099ff..a48acf662 100644 --- a/src/app/modules/builder/main/builder-list/builder-list.component.html +++ b/src/app/modules/builder/main/builder-list/builder-list.component.html @@ -60,6 +60,10 @@
} + + @if (builder.wigetsPicker$ | async; as wigetsPicker) { + + }
} diff --git a/src/app/modules/builder/main/builder-list/builder-list.component.scss b/src/app/modules/builder/main/builder-list/builder-list.component.scss index 2a2c9e8bc..a10a67f8f 100644 --- a/src/app/modules/builder/main/builder-list/builder-list.component.scss +++ b/src/app/modules/builder/main/builder-list/builder-list.component.scss @@ -17,6 +17,16 @@ overflow: auto; padding-bottom: 150px; } + ::ng-deep { + .widget-picker { + position: absolute; + right: 40px; + top: 50%; + transform: translateY(-50%); + z-index: 999; + border-radius: 20px; + } + } } .component-item { position: relative; diff --git a/src/app/modules/builder/main/widget-picker/widget-picker.component.html b/src/app/modules/builder/main/widget-picker/widget-picker.component.html index f8aabf68a..64ecb28b7 100644 --- a/src/app/modules/builder/main/widget-picker/widget-picker.component.html +++ b/src/app/modules/builder/main/widget-picker/widget-picker.component.html @@ -1,43 +1,69 @@ -
+
@if (widgets) { -
- @if (bcData) { -
+ @for (group of widgets; track $index) { +
+ @if (bcData) {
- -
粘贴组件
+
+ +
粘贴组件
+
-
- } - @for (widget of widgets; track widget) { -
+ } +
- @if (widget.icon) { - + @if (group.icon) { + } -
- {{ widget.label }} +
+ {{ group.label }}
- } -
+
+ } + @if (help) { +
+ +
+ } } - diff --git a/src/app/modules/builder/main/widget-picker/widget-picker.component.scss b/src/app/modules/builder/main/widget-picker/widget-picker.component.scss index 1b2143e6e..81efb7100 100644 --- a/src/app/modules/builder/main/widget-picker/widget-picker.component.scss +++ b/src/app/modules/builder/main/widget-picker/widget-picker.component.scss @@ -16,11 +16,7 @@ } } .popup { - display: none; - position: fixed; border-radius: 4px; - justify-content: center; - align-items: center; overflow: hidden; box-sizing: border-box; &[data-popper-placement] { diff --git a/src/app/modules/builder/main/widget-picker/widget-picker.component.ts b/src/app/modules/builder/main/widget-picker/widget-picker.component.ts index 67bb49eae..eb6a6aae1 100644 --- a/src/app/modules/builder/main/widget-picker/widget-picker.component.ts +++ b/src/app/modules/builder/main/widget-picker/widget-picker.component.ts @@ -26,8 +26,9 @@ import { cloneDeep } from 'lodash-es'; }) export class WidgetPickerComponent implements OnInit, AfterViewInit { @Input() content: IWidgetPicker; - @ViewChild('popup', { static: false }) popup: ElementRef; + @ViewChild('groupPopup', { static: false }) groupPopup: ElementRef; public widget$ = new Subject(); + public group$ = new Subject(); help: any; popper: any; @@ -84,7 +85,7 @@ export class WidgetPickerComponent implements OnInit, AfterViewInit { } onLeave(): void { - this.widget$.next(false); + this.group$.next(false); this.popper.destroy(); } copyLayoutLastChild(elements: any[], widget: any): any { @@ -93,23 +94,14 @@ export class WidgetPickerComponent implements OnInit, AfterViewInit { return last; } - onHover(widget: any, ele: any): void { - if (this.popup?.nativeElement) { + onHover(group: any, ele: any): void { + if (this.groupPopup?.nativeElement) { const parentRect = this.ele.nativeElement.getBoundingClientRect(); const widgetRect = ele.getBoundingClientRect(); const offset = widgetRect.left - parentRect.left; - this.widget$.next(widget); - this.popper = createPopper(ele, this.popup.nativeElement, { + this.group$.next(group); + this.popper = createPopper(ele, this.groupPopup.nativeElement, { placement: 'left', - strategy: 'fixed', - modifiers: [ - { - name: 'offset', - options: { - offset: [0, offset + 24], - }, - }, - ], }); } } diff --git a/src/theme/component/builder/_builder-list.scss b/src/theme/component/builder/_builder-list.scss index 87130a488..0a2142ca2 100644 --- a/src/theme/component/builder/_builder-list.scss +++ b/src/theme/component/builder/_builder-list.scss @@ -25,6 +25,10 @@ #builder-list { @include scrollbar(mat.m2-get-color-from-palette($primary)); } + .widget-picker { + background-color: mat.m2-get-color-from-palette($background, card); + @include mat.elevation(4, mat.m2-get-color-from-palette($background, tooltip), 0.5); + } } .preview { background-color: mat.m2-get-color-from-palette($foreground, elevation, 0.85); From 9bcd60465ab04415cb6d3d6c734b9110505b1806 Mon Sep 17 00:00:00 2001 From: biaogebusy <349255833@qq.com> Date: Fri, 3 Jan 2025 16:48:09 +0800 Subject: [PATCH 05/35] feat: widget toolbar --- .../builder/data/widgets-for-builder.ts | 21 +++++++++++++++ .../widget-picker.component.html | 23 ++++++++-------- .../widget-picker/widget-picker.component.ts | 3 +-- src/theme/component/_builder.scss | 22 --------------- .../component/builder/_builder-list.scss | 27 ++++++++++++++++++- 5 files changed, 59 insertions(+), 37 deletions(-) diff --git a/src/app/modules/builder/data/widgets-for-builder.ts b/src/app/modules/builder/data/widgets-for-builder.ts index 07028802f..eadc5718e 100644 --- a/src/app/modules/builder/data/widgets-for-builder.ts +++ b/src/app/modules/builder/data/widgets-for-builder.ts @@ -1,6 +1,9 @@ export const widgets = [ { label: '基础', + icon: { + svg: 'format-letter-case', + }, elements: [ { label: '标题', @@ -315,6 +318,9 @@ export const widgets = [ }, { label: '自定义', + icon: { + svg: 'view-dashboard', + }, elements: [ { label: 'Layout', @@ -395,6 +401,9 @@ export const widgets = [ }, { label: '媒体', + icon: { + svg: 'image', + }, elements: [ { label: '图片', @@ -607,6 +616,9 @@ export const widgets = [ }, { label: 'Box', + icon: { + svg: 'box', + }, elements: [ { label: 'Box', @@ -829,6 +841,9 @@ export const widgets = [ }, { label: '图表', + icon: { + svg: 'chart-box', + }, elements: [ { label: '柱状图', @@ -971,6 +986,9 @@ export const widgets = [ }, { label: '卡片', + icon: { + svg: 'credit-card-chip-outline', + }, elements: [ { label: '卡片', @@ -1130,6 +1148,9 @@ export const widgets = [ }, { label: '其他', + icon: { + svg: 'debug-step-over', + }, elements: [ { label: '进步器', diff --git a/src/app/modules/builder/main/widget-picker/widget-picker.component.html b/src/app/modules/builder/main/widget-picker/widget-picker.component.html index 64ecb28b7..bd31d079c 100644 --- a/src/app/modules/builder/main/widget-picker/widget-picker.component.html +++ b/src/app/modules/builder/main/widget-picker/widget-picker.component.html @@ -1,4 +1,4 @@ -
+
@if (widgets) { @for (group of widgets; track $index) {
@@ -7,7 +7,7 @@ #copy class="item" (click)="onPasteData()" - (mouseenter)="onHover({ content: bcData }, copy)" + (mouseenter)="onHoverGroup({ content: bcData }, copy)" matRipple >
} -
+
@if (group.icon) { } -
- {{ group.label }} -
} @if (help) { -
+
-

{{ group.label }}

+
+

{{ group.label }}

@for (item of group.elements; track $index) {
- - {{ item.label }} + +
{{ item.label }}
}
diff --git a/src/app/modules/builder/main/widget-picker/widget-picker.component.ts b/src/app/modules/builder/main/widget-picker/widget-picker.component.ts index eb6a6aae1..005e4dbee 100644 --- a/src/app/modules/builder/main/widget-picker/widget-picker.component.ts +++ b/src/app/modules/builder/main/widget-picker/widget-picker.component.ts @@ -3,7 +3,6 @@ import { ChangeDetectionStrategy, Component, ElementRef, - Inject, Input, OnInit, ViewChild, @@ -94,7 +93,7 @@ export class WidgetPickerComponent implements OnInit, AfterViewInit { return last; } - onHover(group: any, ele: any): void { + onHoverGroup(group: any, ele: any): void { if (this.groupPopup?.nativeElement) { const parentRect = this.ele.nativeElement.getBoundingClientRect(); const widgetRect = ele.getBoundingClientRect(); diff --git a/src/theme/component/_builder.scss b/src/theme/component/_builder.scss index 6607f40be..626181400 100644 --- a/src/theme/component/_builder.scss +++ b/src/theme/component/_builder.scss @@ -152,28 +152,6 @@ $dark-theme: mat.m2-define-dark-theme( } } - .widget-picker { - .popup { - @include mat.elevation(2, mat.m2-get-color-from-palette($background, hover), 0.4); - background-color: mat.m2-get-color-from-palette($background, card); - border: 1px solid mat.m2-get-color-from-palette($foreground, divider); - .hover-show { - > app-dynamic-component { - > app-spacer { - background-color: mat.m2-get-color-from-palette($primary, 0.5); - } - } - } - } - .item { - .inner { - &:hover { - background-color: mat.m2-get-color-from-palette($primary, 0.1); - } - } - } - } - .builder-template { .card { border: 1px solid mat.m2-get-color-from-palette($foreground, divider); diff --git a/src/theme/component/builder/_builder-list.scss b/src/theme/component/builder/_builder-list.scss index 0a2142ca2..0d320db8a 100644 --- a/src/theme/component/builder/_builder-list.scss +++ b/src/theme/component/builder/_builder-list.scss @@ -27,7 +27,32 @@ } .widget-picker { background-color: mat.m2-get-color-from-palette($background, card); - @include mat.elevation(4, mat.m2-get-color-from-palette($background, tooltip), 0.5); + @include mat.elevation(5, mat.m2-get-color-from-palette($background, tooltip), 0.5); + .box { + color: mat.m2-get-color-from-palette($primary, 600); + } + .group-popup, + .popup { + @include mat.elevation(2, mat.m2-get-color-from-palette($background, hover), 0.4); + background-color: mat.m2-get-color-from-palette($background, card); + border: 1px solid mat.m2-get-color-from-palette($foreground, divider); + } + .group-popup { + .item { + &:hover { + background-color: mat.m2-get-color-from-palette($primary, 0.1); + } + } + } + .popup { + .hover-show { + > app-dynamic-component { + > app-spacer { + background-color: mat.m2-get-color-from-palette($primary, 0.5); + } + } + } + } } } .preview { From 7d0dd537bfd5ee47e338f34a75eab1da854ec72b Mon Sep 17 00:00:00 2001 From: biaogebusy <349255833@qq.com> Date: Fri, 3 Jan 2025 17:54:16 +0800 Subject: [PATCH 06/35] refact: widget picker --- src/app/core/state/BuilderState.ts | 2 +- .../builder-list/builder-list.component.scss | 3 +- .../widget-picker.component.html | 90 +++++++++---------- .../widget-picker.component.scss | 6 ++ .../widget-picker/widget-picker.component.ts | 37 ++++++-- .../component/builder/_builder-list.scss | 14 +-- 6 files changed, 85 insertions(+), 67 deletions(-) diff --git a/src/app/core/state/BuilderState.ts b/src/app/core/state/BuilderState.ts index 6a9934334..5d8fc811b 100644 --- a/src/app/core/state/BuilderState.ts +++ b/src/app/core/state/BuilderState.ts @@ -30,7 +30,7 @@ export class BuilderState { public showcase$ = new Subject(); public themeMode = new BehaviorSubject<'light' | 'dark'>('light'); public rightContent$ = new Subject(); - public wigetsPicker$ = new Subject(); + public wigetsPicker$ = new Subject(); public closeRightDrawer$ = new Subject(); public fixedChange$ = new Subject(); public animateDisable$ = new Subject(); diff --git a/src/app/modules/builder/main/builder-list/builder-list.component.scss b/src/app/modules/builder/main/builder-list/builder-list.component.scss index a10a67f8f..df2b7adab 100644 --- a/src/app/modules/builder/main/builder-list/builder-list.component.scss +++ b/src/app/modules/builder/main/builder-list/builder-list.component.scss @@ -20,11 +20,10 @@ ::ng-deep { .widget-picker { position: absolute; - right: 40px; + right: 0; top: 50%; transform: translateY(-50%); z-index: 999; - border-radius: 20px; } } } diff --git a/src/app/modules/builder/main/widget-picker/widget-picker.component.html b/src/app/modules/builder/main/widget-picker/widget-picker.component.html index bd31d079c..885b89623 100644 --- a/src/app/modules/builder/main/widget-picker/widget-picker.component.html +++ b/src/app/modules/builder/main/widget-picker/widget-picker.component.html @@ -1,58 +1,48 @@ -
+
@if (widgets) { - @for (group of widgets; track $index) { -
- @if (bcData) { -
-
- -
粘贴组件
+
+ @for (group of widgets; track $index) { +
+
+
+ @if (group.icon) { + + }
- } -
-
- @if (group.icon) { - - } -
-
- } - @if (help) { -
- -
- } + } + @if (help) { +
+ +
+ } +
}
@if (group$ | async; as group) {

{{ group.label }}

@for (item of group.elements; track $index) {
{{ item.label }}
@@ -62,15 +52,17 @@

{{ group.label }}

}
- +
diff --git a/src/app/modules/builder/main/widget-picker/widget-picker.component.scss b/src/app/modules/builder/main/widget-picker/widget-picker.component.scss index 81efb7100..7c8396c6b 100644 --- a/src/app/modules/builder/main/widget-picker/widget-picker.component.scss +++ b/src/app/modules/builder/main/widget-picker/widget-picker.component.scss @@ -1,5 +1,8 @@ @import '../../../../../theme/variable/breakpoint'; .widget-picker { + .widget-wrapper { + border-radius: 20px; + } .item { position: relative; .title { @@ -15,6 +18,9 @@ cursor: pointer; } } + .group-popup { + border-radius: 12px; + } .popup { border-radius: 4px; overflow: hidden; diff --git a/src/app/modules/builder/main/widget-picker/widget-picker.component.ts b/src/app/modules/builder/main/widget-picker/widget-picker.component.ts index 005e4dbee..b19edbd8c 100644 --- a/src/app/modules/builder/main/widget-picker/widget-picker.component.ts +++ b/src/app/modules/builder/main/widget-picker/widget-picker.component.ts @@ -26,12 +26,12 @@ import { cloneDeep } from 'lodash-es'; export class WidgetPickerComponent implements OnInit, AfterViewInit { @Input() content: IWidgetPicker; @ViewChild('groupPopup', { static: false }) groupPopup: ElementRef; + @ViewChild('popup', { static: false }) widgetPopup: ElementRef; public widget$ = new Subject(); public group$ = new Subject(); help: any; popper: any; - public bcData: any; ele = inject(ElementRef); widgets = inject(WIDGETS); dialog = inject(MatDialog); @@ -44,16 +44,10 @@ export class WidgetPickerComponent implements OnInit, AfterViewInit { widgetPicker: { help }, } = this.builderService.builderConfig; this.help = help; - this.bcData = this.storage.retrieve(this.builder.COPYWIDGETKEY); } ngAfterViewInit(): void {} - onPasteData(): void { - this.onSelect(this.bcData); - this.storage.clear(this.builder.COPYWIDGETKEY); - } - onSelect(widget: any): void { const { addType, path, content } = this.content; const data = cloneDeep(content); @@ -86,6 +80,7 @@ export class WidgetPickerComponent implements OnInit, AfterViewInit { onLeave(): void { this.group$.next(false); this.popper.destroy(); + this.builder.wigetsPicker$.next(false); } copyLayoutLastChild(elements: any[], widget: any): any { const last = Object.assign({}, elements[elements.length - 1]); @@ -95,12 +90,36 @@ export class WidgetPickerComponent implements OnInit, AfterViewInit { onHoverGroup(group: any, ele: any): void { if (this.groupPopup?.nativeElement) { + this.group$.next(group); + this.popper = createPopper(ele, this.groupPopup.nativeElement, { + placement: 'left', + modifiers: [ + { + name: 'offset', + options: { + offset: [0, 4], + }, + }, + ], + }); + } + } + onHoverWidget(widget: any, ele: any): void { + if (this.widgetPopup?.nativeElement) { const parentRect = this.ele.nativeElement.getBoundingClientRect(); const widgetRect = ele.getBoundingClientRect(); const offset = widgetRect.left - parentRect.left; - this.group$.next(group); - this.popper = createPopper(ele, this.groupPopup.nativeElement, { + this.widget$.next(widget); + this.popper = createPopper(ele, this.widgetPopup.nativeElement, { placement: 'left', + modifiers: [ + { + name: 'offset', + options: { + offset: [0, 2], + }, + }, + ], }); } } diff --git a/src/theme/component/builder/_builder-list.scss b/src/theme/component/builder/_builder-list.scss index 0d320db8a..f822d67bb 100644 --- a/src/theme/component/builder/_builder-list.scss +++ b/src/theme/component/builder/_builder-list.scss @@ -26,16 +26,18 @@ @include scrollbar(mat.m2-get-color-from-palette($primary)); } .widget-picker { - background-color: mat.m2-get-color-from-palette($background, card); - @include mat.elevation(5, mat.m2-get-color-from-palette($background, tooltip), 0.5); - .box { - color: mat.m2-get-color-from-palette($primary, 600); + .widget-wrapper { + background-color: mat.m2-get-color-from-palette($background, card); + @include mat.elevation(5, mat.m2-get-color-from-palette($background, tooltip), 0.5); + .box { + color: mat.m2-get-color-from-palette($primary, 600); + } } .group-popup, .popup { - @include mat.elevation(2, mat.m2-get-color-from-palette($background, hover), 0.4); + @include mat.elevation(10, mat.m2-get-color-from-palette($background, hover), 0.4); background-color: mat.m2-get-color-from-palette($background, card); - border: 1px solid mat.m2-get-color-from-palette($foreground, divider); + border: 1px solid mat.m2-get-color-from-palette($foreground, divider, 0.1); } .group-popup { .item { From 9848cb1ad64c6195cc3ae067a760b65517d48420 Mon Sep 17 00:00:00 2001 From: biaogebusy <349255833@qq.com> Date: Sun, 5 Jan 2025 15:51:37 +0800 Subject: [PATCH 07/35] refact: toolbar --- .../builder/data/widgets-for-builder.ts | 291 +++++++++--------- .../builder-list/builder-list.component.html | 5 +- .../builder-list/builder-list.component.scss | 5 - .../widget-picker.component.html | 25 +- .../widget-picker.component.scss | 34 +- .../widget-picker/widget-picker.component.ts | 47 ++- .../component-toolbar.component.html | 9 +- .../widgets/divider/divider.component.html | 2 +- .../component/builder/_builder-list.scss | 4 +- 9 files changed, 227 insertions(+), 195 deletions(-) diff --git a/src/app/modules/builder/data/widgets-for-builder.ts b/src/app/modules/builder/data/widgets-for-builder.ts index eadc5718e..3286508e2 100644 --- a/src/app/modules/builder/data/widgets-for-builder.ts +++ b/src/app/modules/builder/data/widgets-for-builder.ts @@ -614,6 +614,151 @@ export const widgets = [ }, ], }, + { + label: '图表', + icon: { + svg: 'chart-box', + }, + elements: [ + { + label: '柱状图', + icon: { + svg: 'chart-bar', + }, + preview: '/assets/images/builder/widgets/bar.png', + content: { + type: 'chart', + title: { + text: '年度活动金额预算', + subtext: '南宁', + }, + legend: { + bottom: '10px', + }, + tooltip: { + trigger: 'axis', + }, + dataset: { + source: [ + ['红包预算', '2020', '2021', '2022'], + ['第一季度', 4180, 9056, 7942], + ['第二季度', 7908, 9032, 8471], + ['第三季度', 4785, 7987, 4172], + ], + }, + xAxis: { + type: 'category', + }, + yAxis: {}, + series: [ + { + type: 'bar', + }, + { + type: 'bar', + }, + { + type: 'bar', + }, + ], + }, + }, + { + label: '折线图', + icon: { + svg: 'chart-line', + }, + preview: '/assets/images/builder/widgets/line.png', + content: { + type: 'chart', + title: { + text: '年度活动金额预算', + subtext: '南宁', + }, + legend: { + bottom: '10px', + }, + tooltip: { + trigger: 'axis', + }, + dataset: { + source: [ + ['红包预算', '2020', '2021', '2022'], + ['第一季度', 4180, 9056, 7942], + ['第二季度', 7908, 9032, 8471], + ['第三季度', 4785, 7987, 4172], + ], + }, + xAxis: { + type: 'category', + }, + yAxis: {}, + series: [ + { + type: 'line', + }, + { + type: 'line', + }, + { + type: 'line', + }, + ], + }, + }, + { + label: '饼图', + icon: { + svg: 'chart-pie', + }, + preview: '/assets/images/builder/widgets/pie.png', + content: { + type: 'chart', + title: { + text: '金额预算占比', + subtext: '2022年9月', + left: 'center', + }, + tooltip: { + trigger: 'item', + }, + legend: { + orient: 'vertical', + left: 'left', + }, + xAxis: { + type: 'category', + }, + yAxis: {}, + dataset: { + source: [ + ['预算', '费用'], + ['大额红包总金额', 398], + ['小额红包总金额', 916], + ['提成总额', 370], + ], + }, + series: [ + { + name: 'Access From', + type: 'pie', + radius: '50%', + label: { + formatter: '{b}: {d}%', + }, + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)', + }, + }, + }, + ], + }, + }, + ], + }, { label: 'Box', icon: { @@ -839,151 +984,7 @@ export const widgets = [ }, ], }, - { - label: '图表', - icon: { - svg: 'chart-box', - }, - elements: [ - { - label: '柱状图', - icon: { - svg: 'chart-bar', - }, - preview: '/assets/images/builder/widgets/bar.png', - content: { - type: 'chart', - title: { - text: '年度活动金额预算', - subtext: '南宁', - }, - legend: { - bottom: '10px', - }, - tooltip: { - trigger: 'axis', - }, - dataset: { - source: [ - ['红包预算', '2020', '2021', '2022'], - ['第一季度', 4180, 9056, 7942], - ['第二季度', 7908, 9032, 8471], - ['第三季度', 4785, 7987, 4172], - ], - }, - xAxis: { - type: 'category', - }, - yAxis: {}, - series: [ - { - type: 'bar', - }, - { - type: 'bar', - }, - { - type: 'bar', - }, - ], - }, - }, - { - label: '折线图', - icon: { - svg: 'chart-line', - }, - preview: '/assets/images/builder/widgets/line.png', - content: { - type: 'chart', - title: { - text: '年度活动金额预算', - subtext: '南宁', - }, - legend: { - bottom: '10px', - }, - tooltip: { - trigger: 'axis', - }, - dataset: { - source: [ - ['红包预算', '2020', '2021', '2022'], - ['第一季度', 4180, 9056, 7942], - ['第二季度', 7908, 9032, 8471], - ['第三季度', 4785, 7987, 4172], - ], - }, - xAxis: { - type: 'category', - }, - yAxis: {}, - series: [ - { - type: 'line', - }, - { - type: 'line', - }, - { - type: 'line', - }, - ], - }, - }, - { - label: '饼图', - icon: { - svg: 'chart-pie', - }, - preview: '/assets/images/builder/widgets/pie.png', - content: { - type: 'chart', - title: { - text: '金额预算占比', - subtext: '2022年9月', - left: 'center', - }, - tooltip: { - trigger: 'item', - }, - legend: { - orient: 'vertical', - left: 'left', - }, - xAxis: { - type: 'category', - }, - yAxis: {}, - dataset: { - source: [ - ['预算', '费用'], - ['大额红包总金额', 398], - ['小额红包总金额', 916], - ['提成总额', 370], - ], - }, - series: [ - { - name: 'Access From', - type: 'pie', - radius: '50%', - label: { - formatter: '{b}: {d}%', - }, - emphasis: { - itemStyle: { - shadowBlur: 10, - shadowOffsetX: 0, - shadowColor: 'rgba(0, 0, 0, 0.5)', - }, - }, - }, - ], - }, - }, - ], - }, + { label: '卡片', icon: { diff --git a/src/app/modules/builder/main/builder-list/builder-list.component.html b/src/app/modules/builder/main/builder-list/builder-list.component.html index a48acf662..bd9651b9a 100644 --- a/src/app/modules/builder/main/builder-list/builder-list.component.html +++ b/src/app/modules/builder/main/builder-list/builder-list.component.html @@ -60,9 +60,8 @@
} - - @if (builder.wigetsPicker$ | async; as wigetsPicker) { - + @if (page.body.length > 0) { + }
diff --git a/src/app/modules/builder/main/builder-list/builder-list.component.scss b/src/app/modules/builder/main/builder-list/builder-list.component.scss index df2b7adab..a9aa6824c 100644 --- a/src/app/modules/builder/main/builder-list/builder-list.component.scss +++ b/src/app/modules/builder/main/builder-list/builder-list.component.scss @@ -19,11 +19,6 @@ } ::ng-deep { .widget-picker { - position: absolute; - right: 0; - top: 50%; - transform: translateY(-50%); - z-index: 999; } } } diff --git a/src/app/modules/builder/main/widget-picker/widget-picker.component.html b/src/app/modules/builder/main/widget-picker/widget-picker.component.html index 885b89623..7c73dddd8 100644 --- a/src/app/modules/builder/main/widget-picker/widget-picker.component.html +++ b/src/app/modules/builder/main/widget-picker/widget-picker.component.html @@ -1,6 +1,6 @@
@if (widgets) { -
+
@for (group of widgets; track $index) {
} @if (help) { +
-

{{ group.label }}

+

{{ group.label }}

@for (item of group.elements; track $index) {
{{ group.label }}
}
-