/** * 页面标记组件 —— 在网页上显示一个固定位置的“已锁定”标记 */ export interface PageMarkerOptions { /** 标记显示的文本,默认为“🔒 已锁定” */ text?: string; /** 位置预设:'top-right' | 'top-left' | 'bottom-right' | 'bottom-left',默认 'top-right' */ position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'; /** 背景色,默认 rgba(0,0,0,0.75) */ backgroundColor?: string; /** 字体颜色,默认 #fff */ color?: string; /** 自定义样式,会与默认样式合并 */ customStyle?: Partial; /** 几秒后自动消失,设为 0 则永久存在,默认 0 */ autoRemoveSeconds?: number; /** 是否允许用户点击关闭,默认 false */ closable?: boolean; } export class PageMarker { private element: HTMLDivElement | null = null; private timer: ReturnType | null = null; constructor(private options: PageMarkerOptions = {}) {} /** * 在页面上显示标记 */ show(): void { if (this.element) this.hide(); const { text = '🔒 已锁定', position = 'top-right', backgroundColor = 'rgba(0,0,0,0.75)', color = '#fff', autoRemoveSeconds = 0, closable = false, customStyle = {}, } = this.options; const el = document.createElement('div'); el.textContent = text; el.title = '此页面已被插件锁定'; const baseStyle: Record = { position: 'fixed', zIndex: '99999', padding: '6px 14px', borderRadius: '4px', fontSize: '13px', fontFamily: 'Arial, sans-serif', fontWeight: '600', backgroundColor, color, boxShadow: '0 2px 8px rgba(0,0,0,0.3)', pointerEvents: closable ? 'auto' : 'none', userSelect: 'none', transition: 'opacity 0.2s ease', ...positionStyles(position), ...(customStyle as Record), }; Object.assign(el.style, baseStyle); // 可关闭按钮 if (closable) { const closeBtn = document.createElement('span'); closeBtn.textContent = '×'; closeBtn.style.cssText = 'margin-left:8px;cursor:pointer;font-weight:bold;opacity:0.7'; closeBtn.addEventListener('click', (e) => { e.stopPropagation(); this.hide(); }); el.appendChild(closeBtn); } document.body.appendChild(el); this.element = el; if (autoRemoveSeconds > 0) { this.timer = setTimeout(() => this.hide(), autoRemoveSeconds * 1000); } } /** * 隐藏/移除标记 */ hide(): void { if (this.element) { this.element.style.opacity = '0'; setTimeout(() => { this.element?.remove(); this.element = null; }, 200); } if (this.timer) { clearTimeout(this.timer); this.timer = null; } } /** * 更新标记文本 */ updateText(text: string): void { if (!this.element) return; // 保留关闭按钮 const closeBtn = this.element.querySelector('span'); this.element.childNodes.forEach(node => { if (node !== closeBtn) node.remove(); }); this.element.prepend(document.createTextNode(text)); } /** * 标记当前是否已显示 */ get isVisible(): boolean { return !!this.element; } } function positionStyles(pos: string): Record { const offset = '12px'; switch (pos) { case 'top-right': return { top: offset, right: offset }; case 'top-left': return { top: offset, left: offset }; case 'bottom-right': return { bottom: offset, right: offset }; case 'bottom-left': return { bottom: offset, left: offset }; default: return { top: offset, right: offset }; } } /** * 快捷函数:直接显示一个简单标记 */ export function showPageMarker(options?: PageMarkerOptions): PageMarker { const marker = new PageMarker(options); marker.show(); return marker; }