首页/ mobileweb/ 教师点评H5移动端功能演示/ 代码预览

💻 代码预览 · 教师点评H5移动端功能演示

mw_edu · 上传者 驰旭教育
← 返回详情
index.html · 约 17083 字符
1<!DOCTYPE html>
2<html lang="zh-CN">
3<head>
4<meta charset="UTF-8">
5<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
6<title>教师点评</title>
7<script src="../_vendor/jquery.min.js"></script>
8<style>
9  * { margin:0; padding:0; box-sizing:border-box; -webkit-tap-highlight-color:transparent; }
10  :root{
11    --blue:#2563eb; --blue2:#1d4ed8; --cyan:#06b6d4; --amber:#f59e0b;
12    --red:#ef4444; --green:#22c55e; --bg:#f4f6fb; --card:#ffffff;
13    --text:#1f2937; --mute:#8a93a6; --line:#eef1f6;
14  }
15  body{ font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;
16    background:#dfe4ee; color:var(--text); }
17  .app{ max-width:430px; margin:0 auto; min-height:100vh; background:var(--bg);
18    position:relative; padding-bottom:64px; box-shadow:0 0 28px rgba(0,0,0,.08); }
19  .topbar{ background:linear-gradient(120deg,var(--blue),var(--cyan)); color:#fff;
20    padding:18px 18px 16px; }
21  .topbar .brand{ font-size:21px; font-weight:800; letter-spacing:.5px; }
22  .topbar .sub{ font-size:12.5px; opacity:.9; margin-top:4px; }
23  .views{ padding:14px; }
24  .view{ display:none; }
25  .view.active{ display:block; animation:fade .25s ease; }
26  @keyframes fade{ from{opacity:0;transform:translateY(6px)} to{opacity:1;transform:none} }
27  .card{ background:var(--card); border-radius:16px; padding:15px; margin-bottom:13px;
28    box-shadow:0 4px 16px rgba(31,41,55,.05); }
29  .card h3{ font-size:15px; margin-bottom:12px; display:flex; align-items:center; gap:7px; }
30  .card h3 .ic{ font-size:17px; }
31  .hint{ font-size:12px; color:var(--mute); margin:-6px 0 12px; }
32  /* 选老师 */
33  .chips{ display:flex; gap:9px; overflow-x:auto; padding-bottom:4px; }
34  .chips::-webkit-scrollbar{ display:none; }
35  .tchip{ flex:0 0 auto; padding:9px 13px; border-radius:999px; background:#f0f3f9;
36    border:1.5px solid transparent; font-size:13.5px; font-weight:600; color:#475069; white-space:nowrap; }
37  .tchip.on{ background:#e8f0ff; border-color:var(--blue); color:var(--blue2); }
38  /* 维度打分 */
39  .dim{ display:flex; align-items:center; justify-content:space-between; padding:9px 0; border-bottom:1px solid var(--line); }
40  .dim:last-child{ border-bottom:none; }
41  .dim .name{ font-size:14px; font-weight:600; }
42  .stars{ display:flex; gap:5px; }
43  .star{ font-size:23px; color:#d8dee9; cursor:pointer; transition:.12s; line-height:1; }
44  .star.on{ color:var(--amber); transform:scale(1.06); }
45  textarea{ width:100%; margin-top:10px; border:1.5px solid var(--line); border-radius:12px;
46    padding:11px; font-size:13.5px; resize:none; height:74px; font-family:inherit; color:var(--text); }
47  textarea:focus{ outline:none; border-color:var(--blue); }
48  .btn{ width:100%; margin-top:13px; padding:13px; border:none; border-radius:13px;
49    background:linear-gradient(120deg,var(--blue),var(--cyan)); color:#fff; font-size:15.5px;
50    font-weight:800; cursor:pointer; letter-spacing:1px; }
51  .btn:active{ transform:scale(.99); }
52  /* 榜单 */
53  .lead{ font-size:12.5px; color:var(--mute); margin-bottom:10px; }
54  .trow{ display:flex; align-items:center; gap:12px; padding:12px 4px; border-bottom:1px solid var(--line); cursor:pointer; }
55  .trow:active{ background:#fafbff; }
56  .rank{ width:26px; text-align:center; font-weight:800; font-size:16px; color:var(--mute); }
57  .rank.g{ color:var(--amber); }
58  .ava{ width:42px; height:42px; border-radius:12px; background:#eef2ff; display:flex; align-items:center;
59    justify-content:center; font-size:23px; flex:0 0 auto; }
60  .tinfo{ flex:1; min-width:0; }
61  .tinfo .nm{ font-size:15px; font-weight:700; }
62  .tinfo .sb{ font-size:12px; color:var(--mute); margin-top:2px; }
63  .tscore{ text-align:right; flex:0 0 auto; }
64  .tscore .v{ font-size:19px; font-weight:800; color:var(--blue2); }
65  .tscore .c{ font-size:11.5px; color:var(--mute); margin-top:2px; }
66  .bar{ height:6px; border-radius:6px; background:#eef1f6; margin-top:7px; overflow:hidden; }
67  .bar > i{ display:block; height:100%; border-radius:6px; background:linear-gradient(90deg,var(--blue),var(--cyan)); }
68  /* 公示 */
69  .fault{ border-left:4px solid var(--red); background:#fff5f5; border-radius:0 12px 12px 0; padding:12px 14px; margin-bottom:11px; }
70  .fault .ft{ display:flex; align-items:center; justify-content:space-between; margin-bottom:6px; }
71  .fault .ft .tn{ font-size:14.5px; font-weight:800; }
72  .tag{ font-size:11px; font-weight:700; padding:3px 9px; border-radius:999px; }
73  .tag.red{ background:#ffe1e1; color:#d62727; }
74  .tag.amber{ background:#fff0d6; color:#b9740a; }
75  .tag.green{ background:#ddfbe6; color:#15803d; }
76  .fault .ty{ font-size:13px; font-weight:700; color:#b91c1c; margin-bottom:3px; }
77  .fault .ds{ font-size:12.5px; color:#6b7280; line-height:1.55; }
78  .fault .dt{ font-size:11px; color:#9ca3af; margin-top:6px; }
79  /* 我的 */
80  .empty{ text-align:center; color:var(--mute); padding:50px 20px; font-size:13.5px; }
81  .empty .e{ font-size:40px; margin-bottom:12px; }
82  .rev{ border:1px solid var(--line); border-radius:13px; padding:13px; margin-bottom:11px; }
83  .rev .rh{ display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; }
84  .rev .rh .tn{ font-weight:700; font-size:14.5px; }
85  .rev .rh .tm{ font-size:11px; color:var(--mute); }
86  .rev .rs{ font-size:12px; color:var(--mute); margin-bottom:7px; }
87  .rev .rs b{ color:var(--blue2); }
88  .rev .rt{ font-size:13px; color:#4b5563; line-height:1.55; background:#f7f9fc; border-radius:9px; padding:8px 10px; }
89  /* tabbar */
90  .tabbar{ position:fixed; bottom:0; left:50%; transform:translateX(-50%); width:100%; max-width:430px;
91    height:60px; background:#fff; border-top:1px solid var(--line); display:flex; }
92  .tabbar button{ flex:1; border:none; background:none; font-size:11.5px; color:var(--mute);
93    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px; cursor:pointer; }
94  .tabbar button .ti{ font-size:20px; }
95  .tabbar button.on{ color:var(--blue); font-weight:700; }
96  /* sheet */
97  .mask{ position:fixed; inset:0; background:rgba(15,23,42,.45); opacity:0; pointer-events:none;
98    transition:.25s; z-index:30; }
99  .mask.show{ opacity:1; pointer-events:auto; }
100  .sheet{ position:fixed; left:50%; bottom:0; transform:translate(-50%,100%); width:100%; max-width:430px;
101    background:#fff; border-radius:20px 20px 0 0; padding:20px 18px 28px; transition:.3s; z-index:31; }
102  .sheet.show{ transform:translate(-50%,0); }
103  .sheet .sh{ display:flex; align-items:center; gap:12px; margin-bottom:16px; }
104  .sheet .sh .ava{ width:52px; height:52px; font-size:28px; }
105  .sheet .sh .nm{ font-size:18px; font-weight:800; }
106  .sheet .sh .sb{ font-size:12.5px; color:var(--mute); margin-top:3px; }
107  .sheet .close{ margin-left:auto; font-size:22px; color:var(--mute); cursor:pointer; }
108  .dist{ display:flex; align-items:center; gap:10px; margin:10px 0; }
109  .dist .dn{ width:74px; font-size:13px; color:#475069; flex:0 0 auto; }
110  .dist .db{ flex:1; height:9px; background:#eef1f6; border-radius:9px; overflow:hidden; }
111  .dist .db > i{ display:block; height:100%; background:linear-gradient(90deg,var(--amber),#fb923c); border-radius:9px; }
112  .dist .dv{ width:30px; text-align:right; font-size:12.5px; font-weight:700; color:var(--amber); }
113  /* toast */
114  .toast{ position:fixed; left:50%; top:42%; transform:translate(-50%,-50%) scale(.9); z-index:50;
115    background:rgba(17,24,39,.9); color:#fff; padding:13px 22px; border-radius:12px; font-size:14px;
116    font-weight:700; opacity:0; pointer-events:none; transition:.2s; }
117  .toast.show{ opacity:1; transform:translate(-50%,-50%) scale(1); }
118</style>
119</head>
120<body>
121<div class="app">
122  <header class="topbar">
123    <div class="brand">📝 教师点评</div>
124    <div class="sub">多维度评分 · 公开榜单 · 教师过错公示</div>
125  </header>
126
127  <main class="views">
128    <!-- 点评打分 -->
129    <section class="view active" id="view-pingfen">
130      <div class="card">
131        <h3><span class="ic">🎯</span>选择要评价的教师</h3>
132        <div class="chips" id="teacherChips"></div>
133      </div>
134      <div class="card">
135        <h3><span class="ic">⭐</span>多维度打分</h3>
136        <p class="hint">点击星星为每个维度评分(1~5 星)</p>
137        <div id="dimList"></div>
138        <textarea id="reviewText" placeholder="写下你对老师的具体评价或建议…"></textarea>
139        <button class="btn" id="submitBtn">提交点评</button>
140      </div>
141    </section>
142
143    <!-- 榜单 -->
144    <section class="view" id="view-bangdan">
145      <div class="card">
146        <h3><span class="ic">🏆</span>教师好评榜</h3>
147        <p class="lead">按学生综合评分排序,点击查看维度分布</p>
148        <div id="rankList"></div>
149      </div>
150    </section>
151
152    <!-- 过错公示 -->
153    <section class="view" id="view-gongshi">
154      <div class="card">
155        <h3><span class="ic">📢</span>教师过错公示</h3>
156        <p class="lead">教学失职、违纪行为公开通报,接受监督</p>
157        <div id="faultList"></div>
158      </div>
159    </section>
160
161    <!-- 我的 -->
162    <section class="view" id="view-mine">
163      <div class="card">
164        <h3><span class="ic">👤</span>我的点评</h3>
165        <div id="myList"></div>
166      </div>
167    </section>
168  </main>
169
170  <nav class="tabbar">
171    <button data-v="pingfen" class="on"><span class="ti">📝</span>点评</button>
172    <button data-v="bangdan"><span class="ti">🏆</span>榜单</button>
173    <button data-v="gongshi"><span class="ti">📢</span>公示</button>
174    <button data-v="mine"><span class="ti">👤</span>我的</button>
175  </nav>
176</div>
177
178<div class="mask" id="mask"></div>
179<div class="sheet" id="sheet">
180  <div class="sh">
181    <div class="ava" id="shAva">👩‍🏫</div>
182    <div>
183      <div class="nm" id="shName">教师</div>
184      <div class="sb" id="shSub">科目</div>
185    </div>
186    <div class="close" id="shClose">✕</div>
187  </div>
188  <div id="shDist"></div>
189</div>
190<div class="toast" id="toast"></div>
191
192<script>
193var DIMS = ["教学态度","专业水平","课堂互动","作业批改","责任心","答疑及时"];
194var TEACHERS = [
195  {id:1,name:"王敏",emoji:"👩‍🏫",sub:"高中语文",score:4.8,cnt:326,dims:[5,5,4,5,5,4]},
196  {id:2,name:"李建国",emoji:"👨‍🏫",sub:"初中数学",score:4.6,cnt:288,dims:[5,4,4,5,4,5]},
197  {id:3,name:"张雪",emoji:"👩‍🏫",sub:"小学英语",score:4.9,cnt:412,dims:[5,5,5,5,5,4]},
198  {id:4,name:"陈涛",emoji:"👨‍🏫",sub:"高中物理",score:4.3,cnt:201,dims:[4,5,3,4,4,4]},
199  {id:5,name:"刘洋",emoji:"🧑‍🏫",sub:"初中化学",score:4.5,cnt:243,dims:[4,5,4,4,4,5]},
200  {id:6,name:"赵琳",emoji:"👩‍🏫",sub:"小学音乐",score:4.7,cnt:176,dims:[5,4,5,4,5,4]}
201];
202var FAULTS = [
203  {t:"陈涛",type:"上课迟到",desc:"9月12日第3节课迟到8分钟,影响正常教学秩序。",status:"已通报",tag:"red",date:"09-12"},
204  {t:"李建国",type:"作业批改不及时",desc:"连续两周未批改单元测验,家长多次反映后补批。",status:"处理中",tag:"amber",date:"09-18"},
205  {t:"王敏",type:"课堂言论不当",desc:"授课中使用不恰当比喻,已约谈并责令书面检查。",status:"已整改",tag:"green",date:"09-05"},
206  {t:"刘洋",type:"实验安全管理疏漏",desc:"化学实验课未按要求清点器材,存在安全隐患。",status:"已通报",tag:"red",date:"09-20"},
207  {t:"赵琳",type:"擅自调课",desc:"未报备私自与其他教师调换课程,造成学生空堂。",status:"处理中",tag:"amber",date:"09-15"}
208];
209
210var sel = { tid:null, scores:{} };
211
212function toast(msg){ var t=$("#toast"); t.text(msg).addClass("show"); setTimeout(function(){ t.removeClass("show"); },1400); }
213
214function renderChips(){
215  var h = TEACHERS.map(function(t){
216    return '<div class="tchip" data-tid="'+t.id+'">'+t.emoji+' '+t.name+'</div>';
217  }).join("");
218  $("#teacherChips").html(h);
219  $("#teacherChips .tchip").on("click", function(){
220    $("#teacherChips .tchip").removeClass("on");
221    $(this).addClass("on");
222    sel.tid = parseInt($(this).data("tid"));
223  });
224}
225function renderDims(){
226  var h = DIMS.map(function(d){
227    return '<div class="dim" data-dim="'+d+'"><span class="name">'+d+'</span>'+
228      '<div class="stars">'+'<span class="star" data-v="1">★</span><span class="star" data-v="2">★</span>'+
229      '<span class="star" data-v="3">★</span><span class="star" data-v="4">★</span><span class="star" data-v="5">★</span>'+
230      '</div></div>';
231  }).join("");
232  $("#dimList").html(h);
233  $("#dimList .dim").each(function(){
234    var dim = $(this).data("dim");
235    $(this).find(".star").on("click", function(){
236      var v = parseInt($(this).data("v"));
237      sel.scores[dim] = v;
238      $(this).parent().find(".star").removeClass("on");
239      $(this).prevAll(".star").addBack().addClass("on");
240    });
241  });
242}
243function renderRank(){
244  var sorted = TEACHERS.slice().sort(function(a,b){ return b.score-a.score; });
245  var h = sorted.map(function(t,i){
246    var medal = i===0?"🥇":i===1?"🥈":i===2?"🥉":(i+1);
247    var g = i<3?" g":"";
248    return '<div class="trow" data-tid="'+t.id+'"><div class="rank'+g+'">'+medal+'</div>'+
249      '<div class="ava">'+t.emoji+'</div>'+
250      '<div class="tinfo"><div class="nm">'+t.name+'</div><div class="sb">'+t.sub+'</div>'+
251      '<div class="bar"><i style="width:'+(t.score/5*100)+'%"></i></div></div>'+
252      '<div class="tscore"><div class="v">'+t.score.toFixed(1)+'</div><div class="c">'+t.cnt+' 评</div></div></div>';
253  }).join("");
254  $("#rankList").html(h);
255  $("#rankList .trow").on("click", function(){ openSheet(parseInt($(this).data("tid"))); });
256}
257function renderFaults(){
258  var h = FAULTS.map(function(f){
259    return '<div class="fault"><div class="ft"><span class="tn">'+f.t+'</span>'+
260      '<span class="tag '+f.tag+'">'+f.status+'</span></div>'+
261      '<div class="ty">⚠ '+f.type+'</div><div class="ds">'+f.desc+'</div>'+
262      '<div class="dt">公示日期:'+f.date+'</div></div>';
263  }).join("");
264  $("#faultList").html(h);
265}
266function renderMine(){
267  var raw = localStorage.getItem("teacher_reviews");
268  var list = raw? JSON.parse(raw): [];
269  if(!list.length){ $("#myList").html('<div class="empty"><div class="e">🗒️</div>还没有点评记录<br>去「点评」给老师打分吧</div>'); return; }
270  var h = list.slice().reverse().map(function(r){
271    var avg = (r.scores.reduce(function(a,b){return a+b;},0)/r.scores.length).toFixed(1);
272    var dims = DIMS.map(function(d,i){ return d+" "+r.scores[i]+"★"; }).join(" · ");
273    return '<div class="rev"><div class="rh"><span class="tn">'+r.tname+'</span><span class="tm">'+r.time+'</span></div>'+
274      '<div class="rs">综合 <b>'+avg+'</b> 星 | '+dims+'</div>'+
275      (r.text?'<div class="rt">'+r.text+'</div>':'')+'</div>';
276  }).join("");
277  $("#myList").html(h);
278}
279function openSheet(tid){
280  var t = TEACHERS.filter(function(x){return x.id===tid;})[0]; if(!t) return;
281  $("#shAva").text(t.emoji); $("#shName").text(t.name); $("#shSub").text(t.sub+" · 综合 "+t.score.toFixed(1)+" 星");
282  var d = $("#shDist").empty();
283  DIMS.forEach(function(name,i){
284    d.append('<div class="dist"><span class="dn">'+name+'</span><div class="db"><i style="width:'+(t.dims[i]/5*100)+'%"></i></div><span class="dv">'+t.dims[i]+'</span></div>');
285  });
286  $("#mask").addClass("show"); $("#sheet").addClass("show");
287}
288function closeSheet(){ $("#mask").removeClass("show"); $("#sheet").removeClass("show"); }
289
290$(function(){
291  renderChips(); renderDims(); renderRank(); renderFaults(); renderMine();
292  $(".tabbar button").on("click", function(){
293    $(".tabbar button").removeClass("on"); $(this).addClass("on");
294    $(".view").removeClass("active"); $("#view-"+$(this).data("v")).addClass("active");
295    if($(this).data("v")==="mine") renderMine();
296  });
297  $("#shClose").on("click", closeSheet); $("#mask").on("click", closeSheet);
298  $("#submitBtn").on("click", function(){
299    if(!sel.tid){ toast("请先选择教师"); return; }
300    for(var i=0;i<DIMS.length;i++){ if(!sel.scores[DIMS[i]]){ toast("请完成全部维度评分"); return; } }
301    var t = TEACHERS.filter(function(x){return x.id===sel.tid;})[0];
302    var rec = { tid:sel.tid, tname:t.name, scores:DIMS.map(function(d){return sel.scores[d];}),
303      text:$("#reviewText").val().trim(), time:new Date().toLocaleString("zh-CN",{hour12:false}) };
304    var raw = localStorage.getItem("teacher_reviews"); var list = raw?JSON.parse(raw):[];
305    list.push(rec); localStorage.setItem("teacher_reviews", JSON.stringify(list));
306    toast("点评提交成功 ✓");
307    sel = { tid:null, scores:{} }; $("#teacherChips .tchip").removeClass("on");
308    $("#dimList .star").removeClass("on"); $("#reviewText").val("");
309  });
310});
311</script>
312</body>
313</html>