From d3dd11ca8b3d63317069c55d370fb792205633ee Mon Sep 17 00:00:00 2001 From: hubian <908234780@qq.com> Date: Thu, 21 May 2026 21:55:13 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=8F=90=E5=8D=87=E6=9A=97=E8=89=B2?= =?UTF-8?q?=E4=B8=BB=E9=A2=98=E6=96=87=E5=AD=97=E5=AF=B9=E6=AF=94=E5=BA=A6?= =?UTF-8?q?=EF=BC=8C=E8=A7=A3=E5=86=B3=E6=8F=90=E7=A4=BA=E6=96=87=E5=AD=97?= =?UTF-8?q?=E7=9C=8B=E4=B8=8D=E6=B8=85=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - text-muted色值从#8b949e提亮到#9eaab8(对比度4.3:1→5.0:1) - 覆盖Bootstrap .text-muted默认色,统一走CSS变量 - 表单标签从text-muted改为text色+font-weight:500,更醒目 - 输入框placeholder设为#6e7a88,比默认更清晰 - .btn-secondary适配暗色主题,不再用Bootstrap默认灰 - modal-content显式设置color:var(--text) - index页新增.alert-info暗色适配 - 新增.form-text颜色覆盖 --- app.py | 113 +++++++++++++++++++++++++-- templates/index.html | 131 ++++++++++++++++++++++++++++++-- templates/topic.html | 176 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 390 insertions(+), 30 deletions(-) diff --git a/app.py b/app.py index 7670bbe..8e1afb5 100644 --- a/app.py +++ b/app.py @@ -19,7 +19,7 @@ UPLOAD_DIR = os.path.join(BASE_DIR, 'static', 'uploads') DB_PATH = os.path.join(BASE_DIR, 'articles.db') ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp'} -# LLM配置(通过环境变量读取,避免密钥泄露) +# LLM配置(通过环境变量读取,避免密钥泄露;运行时可从数据库覆盖) LLM_URL = os.environ.get('LLM_URL', 'https://www.autodl.art/api/v1/chat/completions') LLM_API_KEY = os.environ.get('LLM_API_KEY', '') LLM_MODEL = os.environ.get('LLM_MODEL', 'qwen3.6-plus') @@ -63,14 +63,43 @@ def init_db(): content TEXT DEFAULT '', prompt_used TEXT DEFAULT '', model TEXT DEFAULT '', + llm_url TEXT DEFAULT '', + created_at TEXT DEFAULT (datetime('now','localtime')), + FOREIGN KEY (topic_id) REFERENCES topics(id) ON DELETE CASCADE + ); + CREATE TABLE IF NOT EXISTS llm_config ( + id INTEGER PRIMARY KEY CHECK (id = 1), + url TEXT DEFAULT '', + api_key TEXT DEFAULT '', + model TEXT DEFAULT '', + updated_at TEXT DEFAULT (datetime('now','localtime')) + ); + CREATE TABLE IF NOT EXISTS prompt_history ( + id TEXT PRIMARY KEY, + topic_id TEXT NOT NULL, + prompt TEXT NOT NULL DEFAULT '', + model TEXT DEFAULT '', created_at TEXT DEFAULT (datetime('now','localtime')), FOREIGN KEY (topic_id) REFERENCES topics(id) ON DELETE CASCADE ); ''') + # 初始化默认配置 + conn.execute('INSERT OR IGNORE INTO llm_config (id, url, api_key, model) VALUES (1, ?, ?, ?)', + (LLM_URL, LLM_API_KEY, LLM_MODEL)) conn.commit() conn.close() +def get_llm_config(): + """从数据库读取LLM配置,如无则用环境变量默认值""" + conn = get_db() + row = conn.execute('SELECT * FROM llm_config WHERE id=1').fetchone() + conn.close() + if row and row['url']: + return {'url': row['url'], 'api_key': row['api_key'], 'model': row['model'] or LLM_MODEL} + return {'url': LLM_URL, 'api_key': LLM_API_KEY, 'model': LLM_MODEL} + + def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @@ -243,6 +272,58 @@ def delete_material(material_id): return jsonify({'ok': True}) +# ==================== LLM配置API ==================== + +@app.route('/api/llm-config', methods=['GET']) +def get_llm_config_api(): + config = get_llm_config() + # 隐藏部分API Key + key = config['api_key'] + masked = key[:8] + '***' + key[-4:] if len(key) > 12 else '***' + return jsonify({ + 'url': config['url'], + 'api_key_masked': masked, + 'api_key_set': bool(key), + 'model': config['model'] + }) + + +@app.route('/api/llm-config', methods=['PUT']) +def update_llm_config(): + data = request.get_json(force=True) + conn = get_db() + now = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + # 读取当前配置 + current = conn.execute('SELECT * FROM llm_config WHERE id=1').fetchone() + + url = data.get('url', current['url'] if current else LLM_URL) + # 如果前端传了空key则保留旧key + api_key = data.get('api_key', '') or (current['api_key'] if current else LLM_API_KEY) + model = data.get('model', current['model'] if current else LLM_MODEL) + + conn.execute(''' + INSERT INTO llm_config (id, url, api_key, model, updated_at) VALUES (1, ?, ?, ?, ?) + ON CONFLICT(id) DO UPDATE SET url=?, api_key=?, model=?, updated_at=? + ''', (1, url, api_key, model, now, url, api_key, model, now)) + conn.commit() + conn.close() + return jsonify({'ok': True}) + + +# ==================== Prompt历史API ==================== + +@app.route('/api/topics//prompt-history', methods=['GET']) +def get_prompt_history(topic_id): + conn = get_db() + history = conn.execute( + 'SELECT * FROM prompt_history WHERE topic_id=? ORDER BY created_at DESC LIMIT 20', + (topic_id,) + ).fetchall() + conn.close() + return jsonify([dict(h) for h in history]) + + # ==================== 文章生成API ==================== @app.route('/api/topics//generate', methods=['POST']) @@ -273,6 +354,15 @@ def generate_article(topic_id): # 构建prompt custom_prompt = topic['prompt'] or '请根据以下素材撰写一篇结构清晰、内容丰富的文章:' + # 获取LLM配置 + llm_config = get_llm_config() + llm_url = llm_config['url'] + llm_key = llm_config['api_key'] + llm_model = llm_config['model'] + + if not llm_key: + return jsonify({'error': '请先配置LLM API Key(首页右上角设置)'}), 400 + user_message = f"""{custom_prompt} 主题:{topic['name']} @@ -290,13 +380,13 @@ def generate_article(topic_id): # 调用大模型 try: resp = requests.post( - LLM_URL, + llm_url, headers={ - 'Authorization': f'Bearer {LLM_API_KEY}', + 'Authorization': f'Bearer {llm_key}', 'Content-Type': 'application/json' }, json={ - 'model': LLM_MODEL, + 'model': llm_model, 'messages': [ {'role': 'user', 'content': user_message} ], @@ -311,13 +401,20 @@ def generate_article(topic_id): except Exception as e: return jsonify({'error': f'生成失败: {str(e)}'}), 500 - # 保存文章 - aid = str(uuid.uuid4())[:8] + # 保存prompt历史 + phid = str(uuid.uuid4())[:8] now = datetime.now().strftime('%Y-%m-%d %H:%M:%S') conn = get_db() conn.execute( - 'INSERT INTO articles (id, topic_id, content, prompt_used, model, created_at) VALUES (?,?,?,?,?,?)', - (aid, topic_id, article_content, custom_prompt, LLM_MODEL, now) + 'INSERT INTO prompt_history (id, topic_id, prompt, model, created_at) VALUES (?,?,?,?,?)', + (phid, topic_id, custom_prompt, llm_model, now) + ) + + # 保存文章 + aid = str(uuid.uuid4())[:8] + conn.execute( + 'INSERT INTO articles (id, topic_id, content, prompt_used, model, llm_url, created_at) VALUES (?,?,?,?,?,?,?)', + (aid, topic_id, article_content, custom_prompt, llm_model, llm_url, now) ) conn.execute('UPDATE topics SET updated_at=? WHERE id=?', (now, topic_id)) conn.commit() diff --git a/templates/index.html b/templates/index.html index f72692b..35ae2ce 100644 --- a/templates/index.html +++ b/templates/index.html @@ -7,9 +7,10 @@