Files
huangguo_server/tests/checkin/reports/report_20260508_163219.html
T
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

1137 lines
63 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>签到模块测试 - 测试报告</title>
<style>
:root {
--green: #059669; --red: #dc2626; --blue: #2563eb; --purple: #7c3aed;
--gray: #6b7280; --light: #f8fafc; --border: #e5e7eb; --sidebar-w: 320px;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #f0f2f5; color: #1f2937; height: 100vh; overflow: hidden; }
.topbar {
background: linear-gradient(135deg, #667eea, #764ba2);
color: #fff; padding: 16px 28px; display: flex; align-items: center; gap: 32px; flex-wrap: wrap;
position: fixed; top: 0; left: 0; right: 0; z-index: 100; height: auto; min-height: 64px;
}
.topbar h1 { font-size: 18px; white-space: nowrap; }
.topbar .stats { display: flex; gap: 20px; align-items: center; }
.topbar .stat { text-align: center; }
.topbar .stat .num { font-size: 24px; font-weight: 800; }
.topbar .stat .lbl { font-size: 10px; opacity: .7; }
.topbar .stat.pass .num { color: #86efac; }
.topbar .stat.fail .num { color: #fca5a5; }
.topbar .stat.rate .num { color: #93c5fd; }
.topbar .delta { font-size: 10px; opacity: .8; }
.topbar .env-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.topbar .env-tags span { background: rgba(255,255,255,.15); padding: 3px 10px; border-radius: 6px; font-size: 11px; }
.topbar .progress { position: absolute; bottom: 0; left: 0; right: 0; height: 3px; background: rgba(255,255,255,.2); }
.topbar .progress .fill { height: 100%; background: #86efac; }
.layout { display: flex; margin-top: 64px; height: calc(100vh - 64px); }
.sidebar {
width: var(--sidebar-w); min-width: var(--sidebar-w); background: #fff;
border-right: 1px solid var(--border); overflow-y: auto; padding: 12px 0;
}
.sidebar .suite-group { margin-bottom: 4px; }
.sidebar .suite-title {
padding: 8px 16px; font-size: 13px; font-weight: 600; color: #374151;
display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none;
}
.sidebar .suite-title:hover { background: #f9fafb; }
.sidebar .suite-title .arrow { font-size: 10px; color: #aaa; transition: transform .2s; }
.sidebar .suite-group.open .arrow { transform: rotate(90deg); }
.sidebar .suite-title .cnt { margin-left: auto; font-size: 11px; font-weight: 400; color: #aaa; }
.sidebar .suite-title .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.sidebar .dot.pass { background: var(--green); } .sidebar .dot.fail { background: var(--red); } .sidebar .dot.skip { background: #fbbf24; }
.sidebar .case-list { display: none; }
.sidebar .suite-group.open .case-list { display: block; }
.sidebar .case-item {
padding: 6px 16px 6px 36px; font-size: 12px; cursor: pointer;
display: flex; align-items: center; gap: 6px; color: #6b7280;
border-left: 3px solid transparent;
}
.sidebar .case-item:hover { background: #f3f4f6; }
.sidebar .case-item.active { background: #eef2ff; border-left-color: #6366f1; color: #1f2937; font-weight: 500; }
.sidebar .case-item .icon { font-size: 12px; }
.detail {
flex: 1; overflow-y: auto; padding: 28px 36px; background: var(--light);
}
.detail .empty { color: #aaa; font-size: 15px; margin-top: 120px; text-align: center; }
.detail .d-header { margin-bottom: 24px; }
.detail .d-header h2 { font-size: 20px; margin-bottom: 8px; display: flex; align-items: center; gap: 10px; }
.detail .d-header h2 .status { font-size: 22px; }
.detail .d-header .d-meta { font-size: 13px; color: var(--gray); display: flex; gap: 16px; }
.detail .d-section { background: #fff; border-radius: 10px; padding: 20px; margin-bottom: 16px; box-shadow: 0 1px 4px rgba(0,0,0,.05); }
.detail .d-section h3 { font-size: 14px; color: var(--gray); margin-bottom: 12px; font-weight: 500; }
.detail .kv-grid { display: grid; grid-template-columns: 56px 1fr; gap: 6px 12px; font-size: 14px; }
.detail .kv-grid .k { color: var(--gray); text-align: right; font-size: 13px; }
.detail .kv-grid .v { font-family: "SF Mono", Monaco, monospace; word-break: break-all; }
.detail .kv-grid .v.pass { color: var(--green); } .detail .kv-grid .v.fail { color: var(--red); }
.detail .curl-block {
background: #1e293b; color: #e2e8f0; border-radius: 8px; padding: 16px 18px;
font-family: "SF Mono", Monaco, "Cascadia Code", monospace; font-size: 13px;
white-space: pre-wrap; word-break: break-all; line-height: 1.7; position: relative;
}
.detail .curl-block .copy-btn {
position: absolute; top: 10px; right: 10px;
background: #475569; color: #e2e8f0; border: none; border-radius: 5px;
padding: 4px 14px; font-size: 12px; cursor: pointer;
}
.detail .curl-block .copy-btn:hover { background: #64748b; }
.detail .req-info { font-size: 13px; }
.detail .req-row { display: flex; gap: 10px; margin-bottom: 6px; align-items: baseline; }
.detail .req-row .rl { color: var(--gray); min-width: 56px; text-align: right; font-size: 12px; flex-shrink: 0; }
.detail .req-row .rv { font-family: "SF Mono", Monaco, monospace; word-break: break-all; }
.detail .method-badge { display: inline-block; padding: 2px 10px; border-radius: 4px; font-weight: 700; font-size: 12px; color: #fff; }
.detail .method-badge.GET { background: var(--blue); }
.detail .method-badge.POST { background: var(--green); }
.detail .method-badge.PUT { background: #d97706; }
.detail .method-badge.PATCH { background: #7c3aed; }
.detail .method-badge.DELETE { background: var(--red); }
.jtree { font-family: "SF Mono", Monaco, monospace; font-size: 12.5px; line-height: 1.8; background: #1e293b; color: #e2e8f0; border-radius: 8px; padding: 16px 18px; max-height: 500px; overflow: auto; }
.jtree .jk { color: #7dd3fc; } .jtree .js { color: #86efac; } .jtree .jn { color: #fbbf24; } .jtree .jb { color: #f87171; }
.jtree .jt { cursor: pointer; user-select: none; } .jtree .jt::before { content: "▼ "; font-size: 10px; color: #64748b; }
.jtree .jt.closed::before { content: "▶ "; } .jtree .jt.closed + .jc { display: none; }
.jtree .jc { } .jtree .ji { padding-left: 20px; }
.detail .resp-status-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.detail .resp-code { font-size: 14px; font-weight: 700; font-family: monospace; }
.detail .resp-code.ok { color: var(--green); }
.detail .resp-code.err { color: var(--red); }
.detail .loc-link { font-size: 12px; color: #6366f1; font-family: monospace; }
.footer { text-align: center; color: #bbb; font-size: 11px; padding: 16px 0; }
</style>
</head>
<body>
<div class="topbar">
<h1>签到模块测试</h1>
<div class="stats">
<div class="stat"><div class="num">32</div><div class="lbl">总计</div></div>
<div class="stat pass"><div class="num">32</div><div class="lbl">通过</div></div>
<div class="stat fail"><div class="num">0</div><div class="lbl">失败</div></div>
<div class="stat rate"><div class="num">100.0%</div><div class="lbl">通过率</div></div>
</div>
<div class="env-tags">
<span>📅 2026-05-08 16:32:19</span>
<span>⏱ 15s</span>
<span>项目: 91porn-server</span><span>模块: 签到</span><span>时间: 2026-05-08 16:32:04</span>
</div>
<div class="progress"><div class="fill" style="width:100%"></div></div>
</div>
<div class="layout">
<div class="sidebar">
<div class="suite-group " data-suite="0">
<div class="suite-title" onclick="this.parentElement.classList.toggle('open')">
<span class="dot pass"></span>
<span class="arrow"></span>
<span>签到功能</span>
<span class="cnt">32/32</span>
</div>
<div class="case-list">
<div class="case-item" data-suite="0" data-case="0" onclick="showCase( 0 , 0 )">
<span class="icon"></span>
<span>空数据查询-code=200</span>
</div>
<div class="case-item" data-suite="0" data-case="1" onclick="showCase( 0 , 1 )">
<span class="icon"></span>
<span>空数据-todayChecked=false</span>
</div>
<div class="case-item" data-suite="0" data-case="2" onclick="showCase( 0 , 2 )">
<span class="icon"></span>
<span>空数据-连续=0</span>
</div>
<div class="case-item" data-suite="0" data-case="3" onclick="showCase( 0 , 3 )">
<span class="icon"></span>
<span>空数据-累计=0</span>
</div>
<div class="case-item" data-suite="0" data-case="4" onclick="showCase( 0 , 4 )">
<span class="icon"></span>
<span>连续3天-code=200</span>
</div>
<div class="case-item" data-suite="0" data-case="5" onclick="showCase( 0 , 5 )">
<span class="icon"></span>
<span>连续3天-todayChecked=false</span>
</div>
<div class="case-item" data-suite="0" data-case="6" onclick="showCase( 0 , 6 )">
<span class="icon"></span>
<span>连续3天-continuously=3</span>
</div>
<div class="case-item" data-suite="0" data-case="7" onclick="showCase( 0 , 7 )">
<span class="icon"></span>
<span>连续3天-cumulative=3</span>
</div>
<div class="case-item" data-suite="0" data-case="8" onclick="showCase( 0 , 8 )">
<span class="icon"></span>
<span>断签-code=200</span>
</div>
<div class="case-item" data-suite="0" data-case="9" onclick="showCase( 0 , 9 )">
<span class="icon"></span>
<span>断签-continuously=0</span>
</div>
<div class="case-item" data-suite="0" data-case="10" onclick="showCase( 0 , 10 )">
<span class="icon"></span>
<span>断签-cumulative=2</span>
</div>
<div class="case-item" data-suite="0" data-case="11" onclick="showCase( 0 , 11 )">
<span class="icon"></span>
<span>断一天-code=200</span>
</div>
<div class="case-item" data-suite="0" data-case="12" onclick="showCase( 0 , 12 )">
<span class="icon"></span>
<span>断一天-continuously=1</span>
</div>
<div class="case-item" data-suite="0" data-case="13" onclick="showCase( 0 , 13 )">
<span class="icon"></span>
<span>断一天-cumulative=2</span>
</div>
<div class="case-item" data-suite="0" data-case="14" onclick="showCase( 0 , 14 )">
<span class="icon"></span>
<span>跨月-code=200</span>
</div>
<div class="case-item" data-suite="0" data-case="15" onclick="showCase( 0 , 15 )">
<span class="icon"></span>
<span>跨月-continuously=0</span>
</div>
<div class="case-item" data-suite="0" data-case="16" onclick="showCase( 0 , 16 )">
<span class="icon"></span>
<span>今天已签到-code=200</span>
</div>
<div class="case-item" data-suite="0" data-case="17" onclick="showCase( 0 , 17 )">
<span class="icon"></span>
<span>今天已签到-todayChecked=true</span>
</div>
<div class="case-item" data-suite="0" data-case="18" onclick="showCase( 0 , 18 )">
<span class="icon"></span>
<span>今天已签到-continuously=3</span>
</div>
<div class="case-item" data-suite="0" data-case="19" onclick="showCase( 0 , 19 )">
<span class="icon"></span>
<span>双倍奖励-code=200</span>
</div>
<div class="case-item" data-suite="0" data-case="20" onclick="showCase( 0 , 20 )">
<span class="icon"></span>
<span>6天连续&#43;未签到-doubleReward=true</span>
</div>
<div class="case-item" data-suite="0" data-case="21" onclick="showCase( 0 , 21 )">
<span class="icon"></span>
<span>6天连续-continuously=6</span>
</div>
<div class="case-item" data-suite="0" data-case="22" onclick="showCase( 0 , 22 )">
<span class="icon"></span>
<span>断签恢复-code=200</span>
</div>
<div class="case-item" data-suite="0" data-case="23" onclick="showCase( 0 , 23 )">
<span class="icon"></span>
<span>断签恢复-continuously=1</span>
</div>
<div class="case-item" data-suite="0" data-case="24" onclick="showCase( 0 , 24 )">
<span class="icon"></span>
<span>断签恢复-cumulative=3</span>
</div>
<div class="case-item" data-suite="0" data-case="25" onclick="showCase( 0 , 25 )">
<span class="icon"></span>
<span>isCheckedIn-code=200</span>
</div>
<div class="case-item" data-suite="0" data-case="26" onclick="showCase( 0 , 26 )">
<span class="icon"></span>
<span>第1天-isCheckedIn=true</span>
</div>
<div class="case-item" data-suite="0" data-case="27" onclick="showCase( 0 , 27 )">
<span class="icon"></span>
<span>第1天-isReceive=true</span>
</div>
<div class="case-item" data-suite="0" data-case="28" onclick="showCase( 0 , 28 )">
<span class="icon"></span>
<span>第2天-isCheckedIn=true(签到未发奖)</span>
</div>
<div class="case-item" data-suite="0" data-case="29" onclick="showCase( 0 , 29 )">
<span class="icon"></span>
<span>第2天-isReceive=false(奖品未发放)</span>
</div>
<div class="case-item" data-suite="0" data-case="30" onclick="showCase( 0 , 30 )">
<span class="icon"></span>
<span>第3天-isCheckedIn=true</span>
</div>
<div class="case-item" data-suite="0" data-case="31" onclick="showCase( 0 , 31 )">
<span class="icon"></span>
<span>第3天-isReceive=true</span>
</div>
</div>
</div>
</div>
<div class="detail" id="detail">
<div class="empty">👈 点击左侧用例查看详情</div>
</div>
</div>
<script>
const DATA = [
[
{
name: "空数据查询-code=200",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 126 ,
func: "testQueryEmpty",
detail: "",
got: "200",
want: "200",
curl: "curl -X POST \\\n 'http://127.0.0.1:13051/api/app/checkin/prize' \\\n -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk' \\\n -H 'Content-Type: application/json' \\\n -H 'User-Agent: 91porn/3.8.0 (Android; test)' \\\n -H 'X-User-Agent: ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001' \\\n -d '{}'",
reqMethod: "POST",
reqURL: "http://127.0.0.1:13051/api/app/checkin/prize",
reqHeaders: { "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk", "Content-Type": "application/json", "User-Agent": "91porn/3.8.0 (Android; test)", "X-User-Agent": "ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001", },
reqBody: "{}",
respStatus: 200 ,
respBody: "{\"code\":200,\"data\":{\"bigPrizes\":[{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c0\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第1天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":2,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c1\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第2天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},\"... (31 items total)\"],\"checkin\":{\"continuouslyDays\":0,\"cumulativeDays\":0,\"doubleReward\":false,\"todayChecked\":false},\"config\":{\"backgroundImage\":\"cf230705/image/2mf/x9/2n2/v/ddddedb148a7bdc7b4ded365861ddc55.jpeg\",\"description\":\"每日签到领好礼!连续签到天数越多奖励越丰厚,第7天可获得双倍奖励!月卡VIP用户每天额外领取专属奖品。坚持签到31天有超级大礼!\",\"enable\":true,\"integerExchangeList\":[{\"icon\":\"cf230705/image/kc/1ad/2t8/1yc/521c547f934cfb05bc0a105a2eb93c3b.jpeg\",\"name\":\"观影券 X2\"},{\"icon\":\"cf230705/image/4/2ha/x0/2qt/1db16a6ef0d197daf4d084bad2aff665.jpeg\",\"name\":\"VIP体验 X2\"}]},\"prizes\":[{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e02354ba0975cac4a1\",\"image\":\"cf230705/image/1wc/sl/na/14c/164e8a0b0496b2c4525e5f98d116331f.png\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac485\",\"prizeName\":\"积分x3\",\"prizeType\":8,\"score\":3,\"status\":true,\"title\":\"第1天\",\"updatedAt\":\"2026-05-08T13:09:01.62+08:00\"},{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"0001-01-01T08:05:43+08:05\",\"id\":\"69fd9f84fdb9ef08e4d0451a\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fd9f84fdb9ef08e4d0451b\",\"prizeName\":\"测试奖品1\",\"prizeType\":0,\"score\":0,\"status\":true,\"title\":\"测试奖品第1天\",\"updatedAt\":\"0001-01-01T08:05:43+08:05\"},\"... (34 items total)\"]},\"hash\":false,\"msg\":\"success\",\"time\":\"2026-05-08T08:32:06.203Z\",\"tip\":\"\"}",
suite: "签到功能",
attempt: 0
},
{
name: "空数据-todayChecked=false",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 131 ,
func: "testQueryEmpty",
detail: "",
got: "false",
want: "false",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "空数据-连续=0",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 132 ,
func: "testQueryEmpty",
detail: "",
got: "0",
want: "0",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "空数据-累计=0",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 133 ,
func: "testQueryEmpty",
detail: "",
got: "0",
want: "0",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "连续3天-code=200",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 148 ,
func: "testContinuous3Days",
detail: "",
got: "200",
want: "200",
curl: "curl -X POST \\\n 'http://127.0.0.1:13051/api/app/checkin/prize' \\\n -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk' \\\n -H 'Content-Type: application/json' \\\n -H 'User-Agent: 91porn/3.8.0 (Android; test)' \\\n -H 'X-User-Agent: ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001' \\\n -d '{}'",
reqMethod: "POST",
reqURL: "http://127.0.0.1:13051/api/app/checkin/prize",
reqHeaders: { "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk", "Content-Type": "application/json", "User-Agent": "91porn/3.8.0 (Android; test)", "X-User-Agent": "ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001", },
reqBody: "{}",
respStatus: 200 ,
respBody: "{\"code\":200,\"data\":{\"bigPrizes\":[{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c0\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第1天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":2,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c1\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第2天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},\"... (31 items total)\"],\"checkin\":{\"continuouslyDays\":3,\"cumulativeDays\":3,\"doubleReward\":false,\"todayChecked\":false},\"config\":{\"backgroundImage\":\"cf230705/image/2mf/x9/2n2/v/ddddedb148a7bdc7b4ded365861ddc55.jpeg\",\"description\":\"每日签到领好礼!连续签到天数越多奖励越丰厚,第7天可获得双倍奖励!月卡VIP用户每天额外领取专属奖品。坚持签到31天有超级大礼!\",\"enable\":true,\"integerExchangeList\":[{\"icon\":\"cf230705/image/kc/1ad/2t8/1yc/521c547f934cfb05bc0a105a2eb93c3b.jpeg\",\"name\":\"观影券 X2\"},{\"icon\":\"cf230705/image/4/2ha/x0/2qt/1db16a6ef0d197daf4d084bad2aff665.jpeg\",\"name\":\"VIP体验 X2\"}]},\"prizes\":[{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e02354ba0975cac4a1\",\"image\":\"cf230705/image/1wc/sl/na/14c/164e8a0b0496b2c4525e5f98d116331f.png\",\"isCheckedIn\":true,\"isReceive\":true,\"prizeId\":\"69fc99dc2354ba0975cac485\",\"prizeName\":\"积分x3\",\"prizeType\":8,\"score\":3,\"status\":true,\"title\":\"第1天\",\"updatedAt\":\"2026-05-08T13:09:01.62+08:00\"},{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"0001-01-01T08:05:43+08:05\",\"id\":\"69fd9f84fdb9ef08e4d0451a\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":true,\"prizeId\":\"69fd9f84fdb9ef08e4d0451b\",\"prizeName\":\"测试奖品1\",\"prizeType\":0,\"score\":0,\"status\":true,\"title\":\"测试奖品第1天\",\"updatedAt\":\"0001-01-01T08:05:43+08:05\"},\"... (34 items total)\"]},\"hash\":false,\"msg\":\"success\",\"time\":\"2026-05-08T08:32:07.531Z\",\"tip\":\"\"}",
suite: "签到功能",
attempt: 0
},
{
name: "连续3天-todayChecked=false",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 151 ,
func: "testContinuous3Days",
detail: "",
got: "false",
want: "false",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "连续3天-continuously=3",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 152 ,
func: "testContinuous3Days",
detail: "",
got: "3",
want: "3",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "连续3天-cumulative=3",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 153 ,
func: "testContinuous3Days",
detail: "",
got: "3",
want: "3",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "断签-code=200",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 165 ,
func: "testBrokenStreak",
detail: "",
got: "200",
want: "200",
curl: "curl -X POST \\\n 'http://127.0.0.1:13051/api/app/checkin/prize' \\\n -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk' \\\n -H 'Content-Type: application/json' \\\n -H 'User-Agent: 91porn/3.8.0 (Android; test)' \\\n -H 'X-User-Agent: ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001' \\\n -d '{}'",
reqMethod: "POST",
reqURL: "http://127.0.0.1:13051/api/app/checkin/prize",
reqHeaders: { "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk", "Content-Type": "application/json", "User-Agent": "91porn/3.8.0 (Android; test)", "X-User-Agent": "ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001", },
reqBody: "{}",
respStatus: 200 ,
respBody: "{\"code\":200,\"data\":{\"bigPrizes\":[{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c0\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第1天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":2,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c1\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第2天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},\"... (31 items total)\"],\"checkin\":{\"continuouslyDays\":0,\"cumulativeDays\":2,\"doubleReward\":false,\"todayChecked\":false},\"config\":{\"backgroundImage\":\"cf230705/image/2mf/x9/2n2/v/ddddedb148a7bdc7b4ded365861ddc55.jpeg\",\"description\":\"每日签到领好礼!连续签到天数越多奖励越丰厚,第7天可获得双倍奖励!月卡VIP用户每天额外领取专属奖品。坚持签到31天有超级大礼!\",\"enable\":true,\"integerExchangeList\":[{\"icon\":\"cf230705/image/kc/1ad/2t8/1yc/521c547f934cfb05bc0a105a2eb93c3b.jpeg\",\"name\":\"观影券 X2\"},{\"icon\":\"cf230705/image/4/2ha/x0/2qt/1db16a6ef0d197daf4d084bad2aff665.jpeg\",\"name\":\"VIP体验 X2\"}]},\"prizes\":[{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e02354ba0975cac4a1\",\"image\":\"cf230705/image/1wc/sl/na/14c/164e8a0b0496b2c4525e5f98d116331f.png\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac485\",\"prizeName\":\"积分x3\",\"prizeType\":8,\"score\":3,\"status\":true,\"title\":\"第1天\",\"updatedAt\":\"2026-05-08T13:09:01.62+08:00\"},{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"0001-01-01T08:05:43+08:05\",\"id\":\"69fd9f84fdb9ef08e4d0451a\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fd9f84fdb9ef08e4d0451b\",\"prizeName\":\"测试奖品1\",\"prizeType\":0,\"score\":0,\"status\":true,\"title\":\"测试奖品第1天\",\"updatedAt\":\"0001-01-01T08:05:43+08:05\"},\"... (34 items total)\"]},\"hash\":false,\"msg\":\"success\",\"time\":\"2026-05-08T08:32:08.957Z\",\"tip\":\"\"}",
suite: "签到功能",
attempt: 0
},
{
name: "断签-continuously=0",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 167 ,
func: "testBrokenStreak",
detail: "",
got: "0",
want: "0",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "断签-cumulative=2",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 168 ,
func: "testBrokenStreak",
detail: "",
got: "2",
want: "2",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "断一天-code=200",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 180 ,
func: "testBrokenStreakOneDayGap",
detail: "",
got: "200",
want: "200",
curl: "curl -X POST \\\n 'http://127.0.0.1:13051/api/app/checkin/prize' \\\n -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk' \\\n -H 'Content-Type: application/json' \\\n -H 'User-Agent: 91porn/3.8.0 (Android; test)' \\\n -H 'X-User-Agent: ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001' \\\n -d '{}'",
reqMethod: "POST",
reqURL: "http://127.0.0.1:13051/api/app/checkin/prize",
reqHeaders: { "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk", "Content-Type": "application/json", "User-Agent": "91porn/3.8.0 (Android; test)", "X-User-Agent": "ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001", },
reqBody: "{}",
respStatus: 200 ,
respBody: "{\"code\":200,\"data\":{\"bigPrizes\":[{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c0\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第1天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":2,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c1\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第2天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},\"... (31 items total)\"],\"checkin\":{\"continuouslyDays\":1,\"cumulativeDays\":2,\"doubleReward\":false,\"todayChecked\":false},\"config\":{\"backgroundImage\":\"cf230705/image/2mf/x9/2n2/v/ddddedb148a7bdc7b4ded365861ddc55.jpeg\",\"description\":\"每日签到领好礼!连续签到天数越多奖励越丰厚,第7天可获得双倍奖励!月卡VIP用户每天额外领取专属奖品。坚持签到31天有超级大礼!\",\"enable\":true,\"integerExchangeList\":[{\"icon\":\"cf230705/image/kc/1ad/2t8/1yc/521c547f934cfb05bc0a105a2eb93c3b.jpeg\",\"name\":\"观影券 X2\"},{\"icon\":\"cf230705/image/4/2ha/x0/2qt/1db16a6ef0d197daf4d084bad2aff665.jpeg\",\"name\":\"VIP体验 X2\"}]},\"prizes\":[{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e02354ba0975cac4a1\",\"image\":\"cf230705/image/1wc/sl/na/14c/164e8a0b0496b2c4525e5f98d116331f.png\",\"isCheckedIn\":true,\"isReceive\":true,\"prizeId\":\"69fc99dc2354ba0975cac485\",\"prizeName\":\"积分x3\",\"prizeType\":8,\"score\":3,\"status\":true,\"title\":\"第1天\",\"updatedAt\":\"2026-05-08T13:09:01.62+08:00\"},{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"0001-01-01T08:05:43+08:05\",\"id\":\"69fd9f84fdb9ef08e4d0451a\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fd9f84fdb9ef08e4d0451b\",\"prizeName\":\"测试奖品1\",\"prizeType\":0,\"score\":0,\"status\":true,\"title\":\"测试奖品第1天\",\"updatedAt\":\"0001-01-01T08:05:43+08:05\"},\"... (34 items total)\"]},\"hash\":false,\"msg\":\"success\",\"time\":\"2026-05-08T08:32:10.517Z\",\"tip\":\"\"}",
suite: "签到功能",
attempt: 0
},
{
name: "断一天-continuously=1",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 182 ,
func: "testBrokenStreakOneDayGap",
detail: "",
got: "1",
want: "1",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "断一天-cumulative=2",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 183 ,
func: "testBrokenStreakOneDayGap",
detail: "",
got: "2",
want: "2",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "跨月-code=200",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 196 ,
func: "testCrossMonthContinuous",
detail: "",
got: "200",
want: "200",
curl: "curl -X POST \\\n 'http://127.0.0.1:13051/api/app/checkin/prize' \\\n -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk' \\\n -H 'Content-Type: application/json' \\\n -H 'User-Agent: 91porn/3.8.0 (Android; test)' \\\n -H 'X-User-Agent: ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001' \\\n -d '{}'",
reqMethod: "POST",
reqURL: "http://127.0.0.1:13051/api/app/checkin/prize",
reqHeaders: { "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk", "Content-Type": "application/json", "User-Agent": "91porn/3.8.0 (Android; test)", "X-User-Agent": "ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001", },
reqBody: "{}",
respStatus: 200 ,
respBody: "{\"code\":200,\"data\":{\"bigPrizes\":[{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c0\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第1天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":2,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c1\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第2天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},\"... (31 items total)\"],\"checkin\":{\"continuouslyDays\":0,\"cumulativeDays\":3,\"doubleReward\":false,\"todayChecked\":false},\"config\":{\"backgroundImage\":\"cf230705/image/2mf/x9/2n2/v/ddddedb148a7bdc7b4ded365861ddc55.jpeg\",\"description\":\"每日签到领好礼!连续签到天数越多奖励越丰厚,第7天可获得双倍奖励!月卡VIP用户每天额外领取专属奖品。坚持签到31天有超级大礼!\",\"enable\":true,\"integerExchangeList\":[{\"icon\":\"cf230705/image/kc/1ad/2t8/1yc/521c547f934cfb05bc0a105a2eb93c3b.jpeg\",\"name\":\"观影券 X2\"},{\"icon\":\"cf230705/image/4/2ha/x0/2qt/1db16a6ef0d197daf4d084bad2aff665.jpeg\",\"name\":\"VIP体验 X2\"}]},\"prizes\":[{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e02354ba0975cac4a1\",\"image\":\"cf230705/image/1wc/sl/na/14c/164e8a0b0496b2c4525e5f98d116331f.png\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac485\",\"prizeName\":\"积分x3\",\"prizeType\":8,\"score\":3,\"status\":true,\"title\":\"第1天\",\"updatedAt\":\"2026-05-08T13:09:01.62+08:00\"},{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"0001-01-01T08:05:43+08:05\",\"id\":\"69fd9f84fdb9ef08e4d0451a\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fd9f84fdb9ef08e4d0451b\",\"prizeName\":\"测试奖品1\",\"prizeType\":0,\"score\":0,\"status\":true,\"title\":\"测试奖品第1天\",\"updatedAt\":\"0001-01-01T08:05:43+08:05\"},\"... (34 items total)\"]},\"hash\":false,\"msg\":\"success\",\"time\":\"2026-05-08T08:32:12.074Z\",\"tip\":\"\"}",
suite: "签到功能",
attempt: 0
},
{
name: "跨月-continuously=0",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 198 ,
func: "testCrossMonthContinuous",
detail: "",
got: "0",
want: "0",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "今天已签到-code=200",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 216 ,
func: "testTodayChecked",
detail: "",
got: "200",
want: "200",
curl: "curl -X POST \\\n 'http://127.0.0.1:13051/api/app/checkin/prize' \\\n -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk' \\\n -H 'Content-Type: application/json' \\\n -H 'User-Agent: 91porn/3.8.0 (Android; test)' \\\n -H 'X-User-Agent: ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001' \\\n -d '{}'",
reqMethod: "POST",
reqURL: "http://127.0.0.1:13051/api/app/checkin/prize",
reqHeaders: { "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk", "Content-Type": "application/json", "User-Agent": "91porn/3.8.0 (Android; test)", "X-User-Agent": "ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001", },
reqBody: "{}",
respStatus: 200 ,
respBody: "{\"code\":200,\"data\":{\"bigPrizes\":[{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c0\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第1天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":2,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c1\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第2天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},\"... (31 items total)\"],\"checkin\":{\"continuouslyDays\":3,\"cumulativeDays\":3,\"doubleReward\":false,\"todayChecked\":true},\"config\":{\"backgroundImage\":\"cf230705/image/2mf/x9/2n2/v/ddddedb148a7bdc7b4ded365861ddc55.jpeg\",\"description\":\"每日签到领好礼!连续签到天数越多奖励越丰厚,第7天可获得双倍奖励!月卡VIP用户每天额外领取专属奖品。坚持签到31天有超级大礼!\",\"enable\":true,\"integerExchangeList\":[{\"icon\":\"cf230705/image/kc/1ad/2t8/1yc/521c547f934cfb05bc0a105a2eb93c3b.jpeg\",\"name\":\"观影券 X2\"},{\"icon\":\"cf230705/image/4/2ha/x0/2qt/1db16a6ef0d197daf4d084bad2aff665.jpeg\",\"name\":\"VIP体验 X2\"}]},\"prizes\":[{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e02354ba0975cac4a1\",\"image\":\"cf230705/image/1wc/sl/na/14c/164e8a0b0496b2c4525e5f98d116331f.png\",\"isCheckedIn\":true,\"isReceive\":true,\"prizeId\":\"69fc99dc2354ba0975cac485\",\"prizeName\":\"积分x3\",\"prizeType\":8,\"score\":3,\"status\":true,\"title\":\"第1天\",\"updatedAt\":\"2026-05-08T13:09:01.62+08:00\"},{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"0001-01-01T08:05:43+08:05\",\"id\":\"69fd9f84fdb9ef08e4d0451a\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":true,\"prizeId\":\"69fd9f84fdb9ef08e4d0451b\",\"prizeName\":\"测试奖品1\",\"prizeType\":0,\"score\":0,\"status\":true,\"title\":\"测试奖品第1天\",\"updatedAt\":\"0001-01-01T08:05:43+08:05\"},\"... (34 items total)\"]},\"hash\":false,\"msg\":\"success\",\"time\":\"2026-05-08T08:32:13.703Z\",\"tip\":\"\"}",
suite: "签到功能",
attempt: 0
},
{
name: "今天已签到-todayChecked=true",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 218 ,
func: "testTodayChecked",
detail: "",
got: "true",
want: "true",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "今天已签到-continuously=3",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 219 ,
func: "testTodayChecked",
detail: "",
got: "3",
want: "3",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "双倍奖励-code=200",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 237 ,
func: "testDoubleReward",
detail: "",
got: "200",
want: "200",
curl: "curl -X POST \\\n 'http://127.0.0.1:13051/api/app/checkin/prize' \\\n -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk' \\\n -H 'Content-Type: application/json' \\\n -H 'User-Agent: 91porn/3.8.0 (Android; test)' \\\n -H 'X-User-Agent: ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001' \\\n -d '{}'",
reqMethod: "POST",
reqURL: "http://127.0.0.1:13051/api/app/checkin/prize",
reqHeaders: { "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk", "Content-Type": "application/json", "User-Agent": "91porn/3.8.0 (Android; test)", "X-User-Agent": "ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001", },
reqBody: "{}",
respStatus: 200 ,
respBody: "{\"code\":200,\"data\":{\"bigPrizes\":[{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c0\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第1天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":2,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c1\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第2天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},\"... (31 items total)\"],\"checkin\":{\"continuouslyDays\":6,\"cumulativeDays\":6,\"doubleReward\":true,\"todayChecked\":false},\"config\":{\"backgroundImage\":\"cf230705/image/2mf/x9/2n2/v/ddddedb148a7bdc7b4ded365861ddc55.jpeg\",\"description\":\"每日签到领好礼!连续签到天数越多奖励越丰厚,第7天可获得双倍奖励!月卡VIP用户每天额外领取专属奖品。坚持签到31天有超级大礼!\",\"enable\":true,\"integerExchangeList\":[{\"icon\":\"cf230705/image/kc/1ad/2t8/1yc/521c547f934cfb05bc0a105a2eb93c3b.jpeg\",\"name\":\"观影券 X2\"},{\"icon\":\"cf230705/image/4/2ha/x0/2qt/1db16a6ef0d197daf4d084bad2aff665.jpeg\",\"name\":\"VIP体验 X2\"}]},\"prizes\":[{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e02354ba0975cac4a1\",\"image\":\"cf230705/image/1wc/sl/na/14c/164e8a0b0496b2c4525e5f98d116331f.png\",\"isCheckedIn\":true,\"isReceive\":true,\"prizeId\":\"69fc99dc2354ba0975cac485\",\"prizeName\":\"积分x3\",\"prizeType\":8,\"score\":3,\"status\":true,\"title\":\"第1天\",\"updatedAt\":\"2026-05-08T13:09:01.62+08:00\"},{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"0001-01-01T08:05:43+08:05\",\"id\":\"69fd9f84fdb9ef08e4d0451a\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":true,\"prizeId\":\"69fd9f84fdb9ef08e4d0451b\",\"prizeName\":\"测试奖品1\",\"prizeType\":0,\"score\":0,\"status\":true,\"title\":\"测试奖品第1天\",\"updatedAt\":\"0001-01-01T08:05:43+08:05\"},\"... (34 items total)\"]},\"hash\":false,\"msg\":\"success\",\"time\":\"2026-05-08T08:32:15.525Z\",\"tip\":\"\"}",
suite: "签到功能",
attempt: 0
},
{
name: "6天连续+未签到-doubleReward=true",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 239 ,
func: "testDoubleReward",
detail: "",
got: "true",
want: "true",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "6天连续-continuously=6",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 240 ,
func: "testDoubleReward",
detail: "",
got: "6",
want: "6",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "断签恢复-code=200",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 258 ,
func: "testCheckinAfterBroken",
detail: "",
got: "200",
want: "200",
curl: "curl -X POST \\\n 'http://127.0.0.1:13051/api/app/checkin/prize' \\\n -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk' \\\n -H 'Content-Type: application/json' \\\n -H 'User-Agent: 91porn/3.8.0 (Android; test)' \\\n -H 'X-User-Agent: ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001' \\\n -d '{}'",
reqMethod: "POST",
reqURL: "http://127.0.0.1:13051/api/app/checkin/prize",
reqHeaders: { "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk", "Content-Type": "application/json", "User-Agent": "91porn/3.8.0 (Android; test)", "X-User-Agent": "ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001", },
reqBody: "{}",
respStatus: 200 ,
respBody: "{\"code\":200,\"data\":{\"bigPrizes\":[{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c0\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第1天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":2,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c1\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第2天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},\"... (31 items total)\"],\"checkin\":{\"continuouslyDays\":1,\"cumulativeDays\":3,\"doubleReward\":false,\"todayChecked\":false},\"config\":{\"backgroundImage\":\"cf230705/image/2mf/x9/2n2/v/ddddedb148a7bdc7b4ded365861ddc55.jpeg\",\"description\":\"每日签到领好礼!连续签到天数越多奖励越丰厚,第7天可获得双倍奖励!月卡VIP用户每天额外领取专属奖品。坚持签到31天有超级大礼!\",\"enable\":true,\"integerExchangeList\":[{\"icon\":\"cf230705/image/kc/1ad/2t8/1yc/521c547f934cfb05bc0a105a2eb93c3b.jpeg\",\"name\":\"观影券 X2\"},{\"icon\":\"cf230705/image/4/2ha/x0/2qt/1db16a6ef0d197daf4d084bad2aff665.jpeg\",\"name\":\"VIP体验 X2\"}]},\"prizes\":[{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e02354ba0975cac4a1\",\"image\":\"cf230705/image/1wc/sl/na/14c/164e8a0b0496b2c4525e5f98d116331f.png\",\"isCheckedIn\":true,\"isReceive\":true,\"prizeId\":\"69fc99dc2354ba0975cac485\",\"prizeName\":\"积分x3\",\"prizeType\":8,\"score\":3,\"status\":true,\"title\":\"第1天\",\"updatedAt\":\"2026-05-08T13:09:01.62+08:00\"},{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"0001-01-01T08:05:43+08:05\",\"id\":\"69fd9f84fdb9ef08e4d0451a\",\"image\":\"\",\"isCheckedIn\":false,\"isReceive\":false,\"prizeId\":\"69fd9f84fdb9ef08e4d0451b\",\"prizeName\":\"测试奖品1\",\"prizeType\":0,\"score\":0,\"status\":true,\"title\":\"测试奖品第1天\",\"updatedAt\":\"0001-01-01T08:05:43+08:05\"},\"... (34 items total)\"]},\"hash\":false,\"msg\":\"success\",\"time\":\"2026-05-08T08:32:17.371Z\",\"tip\":\"\"}",
suite: "签到功能",
attempt: 0
},
{
name: "断签恢复-continuously=1",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 260 ,
func: "testCheckinAfterBroken",
detail: "",
got: "1",
want: "1",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "断签恢复-cumulative=3",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 261 ,
func: "testCheckinAfterBroken",
detail: "",
got: "3",
want: "3",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "isCheckedIn-code=200",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 279 ,
func: "testIsCheckedIn",
detail: "",
got: "200",
want: "200",
curl: "curl -X POST \\\n 'http://127.0.0.1:13051/api/app/checkin/prize' \\\n -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk' \\\n -H 'Content-Type: application/json' \\\n -H 'User-Agent: 91porn/3.8.0 (Android; test)' \\\n -H 'X-User-Agent: ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001' \\\n -d '{}'",
reqMethod: "POST",
reqURL: "http://127.0.0.1:13051/api/app/checkin/prize",
reqHeaders: { "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aW1lc3RhbXAiOjE3NzgyMjkxMjQsInR5cGUiOjAsInVpZCI6MzAwMTAwfQ.iin-dSFNLY267ImH9PhARkSfGXnkX2yhUsTFdAeIKDk", "Content-Type": "application/json", "User-Agent": "91porn/3.8.0 (Android; test)", "X-User-Agent": "ver=3.8.0\u0026sysType=android\u0026devType=test\u0026devId=checkin-test-001", },
reqBody: "{}",
respStatus: 200 ,
respBody: "{\"code\":200,\"data\":{\"bigPrizes\":[{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c0\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第1天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},{\"bigPrize\":true,\"canClaim\":false,\"checkinDays\":2,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e32354ba0975cac4c1\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":false,\"prizeId\":\"69fc99dc2354ba0975cac481\",\"prizeName\":\"VIP积分x5\",\"prizeType\":8,\"score\":5,\"status\":true,\"title\":\"VIP第2天\",\"updatedAt\":\"2026-05-07T21:55:38.682+08:00\"},\"... (31 items total)\"],\"checkin\":{\"continuouslyDays\":3,\"cumulativeDays\":3,\"doubleReward\":false,\"todayChecked\":true},\"config\":{\"backgroundImage\":\"cf230705/image/2mf/x9/2n2/v/ddddedb148a7bdc7b4ded365861ddc55.jpeg\",\"description\":\"每日签到领好礼!连续签到天数越多奖励越丰厚,第7天可获得双倍奖励!月卡VIP用户每天额外领取专属奖品。坚持签到31天有超级大礼!\",\"enable\":true,\"integerExchangeList\":[{\"icon\":\"cf230705/image/kc/1ad/2t8/1yc/521c547f934cfb05bc0a105a2eb93c3b.jpeg\",\"name\":\"观影券 X2\"},{\"icon\":\"cf230705/image/4/2ha/x0/2qt/1db16a6ef0d197daf4d084bad2aff665.jpeg\",\"name\":\"VIP体验 X2\"}]},\"prizes\":[{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"2026-05-07T21:55:38.682+08:00\",\"id\":\"69fc99e02354ba0975cac4a1\",\"image\":\"cf230705/image/1wc/sl/na/14c/164e8a0b0496b2c4525e5f98d116331f.png\",\"isCheckedIn\":true,\"isReceive\":true,\"prizeId\":\"69fc99dc2354ba0975cac485\",\"prizeName\":\"积分x3\",\"prizeType\":8,\"score\":3,\"status\":true,\"title\":\"第1天\",\"updatedAt\":\"2026-05-08T13:09:01.62+08:00\"},{\"bigPrize\":false,\"canClaim\":false,\"checkinDays\":1,\"checkinType\":1,\"createdAt\":\"0001-01-01T08:05:43+08:05\",\"id\":\"69fd9f84fdb9ef08e4d0451a\",\"image\":\"\",\"isCheckedIn\":true,\"isReceive\":false,\"prizeId\":\"69fd9f84fdb9ef08e4d0451b\",\"prizeName\":\"测试奖品1\",\"prizeType\":0,\"score\":0,\"status\":true,\"title\":\"测试奖品第1天\",\"updatedAt\":\"0001-01-01T08:05:43+08:05\"},\"... (34 items total)\"]},\"hash\":false,\"msg\":\"success\",\"time\":\"2026-05-08T08:32:18.998Z\",\"tip\":\"\"}",
suite: "签到功能",
attempt: 0
},
{
name: "第1天-isCheckedIn=true",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 290 ,
func: "testIsCheckedIn",
detail: "",
got: "true",
want: "true",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "第1天-isReceive=true",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 291 ,
func: "testIsCheckedIn",
detail: "",
got: "true",
want: "true",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "第2天-isCheckedIn=true(签到未发奖)",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 295 ,
func: "testIsCheckedIn",
detail: "",
got: "true",
want: "true",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "第2天-isReceive=false(奖品未发放)",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 296 ,
func: "testIsCheckedIn",
detail: "",
got: "false",
want: "false",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "第3天-isCheckedIn=true",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 300 ,
func: "testIsCheckedIn",
detail: "",
got: "true",
want: "true",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
{
name: "第3天-isReceive=true",
passed: true ,
file: "tests/checkin/suite_checkin.go",
line: 301 ,
func: "testIsCheckedIn",
detail: "",
got: "true",
want: "true",
curl: "",
reqMethod: "",
reqURL: "",
reqHeaders: { },
reqBody: "",
respStatus: 0 ,
respBody: "",
suite: "签到功能",
attempt: 0
},
],
];
function showCase(si, ci) {
document.querySelectorAll('.case-item.active').forEach(el => el.classList.remove('active'));
const item = document.querySelector('.case-item[data-suite="'+si+'"][data-case="'+ci+'"]');
if (item) item.classList.add('active');
const c = DATA[si][ci];
const el = document.getElementById('detail');
let html = '';
html += '<div class="d-header">';
html += '<h2><span class="status">' + (c.passed?'✅':'❌') + '</span> ' + esc(c.name) + '</h2>';
html += '<div class="d-meta">';
html += '<span>套件: ' + esc(c.suite) + '</span>';
if (c.file) html += '<span class="loc-link">📍 ' + esc(c.file) + ':' + c.line + ' → ' + esc(c.func) + '()</span>';
if (c.attempt > 1) html += '<span>重试 #' + c.attempt + '</span>';
html += '</div></div>';
html += '<div class="d-section"><h3>断言结果</h3><div class="kv-grid">';
html += '<span class="k">状态</span><span class="v ' + (c.passed?'pass':'fail') + '">' + (c.passed?'✅ 通过':'❌ 失败') + '</span>';
if (!c.passed && c.detail) html += '<span class="k">原因</span><span class="v fail">' + esc(c.detail) + '</span>';
if (c.got && c.got !== '<nil>') html += '<span class="k">实际值</span><span class="v">' + esc(c.got) + '</span>';
if (c.want && c.want !== '<nil>') html += '<span class="k">期望值</span><span class="v">' + esc(c.want) + '</span>';
html += '</div></div>';
if (c.curl) {
html += '<div class="d-section"><h3>cURL 命令</h3>';
html += '<div class="curl-block"><button class="copy-btn" onclick="copyCurl(this)">复制</button><code id="curl-code-'+si+'-'+ci+'"></code></div>';
html += '</div>';
}
if (c.reqURL) {
html += '<div class="d-section"><h3>请求信息</h3><div class="req-info">';
html += '<div class="req-row"><span class="rl">Method</span><span class="rv"><span class="method-badge ' + esc(c.reqMethod) + '">' + esc(c.reqMethod) + '</span></span></div>';
html += '<div class="req-row"><span class="rl">URL</span><span class="rv">' + esc(c.reqURL) + '</span></div>';
if (c.reqHeaders) {
const hkeys = Object.keys(c.reqHeaders);
for (let hi = 0; hi < hkeys.length; hi++) {
html += '<div class="req-row"><span class="rl">' + (hi===0?'Header':'') + '</span><span class="rv" style="color:#999">' + esc(hkeys[hi]) + ': ' + esc(c.reqHeaders[hkeys[hi]]) + '</span></div>';
}
}
if (c.reqBody && c.reqBody !== 'null') {
html += '<div style="margin-top:12px;font-size:12px;color:#94a3b8;margin-bottom:6px">Request Body</div>';
html += '<div class="jtree" id="req-tree-'+si+'-'+ci+'"></div>';
}
html += '</div></div>';
}
if (c.respBody) {
html += '<div class="d-section"><h3>响应信息</h3>';
const ok = c.respStatus >= 200 && c.respStatus < 300;
html += '<div class="resp-status-bar"><span>Status:</span> <span class="resp-code ' + (ok?'ok':'err') + '">HTTP ' + c.respStatus + '</span></div>';
html += '<div class="jtree" id="resp-tree-'+si+'-'+ci+'"></div>';
html += '</div>';
}
html += '<div class="footer">Generated by tests/framework</div>';
el.innerHTML = html;
if (c.reqBody && c.reqBody !== 'null') {
try { renderTree(document.getElementById('req-tree-'+si+'-'+ci), JSON.parse(c.reqBody)); }
catch(e) { var reqEl = document.getElementById('req-tree-'+si+'-'+ci); if(reqEl) reqEl.textContent = c.reqBody; }
}
if (c.respBody) {
try { renderTree(document.getElementById('resp-tree-'+si+'-'+ci), JSON.parse(c.respBody)); }
catch(e) { var respEl = document.getElementById('resp-tree-'+si+'-'+ci); if(respEl) respEl.textContent = c.respBody; }
}
const curlEl = document.getElementById('curl-code-'+si+'-'+ci);
if (curlEl) curlEl.textContent = c.curl;
}
function renderTree(container, data) {
if (!container) return;
container.innerHTML = '';
container.appendChild(buildNode(data, 0));
}
function buildNode(val, depth) {
if (val === null) return txtSpan('null', 'jb');
if (typeof val === 'boolean') return txtSpan(String(val), 'jb');
if (typeof val === 'number') return txtSpan(String(val), 'jn');
if (typeof val === 'string') return txtSpan('"' + val + '"', 'js');
const isArr = Array.isArray(val);
const keys = isArr ? val.map((_,i) => i) : Object.keys(val);
const wrap = document.createDocumentFragment();
const toggle = document.createElement('span');
toggle.className = 'jt';
toggle.textContent = isArr ? 'Array[' + keys.length + ']' : 'Object{' + keys.length + '}';
toggle.onclick = function(e) { e.stopPropagation(); this.classList.toggle('closed'); };
wrap.appendChild(toggle);
const block = document.createElement('div');
block.className = 'jc';
keys.forEach(k => {
const row = document.createElement('div');
row.className = 'ji';
if (!isArr) {
const kSpan = document.createElement('span');
kSpan.className = 'jk';
kSpan.textContent = '"' + k + '"';
row.appendChild(kSpan);
row.appendChild(document.createTextNode(': '));
}
row.appendChild(buildNode(val[k], depth + 1));
block.appendChild(row);
});
wrap.appendChild(block);
return wrap;
}
function txtSpan(text, cls) {
const s = document.createElement('span');
s.className = cls;
s.textContent = text;
return s;
}
function esc(s) {
if (!s) return '';
const d = document.createElement('div');
d.textContent = s;
return d.innerHTML;
}
function copyCurl(btn) {
const block = btn.parentElement;
const text = block.textContent.replace('复制', '').trim();
navigator.clipboard.writeText(text).then(() => {
btn.textContent = '已复制 ✓';
setTimeout(() => btn.textContent = '复制', 1500);
});
}
(function() {
for (let si = 0; si < DATA.length; si++) {
for (let ci = 0; ci < DATA[si].length; ci++) {
if (!DATA[si][ci].passed) { showCase(si, ci); return; }
}
}
if (DATA.length > 0 && DATA[0].length > 0) showCase(0, 0);
})();
</script>
</body>
</html>