feat: 完善知识库、策略预览与OnlyOffice集成
## 配置与环境 - .env.example: 更新环境变量配置 - docker-compose.yml: 完善Docker编排配置 - docker/README.md: 更新Docker文档 ## 后端知识库模块 - endpoints/knowledge.py: 增强知识库API端点 - schemas/knowledge.py: 扩展知识库数据模型 - services/knowledge.py: 完善知识库业务逻辑 - config.py: 优化配置管理 - storage/knowledge/.index.json: 更新知识库索引 ## 前端功能 - api.js: 完善API服务层 - knowledge.js: 优化知识库服务 - onlyoffice.js: 新增OnlyOffice文档服务集成 - TopBar.vue: 优化顶部导航栏 - PoliciesView.vue: 完善策略视图 - AppShellRouteView.vue: 新增应用外壳路由视图 - views/scripts/PoliciesView.js: 优化策略脚本 - policiesPreviewFormatters.js: 新增策略预览格式化工具 ## 样式 - policies-view.css: 完善策略页样式 ## 测试 - api-request.test.mjs: API请求测试 - onlyoffice-service.test.mjs: OnlyOffice服务测试 - policies-preview-formatters.test.mjs: 策略预览格式化测试
This commit is contained in:
@@ -1,4 +1,37 @@
|
||||
const API_BASE_STORAGE_KEY = 'x-financial-api-base-url'
|
||||
const AUTH_USER_STORAGE_KEY = 'x-financial-auth-user'
|
||||
|
||||
function readCurrentUserHeaders() {
|
||||
if (typeof window === 'undefined') {
|
||||
return {}
|
||||
}
|
||||
|
||||
const raw = window.sessionStorage.getItem(AUTH_USER_STORAGE_KEY)
|
||||
if (!raw) {
|
||||
return {}
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = JSON.parse(raw)
|
||||
const username = String(payload?.username || '').trim()
|
||||
const name = String(payload?.name || username).trim()
|
||||
const roleCodes = Array.isArray(payload?.roleCodes) ? payload.roleCodes.filter(Boolean) : []
|
||||
const isAdmin = Boolean(payload?.isAdmin)
|
||||
|
||||
if (!username && !name) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
'x-auth-username': username,
|
||||
'x-auth-name': name,
|
||||
'x-auth-role-codes': roleCodes.join(','),
|
||||
'x-auth-is-admin': String(isAdmin)
|
||||
}
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeApiBaseUrl(value) {
|
||||
return String(value || '/api/v1').replace(/\/$/, '')
|
||||
@@ -66,22 +99,50 @@ function buildUrl(path) {
|
||||
}
|
||||
|
||||
export async function apiRequest(path, options = {}) {
|
||||
const {
|
||||
contentType = 'application/json',
|
||||
responseType = 'json',
|
||||
headers: customHeaders,
|
||||
...fetchOptions
|
||||
} = options
|
||||
|
||||
const headers = {
|
||||
...readCurrentUserHeaders(),
|
||||
...(customHeaders || {})
|
||||
}
|
||||
|
||||
if (contentType !== null && typeof headers['Content-Type'] === 'undefined') {
|
||||
headers['Content-Type'] = contentType
|
||||
}
|
||||
|
||||
let response
|
||||
|
||||
try {
|
||||
response = await fetch(buildUrl(path), {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...(options.headers || {})
|
||||
},
|
||||
...options
|
||||
...fetchOptions,
|
||||
headers
|
||||
})
|
||||
} catch {
|
||||
throw new Error('无法连接 FastAPI 后端服务,请确认后端已启动且浏览器可访问后端端口。')
|
||||
}
|
||||
|
||||
let payload = null
|
||||
if (responseType === 'blob') {
|
||||
if (!response.ok) {
|
||||
let payload = null
|
||||
|
||||
try {
|
||||
payload = await response.json()
|
||||
} catch {
|
||||
payload = null
|
||||
}
|
||||
|
||||
throw new Error(payload?.detail || '接口请求失败,请稍后重试。')
|
||||
}
|
||||
|
||||
return response.blob()
|
||||
}
|
||||
|
||||
let payload = null
|
||||
try {
|
||||
payload = await response.json()
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user