From 570c0f3d61cc70aa5331ac75710f2b8a18417b6e Mon Sep 17 00:00:00 2001 From: liuguancen Date: Wed, 15 Apr 2026 19:28:23 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=B7=A5=E5=85=B7=E5=B9=BF=E5=9C=BA?= =?UTF-8?q?=E7=BB=9F=E4=B8=8018000=E7=AB=AF=E5=8F=A3=20+=20=E5=8E=BB?= =?UTF-8?q?=E9=99=A4=E7=94=B5=E9=87=8F=E9=99=90=E5=88=B6=20+=20bot?= =?UTF-8?q?=E5=A4=B4=E5=83=8F=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nginx反代(tools-nginx.conf): - 10个工具统一通过18000端口路径分发 - 解决/static/冲突(Lama精确匹配,其余给LibreTranslate) - 解决/api/冲突(PDF用sub_filter改为/pdf-api/,/api/给imgcompress) - Overleaf兜底处理所有未匹配的绝对路径 - 前端工具卡片统一走18000端口+路径 后端: - 去除对话电量限制(validateUser中的num扣减逻辑) 前端: - bot头像更新为战知logo(蓝底白字) - LaTeX公式编辑器"复制为图片"改为"下载为图片"(解决跨域问题) Co-Authored-By: Claude Opus 4.6 (1M context) --- .../chat/gpt/service/impl/GptServiceImpl.java | 8 -- chat_web_front/src/assets/images/chat/ai.png | Bin 6160 -> 5432 bytes .../src/views/applications/index.vue | 29 ++-- scripts/latex-editor/index.html | 37 ++--- scripts/tools-nginx.conf | 133 ++++++++++++++++++ 5 files changed, 171 insertions(+), 36 deletions(-) create mode 100644 scripts/tools-nginx.conf diff --git a/chat_web_backend/src/main/java/com/inspur/llm/chat/gpt/service/impl/GptServiceImpl.java b/chat_web_backend/src/main/java/com/inspur/llm/chat/gpt/service/impl/GptServiceImpl.java index ac1a9b7..37e216a 100644 --- a/chat_web_backend/src/main/java/com/inspur/llm/chat/gpt/service/impl/GptServiceImpl.java +++ b/chat_web_backend/src/main/java/com/inspur/llm/chat/gpt/service/impl/GptServiceImpl.java @@ -51,14 +51,6 @@ public class GptServiceImpl implements IGptService { if (ValidatorUtil.isNull(user)) { throw new ProhibitVisitException(); } - - if (user.getNum() < 1) { - throw new BusinessException("电量不足,请分享好友获取电量或开通会员"); - } - // 扣电量 - UpdateWrapper uw = new UpdateWrapper<>(); - uw.lambda().set(User::getNum, user.getNum() - 1).eq(BaseEntity::getId, user.getId()); - userMapper.update(null, uw); } @Override diff --git a/chat_web_front/src/assets/images/chat/ai.png b/chat_web_front/src/assets/images/chat/ai.png index 3f402e66e727c3225df1d2ecbdfdf92bc1e54b57..ade7afee987e3e4ecdbfbc62ffdf3fc8851c668b 100644 GIT binary patch literal 5432 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 Dmn(<; literal 6160 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[ { name: '📄 文档处理', tools: [ - { id: 'stirling-pdf', name: 'Stirling PDF', icon: '', logoImg: stirlingLogo, description: 'PDF 合并、拆分、压缩、转换、加水印、OCR 识别等 30+ 功能', port: 18080, enabled: true, type: 'newtab' }, - { id: 'trwebocr', name: '图片转文字 OCR', icon: '', logoImg: trwebocrLogo, description: '中文离线 OCR,识别图片中的文字和表格', port: 18083, enabled: true, type: 'newtab' }, - { id: 'libretranslate', name: '智能翻译', icon: '', logoImg: libretranslateLogo, description: '中英互译,支持文本和文件翻译,数据不出内网', port: 18084, enabled: true, type: 'newtab' }, + { id: 'stirling-pdf', name: 'Stirling PDF', icon: '', logoImg: stirlingLogo, description: 'PDF 合并、拆分、压缩、转换、加水印、OCR 识别等 30+ 功能', path: '/spdf/', enabled: true, type: 'newtab' }, + { id: 'trwebocr', name: '图片转文字 OCR', icon: '', logoImg: trwebocrLogo, description: '中文离线 OCR,识别图片中的文字和表格', path: '/ocr/', enabled: true, type: 'newtab' }, + { id: 'libretranslate', name: '智能翻译', icon: '', logoImg: libretranslateLogo, description: '中英互译,支持文本和文件翻译,数据不出内网', path: '/translate/', enabled: true, type: 'newtab' }, ] }, { name: '🖼️ 图片处理', tools: [ - { id: 'imgcompress', name: '图片压缩转换', icon: '🗜️', description: '图片压缩、格式转换、批量处理、AI 智能抠图去背景', port: 18087, enabled: true, type: 'newtab' }, - { id: 'lama-cleaner', name: 'AI 图像擦除', icon: '🧹', description: 'AI 智能擦除图片中的水印、路人、瑕疵,自动修复画面', port: 18088, enabled: true, type: 'newtab' }, - { id: 'webp2jpg', name: '图片格式转换', icon: '🔄', description: '支持 PSD/HEIC/WebP/PNG/JPG 等格式批量互转,纯浏览器处理不上传', port: 18089, enabled: true, type: 'newtab' }, + { id: 'imgcompress', name: '图片压缩转换', icon: '🗜️', description: '图片压缩、格式转换、批量处理、AI 智能抠图去背景', path: '/imgcompress/', enabled: true, type: 'newtab' }, + { id: 'lama-cleaner', name: 'AI 图像擦除', icon: '🧹', description: 'AI 智能擦除图片中的水印、路人、瑕疵,自动修复画面', path: '/lama/', enabled: true, type: 'newtab' }, + { id: 'webp2jpg', name: '图片格式转换', icon: '🔄', description: '支持 PSD/HEIC/WebP/PNG/JPG 等格式批量互转,纯浏览器处理不上传', path: '/webp2jpg/', enabled: true, type: 'newtab' }, ] }, { name: '🎨 创作绘图', tools: [ - { id: 'excalidraw', name: 'Excalidraw', icon: '', logoImg: excalidrawLogo, description: '手绘风格白板,绘制流程图、架构图、示意图', port: 18081, enabled: true, type: 'newtab' }, - { id: 'pptist', name: 'AI PPT 编辑器', icon: '', logoImg: pptistLogo, description: 'AI 生成 PPT 大纲和演示文稿,在线编辑演示', port: 18085, enabled: true, type: 'newtab' }, + { id: 'excalidraw', name: 'Excalidraw', icon: '', logoImg: excalidrawLogo, description: '手绘风格白板,绘制流程图、架构图、示意图', path: '/draw/', enabled: true, type: 'newtab' }, + { id: 'pptist', name: 'AI PPT 编辑器', icon: '', logoImg: pptistLogo, description: 'AI 生成 PPT 大纲和演示文稿,在线编辑演示', path: '/ppt/', enabled: true, type: 'newtab' }, ] }, { name: '📝 科研写作', tools: [ - { id: 'overleaf', name: 'LaTeX 论文编辑器', icon: '📐', description: '在线 LaTeX 编辑器,支持多人协作撰写论文,实时编译预览', port: 18090, enabled: true, type: 'newtab' }, - { id: 'latex-formula', name: 'LaTeX 公式编辑器', icon: '∑', description: '在线编辑数学公式,支持希腊字母、矩阵、积分等,可复制公式或图片', port: 18091, enabled: true, type: 'newtab' }, + { id: 'overleaf', name: 'LaTeX 论文编辑器', icon: '📐', description: '在线 LaTeX 编辑器,支持多人协作撰写论文,实时编译预览', path: '/overleaf/', enabled: true, type: 'newtab' }, + { id: 'latex-formula', name: 'LaTeX 公式编辑器', icon: '∑', description: '在线编辑数学公式,支持希腊字母、矩阵、积分等,可复制公式或图片', path: '/latex/', enabled: true, type: 'newtab' }, ] }, ]); +const TOOL_PORT = 18000; + const openTool = (tool: Tool) => { if (!tool.enabled) return; - const url = tool.url || (tool.port ? `${window.location.protocol}//${window.location.hostname}:${tool.port}${tool.path || ''}` : ''); + let url = ''; + if (tool.path) { + url = `${window.location.protocol}//${window.location.hostname}:${TOOL_PORT}${tool.path}`; + } else if (tool.port) { + url = `${window.location.protocol}//${window.location.hostname}:${tool.port}`; + } if (url) { window.open(url, '_blank'); } diff --git a/scripts/latex-editor/index.html b/scripts/latex-editor/index.html index 5ad9e04..ed7aba2 100644 --- a/scripts/latex-editor/index.html +++ b/scripts/latex-editor/index.html @@ -67,7 +67,7 @@
- +
@@ -121,23 +121,26 @@ function copyLatex() { navigator.clipboard.writeText(document.getElementById('input').value); showToast('公式已复制!'); } -function copyImg() { +function downloadImg() { const el = document.getElementById('preview'); - const svg = el.querySelector('svg') || el.querySelector('.katex'); - if (!svg) return; - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - const data = new XMLSerializer().serializeToString(el); - const img = new Image(); - const blob = new Blob(['
'+el.innerHTML+'
'], {type:'image/svg+xml'}); - const url = URL.createObjectURL(blob); - img.onload = () => { - canvas.width = img.width * 2; canvas.height = img.height * 2; - ctx.scale(2,2); ctx.drawImage(img, 0, 0); - canvas.toBlob(b => { navigator.clipboard.write([new ClipboardItem({'image/png': b})]); showToast('图片已复制!'); }); - URL.revokeObjectURL(url); - }; - img.src = url; + if (!el.querySelector('.katex')) { showToast('请先输入公式'); return; } + // 直接用 KaTeX 的 mathml/svg 渲染结果导出为 SVG 文件下载 + const w = el.scrollWidth + 40, h = el.scrollHeight + 40; + const svgStr = ` + + +
+ ${el.innerHTML} +
+
+
`; + const blob = new Blob([svgStr], {type: 'image/svg+xml'}); + const a = document.createElement('a'); + a.href = URL.createObjectURL(blob); + a.download = 'formula.svg'; + a.click(); + URL.revokeObjectURL(a.href); + showToast('图片已下载!'); } function showToast(msg) { const t = document.getElementById('toast'); diff --git a/scripts/tools-nginx.conf b/scripts/tools-nginx.conf new file mode 100644 index 0000000..69bdc5a --- /dev/null +++ b/scripts/tools-nginx.conf @@ -0,0 +1,133 @@ +server { + listen 18000; + client_max_body_size 500M; + + # 1. Stirling PDF + location /pdf/ { + proxy_pass http://127.0.0.1:18080/; + proxy_set_header Host $host; + proxy_set_header Accept-Encoding ""; + proxy_buffering off; + sub_filter_once off; + sub_filter '"/api/' '"/pdf-api/'; + } + location /pdf-api/ { + proxy_pass http://127.0.0.1:18080/api/; + proxy_set_header Host $host; + proxy_buffering off; + client_max_body_size 500M; + } + + # 2. Excalidraw + location /draw/ { + proxy_pass http://127.0.0.1:18081/; + proxy_set_header Host $host; + } + location /assets/ { proxy_pass http://127.0.0.1:18081/assets/; } + location /v1/ai/ { + proxy_pass http://127.0.0.1:18082/v1/ai/; + proxy_set_header Host $host; + proxy_read_timeout 60s; + proxy_buffering off; + } + + # 3. TrWebOCR + location /ocr/ { + proxy_pass http://127.0.0.1:18083/; + proxy_set_header Host $host; + proxy_buffering off; + } + + # 4. LibreTranslate + location /translate/ { + proxy_pass http://127.0.0.1:18084/; + proxy_set_header Host $host; + } + + # 5. PPTist + location /ppt/ { + proxy_pass http://127.0.0.1:18085/; + proxy_set_header Host $host; + proxy_buffering off; + } + location /pptapi/ { + proxy_pass http://127.0.0.1:18086/; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_buffering off; + proxy_cache off; + } + + # 6. imgcompress + location /imgcompress/ { + proxy_pass http://127.0.0.1:18087/; + proxy_set_header Host $host; + } + + # 7. Lama Cleaner + location /lama/ { + proxy_pass http://127.0.0.1:18088/; + proxy_set_header Host $host; + proxy_buffering off; + } + location /lama/inpaint { + proxy_pass http://127.0.0.1:18088/inpaint; + proxy_set_header Host $host; + proxy_buffering off; + proxy_read_timeout 300s; + client_max_body_size 500M; + } + # Lama Cleaner 的2个精确static文件 + location /static/js/main.1bd455bc.js { proxy_pass http://127.0.0.1:18088/static/js/main.1bd455bc.js; } + location /static/css/main.c28d98ca.css { proxy_pass http://127.0.0.1:18088/static/css/main.c28d98ca.css; } + + # /static/ 其余的给 LibreTranslate + location /static/ { proxy_pass http://127.0.0.1:18084/static/; } + + # LibreTranslate 绝对路径 API + location /languages { proxy_pass http://127.0.0.1:18084/languages; } + location /frontend/settings { proxy_pass http://127.0.0.1:18084/frontend/settings; } + location /detect { proxy_pass http://127.0.0.1:18084/detect; } + + # imgcompress 绝对路径 + location /_next/ { proxy_pass http://127.0.0.1:18087/_next/; } + location /api/ { + proxy_pass http://127.0.0.1:18087/api/; + proxy_set_header Host $host; + proxy_buffering off; + client_max_body_size 500M; + } + + # 8. webp2jpg + location /webp2jpg/ { + proxy_pass http://127.0.0.1:18089/; + proxy_set_header Host $host; + } + location /cdn/ { proxy_pass http://127.0.0.1:18089/cdn/; } + + # 9. Overleaf + location /overleaf/ { + proxy_pass http://127.0.0.1:18090/; + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_buffering off; + } + + # 10. LaTeX 公式编辑器 + location /latex/ { + proxy_pass http://127.0.0.1:18091/; + proxy_set_header Host $host; + } + + # 默认回落到 Overleaf + location / { + proxy_pass http://127.0.0.1:18090; + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_buffering off; + } +}