fix: 提升暗色主题文字对比度,解决提示文字看不清的问题

- 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颜色覆盖
This commit is contained in:
2026-05-21 21:55:13 +08:00
parent d2ce8f54d4
commit d3dd11ca8b
3 changed files with 390 additions and 30 deletions

113
app.py
View File

@@ -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/<topic_id>/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/<topic_id>/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()