| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152 |
- import { Component, input, model, output, signal } from '@angular/core';
- import { UiButton } from '../button/button';
- /**
- * 上传头像:圆形头像预览 + 上传/删除(操作按钮复用 ui-button),
- * 读取本地文件为 dataURL;文件输入为浏览器原生能力,组件内部持有。
- */
- @Component({
- selector: 'ui-upload-avatar',
- imports: [UiButton],
- templateUrl: './upload-avatar.html',
- styleUrl: './upload-avatar.scss',
- })
- export class UiUploadAvatar {
- /** 头像地址(dataURL 或 URL,双向绑定) */
- readonly src = model<string>('');
- /** 头像直径(px) */
- readonly size = input(80);
- /** 是否圆形 */
- readonly circle = input(true, { transform: (v: unknown) => v === true || v === 'true' });
- /** 空态图标 */
- readonly icon = input('fa-solid fa-camera');
- /** 上传成功(拿到 dataURL)时触发 */
- readonly change = output<string>();
- /** 校验通过后输出原始 File(供业务方走真实上传链路) */
- readonly changeFile = output<File>();
- protected readonly uploading = signal(false);
- protected onPick(e: Event): void {
- const input = e.currentTarget as HTMLInputElement;
- const file = input.files?.[0];
- input.value = '';
- if (!file || !file.type.startsWith('image/')) return;
- this.uploading.set(true);
- this.changeFile.emit(file);
- const reader = new FileReader();
- reader.onload = () => {
- this.uploading.set(false);
- if (typeof reader.result === 'string') {
- this.src.set(reader.result);
- this.change.emit(reader.result);
- }
- };
- reader.onerror = () => this.uploading.set(false);
- reader.readAsDataURL(file);
- }
- protected remove(): void {
- this.src.set('');
- }
- }
|