ai-text-summary-ng 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +118 -0
  2. package/ai-text-summary-ng-1.0.0.tgz +0 -0
  3. package/app/app.component.d.ts +38 -0
  4. package/app/components/fmode-avatar/fmode-avatar.component.d.ts +16 -0
  5. package/app/components/fmode-badge/fmode-badge.component.d.ts +8 -0
  6. package/app/components/fmode-button/fmode-button.component.d.ts +10 -0
  7. package/app/components/fmode-card/fmode-card.component.d.ts +6 -0
  8. package/app/components/fmode-digital-human/fmode-digital-human.component.d.ts +10 -0
  9. package/app/components/fmode-divider/fmode-divider.component.d.ts +7 -0
  10. package/app/components/fmode-header/fmode-header.component.d.ts +7 -0
  11. package/app/components/fmode-list/fmode-list.component.d.ts +9 -0
  12. package/app/components/fmode-loading/fmode-loading.component.d.ts +6 -0
  13. package/app/components/fmode-select/fmode-select.component.d.ts +17 -0
  14. package/app/components/fmode-tag/fmode-tag.component.d.ts +9 -0
  15. package/app/components/fmode-textarea/fmode-textarea.component.d.ts +15 -0
  16. package/esm2022/ai-text-summary-ng.mjs +5 -0
  17. package/esm2022/app/app.component.mjs +533 -0
  18. package/esm2022/app/components/fmode-avatar/fmode-avatar.component.mjs +83 -0
  19. package/esm2022/app/components/fmode-badge/fmode-badge.component.mjs +49 -0
  20. package/esm2022/app/components/fmode-button/fmode-button.component.mjs +52 -0
  21. package/esm2022/app/components/fmode-card/fmode-card.component.mjs +34 -0
  22. package/esm2022/app/components/fmode-digital-human/fmode-digital-human.component.mjs +119 -0
  23. package/esm2022/app/components/fmode-divider/fmode-divider.component.mjs +35 -0
  24. package/esm2022/app/components/fmode-header/fmode-header.component.mjs +33 -0
  25. package/esm2022/app/components/fmode-list/fmode-list.component.mjs +50 -0
  26. package/esm2022/app/components/fmode-loading/fmode-loading.component.mjs +25 -0
  27. package/esm2022/app/components/fmode-select/fmode-select.component.mjs +62 -0
  28. package/esm2022/app/components/fmode-tag/fmode-tag.component.mjs +54 -0
  29. package/esm2022/app/components/fmode-textarea/fmode-textarea.component.mjs +75 -0
  30. package/esm2022/public-api.mjs +15 -0
  31. package/fesm2022/ai-text-summary-ng.mjs +1155 -0
  32. package/fesm2022/ai-text-summary-ng.mjs.map +1 -0
  33. package/index.d.ts +5 -0
  34. package/package.json +42 -0
  35. package/public-api.d.ts +13 -0
@@ -0,0 +1,1155 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Input, Component, EventEmitter, Output } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as i2 from '@angular/forms';
6
+ import { FormsModule } from '@angular/forms';
7
+
8
+ class FmodeHeaderComponent {
9
+ title = '';
10
+ subtitle = '';
11
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmodeHeaderComponent, isStandalone: true, selector: "fmode-header", inputs: { title: "title", subtitle: "subtitle" }, ngImport: i0, template: `
13
+ <header class="fmode-header">
14
+ <div class="header-content">
15
+ <h1 class="header-title">{{ title }}</h1>
16
+ <p class="header-subtitle" *ngIf="subtitle">{{ subtitle }}</p>
17
+ </div>
18
+ </header>
19
+ `, isInline: true, styles: [".fmode-header{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;padding:1.5rem 2rem;box-shadow:0 4px 12px #0000001a}.header-content{max-width:1400px;margin:0 auto}.header-title{margin:0;font-size:1.75rem;font-weight:700;letter-spacing:.5px}.header-subtitle{margin:.5rem 0 0;font-size:1rem;opacity:.9}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
20
+ }
21
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeHeaderComponent, decorators: [{
22
+ type: Component,
23
+ args: [{ selector: 'fmode-header', standalone: true, imports: [CommonModule], template: `
24
+ <header class="fmode-header">
25
+ <div class="header-content">
26
+ <h1 class="header-title">{{ title }}</h1>
27
+ <p class="header-subtitle" *ngIf="subtitle">{{ subtitle }}</p>
28
+ </div>
29
+ </header>
30
+ `, styles: [".fmode-header{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;padding:1.5rem 2rem;box-shadow:0 4px 12px #0000001a}.header-content{max-width:1400px;margin:0 auto}.header-title{margin:0;font-size:1.75rem;font-weight:700;letter-spacing:.5px}.header-subtitle{margin:.5rem 0 0;font-size:1rem;opacity:.9}\n"] }]
31
+ }], propDecorators: { title: [{
32
+ type: Input
33
+ }], subtitle: [{
34
+ type: Input
35
+ }] } });
36
+
37
+ class FmodeCardComponent {
38
+ title = '';
39
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
40
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmodeCardComponent, isStandalone: true, selector: "fmode-card", inputs: { title: "title" }, ngImport: i0, template: `
41
+ <div class="fmode-card">
42
+ <div class="card-header" *ngIf="title">
43
+ <h2 class="card-title">{{ title }}</h2>
44
+ </div>
45
+ <div class="card-body">
46
+ <ng-content></ng-content>
47
+ </div>
48
+ </div>
49
+ `, isInline: true, styles: [".fmode-card{background:#fff;border-radius:12px;box-shadow:0 4px 16px #00000014;overflow:hidden;transition:transform .3s,box-shadow .3s}.fmode-card:hover{transform:translateY(-2px);box-shadow:0 8px 24px #0000001f}.card-header{background:linear-gradient(135deg,#f8f9fa,#e9ecef);padding:1rem 1.5rem;border-bottom:2px solid #dee2e6}.card-title{margin:0;font-size:1.1rem;font-weight:600;color:#495057}.card-body{padding:1.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
50
+ }
51
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeCardComponent, decorators: [{
52
+ type: Component,
53
+ args: [{ selector: 'fmode-card', standalone: true, imports: [CommonModule], template: `
54
+ <div class="fmode-card">
55
+ <div class="card-header" *ngIf="title">
56
+ <h2 class="card-title">{{ title }}</h2>
57
+ </div>
58
+ <div class="card-body">
59
+ <ng-content></ng-content>
60
+ </div>
61
+ </div>
62
+ `, styles: [".fmode-card{background:#fff;border-radius:12px;box-shadow:0 4px 16px #00000014;overflow:hidden;transition:transform .3s,box-shadow .3s}.fmode-card:hover{transform:translateY(-2px);box-shadow:0 8px 24px #0000001f}.card-header{background:linear-gradient(135deg,#f8f9fa,#e9ecef);padding:1rem 1.5rem;border-bottom:2px solid #dee2e6}.card-title{margin:0;font-size:1.1rem;font-weight:600;color:#495057}.card-body{padding:1.5rem}\n"] }]
63
+ }], propDecorators: { title: [{
64
+ type: Input
65
+ }] } });
66
+
67
+ class FmodeTextareaComponent {
68
+ value = '';
69
+ valueChange = new EventEmitter();
70
+ placeholder = '';
71
+ label = '';
72
+ rows = 4;
73
+ disabled = false;
74
+ maxLength = 10000;
75
+ showCharCount = true;
76
+ onInputChange(event) {
77
+ const newValue = event.target.value;
78
+ console.log('Textarea onInputChange - newValue:', newValue);
79
+ this.valueChange.emit(newValue);
80
+ }
81
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeTextareaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
82
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmodeTextareaComponent, isStandalone: true, selector: "fmode-textarea", inputs: { value: "value", placeholder: "placeholder", label: "label", rows: "rows", disabled: "disabled", maxLength: "maxLength", showCharCount: "showCharCount" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `
83
+ <div class="fmode-textarea-wrapper">
84
+ <label *ngIf="label" class="textarea-label">{{ label }}</label>
85
+ <textarea
86
+ [value]="value"
87
+ (input)="onInputChange($event)"
88
+ [placeholder]="placeholder"
89
+ [rows]="rows"
90
+ [disabled]="disabled"
91
+ [maxLength]="maxLength"
92
+ class="fmode-textarea"
93
+ ></textarea>
94
+ <div class="textarea-footer" *ngIf="showCharCount">
95
+ <span class="char-count">{{ value?.length || 0 }}/{{ maxLength }}</span>
96
+ </div>
97
+ </div>
98
+ `, isInline: true, styles: [".fmode-textarea-wrapper{display:flex;flex-direction:column;gap:.5rem}.textarea-label{font-weight:600;color:#495057;font-size:.9rem}.fmode-textarea{width:100%;padding:1rem;border:2px solid #dee2e6;border-radius:8px;font-size:1rem;font-family:inherit;line-height:1.6;resize:vertical;transition:border-color .3s,box-shadow .3s;box-sizing:border-box}.fmode-textarea:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 3px #667eea1a}.fmode-textarea:disabled{background:#f8f9fa;cursor:not-allowed;opacity:.7}.textarea-footer{display:flex;justify-content:flex-end;align-items:center}.char-count{font-size:.85rem;color:#6c757d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }] });
99
+ }
100
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeTextareaComponent, decorators: [{
101
+ type: Component,
102
+ args: [{ selector: 'fmode-textarea', standalone: true, imports: [CommonModule, FormsModule], template: `
103
+ <div class="fmode-textarea-wrapper">
104
+ <label *ngIf="label" class="textarea-label">{{ label }}</label>
105
+ <textarea
106
+ [value]="value"
107
+ (input)="onInputChange($event)"
108
+ [placeholder]="placeholder"
109
+ [rows]="rows"
110
+ [disabled]="disabled"
111
+ [maxLength]="maxLength"
112
+ class="fmode-textarea"
113
+ ></textarea>
114
+ <div class="textarea-footer" *ngIf="showCharCount">
115
+ <span class="char-count">{{ value?.length || 0 }}/{{ maxLength }}</span>
116
+ </div>
117
+ </div>
118
+ `, styles: [".fmode-textarea-wrapper{display:flex;flex-direction:column;gap:.5rem}.textarea-label{font-weight:600;color:#495057;font-size:.9rem}.fmode-textarea{width:100%;padding:1rem;border:2px solid #dee2e6;border-radius:8px;font-size:1rem;font-family:inherit;line-height:1.6;resize:vertical;transition:border-color .3s,box-shadow .3s;box-sizing:border-box}.fmode-textarea:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 3px #667eea1a}.fmode-textarea:disabled{background:#f8f9fa;cursor:not-allowed;opacity:.7}.textarea-footer{display:flex;justify-content:flex-end;align-items:center}.char-count{font-size:.85rem;color:#6c757d}\n"] }]
119
+ }], propDecorators: { value: [{
120
+ type: Input
121
+ }], valueChange: [{
122
+ type: Output
123
+ }], placeholder: [{
124
+ type: Input
125
+ }], label: [{
126
+ type: Input
127
+ }], rows: [{
128
+ type: Input
129
+ }], disabled: [{
130
+ type: Input
131
+ }], maxLength: [{
132
+ type: Input
133
+ }], showCharCount: [{
134
+ type: Input
135
+ }] } });
136
+
137
+ class FmodeSelectComponent {
138
+ value = '';
139
+ valueChange = new EventEmitter();
140
+ label = '';
141
+ disabled = false;
142
+ options = [];
143
+ onSelectChange(event) {
144
+ const newValue = event.target.value;
145
+ this.valueChange.emit(newValue);
146
+ }
147
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
148
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmodeSelectComponent, isStandalone: true, selector: "fmode-select", inputs: { value: "value", label: "label", disabled: "disabled", options: "options" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `
149
+ <div class="fmode-select-wrapper">
150
+ <label *ngIf="label" class="select-label">{{ label }}</label>
151
+ <select
152
+ [value]="value"
153
+ (change)="onSelectChange($event)"
154
+ [disabled]="disabled"
155
+ class="fmode-select"
156
+ >
157
+ <option *ngFor="let option of options" [value]="option.value">
158
+ {{ option.label }}
159
+ </option>
160
+ </select>
161
+ </div>
162
+ `, isInline: true, styles: [".fmode-select-wrapper{display:flex;flex-direction:column;gap:.5rem}.select-label{font-weight:600;color:#495057;font-size:.9rem}.fmode-select{width:100%;padding:.75rem 1rem;border:2px solid #dee2e6;border-radius:8px;font-size:1rem;font-family:inherit;background:#fff;cursor:pointer;transition:border-color .3s,box-shadow .3s;box-sizing:border-box}.fmode-select:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 3px #667eea1a}.fmode-select:disabled{background:#f8f9fa;cursor:not-allowed;opacity:.7}.fmode-select option{padding:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }] });
163
+ }
164
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeSelectComponent, decorators: [{
165
+ type: Component,
166
+ args: [{ selector: 'fmode-select', standalone: true, imports: [CommonModule, FormsModule], template: `
167
+ <div class="fmode-select-wrapper">
168
+ <label *ngIf="label" class="select-label">{{ label }}</label>
169
+ <select
170
+ [value]="value"
171
+ (change)="onSelectChange($event)"
172
+ [disabled]="disabled"
173
+ class="fmode-select"
174
+ >
175
+ <option *ngFor="let option of options" [value]="option.value">
176
+ {{ option.label }}
177
+ </option>
178
+ </select>
179
+ </div>
180
+ `, styles: [".fmode-select-wrapper{display:flex;flex-direction:column;gap:.5rem}.select-label{font-weight:600;color:#495057;font-size:.9rem}.fmode-select{width:100%;padding:.75rem 1rem;border:2px solid #dee2e6;border-radius:8px;font-size:1rem;font-family:inherit;background:#fff;cursor:pointer;transition:border-color .3s,box-shadow .3s;box-sizing:border-box}.fmode-select:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 3px #667eea1a}.fmode-select:disabled{background:#f8f9fa;cursor:not-allowed;opacity:.7}.fmode-select option{padding:.5rem}\n"] }]
181
+ }], propDecorators: { value: [{
182
+ type: Input
183
+ }], valueChange: [{
184
+ type: Output
185
+ }], label: [{
186
+ type: Input
187
+ }], disabled: [{
188
+ type: Input
189
+ }], options: [{
190
+ type: Input
191
+ }] } });
192
+
193
+ class FmodeButtonComponent {
194
+ disabled = false;
195
+ type = 'primary';
196
+ size = 'medium';
197
+ onClick = new EventEmitter();
198
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
199
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmodeButtonComponent, isStandalone: true, selector: "fmode-button", inputs: { disabled: "disabled", type: "type", size: "size" }, outputs: { onClick: "onClick" }, ngImport: i0, template: `
200
+ <button
201
+ [disabled]="disabled"
202
+ [class.primary]="type === 'primary'"
203
+ [class.secondary]="type === 'secondary'"
204
+ [class.success]="type === 'success'"
205
+ [class.danger]="type === 'danger'"
206
+ [class.small]="size === 'small'"
207
+ [class.large]="size === 'large'"
208
+ (click)="onClick.emit()"
209
+ class="fmode-button"
210
+ >
211
+ <ng-content></ng-content>
212
+ </button>
213
+ `, isInline: true, styles: [".fmode-button{padding:.75rem 1.5rem;border:none;border-radius:8px;font-size:1rem;font-weight:600;cursor:pointer;transition:all .3s;font-family:inherit;box-sizing:border-box}.fmode-button:disabled{opacity:.5;cursor:not-allowed}.fmode-button.primary{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff}.fmode-button.primary:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 4px 12px #667eea66}.fmode-button.secondary{background:#6c757d;color:#fff}.fmode-button.secondary:hover:not(:disabled){background:#5a6268;transform:translateY(-2px);box-shadow:0 4px 12px #6c757d66}.fmode-button.success{background:#28a745;color:#fff}.fmode-button.success:hover:not(:disabled){background:#218838;transform:translateY(-2px);box-shadow:0 4px 12px #28a74566}.fmode-button.danger{background:#dc3545;color:#fff}.fmode-button.danger:hover:not(:disabled){background:#c82333;transform:translateY(-2px);box-shadow:0 4px 12px #dc354566}.fmode-button.small{padding:.5rem 1rem;font-size:.875rem}.fmode-button.large{padding:1rem 2rem;font-size:1.125rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
214
+ }
215
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeButtonComponent, decorators: [{
216
+ type: Component,
217
+ args: [{ selector: 'fmode-button', standalone: true, imports: [CommonModule], template: `
218
+ <button
219
+ [disabled]="disabled"
220
+ [class.primary]="type === 'primary'"
221
+ [class.secondary]="type === 'secondary'"
222
+ [class.success]="type === 'success'"
223
+ [class.danger]="type === 'danger'"
224
+ [class.small]="size === 'small'"
225
+ [class.large]="size === 'large'"
226
+ (click)="onClick.emit()"
227
+ class="fmode-button"
228
+ >
229
+ <ng-content></ng-content>
230
+ </button>
231
+ `, styles: [".fmode-button{padding:.75rem 1.5rem;border:none;border-radius:8px;font-size:1rem;font-weight:600;cursor:pointer;transition:all .3s;font-family:inherit;box-sizing:border-box}.fmode-button:disabled{opacity:.5;cursor:not-allowed}.fmode-button.primary{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff}.fmode-button.primary:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 4px 12px #667eea66}.fmode-button.secondary{background:#6c757d;color:#fff}.fmode-button.secondary:hover:not(:disabled){background:#5a6268;transform:translateY(-2px);box-shadow:0 4px 12px #6c757d66}.fmode-button.success{background:#28a745;color:#fff}.fmode-button.success:hover:not(:disabled){background:#218838;transform:translateY(-2px);box-shadow:0 4px 12px #28a74566}.fmode-button.danger{background:#dc3545;color:#fff}.fmode-button.danger:hover:not(:disabled){background:#c82333;transform:translateY(-2px);box-shadow:0 4px 12px #dc354566}.fmode-button.small{padding:.5rem 1rem;font-size:.875rem}.fmode-button.large{padding:1rem 2rem;font-size:1.125rem}\n"] }]
232
+ }], propDecorators: { disabled: [{
233
+ type: Input
234
+ }], type: [{
235
+ type: Input
236
+ }], size: [{
237
+ type: Input
238
+ }], onClick: [{
239
+ type: Output
240
+ }] } });
241
+
242
+ class FmodeLoadingComponent {
243
+ loadingText = '';
244
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeLoadingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
245
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmodeLoadingComponent, isStandalone: true, selector: "fmode-loading", inputs: { loadingText: "loadingText" }, ngImport: i0, template: `
246
+ <div class="fmode-loading">
247
+ <div class="loading-spinner"></div>
248
+ <div class="loading-text">{{ loadingText || '加载中...' }}</div>
249
+ </div>
250
+ `, isInline: true, styles: [".fmode-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1rem;padding:2rem}.loading-spinner{width:50px;height:50px;border:4px solid #f3f3f3;border-top:4px solid #667eea;border-radius:50%;animation:spin 1s linear infinite}.loading-text{color:#667eea;font-weight:600;font-size:1.1rem}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
251
+ }
252
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeLoadingComponent, decorators: [{
253
+ type: Component,
254
+ args: [{ selector: 'fmode-loading', standalone: true, imports: [CommonModule], template: `
255
+ <div class="fmode-loading">
256
+ <div class="loading-spinner"></div>
257
+ <div class="loading-text">{{ loadingText || '加载中...' }}</div>
258
+ </div>
259
+ `, styles: [".fmode-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1rem;padding:2rem}.loading-spinner{width:50px;height:50px;border:4px solid #f3f3f3;border-top:4px solid #667eea;border-radius:50%;animation:spin 1s linear infinite}.loading-text{color:#667eea;font-weight:600;font-size:1.1rem}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
260
+ }], propDecorators: { loadingText: [{
261
+ type: Input
262
+ }] } });
263
+
264
+ class FmodeListComponent {
265
+ items = [];
266
+ itemClick = new EventEmitter();
267
+ onItemClick(item) {
268
+ this.itemClick.emit(item);
269
+ }
270
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
271
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmodeListComponent, isStandalone: true, selector: "fmode-list", inputs: { items: "items" }, outputs: { itemClick: "itemClick" }, ngImport: i0, template: `
272
+ <div class="fmode-list">
273
+ <div
274
+ *ngFor="let item of items"
275
+ (click)="onItemClick(item)"
276
+ class="list-item"
277
+ >
278
+ <div class="item-content">{{ item }}</div>
279
+ </div>
280
+
281
+ <div *ngIf="items.length === 0" class="empty-state">
282
+ <span>暂无数据</span>
283
+ </div>
284
+ </div>
285
+ `, isInline: true, styles: [".fmode-list{background:#fff;border-radius:8px;overflow:hidden}.list-item{padding:1rem;border-bottom:1px solid #e9ecef;cursor:pointer;transition:background .3s}.list-item:hover{background:#f8f9fa}.list-item:last-child{border-bottom:none}.item-content{color:#495057;line-height:1.6}.empty-state{padding:2rem;text-align:center;color:#6c757d;font-style:italic}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
286
+ }
287
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeListComponent, decorators: [{
288
+ type: Component,
289
+ args: [{ selector: 'fmode-list', standalone: true, imports: [CommonModule], template: `
290
+ <div class="fmode-list">
291
+ <div
292
+ *ngFor="let item of items"
293
+ (click)="onItemClick(item)"
294
+ class="list-item"
295
+ >
296
+ <div class="item-content">{{ item }}</div>
297
+ </div>
298
+
299
+ <div *ngIf="items.length === 0" class="empty-state">
300
+ <span>暂无数据</span>
301
+ </div>
302
+ </div>
303
+ `, styles: [".fmode-list{background:#fff;border-radius:8px;overflow:hidden}.list-item{padding:1rem;border-bottom:1px solid #e9ecef;cursor:pointer;transition:background .3s}.list-item:hover{background:#f8f9fa}.list-item:last-child{border-bottom:none}.item-content{color:#495057;line-height:1.6}.empty-state{padding:2rem;text-align:center;color:#6c757d;font-style:italic}\n"] }]
304
+ }], propDecorators: { items: [{
305
+ type: Input
306
+ }], itemClick: [{
307
+ type: Output
308
+ }] } });
309
+
310
+ class FmodeAvatarComponent {
311
+ name = '';
312
+ imageUrl = '';
313
+ size = 'medium';
314
+ backgroundColor = '#667eea';
315
+ textColor = '#ffffff';
316
+ alt = 'Avatar';
317
+ rounded = false;
318
+ clickable = false;
319
+ onClick = new EventEmitter();
320
+ get initials() {
321
+ if (!this.name)
322
+ return '';
323
+ const words = this.name.trim().split(/\s+/);
324
+ if (words.length >= 2) {
325
+ return (words[0][0] + words[words.length - 1][0]).toUpperCase();
326
+ }
327
+ return this.name.substring(0, 2).toUpperCase();
328
+ }
329
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeAvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
330
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmodeAvatarComponent, isStandalone: true, selector: "fmode-avatar", inputs: { name: "name", imageUrl: "imageUrl", size: "size", backgroundColor: "backgroundColor", textColor: "textColor", alt: "alt", rounded: "rounded", clickable: "clickable" }, outputs: { onClick: "onClick" }, ngImport: i0, template: `
331
+ <div
332
+ class="fmode-avatar"
333
+ [class.small]="size === 'small'"
334
+ [class.medium]="size === 'medium'"
335
+ [class.large]="size === 'large'"
336
+ [class.xlarge]="size === 'xlarge'"
337
+ [class.rounded]="rounded"
338
+ [class.clickable]="clickable"
339
+ [style.background-image]="imageUrl ? 'url(' + imageUrl + ')' : ''"
340
+ [style.background-color]="!imageUrl ? backgroundColor : ''"
341
+ [style.color]="textColor"
342
+ (click)="onClick.emit()"
343
+ >
344
+ <span *ngIf="!imageUrl" class="avatar-text">{{ initials }}</span>
345
+ <img *ngIf="imageUrl" [src]="imageUrl" [alt]="alt" class="avatar-image">
346
+ </div>
347
+ `, isInline: true, styles: [".fmode-avatar{display:flex;align-items:center;justify-content:center;border-radius:50%;overflow:hidden;font-weight:600;font-size:1.2rem;cursor:default;transition:transform .3s,box-shadow .3s;background-size:cover;background-position:center;background-repeat:no-repeat;box-shadow:0 2px 8px #0000001a}.fmode-avatar.small{width:32px;height:32px;font-size:.8rem}.fmode-avatar.medium{width:48px;height:48px;font-size:1rem}.fmode-avatar.large{width:64px;height:64px;font-size:1.2rem}.fmode-avatar.xlarge{width:96px;height:96px;font-size:1.5rem}.fmode-avatar.rounded{border-radius:12px}.fmode-avatar.clickable{cursor:pointer}.fmode-avatar.clickable:hover{transform:scale(1.05);box-shadow:0 4px 12px #00000026}.avatar-text{text-transform:uppercase;letter-spacing:.5px}.avatar-image{width:100%;height:100%;object-fit:cover;display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
348
+ }
349
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeAvatarComponent, decorators: [{
350
+ type: Component,
351
+ args: [{ selector: 'fmode-avatar', standalone: true, imports: [CommonModule], template: `
352
+ <div
353
+ class="fmode-avatar"
354
+ [class.small]="size === 'small'"
355
+ [class.medium]="size === 'medium'"
356
+ [class.large]="size === 'large'"
357
+ [class.xlarge]="size === 'xlarge'"
358
+ [class.rounded]="rounded"
359
+ [class.clickable]="clickable"
360
+ [style.background-image]="imageUrl ? 'url(' + imageUrl + ')' : ''"
361
+ [style.background-color]="!imageUrl ? backgroundColor : ''"
362
+ [style.color]="textColor"
363
+ (click)="onClick.emit()"
364
+ >
365
+ <span *ngIf="!imageUrl" class="avatar-text">{{ initials }}</span>
366
+ <img *ngIf="imageUrl" [src]="imageUrl" [alt]="alt" class="avatar-image">
367
+ </div>
368
+ `, styles: [".fmode-avatar{display:flex;align-items:center;justify-content:center;border-radius:50%;overflow:hidden;font-weight:600;font-size:1.2rem;cursor:default;transition:transform .3s,box-shadow .3s;background-size:cover;background-position:center;background-repeat:no-repeat;box-shadow:0 2px 8px #0000001a}.fmode-avatar.small{width:32px;height:32px;font-size:.8rem}.fmode-avatar.medium{width:48px;height:48px;font-size:1rem}.fmode-avatar.large{width:64px;height:64px;font-size:1.2rem}.fmode-avatar.xlarge{width:96px;height:96px;font-size:1.5rem}.fmode-avatar.rounded{border-radius:12px}.fmode-avatar.clickable{cursor:pointer}.fmode-avatar.clickable:hover{transform:scale(1.05);box-shadow:0 4px 12px #00000026}.avatar-text{text-transform:uppercase;letter-spacing:.5px}.avatar-image{width:100%;height:100%;object-fit:cover;display:block}\n"] }]
369
+ }], propDecorators: { name: [{
370
+ type: Input
371
+ }], imageUrl: [{
372
+ type: Input
373
+ }], size: [{
374
+ type: Input
375
+ }], backgroundColor: [{
376
+ type: Input
377
+ }], textColor: [{
378
+ type: Input
379
+ }], alt: [{
380
+ type: Input
381
+ }], rounded: [{
382
+ type: Input
383
+ }], clickable: [{
384
+ type: Input
385
+ }], onClick: [{
386
+ type: Output
387
+ }] } });
388
+
389
+ class FmodeBadgeComponent {
390
+ type = 'primary';
391
+ pill = false;
392
+ outline = false;
393
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
394
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmodeBadgeComponent, isStandalone: true, selector: "fmode-badge", inputs: { type: "type", pill: "pill", outline: "outline" }, ngImport: i0, template: `
395
+ <span
396
+ class="fmode-badge"
397
+ [class.primary]="type === 'primary'"
398
+ [class.secondary]="type === 'secondary'"
399
+ [class.success]="type === 'success'"
400
+ [class.warning]="type === 'warning'"
401
+ [class.danger]="type === 'danger'"
402
+ [class.info]="type === 'info'"
403
+ [class.pill]="pill"
404
+ [class.outline]="outline"
405
+ >
406
+ <ng-content></ng-content>
407
+ </span>
408
+ `, isInline: true, styles: [".fmode-badge{display:inline-block;padding:.25rem .75rem;font-size:.875rem;font-weight:600;border-radius:4px;letter-spacing:.5px;transition:all .3s}.fmode-badge.primary{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff}.fmode-badge.secondary{background:#6c757d;color:#fff}.fmode-badge.success{background:#28a745;color:#fff}.fmode-badge.warning{background:#ffc107;color:#212529}.fmode-badge.danger{background:#dc3545;color:#fff}.fmode-badge.info{background:#17a2b8;color:#fff}.fmode-badge.outline{background:transparent;border:2px solid currentColor}.fmode-badge.outline.primary{color:#667eea;border-color:#667eea}.fmode-badge.outline.secondary{color:#6c757d;border-color:#6c757d}.fmode-badge.outline.success{color:#28a745;border-color:#28a745}.fmode-badge.outline.warning{color:#ffc107;border-color:#ffc107}.fmode-badge.outline.danger{color:#dc3545;border-color:#dc3545}.fmode-badge.outline.info{color:#17a2b8;border-color:#17a2b8}.fmode-badge.pill{border-radius:50px;padding:.375rem 1rem}.fmode-badge:hover{transform:translateY(-2px);box-shadow:0 4px 8px #0000001a}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
409
+ }
410
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeBadgeComponent, decorators: [{
411
+ type: Component,
412
+ args: [{ selector: 'fmode-badge', standalone: true, imports: [CommonModule], template: `
413
+ <span
414
+ class="fmode-badge"
415
+ [class.primary]="type === 'primary'"
416
+ [class.secondary]="type === 'secondary'"
417
+ [class.success]="type === 'success'"
418
+ [class.warning]="type === 'warning'"
419
+ [class.danger]="type === 'danger'"
420
+ [class.info]="type === 'info'"
421
+ [class.pill]="pill"
422
+ [class.outline]="outline"
423
+ >
424
+ <ng-content></ng-content>
425
+ </span>
426
+ `, styles: [".fmode-badge{display:inline-block;padding:.25rem .75rem;font-size:.875rem;font-weight:600;border-radius:4px;letter-spacing:.5px;transition:all .3s}.fmode-badge.primary{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff}.fmode-badge.secondary{background:#6c757d;color:#fff}.fmode-badge.success{background:#28a745;color:#fff}.fmode-badge.warning{background:#ffc107;color:#212529}.fmode-badge.danger{background:#dc3545;color:#fff}.fmode-badge.info{background:#17a2b8;color:#fff}.fmode-badge.outline{background:transparent;border:2px solid currentColor}.fmode-badge.outline.primary{color:#667eea;border-color:#667eea}.fmode-badge.outline.secondary{color:#6c757d;border-color:#6c757d}.fmode-badge.outline.success{color:#28a745;border-color:#28a745}.fmode-badge.outline.warning{color:#ffc107;border-color:#ffc107}.fmode-badge.outline.danger{color:#dc3545;border-color:#dc3545}.fmode-badge.outline.info{color:#17a2b8;border-color:#17a2b8}.fmode-badge.pill{border-radius:50px;padding:.375rem 1rem}.fmode-badge:hover{transform:translateY(-2px);box-shadow:0 4px 8px #0000001a}\n"] }]
427
+ }], propDecorators: { type: [{
428
+ type: Input
429
+ }], pill: [{
430
+ type: Input
431
+ }], outline: [{
432
+ type: Input
433
+ }] } });
434
+
435
+ class FmodeDividerComponent {
436
+ text = '';
437
+ vertical = false;
438
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeDividerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
439
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmodeDividerComponent, isStandalone: true, selector: "fmode-divider", inputs: { text: "text", vertical: "vertical" }, ngImport: i0, template: `
440
+ <div
441
+ class="fmode-divider"
442
+ [class.vertical]="vertical"
443
+ [class.with-text]="!!text"
444
+ >
445
+ <span *ngIf="text" class="divider-text">{{ text }}</span>
446
+ </div>
447
+ `, isInline: true, styles: [".fmode-divider{position:relative;display:flex;align-items:center;width:100%;height:1px;background:linear-gradient(90deg,transparent,#e9ecef,transparent);margin:1.5rem 0}.fmode-divider.vertical{width:1px;height:100%;background:linear-gradient(180deg,transparent,#e9ecef,transparent);margin:0 1.5rem}.fmode-divider.with-text:before,.fmode-divider.with-text:after{content:\"\";flex:1;height:1px;background:linear-gradient(90deg,transparent,#e9ecef,transparent)}.fmode-divider.vertical.with-text:before,.fmode-divider.vertical.with-text:after{width:1px;height:100%;background:linear-gradient(180deg,transparent,#e9ecef,transparent)}.divider-text{padding:0 1rem;color:#6c757d;font-size:.875rem;font-weight:500;white-space:nowrap;background:transparent}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
448
+ }
449
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeDividerComponent, decorators: [{
450
+ type: Component,
451
+ args: [{ selector: 'fmode-divider', standalone: true, imports: [CommonModule], template: `
452
+ <div
453
+ class="fmode-divider"
454
+ [class.vertical]="vertical"
455
+ [class.with-text]="!!text"
456
+ >
457
+ <span *ngIf="text" class="divider-text">{{ text }}</span>
458
+ </div>
459
+ `, styles: [".fmode-divider{position:relative;display:flex;align-items:center;width:100%;height:1px;background:linear-gradient(90deg,transparent,#e9ecef,transparent);margin:1.5rem 0}.fmode-divider.vertical{width:1px;height:100%;background:linear-gradient(180deg,transparent,#e9ecef,transparent);margin:0 1.5rem}.fmode-divider.with-text:before,.fmode-divider.with-text:after{content:\"\";flex:1;height:1px;background:linear-gradient(90deg,transparent,#e9ecef,transparent)}.fmode-divider.vertical.with-text:before,.fmode-divider.vertical.with-text:after{width:1px;height:100%;background:linear-gradient(180deg,transparent,#e9ecef,transparent)}.divider-text{padding:0 1rem;color:#6c757d;font-size:.875rem;font-weight:500;white-space:nowrap;background:transparent}\n"] }]
460
+ }], propDecorators: { text: [{
461
+ type: Input
462
+ }], vertical: [{
463
+ type: Input
464
+ }] } });
465
+
466
+ class FmodeTagComponent {
467
+ color = 'primary';
468
+ closable = false;
469
+ onClose = new EventEmitter();
470
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeTagComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
471
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmodeTagComponent, isStandalone: true, selector: "fmode-tag", inputs: { color: "color", closable: "closable" }, outputs: { onClose: "onClose" }, ngImport: i0, template: `
472
+ <span
473
+ class="fmode-tag"
474
+ [class.closable]="closable"
475
+ [class.primary]="color === 'primary'"
476
+ [class.secondary]="color === 'secondary'"
477
+ [class.success]="color === 'success'"
478
+ [class.warning]="color === 'warning'"
479
+ [class.danger]="color === 'danger'"
480
+ [class.info]="color === 'info'"
481
+ >
482
+ <span class="tag-content">
483
+ <ng-content></ng-content>
484
+ </span>
485
+ <span *ngIf="closable" class="tag-close" (click)="onClose.emit()">×</span>
486
+ </span>
487
+ `, isInline: true, styles: [".fmode-tag{display:inline-flex;align-items:center;padding:.375rem .75rem;border-radius:6px;font-size:.875rem;font-weight:500;transition:all .3s;gap:.5rem}.fmode-tag.primary{background:linear-gradient(135deg,#667eea1a,#764ba21a);color:#667eea;border:1px solid rgba(102,126,234,.2)}.fmode-tag.secondary{background:#6c757d1a;color:#6c757d;border:1px solid rgba(108,117,125,.2)}.fmode-tag.success{background:#28a7451a;color:#28a745;border:1px solid rgba(40,167,69,.2)}.fmode-tag.warning{background:#ffc1071a;color:#ffc107;border:1px solid rgba(255,193,7,.2)}.fmode-tag.danger{background:#dc35451a;color:#dc3545;border:1px solid rgba(220,53,69,.2)}.fmode-tag.info{background:#17a2b81a;color:#17a2b8;border:1px solid rgba(23,162,184,.2)}.fmode-tag:hover{transform:translateY(-2px);box-shadow:0 4px 8px #0000001a}.fmode-tag.closable{padding-right:.5rem}.tag-content{display:inline-block}.tag-close{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;cursor:pointer;transition:all .3s;font-size:1.2rem;line-height:1}.tag-close:hover{background:#0000001a;transform:scale(1.1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
488
+ }
489
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeTagComponent, decorators: [{
490
+ type: Component,
491
+ args: [{ selector: 'fmode-tag', standalone: true, imports: [CommonModule], template: `
492
+ <span
493
+ class="fmode-tag"
494
+ [class.closable]="closable"
495
+ [class.primary]="color === 'primary'"
496
+ [class.secondary]="color === 'secondary'"
497
+ [class.success]="color === 'success'"
498
+ [class.warning]="color === 'warning'"
499
+ [class.danger]="color === 'danger'"
500
+ [class.info]="color === 'info'"
501
+ >
502
+ <span class="tag-content">
503
+ <ng-content></ng-content>
504
+ </span>
505
+ <span *ngIf="closable" class="tag-close" (click)="onClose.emit()">×</span>
506
+ </span>
507
+ `, styles: [".fmode-tag{display:inline-flex;align-items:center;padding:.375rem .75rem;border-radius:6px;font-size:.875rem;font-weight:500;transition:all .3s;gap:.5rem}.fmode-tag.primary{background:linear-gradient(135deg,#667eea1a,#764ba21a);color:#667eea;border:1px solid rgba(102,126,234,.2)}.fmode-tag.secondary{background:#6c757d1a;color:#6c757d;border:1px solid rgba(108,117,125,.2)}.fmode-tag.success{background:#28a7451a;color:#28a745;border:1px solid rgba(40,167,69,.2)}.fmode-tag.warning{background:#ffc1071a;color:#ffc107;border:1px solid rgba(255,193,7,.2)}.fmode-tag.danger{background:#dc35451a;color:#dc3545;border:1px solid rgba(220,53,69,.2)}.fmode-tag.info{background:#17a2b81a;color:#17a2b8;border:1px solid rgba(23,162,184,.2)}.fmode-tag:hover{transform:translateY(-2px);box-shadow:0 4px 8px #0000001a}.fmode-tag.closable{padding-right:.5rem}.tag-content{display:inline-block}.tag-close{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;cursor:pointer;transition:all .3s;font-size:1.2rem;line-height:1}.tag-close:hover{background:#0000001a;transform:scale(1.1)}\n"] }]
508
+ }], propDecorators: { color: [{
509
+ type: Input
510
+ }], closable: [{
511
+ type: Input
512
+ }], onClose: [{
513
+ type: Output
514
+ }] } });
515
+
516
+ class FmodeDigitalHumanComponent {
517
+ size = 'medium';
518
+ state = 'waiting';
519
+ speechText = '正在处理...';
520
+ ngOnInit() {
521
+ // 初始化状态
522
+ }
523
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeDigitalHumanComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
524
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmodeDigitalHumanComponent, isStandalone: true, selector: "fmode-digital-human", inputs: { size: "size", state: "state", speechText: "speechText" }, ngImport: i0, template: `
525
+ <div
526
+ class="fmode-digital-human"
527
+ [class.small]="size === 'small'"
528
+ [class.medium]="size === 'medium'"
529
+ [class.large]="size === 'large'"
530
+ [class.xlarge]="size === 'xlarge'"
531
+ >
532
+ <div class="digital-human-container">
533
+ <div class="digital-human-avatar">
534
+ <img src="https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=friendly%20digital%20assistant%20avatar%20with%20glasses%20and%20professional%20appearance&image_size=square_hd"
535
+ alt="Digital Assistant" class="avatar-image">
536
+ </div>
537
+
538
+ <div class="digital-human-animations">
539
+ <div *ngIf="state === 'waiting'" class="animation waiting">
540
+ <div class="pulse"></div>
541
+ <div class="pulse"></div>
542
+ <div class="pulse"></div>
543
+ </div>
544
+
545
+ <div *ngIf="state === 'listening'" class="animation listening">
546
+ <div class="wave">
547
+ <span></span>
548
+ <span></span>
549
+ <span></span>
550
+ <span></span>
551
+ <span></span>
552
+ </div>
553
+ </div>
554
+
555
+ <div *ngIf="state === 'thinking'" class="animation thinking">
556
+ <div class="brain">
557
+ <div class="neuron"></div>
558
+ <div class="neuron"></div>
559
+ <div class="neuron"></div>
560
+ </div>
561
+ </div>
562
+
563
+ <div *ngIf="state === 'speaking'" class="animation speaking">
564
+ <div class="speech-bubble">
565
+ <span>{{ speechText }}</span>
566
+ </div>
567
+ </div>
568
+ </div>
569
+ </div>
570
+ </div>
571
+ `, isInline: true, styles: [".fmode-digital-human{display:flex;flex-direction:column;align-items:center;gap:1rem}.digital-human-container{position:relative;display:flex;flex-direction:column;align-items:center}.digital-human-avatar{border-radius:50%;overflow:hidden;box-shadow:0 4px 16px #667eea4d;background:linear-gradient(135deg,#667eea,#764ba2);transition:all .3s}.avatar-image{width:100%;height:100%;object-fit:cover;display:block}.fmode-digital-human.small .digital-human-avatar{width:64px;height:64px}.fmode-digital-human.medium .digital-human-avatar{width:96px;height:96px}.fmode-digital-human.large .digital-human-avatar{width:128px;height:128px}.fmode-digital-human.xlarge .digital-human-avatar{width:160px;height:160px}.digital-human-animations{position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:.5rem;width:100%;display:flex;justify-content:center}.animation{display:flex;align-items:center;justify-content:center}.waiting .pulse{width:8px;height:8px;background:#667eea;border-radius:50%;margin:0 3px;animation:pulse 1.5s infinite ease-in-out}.waiting .pulse:nth-child(2){animation-delay:.2s}.waiting .pulse:nth-child(3){animation-delay:.4s}@keyframes pulse{0%,to{transform:scale(.8);opacity:.5}50%{transform:scale(1.2);opacity:1}}.listening .wave{display:flex;align-items:center;gap:4px}.listening .wave span{width:4px;background:#667eea;border-radius:2px;animation:wave 1.5s infinite ease-in-out}.listening .wave span:nth-child(1){height:8px;animation-delay:0s}.listening .wave span:nth-child(2){height:12px;animation-delay:.1s}.listening .wave span:nth-child(3){height:16px;animation-delay:.2s}.listening .wave span:nth-child(4){height:12px;animation-delay:.3s}.listening .wave span:nth-child(5){height:8px;animation-delay:.4s}@keyframes wave{0%,to{transform:scaleY(.5);opacity:.5}50%{transform:scaleY(1);opacity:1}}.thinking .brain{position:relative;width:40px;height:30px}.thinking .neuron{position:absolute;width:6px;height:6px;background:#667eea;border-radius:50%;animation:neuron 2s infinite ease-in-out}.thinking .neuron:nth-child(1){top:0;left:17px;animation-delay:0s}.thinking .neuron:nth-child(2){top:12px;left:4px;animation-delay:.3s}.thinking .neuron:nth-child(3){top:12px;right:4px;animation-delay:.6s}@keyframes neuron{0%,to{transform:scale(.5);opacity:0}50%{transform:scale(1);opacity:1}}.speaking .speech-bubble{background:#fff;padding:.5rem 1rem;border-radius:16px;box-shadow:0 2px 8px #0000001a;max-width:200px;text-align:center;animation:speech 1s infinite ease-in-out}.speaking .speech-bubble:after{content:\"\";position:absolute;bottom:-8px;left:50%;transform:translate(-50%);width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid white}.speaking .speech-bubble span{font-size:.875rem;color:#495057;font-weight:500}@keyframes speech{0%,to{transform:translateY(0)}50%{transform:translateY(-2px)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
572
+ }
573
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmodeDigitalHumanComponent, decorators: [{
574
+ type: Component,
575
+ args: [{ selector: 'fmode-digital-human', standalone: true, imports: [CommonModule], template: `
576
+ <div
577
+ class="fmode-digital-human"
578
+ [class.small]="size === 'small'"
579
+ [class.medium]="size === 'medium'"
580
+ [class.large]="size === 'large'"
581
+ [class.xlarge]="size === 'xlarge'"
582
+ >
583
+ <div class="digital-human-container">
584
+ <div class="digital-human-avatar">
585
+ <img src="https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=friendly%20digital%20assistant%20avatar%20with%20glasses%20and%20professional%20appearance&image_size=square_hd"
586
+ alt="Digital Assistant" class="avatar-image">
587
+ </div>
588
+
589
+ <div class="digital-human-animations">
590
+ <div *ngIf="state === 'waiting'" class="animation waiting">
591
+ <div class="pulse"></div>
592
+ <div class="pulse"></div>
593
+ <div class="pulse"></div>
594
+ </div>
595
+
596
+ <div *ngIf="state === 'listening'" class="animation listening">
597
+ <div class="wave">
598
+ <span></span>
599
+ <span></span>
600
+ <span></span>
601
+ <span></span>
602
+ <span></span>
603
+ </div>
604
+ </div>
605
+
606
+ <div *ngIf="state === 'thinking'" class="animation thinking">
607
+ <div class="brain">
608
+ <div class="neuron"></div>
609
+ <div class="neuron"></div>
610
+ <div class="neuron"></div>
611
+ </div>
612
+ </div>
613
+
614
+ <div *ngIf="state === 'speaking'" class="animation speaking">
615
+ <div class="speech-bubble">
616
+ <span>{{ speechText }}</span>
617
+ </div>
618
+ </div>
619
+ </div>
620
+ </div>
621
+ </div>
622
+ `, styles: [".fmode-digital-human{display:flex;flex-direction:column;align-items:center;gap:1rem}.digital-human-container{position:relative;display:flex;flex-direction:column;align-items:center}.digital-human-avatar{border-radius:50%;overflow:hidden;box-shadow:0 4px 16px #667eea4d;background:linear-gradient(135deg,#667eea,#764ba2);transition:all .3s}.avatar-image{width:100%;height:100%;object-fit:cover;display:block}.fmode-digital-human.small .digital-human-avatar{width:64px;height:64px}.fmode-digital-human.medium .digital-human-avatar{width:96px;height:96px}.fmode-digital-human.large .digital-human-avatar{width:128px;height:128px}.fmode-digital-human.xlarge .digital-human-avatar{width:160px;height:160px}.digital-human-animations{position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:.5rem;width:100%;display:flex;justify-content:center}.animation{display:flex;align-items:center;justify-content:center}.waiting .pulse{width:8px;height:8px;background:#667eea;border-radius:50%;margin:0 3px;animation:pulse 1.5s infinite ease-in-out}.waiting .pulse:nth-child(2){animation-delay:.2s}.waiting .pulse:nth-child(3){animation-delay:.4s}@keyframes pulse{0%,to{transform:scale(.8);opacity:.5}50%{transform:scale(1.2);opacity:1}}.listening .wave{display:flex;align-items:center;gap:4px}.listening .wave span{width:4px;background:#667eea;border-radius:2px;animation:wave 1.5s infinite ease-in-out}.listening .wave span:nth-child(1){height:8px;animation-delay:0s}.listening .wave span:nth-child(2){height:12px;animation-delay:.1s}.listening .wave span:nth-child(3){height:16px;animation-delay:.2s}.listening .wave span:nth-child(4){height:12px;animation-delay:.3s}.listening .wave span:nth-child(5){height:8px;animation-delay:.4s}@keyframes wave{0%,to{transform:scaleY(.5);opacity:.5}50%{transform:scaleY(1);opacity:1}}.thinking .brain{position:relative;width:40px;height:30px}.thinking .neuron{position:absolute;width:6px;height:6px;background:#667eea;border-radius:50%;animation:neuron 2s infinite ease-in-out}.thinking .neuron:nth-child(1){top:0;left:17px;animation-delay:0s}.thinking .neuron:nth-child(2){top:12px;left:4px;animation-delay:.3s}.thinking .neuron:nth-child(3){top:12px;right:4px;animation-delay:.6s}@keyframes neuron{0%,to{transform:scale(.5);opacity:0}50%{transform:scale(1);opacity:1}}.speaking .speech-bubble{background:#fff;padding:.5rem 1rem;border-radius:16px;box-shadow:0 2px 8px #0000001a;max-width:200px;text-align:center;animation:speech 1s infinite ease-in-out}.speaking .speech-bubble:after{content:\"\";position:absolute;bottom:-8px;left:50%;transform:translate(-50%);width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid white}.speaking .speech-bubble span{font-size:.875rem;color:#495057;font-weight:500}@keyframes speech{0%,to{transform:translateY(0)}50%{transform:translateY(-2px)}}\n"] }]
623
+ }], propDecorators: { size: [{
624
+ type: Input
625
+ }], state: [{
626
+ type: Input
627
+ }], speechText: [{
628
+ type: Input
629
+ }] } });
630
+
631
+ class AppComponent {
632
+ inputText = '';
633
+ currentSummary = '';
634
+ isLoading = false;
635
+ summaryLength = 'short';
636
+ history = [];
637
+ digitalHumanState = 'waiting';
638
+ digitalHumanSpeech = '等待输入...';
639
+ lengthOptions = [
640
+ { value: 'short', label: '简短' },
641
+ { value: 'long', label: '详细' }
642
+ ];
643
+ testTexts = [
644
+ {
645
+ id: 1,
646
+ title: '人工智能简介',
647
+ content: '人工智能(Artificial Intelligence,简称AI)是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器。该领域的研究包括机器人、语言识别、图像识别、自然语言处理和专家系统等。人工智能从诞生以来,理论和技术日益成熟,应用领域也不断扩大,可以设想,未来人工智能带来的科技产品,将会是人类智慧的"容器"。人工智能可以对人的意识、思维的信息过程的模拟。人工智能不是人的智能,但能像人那样思考、也可能超过人的智能。'
648
+ },
649
+ {
650
+ id: 2,
651
+ title: '气候变化与环境保护',
652
+ content: '气候变化是指气候状态的变化,特别是平均天气模式的长期变化,这种变化可能是由自然内部过程或外部强迫引起的,也可能是由于人类活动改变了地球大气的组成。气候变化对人类社会和自然生态系统产生了深远的影响,包括海平面上升、极端天气事件增加、生物多样性减少等。为了应对气候变化,国际社会采取了一系列措施,如减少温室气体排放、发展可再生能源、提高能源效率等。环境保护是指人类为解决现实或潜在的环境问题,协调人类与环境的关系,保障经济社会的可持续发展而采取的各种行动的总称。'
653
+ },
654
+ {
655
+ id: 3,
656
+ title: '健康生活方式',
657
+ content: '健康的生活方式对于维持身体和心理健康至关重要。这包括均衡的饮食、定期的体育锻炼、充足的睡眠、减少压力以及避免有害习惯如吸烟和过度饮酒。均衡饮食意味着摄入各种营养素,包括蛋白质、碳水化合物、脂肪、维生素和矿物质。定期锻炼可以增强心肺功能、提高肌肉力量和灵活性,并有助于控制体重。充足的睡眠对于身体恢复和大脑功能至关重要。管理压力可以通过冥想、瑜伽、深呼吸或其他放松技巧来实现。避免吸烟和限制酒精摄入可以降低患心脏病、癌症和其他慢性疾病的风险。'
658
+ },
659
+ {
660
+ id: 4,
661
+ title: '科技创新与未来',
662
+ content: '科技创新是推动社会进步和经济发展的重要动力。近年来,人工智能、大数据、物联网、区块链、量子计算等新兴技术的快速发展,正在深刻改变着我们的生活和工作方式。人工智能正在各个领域得到广泛应用,从智能助手到自动驾驶汽车。大数据分析帮助企业做出更明智的决策。物联网连接了各种设备,使我们的生活更加便捷。区块链技术提供了安全、透明的交易方式。量子计算有望解决传统计算机难以处理的复杂问题。这些技术的发展将继续推动产业升级和社会变革,为未来创造更多可能性。'
663
+ },
664
+ {
665
+ id: 5,
666
+ title: '教育的重要性',
667
+ content: '教育是人类社会发展的基石,对于个人和社会都具有重要意义。教育不仅传授知识和技能,还培养人的思维能力、创造力和社会责任感。通过教育,个人可以获得更好的就业机会,提高生活质量。对于社会而言,教育可以促进经济发展、减少贫困、提高社会凝聚力。教育还可以培养公民的民主意识和参与能力,促进社会的公平与正义。在当今快速变化的世界中,终身学习变得越来越重要,人们需要不断更新知识和技能以适应社会的发展。因此,投资教育是对未来最好的投资。'
668
+ }
669
+ ];
670
+ onInputTextChange(value) {
671
+ console.log('onInputTextChange:', value);
672
+ this.inputText = value;
673
+ }
674
+ onSummaryLengthChange(value) {
675
+ console.log('onSummaryLengthChange:', value);
676
+ this.summaryLength = value;
677
+ }
678
+ loadTestText(index) {
679
+ console.log('Loading test text:', index);
680
+ const testText = this.testTexts[index];
681
+ if (testText) {
682
+ this.inputText = testText.content;
683
+ console.log('Test text loaded:', testText.title);
684
+ }
685
+ }
686
+ async summarizeText() {
687
+ console.log('=== summarizeText called ===');
688
+ console.log('inputText:', this.inputText);
689
+ console.log('inputText.trim():', this.inputText.trim());
690
+ console.log('isLoading:', this.isLoading);
691
+ if (!this.inputText.trim() || this.isLoading) {
692
+ console.log('Early return: empty text or already loading');
693
+ return;
694
+ }
695
+ const text = this.inputText.trim();
696
+ console.log('Text length:', text.length);
697
+ if (text.length < 50) {
698
+ alert('请输入至少50个字符的文本内容');
699
+ return;
700
+ }
701
+ if (text.length > 10000) {
702
+ alert('文本长度不能超过10000个字符');
703
+ return;
704
+ }
705
+ // 数字人状态:开始聆听
706
+ this.digitalHumanState = 'listening';
707
+ this.digitalHumanSpeech = '正在聆听...';
708
+ this.isLoading = true;
709
+ console.log('Starting summary generation...');
710
+ try {
711
+ // 模拟聆听过程
712
+ await new Promise(resolve => setTimeout(resolve, 1000));
713
+ // 数字人状态:开始思考
714
+ this.digitalHumanState = 'thinking';
715
+ this.digitalHumanSpeech = '正在思考...';
716
+ const summary = await this.mockAISummary(text, this.summaryLength);
717
+ console.log('Summary generated:', summary);
718
+ // 数字人状态:开始说话
719
+ this.digitalHumanState = 'speaking';
720
+ this.digitalHumanSpeech = '总结完成!';
721
+ this.currentSummary = summary;
722
+ console.log('currentSummary set to:', this.currentSummary);
723
+ const historyItem = {
724
+ id: Date.now(),
725
+ originalText: text,
726
+ summaryText: summary,
727
+ timestamp: new Date()
728
+ };
729
+ this.history.unshift(historyItem);
730
+ if (this.history.length > 10) {
731
+ this.history = this.history.slice(0, 10);
732
+ }
733
+ // 3秒后恢复到等待状态
734
+ setTimeout(() => {
735
+ this.digitalHumanState = 'waiting';
736
+ this.digitalHumanSpeech = '等待输入...';
737
+ }, 3000);
738
+ }
739
+ catch (error) {
740
+ console.error('总结失败:', error);
741
+ alert('总结过程中出现错误,请重试');
742
+ // 错误时恢复到等待状态
743
+ this.digitalHumanState = 'waiting';
744
+ this.digitalHumanSpeech = '等待输入...';
745
+ }
746
+ finally {
747
+ this.isLoading = false;
748
+ console.log('Loading complete');
749
+ }
750
+ }
751
+ async mockAISummary(text, length) {
752
+ return new Promise((resolve) => {
753
+ setTimeout(() => {
754
+ const sentences = text.split(/[。!?.!?]/).filter((s) => s.trim());
755
+ let summary = '';
756
+ const ratio = length === 'short' ? 0.3 : length === 'medium' ? 0.5 : 0.7;
757
+ const targetCount = Math.max(1, Math.floor(sentences.length * ratio));
758
+ if (sentences.length <= 2) {
759
+ summary = `【智能总结】\n${text}`;
760
+ }
761
+ else {
762
+ const keyPoints = sentences.slice(0, Math.min(3, sentences.length));
763
+ summary = `【智能总结】\n核心要点:\n`;
764
+ keyPoints.forEach((point, index) => {
765
+ summary += `${index + 1}. ${point.trim()}\n`;
766
+ });
767
+ const selectedSentences = sentences.slice(0, targetCount);
768
+ const summaryText = selectedSentences.join('。');
769
+ summary += `\n总结:${summaryText}。`;
770
+ }
771
+ resolve(summary);
772
+ }, 1500);
773
+ });
774
+ }
775
+ clearInput() {
776
+ this.inputText = '';
777
+ this.currentSummary = '';
778
+ }
779
+ clearHistory() {
780
+ if (confirm('确定要清空所有历史记录吗?')) {
781
+ this.history = [];
782
+ }
783
+ }
784
+ loadHistoryItem(item) {
785
+ this.inputText = item.originalText;
786
+ this.currentSummary = item.summaryText;
787
+ }
788
+ copySummary() {
789
+ if (this.currentSummary) {
790
+ navigator.clipboard.writeText(this.currentSummary).then(() => {
791
+ alert('已复制到剪贴板');
792
+ }).catch(() => {
793
+ alert('复制失败,请手动复制');
794
+ });
795
+ }
796
+ }
797
+ formatTime(timestamp) {
798
+ const date = new Date(timestamp);
799
+ const now = new Date();
800
+ const diff = now.getTime() - date.getTime();
801
+ const minutes = Math.floor(diff / 60000);
802
+ const hours = Math.floor(diff / 3600000);
803
+ const days = Math.floor(diff / 86400000);
804
+ if (minutes < 1)
805
+ return '刚刚';
806
+ if (minutes < 60)
807
+ return `${minutes}分钟前`;
808
+ if (hours < 24)
809
+ return `${hours}小时前`;
810
+ if (days < 7)
811
+ return `${days}天前`;
812
+ return date.toLocaleDateString('zh-CN');
813
+ }
814
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AppComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
815
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: AppComponent, isStandalone: true, selector: "app-root", ngImport: i0, template: `
816
+ <div class="app-container">
817
+ <fmode-header title="AI 文本智能总结助手" subtitle="基于 fmode-ng UI 组件库"></fmode-header>
818
+
819
+ <div class="main-content">
820
+ <div class="left-panel">
821
+ <fmode-card title="文本输入" class="input-card">
822
+ <div class="input-header">
823
+ <fmode-avatar name="AI" size="large" backgroundColor="#667eea" textColor="#ffffff"></fmode-avatar>
824
+ <div class="input-info">
825
+ <h3>智能文本总结</h3>
826
+ <p>输入长文本,AI 自动生成精简总结</p>
827
+ </div>
828
+ </div>
829
+
830
+ <div class="test-texts-section">
831
+ <h4>测试文本</h4>
832
+ <div class="test-texts-buttons">
833
+ <fmode-button *ngFor="let testText of testTexts; let i = index"
834
+ (onClick)="loadTestText(i)"
835
+ type="secondary"
836
+ size="small"
837
+ >
838
+ {{ testText.title }}
839
+ </fmode-button>
840
+ </div>
841
+ </div>
842
+
843
+ <fmode-divider></fmode-divider>
844
+
845
+ <fmode-textarea
846
+ [value]="inputText"
847
+ (valueChange)="onInputTextChange($event)"
848
+ placeholder="请输入需要总结的长文本内容..."
849
+ [rows]="12"
850
+ [disabled]="isLoading"
851
+ [showCharCount]="true"
852
+ [maxLength]="10000"
853
+ ></fmode-textarea>
854
+
855
+ <div class="control-bar">
856
+ <fmode-select
857
+ [value]="summaryLength"
858
+ (valueChange)="onSummaryLengthChange($event)"
859
+ [options]="lengthOptions"
860
+ label="总结长度"
861
+ [disabled]="isLoading"
862
+ ></fmode-select>
863
+
864
+ <div class="button-group">
865
+ <fmode-button
866
+ (onClick)="summarizeText()"
867
+ [disabled]="isLoading"
868
+ type="primary"
869
+ >
870
+ 智能总结
871
+ </fmode-button>
872
+ <fmode-button
873
+ (onClick)="clearInput()"
874
+ [disabled]="isLoading"
875
+ type="secondary"
876
+ >
877
+ 清空
878
+ </fmode-button>
879
+ </div>
880
+ </div>
881
+ </fmode-card>
882
+
883
+ <fmode-card title="历史记录" class="history-card">
884
+ <div class="history-header">
885
+ <div class="history-info">
886
+ <fmode-avatar name="历史" size="small" backgroundColor="#6c757d" textColor="#ffffff"></fmode-avatar>
887
+ <span class="history-count">共 {{ history.length }} 条记录</span>
888
+ </div>
889
+ <fmode-button
890
+ (onClick)="clearHistory()"
891
+ [disabled]="history.length === 0"
892
+ type="danger"
893
+ >
894
+ 清空历史
895
+ </fmode-button>
896
+ </div>
897
+
898
+ <fmode-divider></fmode-divider>
899
+
900
+ <div class="history-list">
901
+ <div
902
+ *ngFor="let item of history"
903
+ (click)="loadHistoryItem(item)"
904
+ class="history-item"
905
+ >
906
+ <div class="history-item-header">
907
+ <fmode-avatar [name]="formatTime(item.timestamp)" size="small" backgroundColor="#17a2b8" textColor="#ffffff"></fmode-avatar>
908
+ <div class="history-meta">
909
+ <div class="history-time">{{ formatTime(item.timestamp) }}</div>
910
+ <fmode-tag type="info">{{ item.originalText.length }} 字符</fmode-tag>
911
+ </div>
912
+ </div>
913
+ <div class="history-text">{{ item.originalText.substring(0, 100) }}...</div>
914
+ </div>
915
+
916
+ <div *ngIf="history.length === 0" class="empty-history">
917
+ <fmode-avatar name="空" size="large" backgroundColor="#e9ecef" textColor="#6c757d"></fmode-avatar>
918
+ <p>暂无历史记录</p>
919
+ </div>
920
+ </div>
921
+ </fmode-card>
922
+ </div>
923
+
924
+ <div class="right-panel">
925
+ <fmode-card title="总结结果" class="result-card">
926
+ <div class="result-header">
927
+ <fmode-digital-human
928
+ size="large"
929
+ [state]="digitalHumanState"
930
+ [speechText]="digitalHumanSpeech"
931
+ ></fmode-digital-human>
932
+ <div class="result-badges">
933
+ <fmode-badge *ngIf="currentSummary" type="success" [pill]="true">已完成</fmode-badge>
934
+ <fmode-badge *ngIf="!currentSummary" type="secondary" [pill]="true">等待中</fmode-badge>
935
+ </div>
936
+ </div>
937
+
938
+ <fmode-divider></fmode-divider>
939
+
940
+ <div *ngIf="isLoading" class="loading-container">
941
+ <fmode-loading loadingText="正在智能总结中..."></fmode-loading>
942
+ </div>
943
+
944
+ <div *ngIf="!isLoading && !currentSummary" class="empty-result">
945
+ <fmode-avatar name="空" size="xlarge" backgroundColor="#e9ecef" textColor="#6c757d"></fmode-avatar>
946
+ <p>输入文本并点击"智能总结"按钮</p>
947
+ </div>
948
+
949
+ <div *ngIf="!isLoading && currentSummary" class="result-content">
950
+ <pre class="summary-text">{{ currentSummary }}</pre>
951
+
952
+ <fmode-divider></fmode-divider>
953
+
954
+ <div class="result-actions">
955
+ <div class="result-info">
956
+ <fmode-tag type="success">{{ currentSummary.length }} 字符</fmode-tag>
957
+ <fmode-tag type="primary">{{ summaryLength === 'short' ? '简短' : '详细' }}</fmode-tag>
958
+ </div>
959
+ <fmode-button
960
+ (onClick)="copySummary()"
961
+ type="success"
962
+ >
963
+ 复制结果
964
+ </fmode-button>
965
+ </div>
966
+ </div>
967
+ </fmode-card>
968
+ </div>
969
+ </div>
970
+ </div>
971
+ `, isInline: true, styles: [".app-container{min-height:100vh;background:linear-gradient(135deg,#f5f7fa,#e4e8eb)}.main-content{max-width:1400px;margin:0 auto;padding:2rem;display:grid;grid-template-columns:1fr 1fr;gap:2rem}.left-panel{display:flex;flex-direction:column;gap:2rem}.input-card{flex:1}.input-header{display:flex;align-items:center;gap:1rem;margin-bottom:1rem}.input-info{flex:1}.input-info h3{margin:0 0 .25rem;color:#495057;font-size:1.25rem}.input-info p{margin:0;color:#6c757d;font-size:.875rem}.test-texts-section{margin:1rem 0}.test-texts-section h4{margin:0 0 .75rem;color:#495057;font-size:1rem}.test-texts-buttons{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:.5rem}.input-badges{display:flex;gap:.5rem}.control-bar{margin-top:1.5rem;display:flex;flex-direction:column;gap:1rem}.button-group{display:flex;gap:1rem}.history-card{flex:1}.history-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;padding-bottom:1rem;border-bottom:2px solid #e9ecef}.history-info{display:flex;align-items:center;gap:.75rem}.history-count{font-weight:600;color:#495057}.history-list{max-height:300px;overflow-y:auto}.history-item{padding:1rem;border-bottom:1px solid #e9ecef;cursor:pointer;transition:background .3s;display:flex;flex-direction:column;gap:.75rem}.history-item-header{display:flex;align-items:center;gap:.75rem}.history-meta{flex:1;display:flex;flex-direction:column;gap:.25rem}.history-item:hover{background:#f8f9fa}.history-item:last-child{border-bottom:none}.history-time{font-size:.85rem;color:#6c757d}.history-text{color:#495057;line-height:1.5}.empty-history{padding:2rem;text-align:center;color:#6c757d;font-style:italic}.right-panel{display:flex;flex-direction:column}.result-card{flex:1;display:flex;flex-direction:column}.result-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1rem}.result-badges{display:flex;gap:.5rem}.loading-container{flex:1;display:flex;align-items:center;justify-content:center}.empty-result{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1rem;color:#6c757d}.result-content{flex:1;display:flex;flex-direction:column}.summary-text{flex:1;background:#f8f9fa;padding:1.5rem;border-radius:8px;border:2px solid #e9ecef;font-family:Courier New,monospace;line-height:1.8;white-space:pre-wrap;word-wrap:break-word;overflow-y:auto;max-height:500px}.result-actions{margin-top:1rem;display:flex;justify-content:space-between;align-items:center}.result-info{display:flex;gap:.5rem}.empty-history{padding:2rem;text-align:center;color:#6c757d;font-style:italic;display:flex;flex-direction:column;align-items:center;gap:1rem}.empty-result{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1.5rem;color:#6c757d}.empty-icon{font-size:4rem;opacity:.5}@media (max-width: 1024px){.main-content{grid-template-columns:1fr;padding:1rem}.left-panel{order:1}.right-panel{order:2}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FmodeHeaderComponent, selector: "fmode-header", inputs: ["title", "subtitle"] }, { kind: "component", type: FmodeCardComponent, selector: "fmode-card", inputs: ["title"] }, { kind: "component", type: FmodeTextareaComponent, selector: "fmode-textarea", inputs: ["value", "placeholder", "label", "rows", "disabled", "maxLength", "showCharCount"], outputs: ["valueChange"] }, { kind: "component", type: FmodeSelectComponent, selector: "fmode-select", inputs: ["value", "label", "disabled", "options"], outputs: ["valueChange"] }, { kind: "component", type: FmodeButtonComponent, selector: "fmode-button", inputs: ["disabled", "type", "size"], outputs: ["onClick"] }, { kind: "component", type: FmodeLoadingComponent, selector: "fmode-loading", inputs: ["loadingText"] }, { kind: "component", type: FmodeAvatarComponent, selector: "fmode-avatar", inputs: ["name", "imageUrl", "size", "backgroundColor", "textColor", "alt", "rounded", "clickable"], outputs: ["onClick"] }, { kind: "component", type: FmodeBadgeComponent, selector: "fmode-badge", inputs: ["type", "pill", "outline"] }, { kind: "component", type: FmodeDividerComponent, selector: "fmode-divider", inputs: ["text", "vertical"] }, { kind: "component", type: FmodeTagComponent, selector: "fmode-tag", inputs: ["color", "closable"], outputs: ["onClose"] }, { kind: "component", type: FmodeDigitalHumanComponent, selector: "fmode-digital-human", inputs: ["size", "state", "speechText"] }] });
972
+ }
973
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AppComponent, decorators: [{
974
+ type: Component,
975
+ args: [{ selector: 'app-root', standalone: true, imports: [
976
+ CommonModule,
977
+ FmodeHeaderComponent,
978
+ FmodeCardComponent,
979
+ FmodeTextareaComponent,
980
+ FmodeSelectComponent,
981
+ FmodeButtonComponent,
982
+ FmodeLoadingComponent,
983
+ FmodeListComponent,
984
+ FmodeAvatarComponent,
985
+ FmodeBadgeComponent,
986
+ FmodeDividerComponent,
987
+ FmodeTagComponent,
988
+ FmodeDigitalHumanComponent
989
+ ], template: `
990
+ <div class="app-container">
991
+ <fmode-header title="AI 文本智能总结助手" subtitle="基于 fmode-ng UI 组件库"></fmode-header>
992
+
993
+ <div class="main-content">
994
+ <div class="left-panel">
995
+ <fmode-card title="文本输入" class="input-card">
996
+ <div class="input-header">
997
+ <fmode-avatar name="AI" size="large" backgroundColor="#667eea" textColor="#ffffff"></fmode-avatar>
998
+ <div class="input-info">
999
+ <h3>智能文本总结</h3>
1000
+ <p>输入长文本,AI 自动生成精简总结</p>
1001
+ </div>
1002
+ </div>
1003
+
1004
+ <div class="test-texts-section">
1005
+ <h4>测试文本</h4>
1006
+ <div class="test-texts-buttons">
1007
+ <fmode-button *ngFor="let testText of testTexts; let i = index"
1008
+ (onClick)="loadTestText(i)"
1009
+ type="secondary"
1010
+ size="small"
1011
+ >
1012
+ {{ testText.title }}
1013
+ </fmode-button>
1014
+ </div>
1015
+ </div>
1016
+
1017
+ <fmode-divider></fmode-divider>
1018
+
1019
+ <fmode-textarea
1020
+ [value]="inputText"
1021
+ (valueChange)="onInputTextChange($event)"
1022
+ placeholder="请输入需要总结的长文本内容..."
1023
+ [rows]="12"
1024
+ [disabled]="isLoading"
1025
+ [showCharCount]="true"
1026
+ [maxLength]="10000"
1027
+ ></fmode-textarea>
1028
+
1029
+ <div class="control-bar">
1030
+ <fmode-select
1031
+ [value]="summaryLength"
1032
+ (valueChange)="onSummaryLengthChange($event)"
1033
+ [options]="lengthOptions"
1034
+ label="总结长度"
1035
+ [disabled]="isLoading"
1036
+ ></fmode-select>
1037
+
1038
+ <div class="button-group">
1039
+ <fmode-button
1040
+ (onClick)="summarizeText()"
1041
+ [disabled]="isLoading"
1042
+ type="primary"
1043
+ >
1044
+ 智能总结
1045
+ </fmode-button>
1046
+ <fmode-button
1047
+ (onClick)="clearInput()"
1048
+ [disabled]="isLoading"
1049
+ type="secondary"
1050
+ >
1051
+ 清空
1052
+ </fmode-button>
1053
+ </div>
1054
+ </div>
1055
+ </fmode-card>
1056
+
1057
+ <fmode-card title="历史记录" class="history-card">
1058
+ <div class="history-header">
1059
+ <div class="history-info">
1060
+ <fmode-avatar name="历史" size="small" backgroundColor="#6c757d" textColor="#ffffff"></fmode-avatar>
1061
+ <span class="history-count">共 {{ history.length }} 条记录</span>
1062
+ </div>
1063
+ <fmode-button
1064
+ (onClick)="clearHistory()"
1065
+ [disabled]="history.length === 0"
1066
+ type="danger"
1067
+ >
1068
+ 清空历史
1069
+ </fmode-button>
1070
+ </div>
1071
+
1072
+ <fmode-divider></fmode-divider>
1073
+
1074
+ <div class="history-list">
1075
+ <div
1076
+ *ngFor="let item of history"
1077
+ (click)="loadHistoryItem(item)"
1078
+ class="history-item"
1079
+ >
1080
+ <div class="history-item-header">
1081
+ <fmode-avatar [name]="formatTime(item.timestamp)" size="small" backgroundColor="#17a2b8" textColor="#ffffff"></fmode-avatar>
1082
+ <div class="history-meta">
1083
+ <div class="history-time">{{ formatTime(item.timestamp) }}</div>
1084
+ <fmode-tag type="info">{{ item.originalText.length }} 字符</fmode-tag>
1085
+ </div>
1086
+ </div>
1087
+ <div class="history-text">{{ item.originalText.substring(0, 100) }}...</div>
1088
+ </div>
1089
+
1090
+ <div *ngIf="history.length === 0" class="empty-history">
1091
+ <fmode-avatar name="空" size="large" backgroundColor="#e9ecef" textColor="#6c757d"></fmode-avatar>
1092
+ <p>暂无历史记录</p>
1093
+ </div>
1094
+ </div>
1095
+ </fmode-card>
1096
+ </div>
1097
+
1098
+ <div class="right-panel">
1099
+ <fmode-card title="总结结果" class="result-card">
1100
+ <div class="result-header">
1101
+ <fmode-digital-human
1102
+ size="large"
1103
+ [state]="digitalHumanState"
1104
+ [speechText]="digitalHumanSpeech"
1105
+ ></fmode-digital-human>
1106
+ <div class="result-badges">
1107
+ <fmode-badge *ngIf="currentSummary" type="success" [pill]="true">已完成</fmode-badge>
1108
+ <fmode-badge *ngIf="!currentSummary" type="secondary" [pill]="true">等待中</fmode-badge>
1109
+ </div>
1110
+ </div>
1111
+
1112
+ <fmode-divider></fmode-divider>
1113
+
1114
+ <div *ngIf="isLoading" class="loading-container">
1115
+ <fmode-loading loadingText="正在智能总结中..."></fmode-loading>
1116
+ </div>
1117
+
1118
+ <div *ngIf="!isLoading && !currentSummary" class="empty-result">
1119
+ <fmode-avatar name="空" size="xlarge" backgroundColor="#e9ecef" textColor="#6c757d"></fmode-avatar>
1120
+ <p>输入文本并点击"智能总结"按钮</p>
1121
+ </div>
1122
+
1123
+ <div *ngIf="!isLoading && currentSummary" class="result-content">
1124
+ <pre class="summary-text">{{ currentSummary }}</pre>
1125
+
1126
+ <fmode-divider></fmode-divider>
1127
+
1128
+ <div class="result-actions">
1129
+ <div class="result-info">
1130
+ <fmode-tag type="success">{{ currentSummary.length }} 字符</fmode-tag>
1131
+ <fmode-tag type="primary">{{ summaryLength === 'short' ? '简短' : '详细' }}</fmode-tag>
1132
+ </div>
1133
+ <fmode-button
1134
+ (onClick)="copySummary()"
1135
+ type="success"
1136
+ >
1137
+ 复制结果
1138
+ </fmode-button>
1139
+ </div>
1140
+ </div>
1141
+ </fmode-card>
1142
+ </div>
1143
+ </div>
1144
+ </div>
1145
+ `, styles: [".app-container{min-height:100vh;background:linear-gradient(135deg,#f5f7fa,#e4e8eb)}.main-content{max-width:1400px;margin:0 auto;padding:2rem;display:grid;grid-template-columns:1fr 1fr;gap:2rem}.left-panel{display:flex;flex-direction:column;gap:2rem}.input-card{flex:1}.input-header{display:flex;align-items:center;gap:1rem;margin-bottom:1rem}.input-info{flex:1}.input-info h3{margin:0 0 .25rem;color:#495057;font-size:1.25rem}.input-info p{margin:0;color:#6c757d;font-size:.875rem}.test-texts-section{margin:1rem 0}.test-texts-section h4{margin:0 0 .75rem;color:#495057;font-size:1rem}.test-texts-buttons{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:.5rem}.input-badges{display:flex;gap:.5rem}.control-bar{margin-top:1.5rem;display:flex;flex-direction:column;gap:1rem}.button-group{display:flex;gap:1rem}.history-card{flex:1}.history-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;padding-bottom:1rem;border-bottom:2px solid #e9ecef}.history-info{display:flex;align-items:center;gap:.75rem}.history-count{font-weight:600;color:#495057}.history-list{max-height:300px;overflow-y:auto}.history-item{padding:1rem;border-bottom:1px solid #e9ecef;cursor:pointer;transition:background .3s;display:flex;flex-direction:column;gap:.75rem}.history-item-header{display:flex;align-items:center;gap:.75rem}.history-meta{flex:1;display:flex;flex-direction:column;gap:.25rem}.history-item:hover{background:#f8f9fa}.history-item:last-child{border-bottom:none}.history-time{font-size:.85rem;color:#6c757d}.history-text{color:#495057;line-height:1.5}.empty-history{padding:2rem;text-align:center;color:#6c757d;font-style:italic}.right-panel{display:flex;flex-direction:column}.result-card{flex:1;display:flex;flex-direction:column}.result-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1rem}.result-badges{display:flex;gap:.5rem}.loading-container{flex:1;display:flex;align-items:center;justify-content:center}.empty-result{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1rem;color:#6c757d}.result-content{flex:1;display:flex;flex-direction:column}.summary-text{flex:1;background:#f8f9fa;padding:1.5rem;border-radius:8px;border:2px solid #e9ecef;font-family:Courier New,monospace;line-height:1.8;white-space:pre-wrap;word-wrap:break-word;overflow-y:auto;max-height:500px}.result-actions{margin-top:1rem;display:flex;justify-content:space-between;align-items:center}.result-info{display:flex;gap:.5rem}.empty-history{padding:2rem;text-align:center;color:#6c757d;font-style:italic;display:flex;flex-direction:column;align-items:center;gap:1rem}.empty-result{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1.5rem;color:#6c757d}.empty-icon{font-size:4rem;opacity:.5}@media (max-width: 1024px){.main-content{grid-template-columns:1fr;padding:1rem}.left-panel{order:1}.right-panel{order:2}}\n"] }]
1146
+ }] });
1147
+
1148
+ // 导出组件和模块
1149
+
1150
+ /**
1151
+ * Generated bundle index. Do not edit.
1152
+ */
1153
+
1154
+ export { AppComponent, FmodeAvatarComponent, FmodeBadgeComponent, FmodeButtonComponent, FmodeCardComponent, FmodeDigitalHumanComponent, FmodeDividerComponent, FmodeHeaderComponent, FmodeListComponent, FmodeLoadingComponent, FmodeSelectComponent, FmodeTagComponent, FmodeTextareaComponent };
1155
+ //# sourceMappingURL=ai-text-summary-ng.mjs.map