blob: a0314c40d64fb4e622b3feeb0eaffe8f69b3acb9 [file] [log] [blame]
whtb1e79592025-06-07 16:03:09 +08001import React, { useState } from "react";
2
3// 示例申诉数据
4const appeals = [
5 {
6 appeal_id: "a001",
7 user_id: "u001",
8 content: "我没有作弊,请审核我的账号。",
9 file_url: "http://sse.bjtu.edu.cn/media/attachments/2024/10/20241012160658.pdf",
10 status: 0,
11 },
12 {
13 appeal_id: "a002",
14 user_id: "u002",
15 content: "误封申诉,详见附件。",
16 file_url: "http://sse.bjtu.edu.cn/media/attachments/2024/10/20241012160658.pdf",
17 status: 1,
18 },
19];
20
21// 简单PDF预览组件
22function FileViewer({ url }) {
23 if (!url) return <div>无附件</div>;
24 if (url.endsWith(".pdf")) {
25 return (
26 <iframe
27 src={url}
28 title="PDF预览"
29 width="100%"
30 height="400px"
31 style={{ border: "1px solid #ccc", borderRadius: 8 }}
32 />
33 );
34 }
35 // 这里只做PDF示例,实际可扩展为DOC等
36 return <a href={url} target="_blank" rel="noopener noreferrer">下载附件</a>;
37}
38
39export default function AppealPage() {
40 const [selectedId, setSelectedId] = useState(appeals[0].appeal_id);
41 const selectedAppeal = appeals.find(a => a.appeal_id === selectedId);
42
43 const handleApprove = () => {
44 alert("已通过申诉(示例,无实际状态变更)");
45 };
46 const handleReject = () => {
47 alert("已拒绝申诉(示例,无实际状态变更)");
48 };
49
50 return (
51 <div style={{ display: "flex", minHeight: "100vh", background: "#f7faff" }}>
52 {/* 侧栏 */}
53 <div style={{ width: 180, background: "#fff", borderRight: "1px solid #e0e7ff", padding: 0 }}>
54 <h3 style={{ textAlign: "center", padding: "18px 0 0 0", color: "#1976d2" }}>申诉列表</h3>
55 <div style={{ display: "flex", flexDirection: "column", gap: 12, marginTop: 18 }}>
56 {appeals.map(a => (
57 <div
58 key={a.appeal_id}
59 onClick={() => setSelectedId(a.appeal_id)}
60 style={{
61 margin: "0 12px",
62 padding: "16px 10px",
63 borderRadius: 8,
64 background: selectedId === a.appeal_id ? "#e3f2fd" : "#fff",
65 border: `2px solid ${a.status === 1 ? "#43a047" : "#e53935"}`,
66 color: a.status === 1 ? "#43a047" : "#e53935",
67 fontWeight: 600,
68 cursor: "pointer",
69 boxShadow: selectedId === a.appeal_id ? "0 2px 8px #b2d8ea" : "none",
70 transition: "all 0.2s"
71 }}
72 >
73 {a.appeal_id}
74 <span style={{
75 float: "right",
76 fontSize: 12,
77 color: a.status === 1 ? "#43a047" : "#e53935"
78 }}>
79 {a.status === 1 ? "已审核" : "未审核"}
80 </span>
81 </div>
82 ))}
83 </div>
84 </div>
85 {/* 申诉详情 */}
86 <div style={{ flex: 1, padding: "40px 48px" }}>
87 <h2 style={{ marginBottom: 24, color: "#1976d2" }}>申诉详情</h2>
88 <div style={{ background: "#fff", borderRadius: 12, padding: 32, boxShadow: "0 2px 8px #e0e7ff", marginBottom: 32 }}>
89 <div style={{ marginBottom: 18 }}>
90 <b>申诉ID:</b>{selectedAppeal.appeal_id}
91 </div>
92 <div style={{ marginBottom: 18 }}>
93 <b>用户ID:</b>{selectedAppeal.user_id}
94 </div>
95 <div style={{ marginBottom: 18 }}>
96 <b>申诉内容:</b>{selectedAppeal.content}
97 </div>
98 <div style={{ marginBottom: 18 }}>
99 <b>申诉文件:</b>
100 <FileViewer url={selectedAppeal.file_url} />
101 </div>
102 </div>
103 {/* 审核按钮 */}
104 <div style={{ display: "flex", gap: 32, justifyContent: "center" }}>
105 <button
106 style={{
107 background: selectedAppeal.status === 1 ? "#bdbdbd" : "#43a047",
108 color: "#fff",
109 border: "none",
110 borderRadius: 8,
111 padding: "10px 38px",
112 fontWeight: 600,
113 fontSize: 18,
114 cursor: selectedAppeal.status === 1 ? "not-allowed" : "pointer"
115 }}
116 disabled={selectedAppeal.status === 1}
117 onClick={handleApprove}
118 >
119 通过
120 </button>
121 <button
122 style={{
123 background: selectedAppeal.status === 1 ? "#bdbdbd" : "#e53935",
124 color: "#fff",
125 border: "none",
126 borderRadius: 8,
127 padding: "10px 38px",
128 fontWeight: 600,
129 fontSize: 18,
130 cursor: selectedAppeal.status === 1 ? "not-allowed" : "pointer"
131 }}
132 disabled={selectedAppeal.status === 1}
133 onClick={handleReject}
134 >
135 不通过
136 </button>
137 </div>
138 </div>
139 </div>
140 );
141}