|
@@ -104,9 +104,11 @@
|
|
|
.drug-detail h3{font-size:15px;color:var(--bk);margin:16px 0 8px}
|
|
.drug-detail h3{font-size:15px;color:var(--bk);margin:16px 0 8px}
|
|
|
.drug-detail .info-row{font-size:13px;color:var(--sub);margin:4px 0}
|
|
.drug-detail .info-row{font-size:13px;color:var(--sub);margin:4px 0}
|
|
|
.drug-detail .section{background:var(--card);border-radius:8px;padding:12px;margin:8px 0;font-size:14px;line-height:1.8}
|
|
.drug-detail .section{background:var(--card);border-radius:8px;padding:12px;margin:8px 0;font-size:14px;line-height:1.8}
|
|
|
- .search-box{padding:10px 14px;background:#fff;border-bottom:1px solid #e0e0e0;flex-shrink:0}
|
|
|
|
|
- .search-box input{width:100%;padding:10px 14px;border:1px solid #ddd;border-radius:24px;font-size:14px;outline:none;min-height:44px}
|
|
|
|
|
|
|
+ .search-box{padding:10px 14px;background:#fff;border-bottom:1px solid #e0e0e0;flex-shrink:0;display:flex;gap:8px}
|
|
|
|
|
+ .search-box input{flex:1;padding:10px 14px;border:1px solid #ddd;border-radius:24px;font-size:14px;outline:none;min-height:44px}
|
|
|
.search-box input:focus{border-color:var(--bk);box-shadow:0 0 0 2px rgba(0,47,167,.12)}
|
|
.search-box input:focus{border-color:var(--bk);box-shadow:0 0 0 2px rgba(0,47,167,.12)}
|
|
|
|
|
+ .search-box button{padding:8px 16px;border:none;border-radius:24px;background:var(--bk);color:#fff;font-size:14px;font-weight:600;cursor:pointer;white-space:nowrap;min-height:44px}
|
|
|
|
|
+ .search-box button:hover{background:#1a3fbf}
|
|
|
.status-bar{font-size:11px;padding:4px 14px;text-align:center;flex-shrink:0}
|
|
.status-bar{font-size:11px;padding:4px 14px;text-align:center;flex-shrink:0}
|
|
|
.hidden{display:none!important}
|
|
.hidden{display:none!important}
|
|
|
.pager{display:flex;justify-content:center;align-items:center;gap:4px;flex-wrap:wrap}
|
|
.pager{display:flex;justify-content:center;align-items:center;gap:4px;flex-wrap:wrap}
|
|
@@ -155,7 +157,7 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div id="tabDrugs" class="hidden">
|
|
<div id="tabDrugs" class="hidden">
|
|
|
- <div class="search-box"><input id="drugSearchInput" placeholder="搜索药品名称..." oninput="searchDrugs()"></div>
|
|
|
|
|
|
|
+ <div class="search-box"><input id="drugSearchInput" placeholder="搜索药品名称..." oninput="onSearchInput()"><button onclick="searchDrugs()">搜索</button></div>
|
|
|
<div class="drug-list" id="drugList"></div>
|
|
<div class="drug-list" id="drugList"></div>
|
|
|
<div class="drug-pager" id="drugPager"></div>
|
|
<div class="drug-pager" id="drugPager"></div>
|
|
|
</div>
|
|
</div>
|
|
@@ -218,9 +220,8 @@
|
|
|
try {
|
|
try {
|
|
|
fetch(API_BASE + '/api/v1/analytics/events', {
|
|
fetch(API_BASE + '/api/v1/analytics/events', {
|
|
|
method: 'POST', headers: h, body: JSON.stringify(payload), keepalive: true
|
|
method: 'POST', headers: h, body: JSON.stringify(payload), keepalive: true
|
|
|
- }).then(function(r){
|
|
|
|
|
- }).catch(function(e){ console.error('[track] error', e); });
|
|
|
|
|
- } catch(e) { console.error('[track] exception', e); }
|
|
|
|
|
|
|
+ }).catch(function(){});
|
|
|
|
|
+ } catch(e) {}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 自动埋点所有 fetch 调用
|
|
// 自动埋点所有 fetch 调用
|
|
@@ -404,28 +405,31 @@
|
|
|
if(!msgs.length)return;
|
|
if(!msgs.length)return;
|
|
|
renderMessages(msgs);
|
|
renderMessages(msgs);
|
|
|
}
|
|
}
|
|
|
|
|
+ /** 统一渲染 AI 消息的内部 HTML(标签+内容+来源+品牌推荐) */
|
|
|
|
|
+ function buildAiInnerHtml(m) {
|
|
|
|
|
+ var tag=m.intent||'';
|
|
|
|
|
+ var tagHtml=tag?'<div class="tag '+tagClass(tag)+'">'+intentLabel(tag)+'</div>':'<div class="tag tag-fallback">AI 药典助手</div>';
|
|
|
|
|
+ var h = tagHtml+'<div class="content">'+md2html(m.content||'')+'</div>';
|
|
|
|
|
+ if (m.sources && m.sources.length) {
|
|
|
|
|
+ sourcesData = m.sources;
|
|
|
|
|
+ h += buildSourceTags();
|
|
|
|
|
+ sourcesData = [];
|
|
|
|
|
+ }
|
|
|
|
|
+ if (m.brand_recommendations && m.brand_recommendations.length) {
|
|
|
|
|
+ brandRecsData = m.brand_recommendations;
|
|
|
|
|
+ h += buildBrandRecs();
|
|
|
|
|
+ brandRecsData = [];
|
|
|
|
|
+ }
|
|
|
|
|
+ return h;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
function renderMessages(msgs){
|
|
function renderMessages(msgs){
|
|
|
var w=document.getElementById('chat').querySelector('.welcome');if(w)w.remove();
|
|
var w=document.getElementById('chat').querySelector('.welcome');if(w)w.remove();
|
|
|
for(var i=0;i<msgs.length;i++){
|
|
for(var i=0;i<msgs.length;i++){
|
|
|
var m=msgs[i],div=document.createElement('div');
|
|
var m=msgs[i],div=document.createElement('div');
|
|
|
div.className='msg '+m.role;
|
|
div.className='msg '+m.role;
|
|
|
if(m.role==='user'){div.textContent=m.content}
|
|
if(m.role==='user'){div.textContent=m.content}
|
|
|
- else{
|
|
|
|
|
- var tag=m.intent||'';
|
|
|
|
|
- var tagHtml=tag?'<div class="tag '+tagClass(tag)+'">'+intentLabel(tag)+'</div>':'<div class="tag tag-fallback">AI 药典助手</div>';
|
|
|
|
|
- div.innerHTML=tagHtml+'<div class="content">'+md2html(m.content)+'</div>';
|
|
|
|
|
- // 恢复历史记录中的来源引用和品牌推荐
|
|
|
|
|
- if (m.sources && m.sources.length) {
|
|
|
|
|
- sourcesData = m.sources;
|
|
|
|
|
- div.innerHTML += buildSourceTags();
|
|
|
|
|
- sourcesData = [];
|
|
|
|
|
- }
|
|
|
|
|
- if (m.brand_recommendations && m.brand_recommendations.length) {
|
|
|
|
|
- brandRecsData = m.brand_recommendations;
|
|
|
|
|
- div.innerHTML += buildBrandRecs();
|
|
|
|
|
- brandRecsData = [];
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ else{ div.innerHTML = buildAiInnerHtml(m); }
|
|
|
document.getElementById('chat').appendChild(div);
|
|
document.getElementById('chat').appendChild(div);
|
|
|
}
|
|
}
|
|
|
document.getElementById('chat').scrollTop=document.getElementById('chat').scrollHeight;
|
|
document.getElementById('chat').scrollTop=document.getElementById('chat').scrollHeight;
|
|
@@ -779,10 +783,20 @@
|
|
|
renderDrugCards(ALL_DRUGS);
|
|
renderDrugCards(ALL_DRUGS);
|
|
|
}catch(e){ALL_DRUGS=[];renderDrugCards([])}
|
|
}catch(e){ALL_DRUGS=[];renderDrugCards([])}
|
|
|
}
|
|
}
|
|
|
|
|
+ var searchTimer=null;
|
|
|
|
|
+ var lastSearched='';
|
|
|
|
|
+ window.onSearchInput=function(){
|
|
|
|
|
+ if(searchTimer)clearTimeout(searchTimer);
|
|
|
|
|
+ searchTimer=setTimeout(function(){searchDrugs();},2000);
|
|
|
|
|
+ };
|
|
|
window.searchDrugs=function(){
|
|
window.searchDrugs=function(){
|
|
|
- drugKeyword=(document.getElementById('drugSearchInput').value||'').trim();
|
|
|
|
|
|
|
+ if(searchTimer){clearTimeout(searchTimer);searchTimer=null}
|
|
|
|
|
+ var kw=(document.getElementById('drugSearchInput').value||'').trim();
|
|
|
|
|
+ if(kw===lastSearched)return;
|
|
|
|
|
+ drugKeyword=kw;
|
|
|
if (drugKeyword) track('search', {keyword: drugKeyword});
|
|
if (drugKeyword) track('search', {keyword: drugKeyword});
|
|
|
loadDrugList(1);
|
|
loadDrugList(1);
|
|
|
|
|
+ lastSearched=kw;
|
|
|
return false;
|
|
return false;
|
|
|
};
|
|
};
|
|
|
function renderDrugCards(items){
|
|
function renderDrugCards(items){
|
|
@@ -844,7 +858,7 @@
|
|
|
}catch(e){document.getElementById('tabDrugs').innerHTML='<div class="welcome"><p>加载失败</p></div>'}
|
|
}catch(e){document.getElementById('tabDrugs').innerHTML='<div class="welcome"><p>加载失败</p></div>'}
|
|
|
};
|
|
};
|
|
|
window.showDrugList=function(){
|
|
window.showDrugList=function(){
|
|
|
- document.getElementById('tabDrugs').innerHTML='<div class="search-box"><input id="drugSearchInput" placeholder="搜索药品名称..." oninput="searchDrugs()" value="'+escAttr(drugKeyword)+'"></div><div class="drug-list" id="drugList"></div><div class="drug-pager" id="drugPager"></div>';
|
|
|
|
|
|
|
+ document.getElementById('tabDrugs').innerHTML='<div class="search-box"><input id="drugSearchInput" placeholder="搜索药品名称..." oninput="onSearchInput()" value="'+escAttr(drugKeyword)+'"><button onclick="searchDrugs()">搜索</button></div><div class="drug-list" id="drugList"></div><div class="drug-pager" id="drugPager"></div>';
|
|
|
renderDrugCards(ALL_DRUGS);
|
|
renderDrugCards(ALL_DRUGS);
|
|
|
};
|
|
};
|
|
|
window.handleJumpPage=function(){
|
|
window.handleJumpPage=function(){
|