feat: add Docker support and update backend dependencies

- Introduced `requirements.docker.txt` for Docker-specific dependencies.
- Updated `requirements.txt` to include `psycopg[binary]` and `python-multipart`.
- Enhanced test suite in `test_main_endpoints.py` to cover document CRUD operations.
- Modified `docker-compose.yml` to include PostgreSQL and frontend services.
- Added Nginx configuration for reverse proxying API requests.
- Refactored file handling in Vue components to support new document storage backend.
- Created new utility functions in `docsApi.js` for document management.
- Updated configuration to support new API endpoints for document operations.
- Adjusted Vite configuration to proxy API requests to the local backend.
This commit is contained in:
“ydy0615”
2026-06-06 17:18:15 +08:00
parent 81f711ef0b
commit b55af1eff0
20 changed files with 1413 additions and 407 deletions
+120
View File
@@ -0,0 +1,120 @@
import {
API_KEY,
DOCS_BLOB_BASE_URL,
DOCS_FOLDERS_URL,
DOCS_NODES_BASE_URL,
DOCS_NODES_URL,
DOCS_TEXT_FILES_URL,
DOCS_UPLOAD_URL,
} from './config.js'
function buildHeaders(extra = {}) {
return {
'X-API-Key': API_KEY,
...extra,
}
}
async function parseJsonResponse(res) {
if (!res.ok) {
let message = `HTTP ${res.status}`
try {
const data = await res.json()
message = data.detail || data.error || message
} catch {
const text = await res.text()
if (text) message = text
}
throw new Error(message)
}
return res.json()
}
export async function fetchDocNodes() {
const res = await fetch(DOCS_NODES_URL, {
headers: buildHeaders(),
})
const data = await parseJsonResponse(res)
return Array.isArray(data.nodes) ? data.nodes : []
}
export async function createDocFolder(name, parentId = null) {
const res = await fetch(DOCS_FOLDERS_URL, {
method: 'POST',
headers: buildHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ name, parentId }),
})
const data = await parseJsonResponse(res)
return data.node
}
export async function createDocTextFile(name, parentId = null, content = '') {
const res = await fetch(DOCS_TEXT_FILES_URL, {
method: 'POST',
headers: buildHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ name, parentId, content }),
})
const data = await parseJsonResponse(res)
return data.node
}
export async function uploadDocFile(file, parentId = null) {
const formData = new FormData()
formData.append('file', file)
formData.append('parent_id', parentId || '')
const res = await fetch(DOCS_UPLOAD_URL, {
method: 'POST',
headers: buildHeaders(),
body: formData,
})
const data = await parseJsonResponse(res)
return data.node
}
export async function updateDocNode(nodeId, payload) {
const res = await fetch(`${DOCS_NODES_BASE_URL}/${encodeURIComponent(nodeId)}`, {
method: 'PATCH',
headers: buildHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify(payload),
})
const data = await parseJsonResponse(res)
return data.node
}
export async function replaceDocBlob(nodeId, file) {
const formData = new FormData()
formData.append('file', file, file.name || 'file')
const res = await fetch(`${DOCS_BLOB_BASE_URL}/${encodeURIComponent(nodeId)}/blob`, {
method: 'PUT',
headers: buildHeaders(),
body: formData,
})
const data = await parseJsonResponse(res)
return data.node
}
export async function deleteDocNode(nodeId) {
const res = await fetch(`${DOCS_NODES_BASE_URL}/${encodeURIComponent(nodeId)}`, {
method: 'DELETE',
headers: buildHeaders(),
})
return parseJsonResponse(res)
}
export async function fetchDocBlob(nodeId) {
const res = await fetch(`${DOCS_BLOB_BASE_URL}/${encodeURIComponent(nodeId)}/blob`, {
headers: buildHeaders(),
})
if (!res.ok) {
let message = `HTTP ${res.status}`
try {
const data = await res.json()
message = data.detail || data.error || message
} catch {
const text = await res.text()
if (text) message = text
}
throw new Error(message)
}
return res.blob()
}