Spaces:
Sleeping
Sleeping
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)
|