feat(思维导图助手):文档文件上传后缀保持一致
parent
64ac579c2a
commit
59cbda30e2
|
|
@ -38,7 +38,7 @@ RUN python3 -m pip install -U pip -i https://mirrors.aliyun.com/pypi/simple && \
|
||||||
python3 -m pip install \
|
python3 -m pip install \
|
||||||
"numpy==1.26.4" \
|
"numpy==1.26.4" \
|
||||||
"opencv-python==4.11.0.86" \
|
"opencv-python==4.11.0.86" \
|
||||||
"pydantic<2.0" \
|
"pydantic>=2.12,<3" \
|
||||||
"modelscope" \
|
"modelscope" \
|
||||||
"magic-pdf" \
|
"magic-pdf" \
|
||||||
-i https://mirrors.aliyun.com/pypi/simple && \
|
-i https://mirrors.aliyun.com/pypi/simple && \
|
||||||
|
|
@ -73,4 +73,4 @@ RUN /bin/bash -c "export MINERU_MODEL_SOURCE=local && mineru-models-download -s
|
||||||
|
|
||||||
# 7. 入口点
|
# 7. 入口点
|
||||||
ENTRYPOINT ["/bin/bash", "-c", "exec \"$@\"", "--"]
|
ENTRYPOINT ["/bin/bash", "-c", "exec \"$@\"", "--"]
|
||||||
CMD ["python3", "-m", "mineru.cli.main"]
|
CMD ["python3", "-m", "mineru.cli.main"]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Portable Web UI image for UnisMindMap.
|
||||||
|
# Runtime API upstream is configured by MINERU_API_URL, defaulting to Docker DNS name mineru-api.
|
||||||
|
FROM node:18-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm config set registry https://registry.npmmirror.com && npm install
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM nginx:alpine
|
||||||
|
ENV MINERU_API_URL=http://mineru-api:8000
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
COPY nginx.conf.template /etc/nginx/templates/default.conf.template
|
||||||
|
EXPOSE 9898
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
server {
|
||||||
|
listen 9898;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
access_log /var/log/nginx/access.log;
|
||||||
|
error_log /var/log/nginx/error.log;
|
||||||
|
|
||||||
|
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /file_parse {
|
||||||
|
proxy_pass ${MINERU_API_URL}/file_parse;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
client_max_body_size 100M;
|
||||||
|
proxy_connect_timeout 300s;
|
||||||
|
proxy_send_timeout 300s;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass ${MINERU_API_URL}/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
client_max_body_size 100M;
|
||||||
|
proxy_connect_timeout 300s;
|
||||||
|
proxy_send_timeout 300s;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -67,6 +67,7 @@ function loadCachedConfig(): Partial<DocumentConfig> {
|
||||||
export function useDocumentProcessor() {
|
export function useDocumentProcessor() {
|
||||||
// 文件相关
|
// 文件相关
|
||||||
const uploadedFiles: Ref<File[]> = ref([])
|
const uploadedFiles: Ref<File[]> = ref([])
|
||||||
|
const uploadedDisplayFiles: Ref<File[]> = ref([])
|
||||||
const isUploading = ref(false)
|
const isUploading = ref(false)
|
||||||
|
|
||||||
// 配置相关
|
// 配置相关
|
||||||
|
|
@ -127,8 +128,10 @@ export function useDocumentProcessor() {
|
||||||
if (!files || files.length === 0) return
|
if (!files || files.length === 0) return
|
||||||
|
|
||||||
const validFiles: File[] = []
|
const validFiles: File[] = []
|
||||||
|
const displayFiles: File[] = []
|
||||||
const file = files[0]
|
const file = files[0]
|
||||||
uploadedFiles.value = []
|
uploadedFiles.value = []
|
||||||
|
uploadedDisplayFiles.value = []
|
||||||
results.value = null
|
results.value = null
|
||||||
error.value = null
|
error.value = null
|
||||||
if (files.length > 1) {
|
if (files.length > 1) {
|
||||||
|
|
@ -167,6 +170,7 @@ export function useDocumentProcessor() {
|
||||||
isUploading.value = true
|
isUploading.value = true
|
||||||
const markdown = await file.text()
|
const markdown = await file.text()
|
||||||
validFiles.push(file)
|
validFiles.push(file)
|
||||||
|
displayFiles.push(file)
|
||||||
results.value = {
|
results.value = {
|
||||||
markdown,
|
markdown,
|
||||||
source: markdown,
|
source: markdown,
|
||||||
|
|
@ -189,6 +193,7 @@ export function useDocumentProcessor() {
|
||||||
const pdfFile = await convertWordToPdf(file)
|
const pdfFile = await convertWordToPdf(file)
|
||||||
console.log('Conversion successful, PDF file:', pdfFile.name, pdfFile.size)
|
console.log('Conversion successful, PDF file:', pdfFile.name, pdfFile.size)
|
||||||
validFiles.push(pdfFile)
|
validFiles.push(pdfFile)
|
||||||
|
displayFiles.push(file)
|
||||||
error.value = null
|
error.value = null
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error.value = 'Word 转换为 PDF 失败: ' + (err as Error).message
|
error.value = 'Word 转换为 PDF 失败: ' + (err as Error).message
|
||||||
|
|
@ -199,16 +204,19 @@ export function useDocumentProcessor() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
validFiles.push(file)
|
validFiles.push(file)
|
||||||
|
displayFiles.push(file)
|
||||||
console.log('Adding file directly:', fileName)
|
console.log('Adding file directly:', fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadedFiles.value = validFiles
|
uploadedFiles.value = validFiles
|
||||||
|
uploadedDisplayFiles.value = displayFiles
|
||||||
console.log('Final uploaded files:', validFiles.map(f => f.name))
|
console.log('Final uploaded files:', validFiles.map(f => f.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清除所有数据
|
// 清除所有数据
|
||||||
const clearAll = () => {
|
const clearAll = () => {
|
||||||
uploadedFiles.value = []
|
uploadedFiles.value = []
|
||||||
|
uploadedDisplayFiles.value = []
|
||||||
results.value = null
|
results.value = null
|
||||||
error.value = null
|
error.value = null
|
||||||
processingStage.value = ''
|
processingStage.value = ''
|
||||||
|
|
@ -352,6 +360,7 @@ export function useDocumentProcessor() {
|
||||||
return {
|
return {
|
||||||
// 数据
|
// 数据
|
||||||
uploadedFiles,
|
uploadedFiles,
|
||||||
|
uploadedDisplayFiles,
|
||||||
config,
|
config,
|
||||||
results,
|
results,
|
||||||
isUploading,
|
isUploading,
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="uploaded-files" v-else>
|
<div class="uploaded-files" v-else>
|
||||||
<div class="file-item" v-for="(file, index) in uploadedFiles" :key="index">
|
<div class="file-item" v-for="(file, index) in uploadedDisplayFiles" :key="index">
|
||||||
<el-icon class="file-icon"><Document /></el-icon>
|
<el-icon class="file-icon"><Document /></el-icon>
|
||||||
<span class="file-name">{{ file.name }}</span>
|
<span class="file-name">{{ file.name }}</span>
|
||||||
<el-button
|
<el-button
|
||||||
|
|
@ -289,6 +289,7 @@ function isSourceViewMode(value: unknown): value is 'markdown' | 'ast' {
|
||||||
|
|
||||||
const {
|
const {
|
||||||
uploadedFiles,
|
uploadedFiles,
|
||||||
|
uploadedDisplayFiles,
|
||||||
config,
|
config,
|
||||||
results,
|
results,
|
||||||
isUploading,
|
isUploading,
|
||||||
|
|
@ -649,6 +650,7 @@ const handleDrop = async (event: DragEvent) => {
|
||||||
|
|
||||||
const removeFile = (index: number) => {
|
const removeFile = (index: number) => {
|
||||||
uploadedFiles.value.splice(index, 1)
|
uploadedFiles.value.splice(index, 1)
|
||||||
|
uploadedDisplayFiles.value.splice(index, 1)
|
||||||
if (uploadedFiles.value.length === 0) {
|
if (uploadedFiles.value.length === 0) {
|
||||||
isUploadAreaCollapsed.value = false
|
isUploadAreaCollapsed.value = false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue