import { Clipboard } from '@angular/cdk/clipboard'; import { Component, DestroyRef, Input, inject, signal } from '@angular/core'; @Component({ selector: 'app-task-id-copy', standalone: true, template: ` ID: {{ taskId }} {{ feedback() }} `, styles: [` :host { display: block; min-width: 0; font-size: 11px; color: inherit; user-select: text; } .copy-target { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; padding: 3px 0; cursor: pointer; user-select: text; border-radius: 3px; } .value { min-width: 0; overflow-wrap: anywhere; user-select: text; } .material-symbols-outlined { flex-shrink: 0; font-size: 14px; user-select: none; } .copy-target:hover { color: var(--app-primary-text, #2563eb); } .copy-target:focus-visible { outline: 2px solid #60a5fa; outline-offset: 2px; } .feedback { display: block; line-height: 1.6; user-select: text; } .feedback:empty { display: none; } `] }) export class TaskIdCopyComponent { @Input({ required: true }) taskId = ''; readonly feedback = signal(''); private readonly clipboard = inject(Clipboard); private readonly destroyRef = inject(DestroyRef); private timer: ReturnType | undefined; constructor() { this.destroyRef.onDestroy(() => clearTimeout(this.timer)); } async copy(event: Event): Promise { event.stopPropagation(); // A drag selection must remain available for the browser's normal copy action. const selection = window.getSelection(); if (event.type === 'click' && selection && !selection.isCollapsed && (event.currentTarget as HTMLElement).contains(selection.anchorNode)) return; event.preventDefault(); let copied = false; try { if (navigator.clipboard?.writeText) { await navigator.clipboard.writeText(this.taskId); copied = true; } else { copied = this.clipboard.copy(this.taskId); } } catch { try { copied = this.clipboard.copy(this.taskId); } catch { // Keep manual selection available when the browser blocks both clipboard APIs. } } if (this.destroyRef.destroyed) return; this.feedback.set(copied ? '任务 ID 已复制' : '复制失败,请选中任务 ID 手动复制'); clearTimeout(this.timer); this.timer = setTimeout(() => this.feedback.set(''), 3000); } }