File size: 4,517 Bytes
40ff5dd
 
 
 
 
 
 
05c3aec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40ff5dd
 
 
05c3aec
 
40ff5dd
 
05c3aec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40ff5dd
 
05c3aec
 
 
 
 
40ff5dd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
import json
import uuid
from datetime import datetime
from flask import Flask, render_template, request, jsonify

app = Flask(__name__)
DATA_FILE = os.environ.get("DATA_FILE", "requests.json")

DEFAULT_REQUESTS = [
    {
        "id": "1",
        "title": "增加暗色模式",
        "description": "建议增加暗色模式支持,方便夜间使用。",
        "category": "界面设计 (UI/UX)",
        "votes": 15,
        "status": "planned",
        "created_at": datetime.now().isoformat(),
        "comments": []
    },
    {
        "id": "2",
        "title": "支持图片上传",
        "description": "在提交反馈时,希望可以上传截图,这样能更直观地说明问题。",
        "category": "功能建议 (Feature)",
        "votes": 8,
        "status": "pending",
        "created_at": datetime.now().isoformat(),
        "comments": []
    },
    {
        "id": "3",
        "title": "移动端适配优化",
        "description": "目前在手机上查看列表时,排版有些拥挤,建议优化移动端显示。",
        "category": "界面设计 (UI/UX)",
        "votes": 12,
        "status": "in_progress",
        "created_at": datetime.now().isoformat(),
        "comments": []
    }
]

def load_data():
    if not os.path.exists(DATA_FILE):
        save_data(DEFAULT_REQUESTS)
        return DEFAULT_REQUESTS
    try:
        with open(DATA_FILE, "r", encoding="utf-8") as f:
            data = json.load(f)
            if not isinstance(data, list):
                # If data is corrupted (not a list), backup and reset
                print(f"Warning: {DATA_FILE} contains invalid data (not a list). Resetting.")
                os.rename(DATA_FILE, DATA_FILE + ".bak")
                save_data(DEFAULT_REQUESTS)
                return DEFAULT_REQUESTS
            return data
    except Exception as e:
        print(f"Error loading data: {e}. Resetting.")
        # If file is corrupted, reset
        if os.path.exists(DATA_FILE):
             os.rename(DATA_FILE, DATA_FILE + ".bak")
        save_data(DEFAULT_REQUESTS)
        return DEFAULT_REQUESTS

def save_data(data):
    try:
        with open(DATA_FILE, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
    except Exception as e:
        print(f"Error saving data: {e}")

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

@app.route("/api/requests", methods=["GET"])
def get_requests():
    data = load_data()
    # Sort by votes (desc) then date (desc)
    data.sort(key=lambda x: (x.get("votes", 0), x.get("created_at", "")), reverse=True)
    return jsonify(data)

@app.route("/api/requests", methods=["POST"])
def add_request():
    data = load_data()
    payload = request.json
    
    if not payload.get("title") or not payload.get("description"):
        return jsonify({"error": "Title and description are required"}), 400
        
    new_request = {
        "id": str(uuid.uuid4()),
        "title": payload["title"],
        "description": payload["description"],
        "category": payload.get("category", "General"),
        "votes": 1,
        "status": "pending",  # pending, planned, in_progress, completed, rejected
        "created_at": datetime.now().isoformat(),
        "comments": []
    }
    
    data.append(new_request)
    save_data(data)
    return jsonify(new_request)

@app.route("/api/requests/<req_id>/vote", methods=["POST"])
def vote_request(req_id):
    data = load_data()
    for req in data:
        if req["id"] == req_id:
            req["votes"] = req.get("votes", 0) + 1
            save_data(data)
            return jsonify({"success": True, "votes": req["votes"]})
    return jsonify({"error": "Request not found"}), 404

@app.route("/api/requests/<req_id>/status", methods=["POST"])
def update_status(req_id):
    # Simple admin check (in a real app, use auth)
    # Here we just trust the client for the demo/MVP purpose
    payload = request.json
    new_status = payload.get("status")
    
    if new_status not in ["pending", "planned", "in_progress", "completed", "rejected"]:
        return jsonify({"error": "Invalid status"}), 400

    data = load_data()
    for req in data:
        if req["id"] == req_id:
            req["status"] = new_status
            save_data(data)
            return jsonify({"success": True, "status": new_status})
    return jsonify({"error": "Request not found"}), 404

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=7860)