|
|
@@ -0,0 +1,70 @@
|
|
|
+import { CommonModule } from '@angular/common';
|
|
|
+import { ChangeDetectionStrategy, Component, computed, signal } from '@angular/core';
|
|
|
+import { FormsModule } from '@angular/forms';
|
|
|
+import { Check, Clipboard, LayoutTemplate, LucideAngularModule } from 'lucide-angular';
|
|
|
+
|
|
|
+interface GridDevice {
|
|
|
+ name: string;
|
|
|
+ value: string;
|
|
|
+ checked: boolean;
|
|
|
+ columns: string;
|
|
|
+}
|
|
|
+
|
|
|
+@Component({
|
|
|
+ selector: 'app-admin-boot-layout',
|
|
|
+ standalone: true,
|
|
|
+ imports: [CommonModule, FormsModule, LucideAngularModule],
|
|
|
+ templateUrl: './admin-boot-layout.component.html',
|
|
|
+ styleUrl: './admin-boot-layout.component.scss',
|
|
|
+ changeDetection: ChangeDetectionStrategy.OnPush,
|
|
|
+})
|
|
|
+export class AdminBootLayoutComponent {
|
|
|
+ readonly icons = { Check, Clipboard, LayoutTemplate };
|
|
|
+ readonly columnCounts = [2, 3, 4, 5, 6, 7, 8];
|
|
|
+ readonly presets = ['4*4*4', '0*0*0*0', '3*3*6', '6*6', '2*10', '10*2'];
|
|
|
+ readonly frames = [
|
|
|
+ { name: '.container 标准居中', value: 'container' },
|
|
|
+ { name: '.container-fluid 全屏 100%', value: 'container-fluid' },
|
|
|
+ ];
|
|
|
+ readonly frame = signal('container');
|
|
|
+ readonly columnCount = signal(2);
|
|
|
+ readonly devices = signal<GridDevice[]>([
|
|
|
+ { name: '自适应', value: 'col', checked: true, columns: '4*4*4' },
|
|
|
+ { name: '平板 PAD', value: 'col-sm', checked: false, columns: '4*4*4' },
|
|
|
+ { name: '窄屏设备', value: 'col-md', checked: false, columns: '4*4*4' },
|
|
|
+ { name: '传统电脑', value: 'col-lg', checked: false, columns: '4*4*4' },
|
|
|
+ { name: '高清屏幕', value: 'col-xl', checked: false, columns: '4*4*4' },
|
|
|
+ ]);
|
|
|
+ readonly copied = signal(false);
|
|
|
+
|
|
|
+ readonly columnClasses = computed(() => {
|
|
|
+ const classes = Array.from({ length: this.columnCount() }, () => [] as string[]);
|
|
|
+ for (const device of this.devices().filter((item) => item.checked)) {
|
|
|
+ const values = device.columns.split('*');
|
|
|
+ for (let index = 0; index < values.length && index < classes.length; index += 1) {
|
|
|
+ const value = Number.parseInt(values[index] || '0', 10);
|
|
|
+ classes[index].push(value === 0 ? device.value : `${device.value}-${value}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return classes.map((items) => items.join(' ').trim());
|
|
|
+ });
|
|
|
+
|
|
|
+ readonly html = computed(() => {
|
|
|
+ const rows = this.columnClasses().map((className) => ` <div class="${className}"></div>`).join('\n');
|
|
|
+ return `<div class="${this.frame()}">\n <div class="row">\n${rows}\n </div>\n</div>`;
|
|
|
+ });
|
|
|
+
|
|
|
+ updateDevice(index: number, patch: Partial<GridDevice>): void {
|
|
|
+ this.devices.update((items) => items.map((item, itemIndex) => itemIndex === index ? { ...item, ...patch } : item));
|
|
|
+ }
|
|
|
+
|
|
|
+ setPreset(index: number, columns: string): void {
|
|
|
+ this.updateDevice(index, { columns });
|
|
|
+ }
|
|
|
+
|
|
|
+ async copyHtml(): Promise<void> {
|
|
|
+ await navigator.clipboard.writeText(this.html());
|
|
|
+ this.copied.set(true);
|
|
|
+ globalThis.setTimeout(() => this.copied.set(false), 1500);
|
|
|
+ }
|
|
|
+}
|