src/app/layout/html-builder/component/ch/ch-grid/ch-grid.component.ts
encapsulation | ViewEncapsulation.None |
selector | app-ch-grid |
styleUrls | ./ch-grid.component.less |
templateUrl | ./ch-grid.component.html |
Properties |
|
Methods |
|
Inputs |
constructor(pageEditorService: PageEditorService, nzContextMenuService: NzContextMenuService)
|
|||||||||
Parameters :
|
gridItem | |
Type : DropItem
|
|
itemIndex | |
Type : number
|
|
itemParent | |
Type : DropItem[]
|
|
Public click |
click()
|
Returns :
void
|
Public contextMenu | |||||||||
contextMenu(event: MouseEvent, menu: NzDropdownMenuComponent)
|
|||||||||
Parameters :
Returns :
void
|
Public copy |
copy()
|
Returns :
void
|
Public delete |
delete()
|
Returns :
void
|
Public drop | ||||||
drop(event: CdkDragDrop
|
||||||
Parameters :
Returns :
void
|
Public initColData |
initColData()
|
Returns :
void
|
Public ngOnInit |
ngOnInit()
|
Returns :
void
|
Public split | ||||||
split(n: number)
|
||||||
Parameters :
Returns :
void
|
Public colItemsTemp |
Type : ColItem[]
|
Public pageEditorService |
Type : PageEditorService
|
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { SFSchema } from '@delon/form';
import { NzContextMenuService, NzDropdownMenuComponent } from 'ng-zorro-antd/dropdown';
import { ColItem, DropItem, PageEditorService } from 'src/app/layout/html-builder/page-editor/page-editor.service';
@Component({
selector: 'app-ch-grid',
templateUrl: './ch-grid.component.html',
styleUrls: ['./ch-grid.component.less'],
encapsulation: ViewEncapsulation.None
})
export class ChGridComponent implements OnInit {
public schema: SFSchema = {
properties: {
layout: {
type: 'array',
title: '栅格布局',
minItems: 1,
maxItems: 12,
description: '* 栅格布局,基于Boostrap,24分格。',
items: {
type: 'object',
properties: {
pc: {
type: 'number',
title: '桌面',
minimum: 1,
maximum: 24,
default: 4,
},
pad: {
type: 'number',
title: '平板',
minimum: 1,
maximum: 24,
default: 4,
},
phone: {
type: 'number',
title: '手机',
minimum: 1,
maximum: 24,
default: 4,
},
padding: {
type: 'string',
title: '左右边距',
enum: [
{ label: '默认', value: '' },
{ label: '左边距:0', value: 'pl0' },
{ label: '右边距:0', value: 'pr0' },
{ label: '两边距:0', value: 'px0' },
],
default: '',
},
},
},
ui: {
grid: { arraySpan: 8 },
},
},
},
};
@Input()
public gridItem: DropItem;
@Input()
public itemIndex: number;
@Input()
public itemParent: DropItem[];
// 格子分列数据
public colItemsTemp: ColItem[];
constructor(
public pageEditorService: PageEditorService,
private nzContextMenuService: NzContextMenuService,
) { }
public initColData() {
// console.log('initColData');
// 连接拖放组件
if (!this.gridItem.data.layout) {
this.gridItem.data.layout = [
{ pc: 12, pad: 12, phone: 24 },
{ pc: 12, pad: 12, phone: 24 },
];
}
this.colItemsTemp = this.pageEditorService.updateDropConnect(this.gridItem.data.layout);
// 初始化ch-grid栅格数据
if (this.gridItem.colItems.length) {
this.colItemsTemp.forEach((_, index: number) => {
if (this.gridItem.colItems[index]) {
this.colItemsTemp[index].dropItems = this.gridItem.colItems[index].dropItems;
}
});
}
this.gridItem.colItems = this.colItemsTemp;
// console.log(this.pageEditorService.dropItems, this.gridItem);
}
// 拖放组件
public drop(event: CdkDragDrop<DropItem>) {
// console.log('In ChGridComponent');
// console.log(`previousIndex => ${event.previousIndex}, currentIndex => ${event.currentIndex}`);
// console.log('previousContainer.data => ', event.previousContainer.data);
this.gridItem.colItems.forEach((colItem: ColItem) => {
if (event.container.id === colItem.id) {
if (event.previousContainer === event.container) {
moveItemInArray(colItem.dropItems, event.previousIndex, event.currentIndex);
} else {
if (this.gridItem.rootUid === undefined) {
this.gridItem.rootUid = this.gridItem.uid;
}
colItem.dropItems.splice(event.currentIndex, 0, new DropItem(event.previousContainer.data.code, undefined,
this.gridItem.rootUid));
}
}
});
}
// 右键菜单
public contextMenu(event: MouseEvent, menu: NzDropdownMenuComponent): void {
event.stopPropagation();
event.stopImmediatePropagation();
this.nzContextMenuService.create(event, menu);
}
// 分割栅格
public split(n: number) {
if (n !== this.gridItem.data.layout.length) {
switch (n) {
case 2:
this.gridItem.data.layout = this.gridItem.data.layout = [
{ pc: 12, pad: 12, phone: 24 },
{ pc: 12, pad: 12, phone: 24 },
];
break;
case 3:
this.gridItem.data.layout = this.gridItem.data.layout = [
{ pc: 8, pad: 8, phone: 24 },
{ pc: 8, pad: 8, phone: 24 },
{ pc: 8, pad: 8, phone: 24 },
];
break;
case 4:
this.gridItem.data.layout = this.gridItem.data.layout = [
{ pc: 6, pad: 6, phone: 24 },
{ pc: 6, pad: 6, phone: 24 },
{ pc: 6, pad: 6, phone: 24 },
{ pc: 6, pad: 6, phone: 24 },
];
break;
}
this.initColData();
this.click();
}
}
// 复制组件
public copy() {
this.pageEditorService.copyDropItem(this.itemIndex);
}
// 删除组件
public delete() {
this.pageEditorService.removeDropItem(this.itemIndex);
}
// 点击打开属性
public click() {
this.pageEditorService.updatePropForm(this.schema, this.gridItem);
}
public ngOnInit() {
this.initColData();
}
}
<div class="playground row mb2" (contextmenu)="contextMenu($event, menu)" [ngClass]="gridItem.data | props"
(click)="click()">
<div *ngFor="let colItem of gridItem.colItems, let i=index"
[class]="'col-md-'+colItem.pc+' '+'col-sm-'+colItem.pad+' '+'col-xs-'+colItem.phone"
[ngClass]="{'pl0': gridItem.data.layout[i].padding === 'pl0','pr0': gridItem.data.layout[i].padding === 'pr0','px0': gridItem.data.layout[i].padding === 'px0'}">
<div class="col-wrapper" [id]="colItem.id" cdkDropList (cdkDropListDropped)="drop($event)">
<div class="playground-item" *ngFor="let item of colItem.dropItems; index as i;" cdkDrag>
<app-ch-head #player [item]="item" [itemIndex]="i" [itemParent]="colItem.dropItems"
*ngIf="item.code === 'app-ch-head'">
</app-ch-head>
<app-ch-p #player [item]="item" *ngIf="item.code === 'app-ch-p'">
</app-ch-p>
<app-ch-list #player [item]="item" *ngIf="item.code === 'app-ch-list'">
</app-ch-list>
<app-ch-link #player [item]="item" *ngIf="item.code === 'app-ch-link'">
</app-ch-link>
<app-ch-img #player [item]="item" *ngIf="item.code === 'app-ch-img'">
</app-ch-img>
<app-ch-carousel #player [item]="item" *ngIf="item.code === 'app-ch-carousel'">
</app-ch-carousel>
<app-ch-info-card #player [item]="item" *ngIf="item.code === 'app-ch-info-card'">
</app-ch-info-card>
<app-ch-tour-card #player [item]="item" *ngIf="item.code === 'app-ch-tour-card'">
</app-ch-tour-card>
<app-ch-tailormade-form #player [item]="item" *ngIf="item.code === 'app-ch-tailormade-form'">
</app-ch-tailormade-form>
<app-ch-tour-form #player [item]="item" *ngIf="item.code === 'app-ch-tour-form'">
</app-ch-tour-form>
<div class="preview-holder" *cdkDragPreview>我只是一个无情的占位符</div>
<div class="custom-placeholder" *cdkDragPlaceholder></div>
</div>
<span class="col-uid">{{ colItem.id }}</span>
</div>
</div>
</div>
<nz-dropdown-menu #menu="nzDropdownMenu">
<ul nz-menu class="grid-context-ment">
<li nz-menu-item>栅格布局 <i nz-icon nzType="question-circle" nzTheme="twotone"></i></li>
<li nz-menu-divider></li>
<li nz-submenu nzTitle="快速分格">
<ul>
<li nz-menu-item (click)="split(2)">两列布局</li>
<li nz-menu-item (click)="split(3)">三列布局</li>
<li nz-menu-item (click)="split(4)">四列布局</li>
</ul>
</li>
<li nz-menu-item (click)="copy()">复制整行</li>
<li nz-menu-item (click)="delete()">删除整行</li>
</ul>
</nz-dropdown-menu>
./ch-grid.component.less
.col-wrapper {
min-height: 128px;
box-shadow: 0 0 1px brown;
position: relative;
.col-uid {
position: absolute;
right: -24px;
top: 0;
padding: 4px;
background: #000;
opacity: 0.3;
color: #fff;
font-size: 0.9rem;
width: 24px;
writing-mode: vertical-lr;
line-height: normal;
border-radius: 0 4px 4px 0;
cursor: default;
display: none;
}
}
.light {
border: 1px solid lightgreen;
}
/* 拖放动画 */
.cdk-drag-preview {
box-sizing: border-box;
border-radius: 4px;
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14),
0 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.cdk-drag-placeholder {
opacity: 0;
}
.cdk-drag-animating {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
.col-wrapper.cdk-drop-list-dragging .playground-item:not(.cdk-drag-placeholder) {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
.cdk-drop-list-dragging {
background: #f1f1f1;
.col-uid {
background: darkgreen;
}
}
.preview-holder.cdk-drag-preview {
height: 48px;
line-height: 48px;
padding: 0 12px;
border: 1px solid #333;
background: #fff;
}
.custom-placeholder {
background: #ccc;
border: dotted 3px #999;
height: 48px;
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
opacity: 1;
}
.preview-holder.cdk-drag-preview {
height: 48px;
line-height: 48px;
padding: 0 12px;
border: 1px solid #333;
background: #fff;
}
.custom-placeholder {
background: #ccc;
border: dotted 3px #999;
height: 48px;
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
opacity: 1;
}