feat: 完成后台联调与通用列表组件

This commit is contained in:
2026-08-01 12:17:33 +08:00
parent b53fe81999
commit 29dbae573f
50 changed files with 3394 additions and 580 deletions
+31
View File
@@ -0,0 +1,31 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { copyText } from './copyText'
describe('copyText', () => {
afterEach(() => {
vi.restoreAllMocks()
vi.unstubAllGlobals()
Reflect.deleteProperty(document, 'execCommand')
document.querySelectorAll('textarea[aria-hidden="true"]').forEach((element) => element.remove())
})
it('uses the Clipboard API when it is available', async () => {
const writeText = vi.fn().mockResolvedValue(undefined)
vi.stubGlobal('navigator', { clipboard: { writeText } })
await copyText('request-123')
expect(writeText).toHaveBeenCalledWith('request-123')
})
it('falls back to a temporary textarea when Clipboard API access is denied', async () => {
vi.stubGlobal('navigator', { clipboard: { writeText: vi.fn().mockRejectedValue(new Error('denied')) } })
const execCommand = vi.fn().mockReturnValue(true)
Object.defineProperty(document, 'execCommand', { configurable: true, value: execCommand })
await copyText('trace-456')
expect(execCommand).toHaveBeenCalledWith('copy')
expect(document.querySelector('textarea[aria-hidden="true"]')).toBeNull()
})
})
+35
View File
@@ -0,0 +1,35 @@
export async function copyText(value: string) {
if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {
try {
await navigator.clipboard.writeText(value)
return
} catch {
// In insecure development contexts the Clipboard API may exist but reject.
}
}
if (typeof document === 'undefined' || !document.body) {
throw new Error('Clipboard is unavailable')
}
const textarea = document.createElement('textarea')
textarea.value = value
textarea.readOnly = true
textarea.setAttribute('aria-hidden', 'true')
Object.assign(textarea.style, {
position: 'fixed',
inset: '0 auto auto -9999px',
opacity: '0',
pointerEvents: 'none',
})
document.body.appendChild(textarea)
textarea.select()
try {
if (typeof document.execCommand !== 'function' || !document.execCommand('copy')) {
throw new Error('Clipboard copy failed')
}
} finally {
textarea.remove()
}
}
+1
View File
@@ -13,5 +13,6 @@ export function mapPlatformPermission(item: PlatformPermissionResource): Permiss
method: item.httpMethod ?? '-',
status: item.status === 'ACTIVE' ? '启用' : '停用',
sort: item.sortNo,
builtIn: Boolean(item.builtIn),
}
}