完成后端架构重构等

This commit is contained in:
super
2026-04-23 15:25:41 +08:00
parent 6894f9cc57
commit 0391cb223f
86 changed files with 10843 additions and 1757 deletions

View File

@@ -13,7 +13,7 @@ client_name=ShuFuAI
# java_api_base=http://47.111.163.154:18080
# java_api_base=http://127.0.0.1:18080
java_api_base=http://8.136.19.173:18080
java_api_base=http://127.0.0.1:18080
# java_api_base=http://8.136.19.173:18080

View File

@@ -12,9 +12,14 @@ from flask import request, redirect, url_for, session, jsonify, render_template,
from config import mysql_host, mysql_user, mysql_password, mysql_database
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_DIR = os.path.join(BASE_DIR, 'static')
ASSETS_DIR = os.path.join(BASE_DIR, 'assets')
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_DIR = os.path.join(BASE_DIR, 'static')
ASSETS_DIR = os.path.join(BASE_DIR, 'assets')
WEB_SOURCE_DIR = os.path.join(BASE_DIR, 'web_source')
TEMPLATE_FALLBACK_DIRS = (
WEB_SOURCE_DIR,
os.path.join(WEB_SOURCE_DIR, 'templates_backup'),
)
def get_db():
@@ -30,9 +35,13 @@ def get_db():
def _render_html(template_name: str, **context):
"""读取 HTML 模板:若为加密文件则先解密,再渲染。未加密或解密失败时按明文渲染。"""
path = os.path.join(BASE_DIR, "web_source", template_name)
if not os.path.isfile(path):
return render_template(template_name, **context)
path = next(
(candidate for candidate in (os.path.join(base_path, template_name) for base_path in TEMPLATE_FALLBACK_DIRS)
if os.path.isfile(candidate)),
None,
)
if path is None:
return render_template(template_name, **context)
with open(path, "rb") as f:
raw = f.read()
try:
@@ -45,9 +54,13 @@ def _render_html(template_name: str, **context):
def _render_html_new(template_name: str, **context):
"""读取 HTML 模板:若为加密文件则先解密,再渲染。未加密或解密失败时按明文渲染。"""
path = os.path.join(BASE_DIR, "web_source", template_name)
if not os.path.isfile(path):
return render_template(template_name, **context)
path = next(
(candidate for candidate in (os.path.join(base_path, template_name) for base_path in TEMPLATE_FALLBACK_DIRS)
if os.path.isfile(candidate)),
None,
)
if path is None:
return render_template(template_name, **context)
with open(path, "rb") as f:
raw = f.read()
try:

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

View File

@@ -2,7 +2,7 @@
主页面蓝图首页、home、图片工作台、品牌页、静态文件、Logo
"""
import os
from flask import Blueprint, send_file
from flask import Blueprint, send_file, render_template_string
from app_common import (
get_db,
@@ -20,7 +20,39 @@ import requests
from config import base_url,version,JAVA_API_BASE
main_bp = Blueprint('main', __name__)
main_bp = Blueprint('main', __name__)
def _resolve_asset_filename(filename):
"""Resolve hashed Vite assets without maintaining hardcoded alias tables."""
safe_name = os.path.basename(filename)
exact_path = os.path.join(ASSETS_DIR, safe_name)
if os.path.isfile(exact_path):
return safe_name
base_name, ext = os.path.splitext(safe_name)
if not base_name or not ext:
return safe_name
parts = base_name.split('-')
if len(parts) < 2:
return safe_name
try:
asset_names = os.listdir(ASSETS_DIR)
except OSError:
return safe_name
for prefix_length in range(len(parts) - 1, 0, -1):
prefix = '-'.join(parts[:prefix_length])
matches = [
asset_name for asset_name in asset_names
if asset_name.endswith(ext) and asset_name.startswith(prefix)
]
if len(matches) == 1:
return matches[0]
return safe_name
@main_bp.route('/')
@@ -50,10 +82,42 @@ def wb():
return _render_html('index.html')
@main_bp.route('/brand')
@login_required
def brand_page():
return _render_html('brand.html', user_id=session.get('user_id'))
@main_bp.route('/brand')
@login_required
def brand_page():
repo_brand_path = os.path.abspath(os.path.join(BASE_DIR, '..', 'web_source', 'brand.html'))
if os.path.isfile(repo_brand_path):
try:
with open(repo_brand_path, 'rb') as f:
raw = f.read()
try:
from html_crypto import decrypt
content = decrypt(raw).decode('utf-8')
except Exception:
if raw[:7] == b'gAAAAAB':
raise
content = raw.decode('utf-8', errors='replace')
return render_template_string(content, user_id=session.get('user_id'))
except Exception:
pass
return _render_html('brand.html', user_id=session.get('user_id'))
@main_bp.route('/brand/legacy')
@login_required
def brand_page_legacy():
legacy_path = os.path.join(BASE_DIR, 'web_source', 'templates_backup', 'brand.html')
if not os.path.isfile(legacy_path):
return '', 404
with open(legacy_path, 'rb') as f:
content = f.read().decode('utf-8', errors='replace')
content = content.replace(
'<header class="top-bar">',
'<header class="top-bar" style="display:none !important;">',
1,
)
content = content.replace('height: calc(100vh - 56px);', 'height: 100vh;', 1)
return render_template_string(content, user_id=session.get('user_id'))
@@ -69,10 +133,11 @@ def serve_static(filename):
return send_file(file_abs, as_attachment=False)
@main_bp.route('/assets/<path:filename>')
def serve_assets(filename):
"""提供 static 目录及子目录下的静态文件访问。"""
filepath = os.path.normpath(os.path.join(ASSETS_DIR, filename))
@main_bp.route('/assets/<path:filename>')
def serve_assets(filename):
"""提供 static 目录及子目录下的静态文件访问。"""
filename = _resolve_asset_filename(filename)
filepath = os.path.normpath(os.path.join(ASSETS_DIR, filename))
static_abs = os.path.abspath(ASSETS_DIR)
file_abs = os.path.abspath(filepath)
if not file_abs.startswith(static_abs) or not os.path.isfile(file_abs):
@@ -82,14 +147,19 @@ def serve_assets(filename):
@main_bp.route('/new_web_source/<path:filename>')
def serve_new_web_source(filename):
"""提供 static 目录及子目录下的静态文件访问。"""
filepath = os.path.normpath(os.path.join("new_web_source", filename))
static_abs = os.path.abspath("new_web_source")
file_abs = os.path.abspath(filepath)
if not file_abs.startswith(static_abs) or not os.path.isfile(file_abs):
return '', 404
return send_file(file_abs, as_attachment=False)
"""提供 new_web_source 目录下的静态页面文件访问。"""
candidate_dirs = [
os.path.abspath(os.path.join(BASE_DIR, 'new_web_source')),
os.path.abspath(os.path.join(BASE_DIR, '..', 'new_web_source')),
]
for static_abs in candidate_dirs:
filepath = os.path.normpath(os.path.join(static_abs, filename))
file_abs = os.path.abspath(filepath)
if not file_abs.startswith(static_abs):
continue
if os.path.isfile(file_abs):
return send_file(file_abs, as_attachment=False)
return '', 404
@main_bp.route('/logo.jpg', methods=['GET'])
@@ -161,4 +231,4 @@ def proxy(path):
return Response("无法连接到后端服务", status=502)
except Exception as e:
print(f"代理请求失败: {e}")
return Response(f"代理错误: {str(e)}", status=500)
return Response(f"代理错误: {str(e)}", status=500)

View File

@@ -3,11 +3,12 @@ coze_token = "sat_12nW40INoJxArrDXbY4lSCoudbqkOYTcphC99BP2efWyzxmsk4q81WDX3ezWgq
workflow_id = "7608812635877900322"
STITCH_WORKFLOW_ID = "7608813873483300907"
import os
from dotenv import load_dotenv
from queue import Queue
load_dotenv()
_base_url = os.getenv("base_url","http://159.75.121.33:15124")
import os
from dotenv import load_dotenv
from queue import Queue
load_dotenv()
_base_url = os.getenv("base_url","http://159.75.121.33:15124")
base_dir = os.path.dirname(os.path.abspath(__file__))
# MySQL 配置
mysql_host = os.getenv("mysql_host")
@@ -15,10 +16,11 @@ mysql_user = os.getenv("mysql_user")
mysql_password = os.getenv("mysql_password","WTFrb5y6hNLz6hNy")
mysql_database = os.getenv("mysql_database","aiimage")
proxy_url = os.getenv("proxy_url")
proxy_mode = int(os.getenv("proxy_mode",1))
client_name=os.getenv("client_name") + ".exe"
JAVA_API_BASE = os.getenv("java_api_base", "http://127.0.0.1:18080")
proxy_mode = int(os.getenv("proxy_mode",1))
_client_name = os.getenv("client_name", "").strip()
client_name = f"{_client_name}.exe" if _client_name else "client.exe"
JAVA_API_BASE = os.getenv("java_api_base", "http://127.0.0.1:18080")
# 紫鸟浏览器配置
from urllib.parse import unquote

View File

@@ -433,7 +433,7 @@ def main():
webview.start(
debug=True,
storage_path=cache_path,
private_mode=False
private_mode=True
)

View File

@@ -5,8 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>格式转换 - 数富AI</title>
<script type="module" crossorigin src="/assets/convert.js"></script>
<link rel="modulepreload" crossorigin href="/assets/pywebview-DuyK2jB1.js">
<link rel="modulepreload" crossorigin href="/assets/brand-CKgrwtni.js">
<link rel="modulepreload" crossorigin href="/assets/pywebview-9YBa--7x.js">
<link rel="modulepreload" crossorigin href="/assets/brand-CRmRvyGD.js">
<link rel="stylesheet" crossorigin href="/assets/pywebview-D74jYk6P.css">
<link rel="stylesheet" crossorigin href="/assets/convert-7wWJ02Tw.css">
</head>

View File

@@ -5,8 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>数据去重 - 数富AI</title>
<script type="module" crossorigin src="/assets/dedupe.js"></script>
<link rel="modulepreload" crossorigin href="/assets/pywebview-DuyK2jB1.js">
<link rel="modulepreload" crossorigin href="/assets/brand-CKgrwtni.js">
<link rel="modulepreload" crossorigin href="/assets/pywebview-9YBa--7x.js">
<link rel="modulepreload" crossorigin href="/assets/brand-CRmRvyGD.js">
<link rel="stylesheet" crossorigin href="/assets/pywebview-D74jYk6P.css">
<link rel="stylesheet" crossorigin href="/assets/dedupe-BpNHwt51.css">
</head>

View File

@@ -5,8 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>删除品牌 - 数富AI</title>
<script type="module" crossorigin src="/assets/delete-brand.js"></script>
<link rel="modulepreload" crossorigin href="/assets/pywebview-DuyK2jB1.js">
<link rel="modulepreload" crossorigin href="/assets/brand-CKgrwtni.js">
<link rel="modulepreload" crossorigin href="/assets/pywebview-9YBa--7x.js">
<link rel="modulepreload" crossorigin href="/assets/brand-CRmRvyGD.js">
<link rel="stylesheet" crossorigin href="/assets/pywebview-D74jYk6P.css">
<link rel="stylesheet" crossorigin href="/assets/delete-brand-CWLpe7lu.css">
</head>

View File

@@ -5,8 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>数据拆分 - 数富AI</title>
<script type="module" crossorigin src="/assets/split.js"></script>
<link rel="modulepreload" crossorigin href="/assets/pywebview-DuyK2jB1.js">
<link rel="modulepreload" crossorigin href="/assets/brand-CKgrwtni.js">
<link rel="modulepreload" crossorigin href="/assets/pywebview-9YBa--7x.js">
<link rel="modulepreload" crossorigin href="/assets/brand-CRmRvyGD.js">
<link rel="stylesheet" crossorigin href="/assets/pywebview-D74jYk6P.css">
<link rel="stylesheet" crossorigin href="/assets/split-CRUIYKS6.css">
</head>

File diff suppressed because it is too large Load Diff