File size: 6,251 Bytes
44cae7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
from flask import Blueprint, render_template, request, jsonify, redirect, url_for, session, flash, send_file, current_app
import os
from app.models import db, Article, Image
from app.utils import handle_image_upload, login_required, check_auth
from app.ai_service import generate_summary, chat_with_ai
import io
import json

# Blueprints
main = Blueprint('main', __name__)
admin = Blueprint('admin', __name__)
api = Blueprint('api', __name__)

# Main routes
@main.route('/')
def index():
    articles = Article.query.order_by(Article.created_at.desc()).all()
    return render_template('index.html', articles=articles)

@main.route('/article/<slug>')
def article(slug):
    article = Article.query.filter_by(slug=slug).first_or_404()
    return render_template('article.html', article=article)

# Admin routes
# @admin.route('/login', methods=['GET', 'POST'])
# def login():
#     if request.method == 'POST':
#         if check_auth(request.form['username'], request.form['password']):
#             session['logged_in'] = True
#             return redirect(url_for('admin.dashboard'))
#         flash('Invalid credentials')
#     return render_template('admin/login.html')
@admin.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        if session.get('logged_in'):
            session.pop('logged_in', None)
            flash('已成功退出登录')
            return redirect(url_for('main.index'))
            
        if check_auth(request.form['username'], request.form['password']):
            session['logged_in'] = True
            return redirect(url_for('admin.dashboard'))
        flash('用户名或密码错误')
    return render_template('admin/login.html')
@api.route('/search', methods=['GET'])
def search():
    query = request.args.get('q', '')
    if not query:
        return jsonify({'articles': []})
    
    # 简单的模糊搜索:标题或内容包含搜索词
    articles = Article.query.filter(
        db.or_(
            Article.title.ilike(f'%{query}%'),
            Article.content.ilike(f'%{query}%')
        )
    ).order_by(Article.created_at.desc()).all()
    
    # 转换为JSON格式
    articles_data = [{
        'title': article.title,
        'summary': article.summary,
        'slug': article.slug,
        'created_at': article.created_at.strftime('%Y-%m-%d')
    } for article in articles]
    
    return jsonify({'articles': articles_data})
@admin.route('/dashboard')
@login_required
def dashboard():
    articles = Article.query.order_by(Article.created_at.desc()).all()
    return render_template('admin/dashboard.html', articles=articles)

@admin.route('/editor', defaults={'slug': None})
@admin.route('/editor/<slug>')
@login_required
def editor(slug):
    article = Article.query.filter_by(slug=slug).first() if slug else None
    return render_template('editor.html', article=article)

# API routes
@api.route('/articles', methods=['POST'])
@login_required
def create_article():
    try:
        data = request.get_json()
        if not data or 'title' not in data or 'content' not in data:
            return jsonify({'error': '标题和内容不能为空'}), 400
            
        article = Article(
            title=data['title'],
            content=data['content']
        )
        article.summary = generate_summary(data['content'])
        db.session.add(article)
        db.session.commit()
        return jsonify({'slug': article.slug})
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

@api.errorhandler(500)
def handle_500(error):
    return jsonify({'error': '服务器内部错误'}), 500

@api.route('/articles/<slug>', methods=['PUT'])
@login_required
def update_article(slug):
    article = Article.query.filter_by(slug=slug).first_or_404()
    data = request.get_json()
    article.title = data['title']
    article.content = data['content']
    article.summary = generate_summary(data['content'])
    db.session.commit()
    return jsonify({'success': True})

@api.route('/articles/<slug>', methods=['DELETE'])
@login_required
def delete_article(slug):
    article = Article.query.filter_by(slug=slug).first_or_404()
    db.session.delete(article)
    db.session.commit()
    return jsonify({'success': True})

@api.route('/upload', methods=['POST'])
@login_required
def upload():
    if 'file' not in request.files:
        return jsonify({'error': 'No file provided'}), 400
    
    file = request.files['file']
    path = handle_image_upload(file)
    
    if path:
        return jsonify({'url': path})
    
    return jsonify({'error': 'Invalid file'}), 400

@api.route('/images/<int:image_id>')
def get_image(image_id):
    image = Image.query.get_or_404(image_id)
    return send_file(
        io.BytesIO(image.data),
        mimetype=image.mime_type,
        as_attachment=False
    )

@api.route('/chat', methods=['POST'])
def chat():
    data = request.get_json()
    response = chat_with_ai(data['messages'])
    return jsonify({'response': response})

@api.route('/export', methods=['GET'])
@login_required
def export_data():
    db_path = os.path.join(current_app.root_path, '..', 'instance', 'blog.db')
    return send_file(
        db_path,
        as_attachment=True,
        download_name='blog-backup.db',
        mimetype='application/x-sqlite3'
    )

@api.route('/import', methods=['POST'])
@login_required
def import_data():
    if 'file' not in request.files:
        return jsonify({'error': 'No file provided'}), 400
        
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'No file selected'}), 400
        
    if not file.filename.endswith('.db'):
        return jsonify({'error': 'Invalid file type'}), 400
        
    try:
        db_path = os.path.join(current_app.root_path, '..', 'instance', 'blog.db')
        file.save(db_path)
        db.session.remove()  # Close any existing connections
        return jsonify({'success': True})
    except Exception as e:
        return jsonify({'error': str(e)}), 500