feat(nginx): configure client max body size and update timeouts for API proxy
Deployment Config CI / Deployment Config (push) Successful in 15s
Frontend CI / Frontend (push) Successful in 2m16s

feat(clipboard): implement copyTextToClipboard utility function
feat(desktop): add upload timeout for desktop client release API
feat(k3s): add nginx config and update kustomization for ops-web
This commit is contained in:
2026-05-31 15:01:14 +08:00
parent 9dfc3746c3
commit de9c52be6d
7 changed files with 130 additions and 7 deletions
+44
View File
@@ -0,0 +1,44 @@
export async function copyTextToClipboard(text: string): Promise<void> {
if (!text) {
throw new Error('clipboard_empty_text')
}
if (window.isSecureContext && navigator.clipboard?.writeText) {
try {
await navigator.clipboard.writeText(text)
return
} catch {
// Fall back to execCommand for browsers that expose clipboard but deny it.
}
}
if (copyTextWithSelection(text)) {
return
}
throw new Error('clipboard_write_failed')
}
function copyTextWithSelection(text: string): boolean {
const textarea = document.createElement('textarea')
const activeElement = document.activeElement instanceof HTMLElement ? document.activeElement : null
textarea.value = text
textarea.setAttribute('readonly', '')
textarea.style.position = 'fixed'
textarea.style.top = '0'
textarea.style.left = '-9999px'
textarea.style.opacity = '0'
document.body.appendChild(textarea)
textarea.focus()
textarea.select()
textarea.setSelectionRange(0, text.length)
try {
return document.execCommand('copy')
} finally {
document.body.removeChild(textarea)
activeElement?.focus({ preventScroll: true })
}
}
@@ -75,6 +75,8 @@ export interface DesktopClientReleaseDownloadURLResult {
expires_in?: number | null
}
const DESKTOP_CLIENT_RELEASE_UPLOAD_TIMEOUT_MS = 15 * 60 * 1000
export const platformOptions = [
{ label: 'macOS', value: 'darwin' },
{ label: 'Windows', value: 'win32' },
@@ -138,7 +140,9 @@ export const desktopClientReleaseApi = {
code: number
message: string
data: DesktopClientReleaseUploadResult
}>('/desktop-client/releases/upload', form)
}>('/desktop-client/releases/upload', form, {
timeout: DESKTOP_CLIENT_RELEASE_UPLOAD_TIMEOUT_MS,
})
return response.data.data
},
resolveDownloadURL(id: number) {
@@ -357,6 +357,7 @@ import {
type DesktopReleasePlatform,
type DesktopReleaseSource,
} from '@/lib/desktop-client-releases'
import { copyTextToClipboard } from '@/lib/clipboard'
import { showOpsError } from '@/lib/errors'
const enabledOptions = [
@@ -763,19 +764,31 @@ async function deleteRelease(row: DesktopClientRelease) {
}
async function copyDownloadURL(row: DesktopClientRelease) {
let downloadURL = ''
try {
const result = await desktopClientReleaseApi.resolveDownloadURL(row.id)
await navigator.clipboard.writeText(result.download_url)
message.success('下载地址已复制')
downloadURL = result.download_url
} catch (error) {
showOpsError(error)
return
}
try {
await copyTextToClipboard(downloadURL)
message.success('下载地址已复制')
} catch {
message.error('复制失败,请在接口返回中手动复制下载地址')
}
}
async function copyFormDownloadURL() {
if (form.download_url) {
await navigator.clipboard.writeText(form.download_url)
message.success('下载地址已复制')
try {
await copyTextToClipboard(form.download_url)
message.success('下载地址已复制')
} catch {
message.error('复制失败,请手动复制下载地址')
}
return
}
if (!editingRow.value?.id) return