项目初始化
This commit is contained in:
@ -0,0 +1,83 @@
|
||||
<nz-drawer [(nzVisible)]="collapse" [nzPlacement]="dir === 'rtl' ? 'left' : 'right'" [nzWidth]="300"
|
||||
(nzOnClose)="toggle()">
|
||||
<div *nzDrawerContent class="setting-drawer__content">
|
||||
<div class="setting-drawer__body">
|
||||
<h3 class="setting-drawer__title">整体风格设置</h3>
|
||||
<div class="setting-drawer__blockChecbox">
|
||||
<div *ngFor="let t of themes" class="setting-drawer__blockChecbox-item" (click)="setLayout('theme', t.key)"
|
||||
[nz-tooltip]="t.title">
|
||||
<img src="{{ t.img }}" alt="{{ t.key }}" />
|
||||
<div *ngIf="layout.theme === t.key" class="setting-drawer__blockChecbox-selectIcon">
|
||||
<i nz-icon nzType="check"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-drawer__body setting-drawer__theme">
|
||||
<h3 class="setting-drawer__title">主题色</h3>
|
||||
<span *ngFor="let c of colors" (click)="changeColor(c.color)" nz-tooltip="c.key" class="setting-drawer__theme-tag"
|
||||
[ngStyle]="{ 'background-color': c.color }">
|
||||
<i *ngIf="color === c.color" nz-icon nzType="check"></i>
|
||||
</span>
|
||||
</div>
|
||||
<nz-divider></nz-divider>
|
||||
<div class="setting-drawer__body">
|
||||
<h3 class="setting-drawer__title">导航模式</h3>
|
||||
<div class="setting-drawer__blockChecbox">
|
||||
<div *ngFor="let t of menuModes" class="setting-drawer__blockChecbox-item" (click)="setLayout('menu', t.key)"
|
||||
nz-tooltip="{{ t.title }}">
|
||||
<img src="{{ t.img }}" alt="{{ t.key }}" />
|
||||
<div *ngIf="layout.menu === t.key" class="setting-drawer__blockChecbox-selectIcon">
|
||||
<i nz-icon nzType="check"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-drawer__body-item">
|
||||
内容区域宽度
|
||||
<nz-select [(ngModel)]="layout.contentWidth" (ngModelChange)="setLayout('contentWidth', layout.contentWidth)"
|
||||
nzSize="small">
|
||||
<nz-option *ngFor="let i of contentWidths" [nzLabel]="i.title" [nzValue]="i.key" [nzDisabled]="i.disabled">
|
||||
</nz-option>
|
||||
</nz-select>
|
||||
</div>
|
||||
<div class="setting-drawer__body-item">
|
||||
固定 Header
|
||||
<nz-switch nzSize="small" [(ngModel)]="layout.fixedHeader"
|
||||
(ngModelChange)="setLayout('fixedHeader', layout.fixedHeader)"></nz-switch>
|
||||
</div>
|
||||
<div class="setting-drawer__body-item" nz-tooltip="{{ !brand.fixedHeader ? '固定 Header 时可配置' : '' }}"
|
||||
nzTooltipPlacement="left">
|
||||
<span [style.opacity]="!brand.fixedHeader ? 0.5 : 1">下滑时隐藏 Header</span>
|
||||
<nz-switch [nzDisabled]="!brand.fixedHeader" nzSize="small" [(ngModel)]="layout.autoHideHeader"
|
||||
(ngModelChange)="setLayout('autoHideHeader', layout.autoHideHeader)"></nz-switch>
|
||||
</div>
|
||||
<div class="setting-drawer__body-item" nz-tooltip="{{ brand.menu === 'top' ? '侧边菜单布局时可配置' : '' }}"
|
||||
nzTooltipPlacement="left">
|
||||
<span [style.opacity]="brand.menu === 'top' ? 0.5 : 1">固定侧边菜单</span>
|
||||
<nz-switch [nzDisabled]="brand.menu === 'top'" nzSize="small" [(ngModel)]="layout.fixSiderbar"
|
||||
(ngModelChange)="setLayout('fixSiderbar', layout.fixSiderbar)"></nz-switch>
|
||||
</div>
|
||||
<div class="setting-drawer__body-item" nz-tooltip="{{ brand.menu === 'top' ? '' : '顶部菜单布局时可配置' }}"
|
||||
nzTooltipPlacement="left">
|
||||
<span [style.opacity]="brand.menu !== 'top' ? 0.5 : 1">只显示图标</span>
|
||||
<nz-switch [nzDisabled]="brand.menu !== 'top'" nzSize="small" [(ngModel)]="layout.onlyIcon"
|
||||
(ngModelChange)="setLayout('onlyIcon', layout.onlyIcon)"></nz-switch>
|
||||
</div>
|
||||
</div>
|
||||
<nz-divider></nz-divider>
|
||||
<div class="setting-drawer__body">
|
||||
<h3 class="setting-drawer__title">其他设置</h3>
|
||||
<div class="setting-drawer__body-item">
|
||||
色弱模式
|
||||
<nz-switch nzSize="small" [(ngModel)]="layout.colorWeak"
|
||||
(ngModelChange)="setLayout('colorWeak', layout.colorWeak)"></nz-switch>
|
||||
</div>
|
||||
</div>
|
||||
<nz-divider></nz-divider>
|
||||
<button (click)="copy()" type="button" nz-button nzBlock>拷贝设置</button>
|
||||
<nz-alert class="mt-md" nzType="warning" nzMessage="配置栏只在开发环境用于预览,生产环境不会展现,请拷贝后手动修改配置文件"></nz-alert>
|
||||
</div>
|
||||
</nz-drawer>
|
||||
<div class="setting-drawer__handle" [ngClass]="{ 'setting-drawer__handle-opened': collapse }" (click)="toggle()">
|
||||
<i nz-icon [nzType]="!collapse ? 'setting' : 'close'" class="setting-drawer__handle-icon"></i>
|
||||
</div>
|
||||
240
src/app/layout/pro/setting-drawer/setting-drawer.component.ts
Normal file
240
src/app/layout/pro/setting-drawer/setting-drawer.component.ts
Normal file
@ -0,0 +1,240 @@
|
||||
import { Direction, Directionality } from '@angular/cdk/bidi';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, NgZone, OnDestroy, OnInit, Optional } from '@angular/core';
|
||||
import { copy, LazyService } from '@delon/util';
|
||||
import { NzMessageService } from 'ng-zorro-antd/message';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
import { BrandService } from '../pro.service';
|
||||
import { ProLayout } from '../pro.types';
|
||||
|
||||
@Component({
|
||||
selector: 'pro-setting-drawer',
|
||||
templateUrl: './setting-drawer.component.html',
|
||||
preserveWhitespaces: false,
|
||||
host: {
|
||||
'[class.setting-drawer]': 'true',
|
||||
'[class.setting-drawer-rtl]': `dir === 'rtl'`
|
||||
},
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ProSettingDrawerComponent implements OnInit, OnDestroy {
|
||||
private loadedLess = false;
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
get layout(): ProLayout {
|
||||
return this.brand.layout;
|
||||
}
|
||||
|
||||
collapse = false;
|
||||
dir: Direction = 'ltr';
|
||||
|
||||
themes = [
|
||||
{
|
||||
key: 'dark',
|
||||
title: '暗色菜单风格',
|
||||
img: 'https://gw.alipayobjects.com/zos/rmsportal/LCkqqYNmvBEbokSDscrm.svg'
|
||||
},
|
||||
{
|
||||
key: 'light',
|
||||
title: '亮色菜单风格',
|
||||
img: 'https://gw.alipayobjects.com/zos/rmsportal/jpRkZQMyYRryryPNtyIC.svg'
|
||||
}
|
||||
];
|
||||
|
||||
color = '#2F54EB';
|
||||
colors = [
|
||||
{
|
||||
key: '薄暮',
|
||||
color: '#F5222D'
|
||||
},
|
||||
{
|
||||
key: '火山',
|
||||
color: '#FA541C'
|
||||
},
|
||||
{
|
||||
key: '日暮',
|
||||
color: '#FAAD14'
|
||||
},
|
||||
{
|
||||
key: '明青',
|
||||
color: '#13C2C2'
|
||||
},
|
||||
{
|
||||
key: '极光绿',
|
||||
color: '#52C41A'
|
||||
},
|
||||
{
|
||||
key: '拂晓蓝(默认)',
|
||||
color: '#1890ff'
|
||||
},
|
||||
{
|
||||
key: '极客蓝',
|
||||
color: '#2F54EB'
|
||||
},
|
||||
{
|
||||
key: '酱紫',
|
||||
color: '#722ED1'
|
||||
}
|
||||
];
|
||||
|
||||
menuModes = [
|
||||
{
|
||||
key: 'side',
|
||||
title: '侧边菜单布局',
|
||||
img: 'https://gw.alipayobjects.com/zos/rmsportal/JopDzEhOqwOjeNTXkoje.svg'
|
||||
},
|
||||
{
|
||||
key: 'top',
|
||||
title: '顶部菜单布局',
|
||||
img: 'https://gw.alipayobjects.com/zos/rmsportal/KDNDBbriJhLwuqMoxcAr.svg'
|
||||
}
|
||||
];
|
||||
|
||||
contentWidths = [
|
||||
{
|
||||
key: 'fixed',
|
||||
title: '定宽',
|
||||
disabled: false
|
||||
},
|
||||
{
|
||||
key: 'fluid',
|
||||
title: '流式',
|
||||
disabled: false
|
||||
}
|
||||
];
|
||||
|
||||
constructor(
|
||||
public brand: BrandService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
private msg: NzMessageService,
|
||||
private lazy: LazyService,
|
||||
private zone: NgZone,
|
||||
@Inject(DOCUMENT) private doc: any,
|
||||
@Optional() private directionality: Directionality
|
||||
) {
|
||||
this.setLayout('menu', this.brand.menu, false);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.dir = this.directionality.value;
|
||||
this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => {
|
||||
this.dir = direction;
|
||||
this.cdr.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
private loadLess(): Promise<void> {
|
||||
if (this.loadedLess) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return this.lazy
|
||||
.loadStyle('./assets/color.less', 'stylesheet/less')
|
||||
.then(() => {
|
||||
const lessConfigNode = this.doc.createElement('script');
|
||||
lessConfigNode.innerHTML = `
|
||||
window.less = {
|
||||
async: true,
|
||||
env: 'production',
|
||||
javascriptEnabled: true
|
||||
};
|
||||
`;
|
||||
this.doc.body.appendChild(lessConfigNode);
|
||||
})
|
||||
.then(() => this.lazy.loadScript('https://gw.alipayobjects.com/os/lib/less.js/3.8.1/less.min.js'))
|
||||
.then(() => {
|
||||
this.loadedLess = true;
|
||||
});
|
||||
}
|
||||
|
||||
private runLess(): void {
|
||||
const { color, zone, msg, cdr: cd } = this;
|
||||
const msgId = msg.loading(`正在编译主题!`, { nzDuration: 0 }).messageId;
|
||||
setTimeout(() => {
|
||||
zone.runOutsideAngular(() => {
|
||||
this.loadLess().then(() => {
|
||||
(window as any).less
|
||||
.modifyVars({
|
||||
[`@primary-color`]: color
|
||||
})
|
||||
.then(() => {
|
||||
msg.success('成功');
|
||||
msg.remove(msgId);
|
||||
zone.run(() => cd.detectChanges());
|
||||
});
|
||||
});
|
||||
});
|
||||
}, 200);
|
||||
}
|
||||
|
||||
toggle(): void {
|
||||
this.collapse = !this.collapse;
|
||||
}
|
||||
|
||||
changeColor(color: string): void {
|
||||
this.color = color;
|
||||
this.runLess();
|
||||
}
|
||||
|
||||
setLayout(name: string, value: any, cd: boolean = true): void {
|
||||
switch (name) {
|
||||
case 'menu':
|
||||
const isTop = value === 'top';
|
||||
this.contentWidths.find(w => w.key === 'fixed')!.disabled = !isTop;
|
||||
const newLayout = {
|
||||
...this.brand.layout,
|
||||
contentWidth: isTop ? 'fixed' : 'fluid',
|
||||
onlyIcon: isTop,
|
||||
collapsed: isTop && !this.brand.isMobile ? false : this.brand.layout.collapsed
|
||||
};
|
||||
this.brand.setLayout(newLayout);
|
||||
break;
|
||||
case 'fixedHeader':
|
||||
this.brand.setLayout('autoHideHeader', false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this.brand.setLayout(name, value);
|
||||
if (cd) {
|
||||
setTimeout(() => {
|
||||
// Re-render G2 muse be trigger window resize
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
this.cdr.markForCheck();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
copy(): void {
|
||||
const { color, layout } = this;
|
||||
const vars: { [key: string]: string } = {
|
||||
[`@primary-color`]: color
|
||||
};
|
||||
const colorVars = Object.keys(vars)
|
||||
.map(key => `${key}: ${vars[key]};`)
|
||||
.join('\n');
|
||||
const layoutVars = Object.keys(layout)
|
||||
.filter(
|
||||
key => ~['theme', 'menu', 'contentWidth', 'fixedHeader', 'autoHideHeader', 'fixSiderbar', 'colorWeak', 'onlyIcon'].indexOf(key)
|
||||
)
|
||||
.map(key => {
|
||||
const value = layout[key];
|
||||
if (typeof value === 'boolean') {
|
||||
return ` ${key}: ${value},`;
|
||||
} else {
|
||||
return ` ${key}: '${value}',`;
|
||||
}
|
||||
})
|
||||
.join('\n');
|
||||
copy(
|
||||
`在 [src/styles/theme.less] 配置以下:\n{{colorVars}}\n\n在 [src/environments/*] 的 pro 配置以下:\nexport const environment = {\n ...\n pro: {\n{{layoutVars}}\n }\n}`
|
||||
);
|
||||
this.msg.success(`拷贝成功,请根据剪切板内容进行替换`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user