refactor(web): update service clients

- services/agentAssets.js: update agent assets service client
- services/api.js: update API service client
- services/employees.js: update employees service client
This commit is contained in:
caoxiaozhu
2026-05-14 02:58:35 +00:00
parent 3c28cab288
commit feacf2765d
3 changed files with 124 additions and 47 deletions

View File

@@ -1,4 +1,4 @@
import { apiRequest } from './api.js'
import { apiRequest, pickSafeHeaderValue } from './api.js'
const AUTH_USER_STORAGE_KEY = 'x-financial-auth-user'
@@ -14,7 +14,11 @@ function readActorName() {
try {
const payload = JSON.parse(raw)
return String(payload?.name || payload?.username || 'system').trim() || 'system'
return (
pickSafeHeaderValue(payload?.name, payload?.username) ||
pickSafeHeaderValue(payload?.username, 'system') ||
'system'
)
} catch {
return 'system'
}

View File

@@ -1,6 +1,36 @@
const API_BASE_STORAGE_KEY = 'x-financial-api-base-url'
const AUTH_USER_STORAGE_KEY = 'x-financial-auth-user'
function isHeaderValueSafe(value) {
const normalized = String(value || '').trim()
if (!normalized) {
return false
}
for (let index = 0; index < normalized.length; index += 1) {
const codePoint = normalized.charCodeAt(index)
if (codePoint > 255 || codePoint === 10 || codePoint === 13 || codePoint === 0) {
return false
}
}
return true
}
export function pickSafeHeaderValue(value, fallback = '') {
const normalized = String(value || '').trim()
if (isHeaderValueSafe(normalized)) {
return normalized
}
const fallbackValue = String(fallback || '').trim()
if (isHeaderValueSafe(fallbackValue)) {
return fallbackValue
}
return ''
}
function readCurrentUserHeaders() {
if (typeof window === 'undefined') {
return {}
@@ -17,17 +47,27 @@ function readCurrentUserHeaders() {
const name = String(payload?.name || username).trim()
const roleCodes = Array.isArray(payload?.roleCodes) ? payload.roleCodes.filter(Boolean) : []
const isAdmin = Boolean(payload?.isAdmin)
const safeUsername = pickSafeHeaderValue(username)
const safeName = pickSafeHeaderValue(name)
if (!username && !name) {
if (!safeUsername && !safeName) {
return {}
}
return {
'x-auth-username': username,
'x-auth-name': name,
const headers = {
'x-auth-role-codes': roleCodes.join(','),
'x-auth-is-admin': String(isAdmin)
}
if (safeUsername) {
headers['x-auth-username'] = safeUsername
}
if (safeName) {
headers['x-auth-name'] = safeName
}
return headers
} catch {
return {}
}
@@ -158,6 +198,29 @@ function resolveErrorMessage(payload, fallback = '接口请求失败,请稍后
return fallback
}
function sanitizeHeaders(headers) {
const nextHeaders = {}
Object.entries(headers || {}).forEach(([key, value]) => {
if (typeof value === 'undefined' || value === null) {
return
}
const normalizedValue = String(value).trim()
if (!normalizedValue) {
return
}
if (!isHeaderValueSafe(normalizedValue)) {
return
}
nextHeaders[key] = normalizedValue
})
return nextHeaders
}
export async function apiRequest(path, options = {}) {
const {
contentType = 'application/json',
@@ -166,10 +229,10 @@ export async function apiRequest(path, options = {}) {
...fetchOptions
} = options
const headers = {
const headers = sanitizeHeaders({
...readCurrentUserHeaders(),
...(customHeaders || {})
}
})
if (contentType !== null && typeof headers['Content-Type'] === 'undefined') {
headers['Content-Type'] = contentType
@@ -182,7 +245,11 @@ export async function apiRequest(path, options = {}) {
...fetchOptions,
headers
})
} catch {
} catch (error) {
if (String(error?.message || '').includes('ByteString')) {
throw new Error('当前登录用户信息包含浏览器不支持的请求头字符,请重新登录后重试。')
}
throw new Error('无法连接 FastAPI 后端服务,请确认后端已启动且浏览器可访问后端端口。')
}

View File

@@ -35,3 +35,9 @@ export function disableEmployee(employeeId) {
method: 'POST'
})
}
export function enableEmployee(employeeId) {
return apiRequest(`/employees/${employeeId}/enable`, {
method: 'POST'
})
}