|
@@ -286,6 +286,7 @@ let stats = { pass: 0, fail: 0, pending: 0, total: 0 };
|
|
|
* 示例:":2069620495151230978," → ":\"2069620495151230978\","
|
|
* 示例:":2069620495151230978," → ":\"2069620495151230978\","
|
|
|
*/
|
|
*/
|
|
|
function safeJsonParse(text) {
|
|
function safeJsonParse(text) {
|
|
|
|
|
+ if (!text || text.trim() === '' || text.trim() === 'null') return null;
|
|
|
const safeText = text.replace(/([:,\[]\s*)(\d{16,})(\s*[,\]\}])/g, '$1"$2"$3');
|
|
const safeText = text.replace(/([:,\[]\s*)(\d{16,})(\s*[,\]\}])/g, '$1"$2"$3');
|
|
|
return JSON.parse(safeText);
|
|
return JSON.parse(safeText);
|
|
|
}
|
|
}
|
|
@@ -647,6 +648,11 @@ function renderModule(module) {
|
|
|
case 'admin-audit': html = renderAdminAuditModule(); break;
|
|
case 'admin-audit': html = renderAdminAuditModule(); break;
|
|
|
}
|
|
}
|
|
|
panels.innerHTML = html;
|
|
panels.innerHTML = html;
|
|
|
|
|
+ // 修复含引号的默认值:从 data-raw 属性恢复正确的 input value
|
|
|
|
|
+ panels.querySelectorAll('input[data-raw]').forEach(input => {
|
|
|
|
|
+ input.value = input.getAttribute('data-raw');
|
|
|
|
|
+ input.removeAttribute('data-raw');
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function toValidatorName(id) {
|
|
function toValidatorName(id) {
|
|
@@ -1146,7 +1152,10 @@ function testSection(id, title, method, methodClass, path, authTag, authClass, f
|
|
|
if (fields) {
|
|
if (fields) {
|
|
|
fieldsHtml = '<div class="form-grid">';
|
|
fieldsHtml = '<div class="form-grid">';
|
|
|
fields.forEach(f => {
|
|
fields.forEach(f => {
|
|
|
- fieldsHtml += `<div class="form-group"><label>${f.label}</label><input type="text" id="${id}-${f.name}" placeholder="${f.placeholder || ''}" value="${f.default || ''}"></div>`;
|
|
|
|
|
|
|
+ const escapedDefault = (f.default || '').replace(/"/g, '"');
|
|
|
|
|
+ const escapedPlaceholder = (f.placeholder || '').replace(/"/g, '"');
|
|
|
|
|
+ const hasRaw = f.default && f.default.includes('"');
|
|
|
|
|
+ fieldsHtml += `<div class="form-group"><label>${f.label}</label><input type="text" id="${id}-${f.name}" placeholder="${escapedPlaceholder}" value="${escapedDefault}"${hasRaw ? ` data-raw="${escapedDefault}"` : ''}></div>`;
|
|
|
});
|
|
});
|
|
|
fieldsHtml += '</div>';
|
|
fieldsHtml += '</div>';
|
|
|
}
|
|
}
|
|
@@ -1488,12 +1497,13 @@ function renderSearchRecordModule() {
|
|
|
</div>
|
|
</div>
|
|
|
${testSection('sr-save', '保存搜索记录', 'POST', 'post', '/api/search-record/history', '需认证', 'auth-required',
|
|
${testSection('sr-save', '保存搜索记录', 'POST', 'post', '/api/search-record/history', '需认证', 'auth-required',
|
|
|
[{label:'药品名称(drugName)', name:'drugName', placeholder:'阿莫西林', default:'阿莫西林'},
|
|
[{label:'药品名称(drugName)', name:'drugName', placeholder:'阿莫西林', default:'阿莫西林'},
|
|
|
- {label:'搜索时间(searchedAt)', name:'searchedAt', placeholder:'2026-06-26T08:30:00.000Z', default:'2026-06-26T08:30:00.000Z'},
|
|
|
|
|
|
|
+ {label:'搜索时间(searchedAt)', name:'searchedAt', placeholder:'yyyy-MM-dd HH:mm:ss', default:'2026-06-26 08:30:00'},
|
|
|
{label:'状态文案(statusText)', name:'statusText', placeholder:'已返回 2 个平台的可比价结果。', default:'已返回 2 个平台的可比价结果。'},
|
|
{label:'状态文案(statusText)', name:'statusText', placeholder:'已返回 2 个平台的可比价结果。', default:'已返回 2 个平台的可比价结果。'},
|
|
|
{label:'平台结果(platformResults)', name:'platformResults', placeholder:'[{"platformId":"yiyaocheng","platformName":"壹药城"}]', default:'[{"platformId":"yiyaocheng","platformName":"壹药城","response":{"status":"ok","products":[]}}]', type:'json'},
|
|
{label:'平台结果(platformResults)', name:'platformResults', placeholder:'[{"platformId":"yiyaocheng","platformName":"壹药城"}]', default:'[{"platformId":"yiyaocheng","platformName":"壹药城","response":{"status":"ok","products":[]}}]', type:'json'},
|
|
|
- {label:'搜索日志(searchLog)', name:'searchLog', placeholder:'null', default:'null', type:'json'}], true, null, '保存一次完整的比价搜索快照,包含平台响应数据。platformResults和searchLog支持任意JSON结构')}
|
|
|
|
|
- ${testSection('sr-list', '搜索记录列表', 'GET', 'get', '/api/search-record/history?limit={limit}', '需认证', 'auth-required',
|
|
|
|
|
- [{label:'条数(limit)', name:'limit', placeholder:'20', default:'20'}], true, null, '获取当前用户最近的搜索记录,默认20条,最多50条')}
|
|
|
|
|
|
|
+ {label:'搜索日志(searchLog)', name:'searchLog', placeholder:'null', default:'null', type:'json'}], true, null, '保存一次完整的比价搜索快照,包含平台响应数据。platformResults和searchLog支持任意JSON结构。searchedAt格式:yyyy-MM-dd HH:mm:ss')}
|
|
|
|
|
+ ${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, null, '分页查询当前用户搜索记录,返回分页对象含total/records/pages等字段')}
|
|
|
${testSection('sr-detail', '记录详情', 'GET', 'get', '/api/search-record/history/{id}', '需认证', 'auth-required',
|
|
${testSection('sr-detail', '记录详情', 'GET', 'get', '/api/search-record/history/{id}', '需认证', 'auth-required',
|
|
|
[{label:'记录ID(id)', name:'id', placeholder:'1', default:'1'}], true, null, '读取单条搜索记录详情(包含完整的platformResults)')}
|
|
[{label:'记录ID(id)', name:'id', placeholder:'1', default:'1'}], true, null, '读取单条搜索记录详情(包含完整的platformResults)')}
|
|
|
${testSection('sr-delete', '删除记录', 'DELETE', 'delete', '/api/search-record/history/{id}', '需认证', 'auth-required',
|
|
${testSection('sr-delete', '删除记录', 'DELETE', 'delete', '/api/search-record/history/{id}', '需认证', 'auth-required',
|
|
@@ -1974,7 +1984,7 @@ function validate_searchRecords(result) { return result.data?.code === 200 && re
|
|
|
|
|
|
|
|
// 搜索记录模块验证器
|
|
// 搜索记录模块验证器
|
|
|
function validate_srSave(result) { return result.data?.code === 200 && result.data?.data?.id && result.data?.data?.drugName; }
|
|
function validate_srSave(result) { return result.data?.code === 200 && result.data?.data?.id && result.data?.data?.drugName; }
|
|
|
-function validate_srList(result) { return result.data?.code === 200 && Array.isArray(result.data?.data); }
|
|
|
|
|
|
|
+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_srDetail(result) { return result.data?.code === 200 && result.data?.data?.id; }
|
|
|
// 平台会话模块验证器
|
|
// 平台会话模块验证器
|
|
|
function validate_psUpload(result) { return result.data?.code === 200 && result.data?.data?.platformCode; }
|
|
function validate_psUpload(result) { return result.data?.code === 200 && result.data?.data?.platformCode; }
|