Tessy vs 其他测试工具:如何为你的嵌入式项目选择最佳单元测试方案

核心内容摘要

数学建模核心算法精讲:从基础优化到智能预测
摆脱论文困扰! 8个降AI率平台测评对比,自考必备降AIGC神器

ChatTTS GPU加速实战:从环境配置到性能优化全指南

转载请注明出处小锋学长生活大爆炸[xfxuezhagn.cn]如果本文帮助到了你欢迎[点赞、收藏、关注]哦~网页效果https://supervisor.xfxuezhang.cn/创建Cloudflare数据库

创建D1 SQL数据库名称随便填比如mentors。

“控制台”输入sql语句PRAGMA foreign_keys ON; -- 导师表 CREATE TABLE IF NOT EXISTS mentors ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, school TEXT NOT NULL, college TEXT, field TEXT, created_at TEXT NOT NULL DEFAULT (datetime(now)) ); -- 检索与排序索引 CREATE INDEX IF NOT EXISTS idx_mentors_name ON mentors(name); CREATE INDEX IF NOT EXISTS idx_mentors_school ON mentors(school); CREATE INDEX IF NOT EXISTS idx_mentors_college ON mentors(college); CREATE INDEX IF NOT EXISTS idx_mentors_field ON mentors(field); CREATE INDEX IF NOT EXISTS idx_mentors_created_at ON mentors(created_at); -- 点评表 CREATE TABLE IF NOT EXISTS reviews ( id INTEGER PRIMARY KEY AUTOINCREMENT, mentor_id INTEGER NOT NULL, nickname TEXT NOT NULL, rating INTEGER NOT NULL CHECK (rating 1 AND rating

, content TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (datetime(now)), ip_country TEXT, ip_region TEXT, ip_city TEXT, FOREIGN KEY (mentor_id) REFERENCES mentors(id) ON DELETE CASCADE ); -- 点评查询索引 CREATE INDEX IF NOT EXISTS idx_reviews_mentor_id ON reviews(mentor_id); CREATE INDEX IF NOT EXISTS idx_reviews_created_at ON reviews(created_at); CREATE INDEX IF NOT EXISTS idx_reviews_rating ON reviews(rating);

示例数据INSERT INTO mentors (name, school, college, field) VALUES (张三, 某某大学, 计算机学院, 机器学习), (李四, 某某大学, 信息学院, 计算机视觉), (王五, 某研究所, NULL, 自然语言处理); INSERT INTO reviews (mentor_id, nickname, rating, content, ip_country, ip_region, ip_city) VALUES (1, 匿名, 5, 指导很细致组会频率合适。

, CN, Beijing, Beijing), (1, A同学, 4, 对产出要求高适合自驱强的人。

, CN, Shanghai, Shanghai), (2, 匿名, 3, 方向不错但需要更主动沟通。

, NULL, NULL, NULL);创建Cloudflare Worker

新建Worker名称随便填比如supervisor。

点击“绑定”选择创建的D1数据库名称填“DB”。

点击“编辑代码”填入// 删除评论的密码需要更改 const DELETE_REVIEW_PASSWORD delreview; // 删除导师的密码需要更改 const DELETE_MENTOR_PASSWORD delmentor; /******************************************************/ function json(data, status 200, headers {}) { return new Response(JSON.stringify(data, null,

, { status, headers: { content-type: application/json; charsetutf-8, cache-control: no-store, ...headers, }, }); } function bad(msg, status

{ return json({ ok: false, error: msg }, status); } async function readJson(request) { const ct request.headers.get(content-type) || ; if (!ct.includes(application/json)) return null; try { return await request.json(); } catch { return null; } } function getPath(url) { return new URL(url).pathname; } function htmlPage() { return !doctype html html langzh head meta charsetutf-8 / meta nameviewport contentwidthdevice-width,initial-scale1 / title导师评价网/title style :root{ --bg:#f6f7fb; --bg2:#eef2ff; --card:#ffffff; --line:rgba(15,23,42,.

; --text:#0f172a; --muted:rgba(15,23,42,.

; --accent:#2563eb; --accent2:rgba(37,99,235,.

; --danger:#e11d48; --danger2:rgba(225,29,72,.

; } *{box-sizing:border-box} body{ margin:0; font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Ubuntu,Helvetica Neue,Arial; color:var(--text); background: radial-gradient(900px 520px at 18% 0%, rgba(37,99,235,.

, transparent 62%), radial-gradient(900px 520px at 82% 0%, rgba(147,197,253,.

, transparent 62%), linear-gradient(180deg, var(--bg

, var(--bg)); min-height:100vh; } .wrap{max-width:920px;margin:0 auto;padding:18px 14px 40px} .top{ border:1px solid var(--line); background:linear-gradient(180deg, rgba(255,255,255,.

, rgba(255,255,255,.

); border-radius:18px; padding:14px 14px; box-shadow:0 18px 50px rgba(15,23,42,.

; } h1{margin:0;font-size:18px;letter-spacing:.3px} .sub{margin-top:6px;color:var(--muted);font-size:13px;line-height:

6} .stack{display:flex;flex-direction:column;gap:12px;margin-top:12px} .card{ border:1px solid var(--line); background:var(--card); border-radius:18px; padding:14px; box-shadow:0 14px 40px rgba(15,23,42,.

; } .titleRow{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px} .title{font-weight:800;font-size:14px} .muted{color:var(--muted);font-size:13px} .row{display:flex;gap:10px;flex-wrap:wrap} .grow{flex:1;min-width:240px} .starPicker{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border:1px solid var(--line);border-radius:14px;background:#fff} .starBtn{border:0;background:transparent;padding:4px 2px;cursor:pointer;font-size:18px;line-height:1;color:rgba(15,23,42,.

} .starBtn.on{color:#f59e0b} .starHelp{margin-left:6px;color:var(--muted);font-size:12px} input,textarea,button{ border-radius:14px; border:1px solid var(--line); background:#fff; color:var(--text); padding:10px 12px; font-size:14px; outline:none; } input::placeholder,textarea::placeholder{color:rgba(15,23,42,.

} textarea{width:100%;min-height:96px;resize:vertical} button{ cursor:pointer; background:var(--accent

; border-color:rgba(37,99,235,.

; color:var(--text); } button:hover{background:rgba(37,99,235,.

} button.primary{ background:var(--accent); border-color:var(--accent); color:#fff; } button.primary:hover{filter:brightness(.

} button.secondary{ background:#fff; border-color:var(--line); color:var(--text); } button.secondary:hover{background:rgba(15,23,42,.

} button.danger{ background:var(--danger

; border-color:rgba(225,29,72,.

; color:var(--danger); } button.danger:hover{background:rgba(225,29,72,.

} .pill{ display:inline-flex;align-items:center;gap:6px; padding:3px 10px;border-radius:999px; border:1px solid var(--line); background:rgba(15,23,42,.

; color:var(--muted); font-size:12px; margin-right:6px; margin-top:6px; } .list{display:flex;flex-direction:column;gap:10px} .mentor-item{ border:1px solid var(--line); background:#fff; border-radius:16px; padding:12px; cursor:pointer; transition:transform .08s ease, background .08s ease, border-color .08s ease; } .mentor-item:hover{transform:translateY(-1px);background:rgba(37,99,235,.

;border-color:rgba(37,99,235,.

} .mentor-item.selected{background:rgba(37,99,235,.

;border-color:rgba(37,99,235,.

} .mentorHead{display:flex;align-items:flex-start;justify-content:space-between;gap:10px} .mentorName{font-weight:900;font-size:15px} .smallRight{color:var(--muted);font-size:12px;text-align:right} .stars{letter-spacing:.8px} .divider{height:1px;background:rgba(15,23,42,.

;margin:12px 0} .review{ border:1px solid var(--line); background:#fff; border-radius:16px; padding:12px; } .reviewTop{display:flex;align-items:center;justify-content:space-between;gap:10px} .reviewBody{white-space:pre-wrap;margin-top:8px} .twoLine{display:flex;flex-direction:column;gap:6px;margin-top:8px} .badge{ display:inline-flex;align-items:center; padding:2px 8px;border-radius:999px; border:1px solid var(--line); background:rgba(15,23,42,.

; color:var(--muted); font-size:12px; } /style /head body div classwrap div classtop h1导师评价网/h1 div classsub 用于信息分享与经验交流。

请在发布前尽量核实事实避免夸大或误导。

br/ 请勿发布他人隐私信息、联系方式、身份证号、真实住址等敏感内容。

br/ 本站内容由用户提交仅供参考不构成任何建议或承诺。

若内容侵权或不实可联系管理员处理。

/div /div div classstack div classcard div classtitleRow div classtitle导师检索/div div classmuted支持模糊匹配/div /div div classrow input idq classgrow placeholder输入姓名 学校 学院 方向 / button idbtnSearch classprimary搜索/button /div /div div classcard div classtitleRow div classtitle新增导师/div div idaddMentorMsg classmuted/div /div div classrow input idnewName classgrow placeholder姓名 必填 / input idnewSchool classgrow placeholder学校 必填 / /div div classrow stylemargin-top:10px input idnewCollege classgrow placeholder学院 可选 / input idnewField classgrow placeholder方向 可选 / /div div classrow stylemargin-top:10px button idbtnAddMentor classprimary新增/button button idbtnClearMentor classsecondary清空/button /div /div div classcard div classtitleRow div classtitle导师列表/div div idmentorListHint classmuted请输入关键词搜索或直接浏览最近导师/div /div div idmentorList classlist/div /div div classcard idmentorPanel styledisplay:none div classtitleRow div classtitle当前导师/div button idbtnDeleteMentor classdanger删除导师/button /div div idcurrentMentor/div div classdivider/div div classtitleRow stylemargin-bottom:8px div classtitle写点评/div div idaddReviewMsg classmuted/div /div div classrow input idnick classgrow placeholder昵称 必填 / div classstarPicker div idratingStars/div span classstarHelp点击选择评分/span /div input idratingValue typehidden value5 / /div div stylemargin-top:10px textarea idcontent placeholder点评内容 必填/textarea /div div classrow stylemargin-top:10px button idbtnAddReview classprimary发布/button button idbtnClearReview classsecondary清空/button /div div classdivider/div div classtitleRow stylemargin-bottom:8px div classtitle点评列表/div div classrow stylegap:8px span idmentorAvg classbadge styledisplay:none/span span idmentorCount classbadge styledisplay:none/span /div /div div idreviewList/div /div /div /div script let currentMentorId null; async function api(url, options) { const res await fetch(url, options); const data await res.json().catch(() null); if (!res.ok) { const msg data data.error ? data.error : 请求失败; throw new Error(msg); } return data; } function escapeHtml(s) { return String(s).replace(/[]/g, c ({:amp;,:lt;,:gt;,:quot;,:#39;}[c])); } function stars(n) { const v Math.max(1, Math.min(5, Number(n) ||

); let s ; for (let i 1; i 5; i) s (i v ? ★ : ☆); return s; } function starsFromAvg(avg) { if (avg null) return ☆☆☆☆☆; const v Math.max(0, Math.min(5, Number(avg))); const rounded Math.round(v); return stars(rounded); } function renderRatingStars(value) { const box document.getElementById(ratingStars); const v Math.max(1, Math.min(5, Number(value) ||

); box.innerHTML ; for (let i 1; i 5; i) { const b document.createElement(button); b.type button; b.className starBtn (i v ? on : ); b.textContent ★; b.onclick () { document.getElementById(ratingValue).value String(i); renderRatingStars(i); }; box.appendChild(b); } } function initRatingStars() { const init Number(document.getElementById(ratingValue).value ||

; renderRatingStars(init); } function setMentorBadges(avg, count) { const a document.getElementById(mentorAvg); const c document.getElementById(mentorCount); if (avg null) { a.style.display none; } else { a.style.display inline-flex; a.innerHTML 均分 Number(avg).toFixed(

starsFromAvg(avg); } c.style.display inline-flex; c.textContent 评论数 (count ||

; } function highlightSelectedMentor() { document.querySelectorAll(.mentor-item).forEach(el { el.classList.toggle(selected, Number(el.dataset.id) Number(currentMentorId)); }); } function mentorItem(m) { const div document.createElement(div); div.className mentor-item; div.dataset.id m.id; const avgText m.avg_rating null ? - : Number(m.avg_rating).toFixed(

; const star starsFromAvg(m.avg_rating); div.innerHTML \ div classmentorHead div div classmentorName\${escapeHtml(m.name)}/div div \${m.school ? span classpillescapeHtml(m.school)/span : } \${m.college ? span classpillescapeHtml(m.college)/span : } \${m.field ? span classpillescapeHtml(m.field)/span : } /div /div div classsmallRight div classstars\${star}/div div均分 \${avgText}/div div评论 \${m.review_count}/div /div /div \; div.onclick () selectMentor(m.id); return div; } function reviewCard(r) { const loc [r.ip_city, r.ip_region, r.ip_country].filter(Boolean).join( ); const div document.createElement(div); div.className review; div.innerHTML \ div classreviewTop div b\${escapeHtml(r.nickname || )}/b span classmuted 评分 /span span classstars\${stars(r.rating)}/span /div button classdanger删除/button /div div classreviewBody\${escapeHtml(r.content)}/div div classtwoLine div classmuted归属地 \${escapeHtml(loc || 未知)}/div div classmuted\${escapeHtml(r.created_at)}/div /div \; div.querySelector(button).onclick async () { const pwd prompt(请输入删除评论密码); if (pwd null) return; try { await api(/api/reviews/ r.id, { method: DELETE, headers: {content-type:application/json}, body: JSON.stringify({ password: pwd }) }); await loadReviews(currentMentorId); await searchMentors(); } catch (e) { alert(e.message); } }; return div; } async function searchMentors() { const q document.getElementById(q).value.trim(); const data await api(/api/mentors?query encodeURIComponent(q)); const list document.getElementById(mentorList); const hint document.getElementById(mentorListHint); list.innerHTML ; const n (data.items || []).length; if (n

{ hint.textContent q ? 没有找到匹配导师可换关键词或先新增导师 : 目前还没有导师记录可先新增导师; list.innerHTML div classmuted stylepadding:10px暂无结果/div; return; } hint.textContent q ? 共找到 n 位导师 : 最近导师共 n 位; data.items.forEach(m list.appendChild(mentorItem(m))); highlightSelectedMentor(); } async function selectMentor(id) { currentMentorId id; document.getElementById(mentorPanel).style.display block; document.getElementById(btnDeleteMentor).onclick async () { const pwd prompt(请输入删除导师密码); if (pwd null) return; if (!currentMentorId) return; const ok confirm(确认删除该导师及其所有点评此操作不可恢复); if (!ok) return; try { await api(/api/mentors/ currentMentorId, { method: DELETE, headers: {content-type:application/json}, body: JSON.stringify({ password: pwd }) }); alert(删除成功); currentMentorId null; document.getElementById(mentorPanel).style.display none; document.getElementById(currentMentor).innerHTML ; document.getElementById(reviewList).innerHTML ; setMentorBadges(null,

; await searchMentors(); } catch (e) { alert(e.message); } }; const m await api(/api/mentors/ id); document.getElementById(currentMentor).innerHTML \ div stylefont-weight:900;font-size:16px\${escapeHtml(m.name)}/div div stylemargin-top:6px \${m.school ? span classpillescapeHtml(m.school)/span : } \${m.college ? span classpillescapeHtml(m.college)/span : } \${m.field ? span classpillescapeHtml(m.field)/span : } /div div classmuted stylemargin-top:8px创建时间 \${escapeHtml(m.created_at)}/div \; highlightSelectedMentor(); await loadReviews(id); } async function loadReviews(mentorId) { const box document.getElementById(reviewList); box.innerHTML div classmuted加载中/div; const data await api(/api/mentors/ mentorId /reviews); box.innerHTML ; if (!data.items.length) { box.innerHTML div classmuted暂无点评/div; setMentorBadges(null,

; return; } let sum 0; data.items.forEach(r sum Number(r.rating) ||

; const avg sum / data.items.length; setMentorBadges(avg, data.items.length); data.items.forEach(r box.appendChild(reviewCard(r))); } async function addMentor() { const name document.getElementById(newName).value.trim(); const school document.getElementById(newSchool).value.trim(); const college document.getElementById(newCollege).value.trim(); const field document.getElementById(newField).value.trim(); const msg document.getElementById(addMentorMsg); msg.textContent ; if (!name || !school) { msg.textContent 姓名和学校必填; return; } try { const data await api(/api/mentors, { method:POST, headers: {content-type:application/json}, body: JSON.stringify({ name, school, college, field }) }); msg.textContent 已新增 ID data.id; document.getElementById(newName).value ; document.getElementById(newSchool).value ; document.getElementById(newCollege).value ; document.getElementById(newField).value ; await searchMentors(); await selectMentor(data.id); } catch (e) { msg.textContent e.message; } } async function addReview() { const msg document.getElementById(addReviewMsg); msg.textContent ; if (!currentMentorId) { msg.textContent 请先选择导师; return; } const nickname document.getElementById(nick).value.trim(); const rating Number(document.getElementById(ratingValue).value); const content document.getElementById(content).value.trim(); if (!nickname) { msg.textContent 昵称必填; return; } if (!content) { msg.textContent 点评内容必填; return; } try { await api(/api/mentors/ currentMentorId /reviews, { method:POST, headers: {content-type:application/json}, body: JSON.stringify({ nickname, rating, content }) }); msg.textContent 已发布; document.getElementById(content).value ; await loadReviews(currentMentorId); await searchMentors(); } catch (e) { msg.textContent e.message; } } document.getElementById(btnSearch).onclick searchMentors; document.getElementById(q).addEventListener(keydown, e { if (e.key Enter) searchMentors(); }); document.getElementById(btnAddMentor).onclick addMentor; document.getElementById(btnClearMentor).onclick () { document.getElementById(newName).value ; document.getElementById(newSchool).value ; document.getElementById(newCollege).value ; document.getElementById(newField).value ; document.getElementById(addMentorMsg).textContent ; }; document.getElementById(btnAddReview).onclick addReview; document.getElementById(btnClearReview).onclick () { document.getElementById(nick).value ; document.getElementById(ratingValue).value 5; renderRatingStars(

; document.getElementById(content).value ; document.getElementById(addReviewMsg).textContent ; }; setMentorBadges(null,

; initRatingStars(); searchMentors(); /script /body /html; } export default { async fetch(request, env) { const url new URL(request.url); const path getPath(request.url); if (request.method GET path /) { return new Response(htmlPage(), { headers: { content-type: text/html; charsetutf-8, cache-control: no-store, }, }); } if (path.startsWith(/api/)) { try { return await handleApi(request, env, url); } catch (e) { return bad(e e.message ? e.message : 服务器错误,

; } } return new Response(Not Found, { status: 404 }); }, }; async function handleApi(request, env, url) { const { DB } env; const path url.pathname; if (!DB) return bad(未绑定 D1 数据库 DB,

; if (request.method GET path /api/mentors) { const q (url.searchParams.get(query) || ).trim(); const like %${q}%; const sql SELECT m.id, m.name, m.school, m.college, m.field, m.created_at, COUNT(r.id) AS review_count, AVG(r.rating) AS avg_rating FROM mentors m LEFT JOIN reviews r ON r.mentor_id m.id WHERE (? OR m.name LIKE ? OR IFNULL(m.school,) LIKE ? OR IFNULL(m.college,) LIKE ? OR IFNULL(m.field,) LIKE ? ) GROUP BY m.id ORDER BY m.created_at DESC LIMIT 50 ; const rs await DB.prepare(sql).bind(q, like, like, like, like).all(); return json({ ok: true, items: rs.results || [] }); } if (request.method POST path /api/mentors) { const body await readJson(request); if (!body) return bad(请用 JSON 请求); const name (body.name || ).trim(); const school (body.school || ).trim(); const college (body.college || ).trim(); const field (body.field || ).trim(); if (!name || !school) return bad(姓名和学校必填); const insert await DB.prepare( INSERT INTO mentors (name, school, college, field) VALUES (?, ?, ?, ?) ).bind( name, school, college || null, field || null ).run(); return json({ ok: true, id: insert.meta.last_row_id },

; } const mentorIdMatch path.match(/^\/api\/mentors\/(\d)$/); if (request.method GET mentorIdMatch) { const mentorId Number(mentorIdMatch[1]); const rs await DB.prepare(SELECT * FROM mentors WHERE id ?).bind(mentorId).first(); if (!rs) return bad(导师不存在,

; return json({ ok: true, ...rs }); } const mentorReviewsMatch path.match(/^\/api\/mentors\/(\d)\/reviews$/); if (request.method GET mentorReviewsMatch) { const mentorId Number(mentorReviewsMatch[1]); const exists await DB.prepare(SELECT 1 FROM mentors WHERE id ?).bind(mentorId).first(); if (!exists) return bad(导师不存在,

; const rs await DB.prepare( SELECT id, mentor_id, nickname, rating, content, created_at, ip_country, ip_region, ip_city FROM reviews WHERE mentor_id ? ORDER BY created_at DESC LIMIT 100 ).bind(mentorId).all(); return json({ ok: true, items: rs.results || [] }); } if (request.method POST mentorReviewsMatch) { const mentorId Number(mentorReviewsMatch[1]); const exists await DB.prepare(SELECT 1 FROM mentors WHERE id ?).bind(mentorId).first(); if (!exists) return bad(导师不存在,

; const body await readJson(request); if (!body) return bad(请用 JSON 请求); const nickname (body.nickname || ).trim(); const content (body.content || ).trim(); const rating Number(body.rating); if (!nickname) return bad(昵称必填); if (!content) return bad(点评内容必填); if (!Number.isFinite(rating) || rating 1 || rating

return bad(评分需在 1 到

; const cf request.cf || {}; const ip_country (cf.country || ).trim(); const ip_region (cf.region || ).trim(); const ip_city (cf.city || ).trim(); const insert await DB.prepare( INSERT INTO reviews (mentor_id, nickname, rating, content, ip_country, ip_region, ip_city) VALUES (?, ?, ?, ?, ?, ?, ?) ).bind( mentorId, nickname, rating, content, ip_country || null, ip_region || null, ip_city || null ).run(); return json({ ok: true, id: insert.meta.last_row_id },

; } const reviewIdMatch path.match(/^\/api\/reviews\/(\d)$/); if (request.method DELETE reviewIdMatch) { const reviewId Number(reviewIdMatch[1]); const body await readJson(request); const pwd body typeof body.password string ? body.password : ; if (pwd ! DELETE_REVIEW_PASSWORD) return bad(密码错误,

; const del await DB.prepare(DELETE FROM reviews WHERE id ?).bind(reviewId).run(); if (!del.meta.changes) return bad(评论不存在,

; return json({ ok: true }); } const mentorIdDeleteMatch path.match(/^\/api\/mentors\/(\d)$/); if (request.method DELETE mentorIdDeleteMatch) { const mentorId Number(mentorIdDeleteMatch[1]); const body await readJson(request); const pwd body typeof body.password string ? body.password : ; if (pwd ! DELETE_MENTOR_PASSWORD) return bad(密码错误,

; const exists await DB.prepare(SELECT 1 FROM mentors WHERE id ?).bind(mentorId).first(); if (!exists) return bad(导师不存在,

; // 保险起见先删评论再删导师 await DB.prepare(DELETE FROM reviews WHERE mentor_id ?).bind(mentorId).run(); const del await DB.prepare(DELETE FROM mentors WHERE id ?).bind(mentorId).run(); if (!del.meta.changes) return bad(导师不存在,

; return json({ ok: true }); } return bad(接口不存在,

; }

点击“部署”。

完工

免费软件污-免费软件污应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123