admin-boot-layout.component.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import { CommonModule } from '@angular/common';
  2. import { ChangeDetectionStrategy, Component, computed, signal } from '@angular/core';
  3. import { FormsModule } from '@angular/forms';
  4. import { Check, Clipboard, LayoutTemplate, LucideAngularModule } from 'lucide-angular';
  5. interface GridDevice {
  6. name: string;
  7. value: string;
  8. checked: boolean;
  9. columns: string;
  10. }
  11. @Component({
  12. selector: 'app-admin-boot-layout',
  13. standalone: true,
  14. imports: [CommonModule, FormsModule, LucideAngularModule],
  15. templateUrl: './admin-boot-layout.component.html',
  16. styleUrl: './admin-boot-layout.component.scss',
  17. changeDetection: ChangeDetectionStrategy.OnPush,
  18. })
  19. export class AdminBootLayoutComponent {
  20. readonly icons = { Check, Clipboard, LayoutTemplate };
  21. readonly columnCounts = [2, 3, 4, 5, 6, 7, 8];
  22. readonly presets = ['4*4*4', '0*0*0*0', '3*3*6', '6*6', '2*10', '10*2'];
  23. readonly frames = [
  24. { name: '.container 标准居中', value: 'container' },
  25. { name: '.container-fluid 全屏 100%', value: 'container-fluid' },
  26. ];
  27. readonly frame = signal('container');
  28. readonly columnCount = signal(2);
  29. readonly devices = signal<GridDevice[]>([
  30. { name: '自适应', value: 'col', checked: true, columns: '4*4*4' },
  31. { name: '平板 PAD', value: 'col-sm', checked: false, columns: '4*4*4' },
  32. { name: '窄屏设备', value: 'col-md', checked: false, columns: '4*4*4' },
  33. { name: '传统电脑', value: 'col-lg', checked: false, columns: '4*4*4' },
  34. { name: '高清屏幕', value: 'col-xl', checked: false, columns: '4*4*4' },
  35. ]);
  36. readonly copied = signal(false);
  37. readonly columnClasses = computed(() => {
  38. const classes = Array.from({ length: this.columnCount() }, () => [] as string[]);
  39. for (const device of this.devices().filter((item) => item.checked)) {
  40. const values = device.columns.split('*');
  41. for (let index = 0; index < values.length && index < classes.length; index += 1) {
  42. const value = Number.parseInt(values[index] || '0', 10);
  43. classes[index].push(value === 0 ? device.value : `${device.value}-${value}`);
  44. }
  45. }
  46. return classes.map((items) => items.join(' ').trim());
  47. });
  48. readonly html = computed(() => {
  49. const rows = this.columnClasses().map((className) => ` <div class="${className}"></div>`).join('\n');
  50. return `<div class="${this.frame()}">\n <div class="row">\n${rows}\n </div>\n</div>`;
  51. });
  52. updateDevice(index: number, patch: Partial<GridDevice>): void {
  53. this.devices.update((items) => items.map((item, itemIndex) => itemIndex === index ? { ...item, ...patch } : item));
  54. }
  55. setPreset(index: number, columns: string): void {
  56. this.updateDevice(index, { columns });
  57. }
  58. async copyHtml(): Promise<void> {
  59. await navigator.clipboard.writeText(this.html());
  60. this.copied.set(true);
  61. globalThis.setTimeout(() => this.copied.set(false), 1500);
  62. }
  63. }