fix: harden security and tune task performance
This commit is contained in:
@@ -6,9 +6,6 @@
|
||||
<meta name="color-scheme" content="dark" />
|
||||
<meta name="theme-color" content="#0F172A" />
|
||||
<title>SVN 日志工作台 v2</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@300;400;500;600;700&family=Fira+Code:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -29,8 +29,10 @@ const HTTP_ERRORS = {
|
||||
}
|
||||
|
||||
export function useApi() {
|
||||
const apiBaseUrl = normalizeApiBaseUrl(import.meta.env.VITE_API_BASE_URL || '')
|
||||
|
||||
async function apiFetch(url, options = {}) {
|
||||
const res = await fetch(url, {
|
||||
const res = await fetch(buildApiUrl(url), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
...options,
|
||||
})
|
||||
@@ -44,7 +46,7 @@ export function useApi() {
|
||||
}
|
||||
|
||||
function buildDownloadUrl(path) {
|
||||
return `/api/files/download?path=${encodeURIComponent(path || '')}`
|
||||
return buildApiUrl(`/api/files/download?path=${encodeURIComponent(path || '')}`)
|
||||
}
|
||||
|
||||
async function downloadFile(path) {
|
||||
@@ -72,5 +74,16 @@ export function useApi() {
|
||||
URL.revokeObjectURL(blobUrl)
|
||||
}
|
||||
|
||||
function buildApiUrl(path) {
|
||||
if (/^https?:\/\//i.test(path)) return path
|
||||
return `${apiBaseUrl}${path.startsWith('/') ? path : `/${path}`}`
|
||||
}
|
||||
|
||||
return { apiFetch, buildDownloadUrl, downloadFile }
|
||||
}
|
||||
|
||||
function normalizeApiBaseUrl(value) {
|
||||
const trimmed = String(value || '').trim()
|
||||
if (!trimmed) return ''
|
||||
return trimmed.replace(/\/+$/, '')
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
SVN Log Tool v2 — OLED Dark Theme
|
||||
Design System: Dark Mode (OLED) by UI/UX Pro Max
|
||||
Colors: #0F172A bg, #1E293B surface, #22C55E accent
|
||||
Fonts: Fira Sans (body), Fira Code (heading/data)
|
||||
Fonts: system UI stack with monospace data display
|
||||
============================================= */
|
||||
|
||||
:root {
|
||||
@@ -29,8 +29,8 @@
|
||||
--c-info-bg: rgba(59, 130, 246, 0.12);
|
||||
--c-code-bg: #0C1929;
|
||||
|
||||
--font-sans: 'Fira Sans', system-ui, -apple-system, sans-serif;
|
||||
--font-mono: 'Fira Code', 'JetBrains Mono', 'Consolas', monospace;
|
||||
--font-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
--font-mono: 'SFMono-Regular', 'Cascadia Code', 'Consolas', monospace;
|
||||
|
||||
--space-xs: 4px;
|
||||
--space-sm: 8px;
|
||||
|
||||
@@ -88,6 +88,7 @@ const { toast } = useToast()
|
||||
const tasks = ref([])
|
||||
const files = ref([])
|
||||
const health = ref(null)
|
||||
const pollIntervalMs = resolvePollInterval()
|
||||
let timer = null
|
||||
|
||||
const stats = computed(() => ({
|
||||
@@ -153,7 +154,7 @@ async function cancelTask(taskId) {
|
||||
|
||||
onMounted(() => {
|
||||
refresh()
|
||||
timer = setInterval(refresh, 8000)
|
||||
timer = setInterval(refresh, pollIntervalMs)
|
||||
document.addEventListener('visibilitychange', onVisibilityChange)
|
||||
})
|
||||
onUnmounted(() => {
|
||||
@@ -166,7 +167,13 @@ function onVisibilityChange() {
|
||||
if (timer) { clearInterval(timer); timer = null }
|
||||
} else {
|
||||
refresh()
|
||||
if (!timer) timer = setInterval(refresh, 8000)
|
||||
if (!timer) timer = setInterval(refresh, pollIntervalMs)
|
||||
}
|
||||
}
|
||||
|
||||
function resolvePollInterval() {
|
||||
const value = Number(import.meta.env.VITE_DASHBOARD_POLL_INTERVAL_MS || 8000)
|
||||
if (!Number.isFinite(value)) return 8000
|
||||
return Math.max(3000, value)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -22,5 +22,12 @@ export default defineConfig({
|
||||
build: {
|
||||
outDir: resolve(__dirname, '..', 'src', 'main', 'resources', 'static', 'v2'),
|
||||
emptyOutDir: true,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: {
|
||||
vendor: ['vue', 'vue-router'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user