暂提更新
This commit is contained in:
Binary file not shown.
1
app/assets/convert-6b0yq-M0.css
Normal file
1
app/assets/convert-6b0yq-M0.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
app/assets/dedupe-Day_nGxq.css
Normal file
1
app/assets/dedupe-Day_nGxq.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
app/assets/split-BsJfbBqn.css
Normal file
1
app/assets/split-BsJfbBqn.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
@@ -2,8 +2,7 @@
|
|||||||
主页面蓝图:首页、home、图片工作台、品牌页、静态文件、Logo
|
主页面蓝图:首页、home、图片工作台、品牌页、静态文件、Logo
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import requests
|
from flask import Blueprint, send_file
|
||||||
from flask import Blueprint, Response, request, send_file
|
|
||||||
|
|
||||||
from app_common import (
|
from app_common import (
|
||||||
get_db,
|
get_db,
|
||||||
@@ -16,10 +15,10 @@ from app_common import (
|
|||||||
ASSETS_DIR
|
ASSETS_DIR
|
||||||
)
|
)
|
||||||
from flask import redirect, url_for, session
|
from flask import redirect, url_for, session
|
||||||
|
from flask import Flask, request, Response, stream_with_context
|
||||||
|
import requests
|
||||||
|
|
||||||
from config import base_url,version,java_api_base
|
from config import base_url,version,JAVA_API_BASE
|
||||||
|
|
||||||
JAVA_API_BASE = java_api_base
|
|
||||||
|
|
||||||
main_bp = Blueprint('main', __name__)
|
main_bp = Blueprint('main', __name__)
|
||||||
|
|
||||||
@@ -93,36 +92,60 @@ def serve_new_web_source(filename):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@main_bp.route('/newApi/<path:subpath>', methods=['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'])
|
|
||||||
def proxy_new_api(subpath):
|
|
||||||
target_url = f"{JAVA_API_BASE}/{subpath}"
|
|
||||||
try:
|
|
||||||
headers = {
|
|
||||||
key: value
|
|
||||||
for key, value in request.headers.items()
|
|
||||||
if key.lower() not in {'host', 'content-length'}
|
|
||||||
}
|
|
||||||
upstream = requests.request(
|
|
||||||
method=request.method,
|
|
||||||
url=target_url,
|
|
||||||
params=request.args,
|
|
||||||
data=request.get_data(),
|
|
||||||
headers=headers,
|
|
||||||
cookies=request.cookies,
|
|
||||||
allow_redirects=False,
|
|
||||||
timeout=300,
|
|
||||||
)
|
|
||||||
excluded_headers = {'content-encoding', 'content-length', 'transfer-encoding', 'connection'}
|
|
||||||
response_headers = [
|
|
||||||
(name, value)
|
|
||||||
for name, value in upstream.headers.items()
|
|
||||||
if name.lower() not in excluded_headers
|
|
||||||
]
|
|
||||||
return Response(upstream.content, upstream.status_code, response_headers)
|
|
||||||
except requests.RequestException as exc:
|
|
||||||
return {'success': False, 'message': str(exc), 'data': None}, 502
|
|
||||||
|
|
||||||
|
|
||||||
@main_bp.route('/logo.jpg', methods=['GET'])
|
@main_bp.route('/logo.jpg', methods=['GET'])
|
||||||
def get_logo_image():
|
def get_logo_image():
|
||||||
return send_file(os.path.join(BASE_DIR, "logo.jpg"), mimetype='image/jpeg')
|
return send_file(os.path.join(BASE_DIR, "logo.jpg"), mimetype='image/jpeg')
|
||||||
|
|
||||||
|
|
||||||
|
@main_bp.route('/newApi/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])
|
||||||
|
def proxy(path):
|
||||||
|
target_url = f"{JAVA_API_BASE}/{path}"
|
||||||
|
|
||||||
|
# 复制请求参数
|
||||||
|
params = request.args.to_dict()
|
||||||
|
|
||||||
|
# 处理请求头
|
||||||
|
headers = {}
|
||||||
|
for key, value in request.headers:
|
||||||
|
if key.lower() in ['host', 'content-length', 'connection']:
|
||||||
|
continue
|
||||||
|
headers[key] = value
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 使用流式请求
|
||||||
|
req = requests.request(
|
||||||
|
method=request.method,
|
||||||
|
url=target_url,
|
||||||
|
params=params,
|
||||||
|
headers=headers,
|
||||||
|
data=request.get_data() if request.get_data() else None,
|
||||||
|
cookies=request.cookies,
|
||||||
|
stream=True, # 启用流式传输
|
||||||
|
timeout=30
|
||||||
|
)
|
||||||
|
|
||||||
|
# 流式响应
|
||||||
|
def generate():
|
||||||
|
for chunk in req.iter_content(chunk_size=8192):
|
||||||
|
if chunk:
|
||||||
|
yield chunk
|
||||||
|
|
||||||
|
# 构建响应
|
||||||
|
response = Response(stream_with_context(generate()), status=req.status_code)
|
||||||
|
|
||||||
|
# 复制响应头
|
||||||
|
for key, value in req.headers.items():
|
||||||
|
if key.lower() not in ['content-encoding', 'content-length', 'transfer-encoding', 'connection']:
|
||||||
|
response.headers[key] = value
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
except requests.exceptions.Timeout:
|
||||||
|
print("后端服务超时")
|
||||||
|
return Response("后端服务超时", status=504)
|
||||||
|
except requests.exceptions.ConnectionError:
|
||||||
|
print("无法连接到后端服务")
|
||||||
|
return Response("无法连接到后端服务", status=502)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"代理请求失败: {e}")
|
||||||
|
return Response(f"代理错误: {str(e)}", status=500)
|
||||||
@@ -8,6 +8,7 @@ from dotenv import load_dotenv
|
|||||||
load_dotenv()
|
load_dotenv()
|
||||||
_base_url = os.getenv("base_url","http://159.75.121.33:15124")
|
_base_url = os.getenv("base_url","http://159.75.121.33:15124")
|
||||||
java_api_base = os.getenv("java_api_base", "http://127.0.0.1:18080")
|
java_api_base = os.getenv("java_api_base", "http://127.0.0.1:18080")
|
||||||
|
JAVA_API_BASE = java_api_base
|
||||||
|
|
||||||
# MySQL 配置
|
# MySQL 配置
|
||||||
mysql_host = os.getenv("mysql_host")
|
mysql_host = os.getenv("mysql_host")
|
||||||
|
|||||||
29
app/main.py
29
app/main.py
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
基于 pywebview 实现的跨平台 UI,需先登录方可使用
|
基于 pywebview 实现的跨平台 UI,需先登录方可使用
|
||||||
"""
|
"""
|
||||||
from config import cache_path,debug,version,java_api_base
|
from config import cache_path,debug,version,JAVA_API_BASE
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
@@ -26,7 +26,6 @@ with open("version.txt","w",encoding="utf-8") as file:
|
|||||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
APP_URL = "http://127.0.0.1:5123"
|
APP_URL = "http://127.0.0.1:5123"
|
||||||
PORT = 5123
|
PORT = 5123
|
||||||
JAVA_API_BASE = java_api_base
|
|
||||||
|
|
||||||
|
|
||||||
def generate_images(params):
|
def generate_images(params):
|
||||||
@@ -235,6 +234,27 @@ class WindowAPI:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {'success': False, 'error': str(e)}
|
return {'success': False, 'error': str(e)}
|
||||||
|
|
||||||
|
def upload_file_to_java(self, file_path):
|
||||||
|
"""按本地路径读取文件并上传到 Java 后端临时目录。"""
|
||||||
|
if not file_path or not str(file_path).strip():
|
||||||
|
return {'success': False, 'error': '文件路径为空'}
|
||||||
|
normalized_path = os.path.abspath(str(file_path).strip())
|
||||||
|
if not os.path.isfile(normalized_path):
|
||||||
|
return {'success': False, 'error': '文件不存在'}
|
||||||
|
try:
|
||||||
|
with open(normalized_path, 'rb') as file_obj:
|
||||||
|
response = requests.post(
|
||||||
|
f"{JAVA_API_BASE}/api/files/upload",
|
||||||
|
files={'file': (os.path.basename(normalized_path), file_obj)},
|
||||||
|
timeout=120,
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
payload = response.json()
|
||||||
|
if not isinstance(payload, dict):
|
||||||
|
return {'success': False, 'error': 'Java 返回格式错误'}
|
||||||
|
return payload
|
||||||
|
except Exception as e:
|
||||||
|
return {'success': False, 'error': str(e)}
|
||||||
|
|
||||||
def _select_folder_win32():
|
def _select_folder_win32():
|
||||||
"""Windows: 用 ctypes 调用系统文件夹选择对话框,打包成 exe 后也能正常弹窗(不依赖 tkinter)"""
|
"""Windows: 用 ctypes 调用系统文件夹选择对话框,打包成 exe 后也能正常弹窗(不依赖 tkinter)"""
|
||||||
@@ -346,7 +366,7 @@ def main():
|
|||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
window = webview.create_window(
|
window = webview.create_window(
|
||||||
title="南日AI",
|
title="数富AI",
|
||||||
url=APP_URL,
|
url=APP_URL,
|
||||||
width=1400,
|
width=1400,
|
||||||
height=900,
|
height=900,
|
||||||
@@ -357,7 +377,8 @@ def main():
|
|||||||
easy_drag=True
|
easy_drag=True
|
||||||
)
|
)
|
||||||
api = WindowAPI(window)
|
api = WindowAPI(window)
|
||||||
window.expose(api.close, api.minimize, api.maximize, api.toggle_maximize, generate_images, api.save_image, api.save_image_to_folder, api.select_folder, api.select_brand_xlsx_files, api.select_brand_folder, api.upload_file_to_java, api.save_file_from_url, api.save_template_xlsx,api.save_template_zip)
|
window.expose(api.close, api.minimize, api.maximize, api.toggle_maximize, generate_images, api.save_image, api.save_image_to_folder, api.select_folder, api.select_brand_xlsx_files, api.select_brand_folder,
|
||||||
|
api.save_file_from_url, api.save_template_xlsx,api.save_template_zip,api.upload_file_to_java)
|
||||||
webview.start(
|
webview.start(
|
||||||
debug=True,
|
debug=True,
|
||||||
storage_path=cache_path,
|
storage_path=cache_path,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<script type="module" crossorigin src="/assets/convert.js"></script>
|
<script type="module" crossorigin src="/assets/convert.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-DVgP2-kW.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-DVgP2-kW.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-IqgMfeBe.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-IqgMfeBe.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/convert-B191qXN9.css">
|
<link rel="stylesheet" crossorigin href="/assets/convert-6b0yq-M0.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<script type="module" crossorigin src="/assets/dedupe.js"></script>
|
<script type="module" crossorigin src="/assets/dedupe.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-DVgP2-kW.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-DVgP2-kW.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-IqgMfeBe.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-IqgMfeBe.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/dedupe-BKyfmsjj.css">
|
<link rel="stylesheet" crossorigin href="/assets/dedupe-Day_nGxq.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<script type="module" crossorigin src="/assets/split.js"></script>
|
<script type="module" crossorigin src="/assets/split.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-DVgP2-kW.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-DVgP2-kW.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-IqgMfeBe.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-IqgMfeBe.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/split-CYvQPVKL.css">
|
<link rel="stylesheet" crossorigin href="/assets/split-BsJfbBqn.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user