|
@@ -9,11 +9,9 @@
|
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
|
html{width:100%;height:100%;overflow:hidden}
|
|
html{width:100%;height:100%;overflow:hidden}
|
|
|
body{font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;background:var(--bg);width:100%;height:var(--app-height);min-height:100%;display:flex;flex-direction:column;overflow:hidden}
|
|
body{font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;background:var(--bg);width:100%;height:var(--app-height);min-height:100%;display:flex;flex-direction:column;overflow:hidden}
|
|
|
- .header{background:linear-gradient(135deg,var(--bk),#1a3fbf);color:#fff;padding:12px 14px;text-align:center;flex-shrink:0;position:relative;overflow:hidden;z-index:10}
|
|
|
|
|
- .header::after{content:'';position:absolute;top:-40px;right:-30px;width:120px;height:120px;background:var(--rd);border-radius:50%;opacity:.15}
|
|
|
|
|
- .header h1{font-size:17px;font-weight:700;position:relative;z-index:1}
|
|
|
|
|
- .header .sub{font-size:11px;opacity:.85;margin-top:2px;position:relative;z-index:1}
|
|
|
|
|
- .header .badge{display:inline-block;font-size:10px;background:rgba(255,255,255,.2);padding:2px 8px;border-radius:10px;margin-top:4px;position:relative;z-index:1}
|
|
|
|
|
|
|
+ .header{background:linear-gradient(135deg,var(--bk),#1a3fbf);color:#fff;padding:8px 14px;text-align:left;flex-shrink:0;position:relative;z-index:10}
|
|
|
|
|
+ .header h1{font-size:14px;font-weight:800;position:relative;z-index:1;margin:0;display:inline}
|
|
|
|
|
+ .header .header-title{font-weight:700}.header .sub{font-size:10px;opacity:.9;margin-left:8px;position:relative;z-index:1;line-height:1.5;display:inline}
|
|
|
.nav{display:flex;background:#fff;border-bottom:1px solid #e0e0e0;flex-shrink:0;z-index:10}
|
|
.nav{display:flex;background:#fff;border-bottom:1px solid #e0e0e0;flex-shrink:0;z-index:10}
|
|
|
.nav-btn{flex:1;padding:12px;text-align:center;font-size:13px;color:var(--sub);cursor:pointer;border:none;background:none;border-bottom:2px solid transparent;transition:all .2s;min-height:44px}
|
|
.nav-btn{flex:1;padding:12px;text-align:center;font-size:13px;color:var(--sub);cursor:pointer;border:none;background:none;border-bottom:2px solid transparent;transition:all .2s;min-height:44px}
|
|
|
.nav-btn.active{color:var(--bk);border-bottom-color:var(--bk);font-weight:600}
|
|
.nav-btn.active{color:var(--bk);border-bottom-color:var(--bk);font-weight:600}
|
|
@@ -107,14 +105,14 @@
|
|
|
.login-modal-btn+.login-modal-btn{border-left:1px solid #eee}
|
|
.login-modal-btn+.login-modal-btn{border-left:1px solid #eee}
|
|
|
.login-modal-btn:focus-visible{outline:2px solid var(--bk);outline-offset:-3px}
|
|
.login-modal-btn:focus-visible{outline:2px solid var(--bk);outline-offset:-3px}
|
|
|
.login-modal-btn-primary{color:var(--bk);font-weight:600}
|
|
.login-modal-btn-primary{color:var(--bk);font-weight:600}
|
|
|
-@media(max-width:400px){.input-area{padding:8px 6px;gap:4px}.input-area input{padding:8px 10px;font-size:13px;min-height:40px}.btn{padding:6px 10px;font-size:12px;min-height:40px}.media-btn{min-width:40px;padding:4px 6px;font-size:20px;border-radius:10px}.media-label{font-size:9px}.tags{padding:6px 8px 8px;gap:4px}.tag-btn{font-size:11px;padding:4px 10px}.chat{padding:10px 8px}.msg{max-width:90%}.header h1{font-size:15px}.header .sub{font-size:10px}.drug-list{padding:10px 8px}.drug-detail{padding:14px 10px}.search-box{padding:8px 10px}.drug-pager{padding:6px 8px}.pager button,.pager select{padding:4px 6px;font-size:11px}}
|
|
|
|
|
|
|
+@media(max-width:400px){.input-area{padding:8px 6px;gap:4px}.input-area input{padding:8px 10px;font-size:13px;min-height:40px}.btn{padding:6px 10px;font-size:12px;min-height:40px}.media-btn{min-width:40px;padding:4px 6px;font-size:20px;border-radius:10px}.media-label{font-size:9px}.tags{padding:6px 8px 8px;gap:4px}.tag-btn{font-size:11px;padding:4px 10px}.chat{padding:10px 8px}.msg{max-width:90%}.header h1{font-size:15px}.header .header-title{font-weight:700}.header .sub{font-size:10px}.drug-list{padding:10px 8px}.drug-detail{padding:14px 10px}.search-box{padding:8px 10px}.drug-pager{padding:6px 8px}.pager button,.pager select{padding:4px 6px;font-size:11px}}
|
|
|
</style>
|
|
</style>
|
|
|
</head>
|
|
</head>
|
|
|
<body>
|
|
<body>
|
|
|
<div class="header">
|
|
<div class="header">
|
|
|
- <h1>AI 药典助手</h1>
|
|
|
|
|
-
|
|
|
|
|
- <div class="sub">基于《中华人民共和国药典》& 通义千问</div>
|
|
|
|
|
|
|
+ <div class="sub">
|
|
|
|
|
+ <span><span class="header-title">AI药典助手温馨提示:</span></span>
|
|
|
|
|
+ 内容基于最新版《中华药典》& 通义千问生成,仅供学习参考,不构成处方和用药建议</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="nav">
|
|
<div class="nav">
|
|
|
<button class="nav-btn active" data-tab="chat" onclick="switchTab('chat')">AI 对话</button>
|
|
<button class="nav-btn active" data-tab="chat" onclick="switchTab('chat')">AI 对话</button>
|
|
@@ -126,14 +124,14 @@
|
|
|
<div id="previewArea" style="display:none;padding:8px 14px;background:#fffef5;border-top:1px solid #f0e68c;align-items:center;gap:10px;flex-wrap:wrap">
|
|
<div id="previewArea" style="display:none;padding:8px 14px;background:#fffef5;border-top:1px solid #f0e68c;align-items:center;gap:10px;flex-wrap:wrap">
|
|
|
<span id="previewLabel" style="font-size:13px;color:#666;font-weight:500"></span>
|
|
<span id="previewLabel" style="font-size:13px;color:#666;font-weight:500"></span>
|
|
|
<img id="previewThumb" style="max-width:80px;max-height:60px;border-radius:6px;display:none;border:1px solid #ddd">
|
|
<img id="previewThumb" style="max-width:80px;max-height:60px;border-radius:6px;display:none;border:1px solid #ddd">
|
|
|
- <video id="previewVid" style="max-width:150px;max-height:84px;border-radius:6px;display:none;border:1px solid #ddd" muted></video>
|
|
|
|
|
|
|
+
|
|
|
<button class="btn btn-secondary" style="font-size:12px;padding:4px 12px;min-height:auto" onclick="clearMedia()">✕ 移除附件</button>
|
|
<button class="btn btn-secondary" style="font-size:12px;padding:4px 12px;min-height:auto" onclick="clearMedia()">✕ 移除附件</button>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="input-area">
|
|
<div class="input-area">
|
|
|
<button class="media-btn" onclick="document.getElementById('imageInput').click()" title="上传图片">📷<span class="media-label">图片</span></button>
|
|
<button class="media-btn" onclick="document.getElementById('imageInput').click()" title="上传图片">📷<span class="media-label">图片</span></button>
|
|
|
- <button class="media-btn" onclick="document.getElementById('videoInput').click()" title="上传视频">🎬<span class="media-label">视频</span></button>
|
|
|
|
|
|
|
+
|
|
|
<input type="file" id="imageInput" accept="image/*" onchange="onFilePicked('image')" style="display:none">
|
|
<input type="file" id="imageInput" accept="image/*" onchange="onFilePicked('image')" style="display:none">
|
|
|
- <input type="file" id="videoInput" accept="video/*" onchange="onFilePicked('video')" style="display:none">
|
|
|
|
|
|
|
+
|
|
|
<input id="userInput" placeholder="输入药品问题,或上传图片/视频...">
|
|
<input id="userInput" placeholder="输入药品问题,或上传图片/视频...">
|
|
|
<button class="btn btn-danger" id="sendBtn" onclick="send()">发送</button>
|
|
<button class="btn btn-danger" id="sendBtn" onclick="send()">发送</button>
|
|
|
<button class="btn btn-secondary" id="stopBtn" onclick="stopCurrent()" style="display:none">停止</button>
|
|
<button class="btn btn-secondary" id="stopBtn" onclick="stopCurrent()" style="display:none">停止</button>
|
|
@@ -369,25 +367,18 @@
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function onFilePicked(type){
|
|
function onFilePicked(type){
|
|
|
- var input=document.getElementById(type==='video'?'videoInput':'imageInput');
|
|
|
|
|
|
|
+ var input=document.getElementById('imageInput');
|
|
|
var file=input.files[0];if(!file)return;
|
|
var file=input.files[0];if(!file)return;
|
|
|
- if(type==='video'&&file.size>50*1024*1024){alert('视频不能超过50MB');input.value='';return}
|
|
|
|
|
- if(type==='image'&&file.size>7*1024*1024){alert('图片不能超过7MB');input.value='';return}
|
|
|
|
|
|
|
+ if(file.size>7*1024*1024){alert('图片不能超过7MB');input.value='';return}
|
|
|
var reader=new FileReader();
|
|
var reader=new FileReader();
|
|
|
reader.onload=function(e){
|
|
reader.onload=function(e){
|
|
|
var b64=e.target.result.split(',')[1];
|
|
var b64=e.target.result.split(',')[1];
|
|
|
- pendingMedia={type:type,base64:b64,mime:file.type||(type==='video'?'video/mp4':'image/jpeg'),name:file.name};
|
|
|
|
|
|
|
+ pendingMedia={type:'image',base64:b64,mime:file.type||'image/jpeg',name:file.name};
|
|
|
var preview=document.getElementById('previewArea');preview.style.display='flex';
|
|
var preview=document.getElementById('previewArea');preview.style.display='flex';
|
|
|
- document.getElementById('previewLabel').textContent=(type==='video'?'🎬 ':'📷 ')+file.name;
|
|
|
|
|
- if(type==='image'){
|
|
|
|
|
- document.getElementById('previewThumb').src=e.target.result;document.getElementById('previewThumb').style.display='block';
|
|
|
|
|
- document.getElementById('previewVid').style.display='none';
|
|
|
|
|
- }else{
|
|
|
|
|
- document.getElementById('previewVid').src=e.target.result;document.getElementById('previewVid').style.display='block';
|
|
|
|
|
- document.getElementById('previewThumb').style.display='none';
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ document.getElementById('previewLabel').textContent='📷 '+file.name;
|
|
|
|
|
+ document.getElementById('previewThumb').src=e.target.result;document.getElementById('previewThumb').style.display='block';
|
|
|
var inp=document.getElementById('userInput');
|
|
var inp=document.getElementById('userInput');
|
|
|
- if(!inp.value.trim())inp.placeholder=type==='video'?'视频已就绪,可输入补充问题...':'图片已就绪,可输入补充问题...';
|
|
|
|
|
|
|
+ if(!inp.value.trim())inp.placeholder='图片已就绪,可输入补充问题...';
|
|
|
};
|
|
};
|
|
|
reader.readAsDataURL(file);
|
|
reader.readAsDataURL(file);
|
|
|
}
|
|
}
|
|
@@ -395,9 +386,7 @@
|
|
|
pendingMedia=null;
|
|
pendingMedia=null;
|
|
|
document.getElementById('previewArea').style.display='none';
|
|
document.getElementById('previewArea').style.display='none';
|
|
|
document.getElementById('imageInput').value='';
|
|
document.getElementById('imageInput').value='';
|
|
|
- document.getElementById('videoInput').value='';
|
|
|
|
|
document.getElementById('previewThumb').style.display='none';
|
|
document.getElementById('previewThumb').style.display='none';
|
|
|
- document.getElementById('previewVid').style.display='none';
|
|
|
|
|
document.getElementById('userInput').placeholder='输入药品问题...';
|
|
document.getElementById('userInput').placeholder='输入药品问题...';
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -417,9 +406,6 @@
|
|
|
if(media&&media.type==='image'){
|
|
if(media&&media.type==='image'){
|
|
|
endpoint=API_BASE+'/api/v1/chat/stream-image';
|
|
endpoint=API_BASE+'/api/v1/chat/stream-image';
|
|
|
body=JSON.stringify({imageBase64:media.base64,mimeType:media.mime,message:query});
|
|
body=JSON.stringify({imageBase64:media.base64,mimeType:media.mime,message:query});
|
|
|
- }else if(media&&media.type==='video'){
|
|
|
|
|
- endpoint=API_BASE+'/api/v1/chat/stream-multimodal';
|
|
|
|
|
- body=JSON.stringify({mediaType:'video',mediaBase64:media.base64,mediaMime:media.mime,message:query});
|
|
|
|
|
}else{
|
|
}else{
|
|
|
endpoint=API_BASE+'/api/v1/chat/stream';
|
|
endpoint=API_BASE+'/api/v1/chat/stream';
|
|
|
body=JSON.stringify({message:query});
|
|
body=JSON.stringify({message:query});
|
|
@@ -535,10 +521,10 @@
|
|
|
document.getElementById('sendBtn').disabled=true;document.getElementById('stopBtn').style.display='inline-block';
|
|
document.getElementById('sendBtn').disabled=true;document.getElementById('stopBtn').style.display='inline-block';
|
|
|
var w=document.getElementById('chat').querySelector('.welcome');if(w)w.remove();
|
|
var w=document.getElementById('chat').querySelector('.welcome');if(w)w.remove();
|
|
|
var userDisplay=text;
|
|
var userDisplay=text;
|
|
|
- if(media){var mi=media.type==='video'?'🎬 [视频] ':'📷 [图片] ';userDisplay=mi+(text||('请分析此'+(media.type==='video'?'视频':'图片')))}
|
|
|
|
|
|
|
+ if(media){userDisplay='📷 [图片] '+(text||'请分析此图片')}
|
|
|
addMsg('user',userDisplay);
|
|
addMsg('user',userDisplay);
|
|
|
var query=text;
|
|
var query=text;
|
|
|
- if(media&&!text){query='请分析此'+(media.type==='video'?'视频':'图片')+'中的药品信息'}
|
|
|
|
|
|
|
+ if(media&&!text){query='请分析此图片中的药品信息'}
|
|
|
if(!query){query='请介绍一下自己'}
|
|
if(!query){query='请介绍一下自己'}
|
|
|
if(media)pendingMedia=null;if(media)clearMedia();
|
|
if(media)pendingMedia=null;if(media)clearMedia();
|
|
|
currentIntent=classifyIntent(query);
|
|
currentIntent=classifyIntent(query);
|