File size: 4,955 Bytes
adb7761
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b0fefeb
 
 
 
 
 
 
 
adb7761
 
 
b0fefeb
 
 
 
adb7761
 
 
 
 
 
 
 
 
b0fefeb
 
adb7761
 
 
 
 
 
 
 
 
 
 
 
 
 
b0fefeb
adb7761
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b0fefeb
adb7761
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b0fefeb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
adb7761
 
b0fefeb
 
adb7761
 
 
 
 
 
 
4c2d124
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
import os
import re
from flask import Flask, jsonify, send_from_directory, render_template, request

app = Flask(__name__)
PROBLEMS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'problems')

def parse_problem_metadata(filename):
    filepath = os.path.join(PROBLEMS_DIR, filename)
    with open(filepath, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # 默认标题为文件名
    title = filename
    
    # 尝试解析 @title
    # 匹配 /** ... @title 标题 ... */ 或 // @title 标题
    title_match = re.search(r'@title\s+(.+)', content)
    if title_match:
        title = title_match.group(1).strip()
    
    # 解析 @category
    category_match = re.search(r'@category\s+(.+)', content)
    category = category_match.group(1).strip() if category_match else '练习题'

    # 解析 @pinned
    pinned_match = re.search(r'@pinned\s+(.+)', content)
    is_pinned = (pinned_match.group(1).strip().lower() == 'true') if pinned_match else False

    return {
        'id': filename,
        'title': title,
        'category': category,
        'pinned': is_pinned,
        'content': content,
        'ctime': os.path.getctime(filepath)
    }

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/api/problems', methods=['GET'])
def get_problems():
    files = [f for f in os.listdir(PROBLEMS_DIR) if f.endswith('.js') or f.endswith('.ts')]
    # 按创建时间倒序排序 (最新的在最前)
    files.sort(key=lambda x: os.path.getctime(os.path.join(PROBLEMS_DIR, x)), reverse=True)
    
    problems = []
    for f in files:
        try:
            problems.append(parse_problem_metadata(f))
        except Exception as e:
            print(f"Error parsing {f}: {e}")
            
    return jsonify(problems)

@app.route('/api/problems', methods=['POST'])
def create_problem():
    data = request.json
    filename = data.get('filename')
    category = data.get('category', '练习题')
    
    if not filename:
        return jsonify({'error': 'Filename is required'}), 400
    
    if not (filename.endswith('.js') or filename.endswith('.ts')):
        filename += '.js'
        
    filepath = os.path.join(PROBLEMS_DIR, filename)
    
    if os.path.exists(filepath):
        return jsonify({'error': 'File already exists'}), 409
        
    # 默认模板
    content = f"""/**
 * @title {filename}
 * @category {category}
 * @description 在此处添加题目描述
 */

function solve() {{
    // TODO: Implement solution
}}

console.log(solve());
"""
    
    try:
        with open(filepath, 'w', encoding='utf-8') as f:
            f.write(content)
        return jsonify(parse_problem_metadata(filename)), 201
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/problems/<path:filename>', methods=['GET'])
def get_problem_content(filename):
    return send_from_directory(PROBLEMS_DIR, filename)

@app.route('/api/problems/<path:filename>', methods=['PUT'])
def update_problem(filename):
    filepath = os.path.join(PROBLEMS_DIR, filename)
    
    if not os.path.exists(filepath):
        return jsonify({'error': 'File not found'}), 404
        
    data = request.json
    
    # Handle Rename
    new_filename = data.get('new_filename')
    if new_filename:
        if not (new_filename.endswith('.js') or new_filename.endswith('.ts')):
            new_filename += '.js'
            
        new_filepath = os.path.join(PROBLEMS_DIR, new_filename)
        if os.path.exists(new_filepath) and new_filename != filename:
            return jsonify({'error': 'Target filename already exists'}), 409
            
        try:
            os.rename(filepath, new_filepath)
            return jsonify(parse_problem_metadata(new_filename))
        except Exception as e:
            return jsonify({'error': str(e)}), 500

    # Handle Content Update
    content = data.get('content')
    if content is not None:
        try:
            with open(filepath, 'w', encoding='utf-8') as f:
                f.write(content)
            # 返回新的 metadata 以便前端更新标题
            return jsonify(parse_problem_metadata(filename))
        except Exception as e:
            return jsonify({'error': str(e)}), 500
            
    return jsonify({'error': 'No valid operation specified'}), 400

@app.route('/api/problems/<path:filename>', methods=['DELETE'])
def delete_problem(filename):
    filepath = os.path.join(PROBLEMS_DIR, filename)
    
    if not os.path.exists(filepath):
        return jsonify({'error': 'File not found'}), 404
        
    try:
        os.remove(filepath)
        return jsonify({'message': 'Deleted successfully'})
    except Exception as e:
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    # 确保 problems 目录存在
    if not os.path.exists(PROBLEMS_DIR):
        os.makedirs(PROBLEMS_DIR)
    app.run(host='0.0.0.0', port=7860, debug=True)