|
|
@@ -191,6 +191,7 @@
|
|
|
<div class="module-tab" data-module="business-license">4.入驻信息提交</div>
|
|
|
<div class="module-tab" data-module="activity-available">5.我可参加的活动</div>
|
|
|
<div class="module-tab" data-module="activity-rewards-tab">6.各种活动奖励</div>
|
|
|
+ <div class="module-tab" data-module="search-record">7.搜索记录</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 运营侧模块标签栏 -->
|
|
|
@@ -217,7 +218,7 @@ const SMS_CODE = () => document.getElementById('smsCode')?.value || '123456';
|
|
|
|
|
|
let stats = { pass: 0, fail: 0, pending: 0, total: 0 };
|
|
|
|
|
|
-const USER_MODULES = ['checkin', 'activity-invite', 'activity-lottery', 'business-license', 'activity-available', 'activity-rewards-tab'];
|
|
|
+const USER_MODULES = ['checkin', 'activity-invite', 'activity-lottery', 'business-license', 'activity-available', 'activity-rewards-tab', 'search-record'];
|
|
|
const ADMIN_MODULES = ['admin-checkin', 'admin-activity-invite', 'admin-activity-checkin', 'admin-activity-lottery', 'admin-license'];
|
|
|
|
|
|
// ===================== 大整数安全JSON解析 =====================
|
|
|
@@ -438,6 +439,7 @@ function renderModule(module) {
|
|
|
case 'business-license': html = renderBusinessLicenseModule(); break;
|
|
|
case 'activity-available': html = renderActivityAvailableModule(); break;
|
|
|
case 'activity-rewards-tab': html = renderActivityRewardsModule(); break;
|
|
|
+ case 'search-record': html = renderSearchRecordModule(); break;
|
|
|
case 'admin-checkin': html = renderAdminCheckinModule(); break;
|
|
|
case 'admin-activity-invite': html = renderAdminActivityInviteModule(); break;
|
|
|
case 'admin-activity-checkin': html = renderAdminActivityCheckinModule(); break;
|
|
|
@@ -606,7 +608,8 @@ const FIELD_DESC = {
|
|
|
['data.membershipLevel', 'String', '当前用户会员等级'],
|
|
|
['data.requireMembershipLevel', 'String', '所需会员等级'],
|
|
|
['data.availableChances', 'Integer', '今日可用抽奖机会数'],
|
|
|
- ['data.usedChances', 'Integer', '今日已用抽奖机会数']
|
|
|
+ ['data.usedChances', 'Integer', '今日已用抽奖机会数'],
|
|
|
+ ['data.reason', 'String/null', '状态原因说明(机会为0时返回具体原因,有机会时为null)']
|
|
|
],
|
|
|
'activityLotteryPrizes': [
|
|
|
['data[].id', 'Long', '奖品ID'],
|
|
|
@@ -763,6 +766,33 @@ const FIELD_DESC = {
|
|
|
['data.showVerifiedBadge', 'Boolean', '是否显示认证标识'],
|
|
|
['data.reviewRemark', 'String', '审核备注'],
|
|
|
['data.createTime', 'DateTime', '创建时间']
|
|
|
+ ],
|
|
|
+ 'searchRecordResponse': [
|
|
|
+ ['id', 'Long', '记录ID(雪花算法)'],
|
|
|
+ ['drugName', 'String', '药品名称'],
|
|
|
+ ['searchedAt', 'DateTime', '搜索时间(yyyy-MM-dd HH:mm:ss)'],
|
|
|
+ ['statusText', 'String', '状态文案'],
|
|
|
+ ['platformCount', 'Integer', '涉及平台数量'],
|
|
|
+ ['quoteCount', 'Integer', '总报价条数'],
|
|
|
+ ['platformResults', 'Object/Array', '平台搜索结果(仅详情接口返回)'],
|
|
|
+ ['searchLog', 'Object/null', '搜索日志(仅详情接口返回)']
|
|
|
+ ],
|
|
|
+ 'searchQueryResponse': [
|
|
|
+ ['data.keyword', 'String', '搜索关键词'],
|
|
|
+ ['data.totalCount', 'Integer', '结果总数'],
|
|
|
+ ['data.lowestPrice', 'BigDecimal', '最低价'],
|
|
|
+ ['data.lowestPricePlatform', 'String', '最低价平台名称'],
|
|
|
+ ['data.searchTime', 'DateTime', '搜索时间'],
|
|
|
+ ['data.prices[].platformCode', 'String', '平台代码'],
|
|
|
+ ['data.prices[].platformName', 'String', '平台名称'],
|
|
|
+ ['data.prices[].price', 'BigDecimal', '价格(元)'],
|
|
|
+ ['data.prices[].spec', 'String', '规格'],
|
|
|
+ ['data.prices[].manufacturer', 'String', '厂家'],
|
|
|
+ ['data.prices[].expiry', 'String', '效期'],
|
|
|
+ ['data.prices[].moq', 'Integer', '最小起订量'],
|
|
|
+ ['data.prices[].stockStatus', 'String', '库存状态(IN_STOCK/LOW_STOCK/OUT_OF_STOCK)'],
|
|
|
+ ['data.prices[].isLowest', 'Boolean', '是否为最低价'],
|
|
|
+ ['data.prices[].purchaseUrl', 'String', '平台跳转链接']
|
|
|
]
|
|
|
};
|
|
|
|
|
|
@@ -918,7 +948,7 @@ function renderActivityLotteryModule() {
|
|
|
<button class="btn btn-warning btn-sm" onclick="runActivityLotteryTests()">运行全部比价抽奖测试</button>
|
|
|
</div>
|
|
|
${testSection('activity-lottery-prizes', '奖励信息(可抽奖品列表)', 'GET', 'get', '/api/activity/lottery/prizes', '需认证', 'auth-required', null, true, 'activityLotteryPrizes', '查看当前可抽奖品列表(仅启用奖品,不显示概率权重等敏感信息)')}
|
|
|
- ${testSection('activity-lottery-status', '比价抽奖活动状态', 'GET', 'get', '/api/activity/lottery/status', '需认证', 'auth-required', null, true, 'activityLotteryStatus', '查询抽奖活动状态:是否开启、是否满足资格、今日可用机会')}
|
|
|
+ ${testSection('activity-lottery-status', '比价抽奖活动状态', 'GET', 'get', '/api/activity/lottery/status', '需认证', 'auth-required', null, true, 'activityLotteryStatus', '查询抽奖活动状态:是否开启、是否满足资格、今日可用机会。机会为0时reason字段告知具体原因(活动未开启/不在时间窗/会员等级不足/尚未比价/机会已用完)')}
|
|
|
${testSection('activity-lottery-draw', '执行抽奖', 'POST', 'post', '/api/activity/lottery/draw', '需认证', 'auth-required', null, true, 'activityLotteryDraw', '消耗一次抽奖机会,随机抽取奖品(会员/爬虫次数/谢谢参与)')}
|
|
|
${testSection('activity-lottery-records', '我的抽奖记录', 'GET', 'get', '/api/activity/lottery/records?limit=20', '需认证', 'auth-required',
|
|
|
[{label:'条数(limit,可选)', name:'limit', placeholder:'20', default:'20'}], true, 'activityLotteryRecords', '获取当前用户的抽奖历史记录,包含奖品名称、奖励类型、会员天数、是否中奖等完整中奖信息')}`;
|
|
|
@@ -999,6 +1029,30 @@ function renderActivityRewardsModule() {
|
|
|
], true, 'activityRewards', '按活动类型分页查询当前用户的三种活动中奖/奖励记录。type: INVITE-邀请有礼 / CHECKIN-签到有礼 / LOTTERY-比价抽奖')}`;
|
|
|
}
|
|
|
|
|
|
+// ==================== 用户端:搜索记录模块 ====================
|
|
|
+function renderSearchRecordModule() {
|
|
|
+ return `
|
|
|
+ <div class="batch-buttons">
|
|
|
+ <button class="btn btn-warning btn-sm" onclick="runSearchRecordTests()">运行全部搜索记录测试</button>
|
|
|
+ </div>
|
|
|
+ ${testSection('sr-save', '保存搜索记录', 'POST', 'post', '/api/search-record/history', '需认证', 'auth-required',
|
|
|
+ [{label:'药品名称(drugName)', name:'drugName', placeholder:'阿莫西林', default:'阿莫西林'},
|
|
|
+ {label:'搜索时间(searchedAt)', name:'searchedAt', placeholder:'yyyy-MM-dd HH:mm:ss', default:'2026-07-10 08:30:00'},
|
|
|
+ {label:'状态文案(statusText)', name:'statusText', placeholder:'已返回 2 个平台的可比价结果。', default:'已返回 2 个平台的可比价结果。'},
|
|
|
+ {label:'平台结果(platformResults)', name:'platformResults', placeholder:'JSON数组', default:'[{"platformCode":"yiyaocheng","platformName":"壹药城","response":{"products":[{"drugName":"阿莫西林","price":12.5}]}}]', type:'json'},
|
|
|
+ {label:'搜索日志(searchLog)', name:'searchLog', placeholder:'null', default:'null', type:'json'}], true, 'searchRecordResponse', '保存一次完整的比价搜索快照。platformResults为JSON数组,每个元素含platformCode/platformName/response;后端自动计算platformCount和quoteCount')}
|
|
|
+ ${testSection('sr-list', '搜索记录列表', 'GET', 'get', '/api/search-record/history?pageNo={pageNo}&pageSize={pageSize}', '需认证', 'auth-required',
|
|
|
+ [{label:'页码(pageNo)', name:'pageNo', placeholder:'1', default:'1'},
|
|
|
+ {label:'每页条数(pageSize)', name:'pageSize', placeholder:'20', default:'20'}], true, 'searchRecordResponse', '分页查询当前用户搜索记录(轻量摘要,不含platformResults/searchLog大字段)')}
|
|
|
+ ${testSection('sr-detail', '记录详情', 'GET', 'get', '/api/search-record/history/{id}', '需认证', 'auth-required',
|
|
|
+ [{label:'记录ID(id)', name:'id', placeholder:'1', default:'1'}], true, 'searchRecordResponse', '读取单条搜索记录详情(含完整platformResults和searchLog)')}
|
|
|
+ ${testSection('sr-lottery-status', '比价抽奖状态', 'GET', 'get', '/api/activity/lottery/status', '需认证', 'auth-required', null, true, 'activityLotteryStatus', '查询今日抽奖状态。活动规则:2026.7.10-7.31,高级会员每自然日首次成功比价后自动获得1次抽奖机会,先到先得。reason字段说明为什么无机会')}
|
|
|
+ ${testSection('sr-lottery-draw', '执行抽奖', 'POST', 'post', '/api/activity/lottery/draw', '需认证', 'auth-required', null, true, 'activityLotteryDraw', '消耗一次抽奖机会随机中奖(会员天数/谢谢参与),先到先得。前提:当日首次成功比价后后端自动发放机会,每日限1次')}
|
|
|
+ ${testSection('sr-delete', '删除记录', 'DELETE', 'delete', '/api/search-record/history/{id}', '需认证', 'auth-required',
|
|
|
+ [{label:'记录ID(id)', name:'id', placeholder:'1', default:'1'}], false, null, '删除单条搜索记录(幂等,不存在也返回成功)')}
|
|
|
+ ${testSection('sr-clear', '清空记录', 'DELETE', 'delete', '/api/search-record/history', '需认证', 'auth-required', null, false, null, '清空当前用户全部搜索记录')}`;
|
|
|
+}
|
|
|
+
|
|
|
// ==================== 运营端:签到管理模块 ====================
|
|
|
function renderAdminCheckinModule() {
|
|
|
return `
|
|
|
@@ -1349,6 +1403,7 @@ function runAdminActivityInviteTests() { runBatchTests('admin-activity-invite');
|
|
|
function runAdminActivityCheckinTests() { runBatchTests('admin-activity-checkin'); }
|
|
|
function runAdminActivityLotteryTests() { runBatchTests('admin-activity-lottery'); }
|
|
|
function runAdminLicenseTests() { runBatchTests('admin-license'); }
|
|
|
+function runSearchRecordTests() { runBatchTests('search-record'); }
|
|
|
|
|
|
// ===================== 验证器 =====================
|
|
|
function validate_checkinStatus(result) { return result.data?.code === 200 && result.data?.data?.checkedToday !== undefined; }
|
|
|
@@ -1393,6 +1448,13 @@ function validate_adminLicenseList(result) { return result.data?.code === 200 &&
|
|
|
function validate_adminLicenseApprove(result) { return result.data?.code === 200; }
|
|
|
function validate_adminLicenseReject(result) { return result.data?.code === 200; }
|
|
|
|
|
|
+// 搜索记录模块
|
|
|
+function validate_srSave(result) { return result.data?.code === 200 && result.data?.data?.id; }
|
|
|
+function validate_srList(result) { return result.data?.code === 200 && result.data?.data?.records !== undefined; }
|
|
|
+function validate_srDetail(result) { return result.data?.code === 200 && result.data?.data?.id; }
|
|
|
+function validate_srLotteryStatus(result) { return result.data?.code === 200 && result.data?.data?.enabled !== undefined; }
|
|
|
+function validate_srLotteryDraw(result) { return result.data?.code === 200 && result.data?.data?.prizeName !== undefined; }
|
|
|
+
|
|
|
// ===================== 初始化 =====================
|
|
|
window.addEventListener('DOMContentLoaded', () => {
|
|
|
const params = new URLSearchParams(window.location.search);
|