157 lines
21 KiB
HTML
157 lines
21 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}AlphaX Agent — 智能问答{% endblock %}
|
||
{% block extra_head_css %}
|
||
<style>
|
||
.chat-shell{height:100vh;max-height:100vh;display:grid;grid-template-columns:300px minmax(0,1fr);background:#f4f5f7;overflow:hidden}
|
||
.session-pane{border-right:1px solid var(--hairline-soft);background:var(--canvas);display:flex;flex-direction:column;min-width:0}
|
||
.session-head{padding:18px 16px;border-bottom:1px solid var(--hairline-soft);display:flex;align-items:center;justify-content:space-between;gap:10px}
|
||
.session-title{font-size:17px;font-weight:950;letter-spacing:-.3px}
|
||
.icon-btn{width:34px;height:34px;border:1px solid var(--hairline);border-radius:var(--radius-md);background:var(--canvas);display:grid;place-items:center;cursor:pointer;color:var(--ink);font-weight:950}
|
||
.session-list{overflow:auto;min-height:0;flex:1;padding:8px}
|
||
.session-row{padding:12px;border-radius:var(--radius-md);cursor:pointer;border:1px solid transparent;background:transparent;transition:.12s}
|
||
.session-row:hover{background:var(--surface)}
|
||
.session-row.active{background:#1c1c1e;color:#fff}
|
||
.session-row b{display:block;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.session-row span{display:block;margin-top:4px;color:var(--stone);font-size:11px;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
||
.session-row.active span{color:rgba(255,255,255,.66)}
|
||
.chat-main{display:grid;grid-template-rows:auto minmax(0,1fr) auto;min-width:0;max-height:100vh}
|
||
.hero{border-bottom:1px solid var(--hairline-soft);background:linear-gradient(180deg,#fff,#fafafa);padding:18px 22px;display:flex;justify-content:space-between;gap:16px;align-items:flex-start}
|
||
.hero h1{font-size:23px;font-weight:950;letter-spacing:-.7px;margin:0}
|
||
.hero p{margin-top:4px;color:var(--slate);font-size:13px;line-height:1.6}
|
||
.status-pill{display:inline-flex;align-items:center;height:30px;padding:0 10px;border:1px solid var(--hairline-soft);border-radius:999px;background:var(--surface);color:var(--stone);font-size:11px;font-weight:900;white-space:nowrap}
|
||
.messages{overflow:auto;min-height:0;padding:18px 22px 24px;display:flex;flex-direction:column;gap:14px}
|
||
.msg{display:grid;grid-template-columns:36px minmax(0,1fr);gap:10px;max-width:1120px}
|
||
.avatar{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;font-weight:950;font-size:12px;background:var(--yellow);color:#1c1c1e}
|
||
.avatar.ai{background:#1c1c1e;color:#fff}
|
||
.bubble{border:1px solid var(--hairline-soft);border-radius:var(--radius-md);background:var(--canvas);padding:14px;box-shadow:0 8px 24px rgba(5,0,56,.035);min-width:0}
|
||
.msg.user .bubble{background:#1c1c1e;color:#fff;border-color:#1c1c1e}
|
||
.bubble-text{font-size:14px;line-height:1.75;white-space:pre-wrap}
|
||
.answer-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:10px}
|
||
.answer-head b{font-size:16px;color:var(--ink);line-height:1.35}
|
||
.tag{display:inline-flex;align-items:center;border-radius:999px;padding:4px 8px;background:rgba(66,98,255,.08);color:var(--blue);font-size:11px;font-weight:950;white-space:nowrap}
|
||
.answer-text{font-size:14px;color:var(--slate);line-height:1.75;margin-bottom:12px}
|
||
.answer-body{display:grid;gap:10px;margin-bottom:12px}
|
||
.answer-block{font-size:14px;color:var(--slate);line-height:1.75;white-space:pre-wrap}
|
||
.answer-block.is-title{font-size:13px;font-weight:950;color:var(--ink);background:var(--surface);border:1px solid var(--hairline-soft);border-radius:10px;padding:8px 10px;line-height:1.5}
|
||
.progress-box{border:1px solid var(--hairline-soft);border-radius:var(--radius-md);background:var(--surface);padding:11px 12px;margin-bottom:12px}
|
||
.progress-row{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:12px;color:var(--slate);padding:5px 0}
|
||
.progress-row strong{color:var(--ink);font-size:12px}
|
||
.progress-dots{display:inline-flex;gap:4px;align-items:center}
|
||
.progress-dots i{width:6px;height:6px;border-radius:50%;background:var(--stone);animation:pulse .9s infinite ease-in-out}
|
||
.progress-dots i:nth-child(2){animation-delay:.15s}
|
||
.progress-dots i:nth-child(3){animation-delay:.3s}
|
||
.evidence-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:10px;margin-top:10px}
|
||
.panel{border:1px solid var(--hairline-soft);border-radius:var(--radius-md);background:var(--surface);padding:11px;min-width:0}
|
||
.panel h3{font-size:12px;font-weight:950;color:var(--ink);margin-bottom:8px}
|
||
.ev-list{display:grid;gap:7px}
|
||
.ev{font-size:12px;color:var(--slate);line-height:1.55;padding-left:11px;position:relative}
|
||
.ev:before{content:"";position:absolute;left:0;top:.65em;width:4px;height:4px;border-radius:50%;background:var(--blue)}
|
||
.record-list{display:flex;gap:6px;flex-wrap:wrap}
|
||
.record{border:1px solid var(--hairline);background:#fff;border-radius:999px;padding:5px 8px;font-size:11px;font-weight:850;color:var(--slate)}
|
||
.mini-section{border:1px solid var(--hairline-soft);border-radius:var(--radius-md);background:var(--surface);padding:11px;margin-top:10px}
|
||
.mini-section h3{font-size:12px;font-weight:950;color:var(--ink);margin-bottom:8px}
|
||
.brief-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin-top:10px}
|
||
.brief{border:1px solid var(--hairline-soft);border-radius:var(--radius-md);background:#fff;padding:10px;min-width:0}
|
||
.brief span{display:block;font-size:10px;color:var(--stone);font-weight:950}
|
||
.brief b{display:block;margin-top:4px;font-size:14px;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.notice-box{border:1px solid rgba(255,183,77,.42);background:rgba(255,183,77,.11);border-radius:var(--radius-md);padding:12px;color:#6d4700;font-size:13px;line-height:1.65;margin-top:10px}
|
||
.tf-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin-top:10px}
|
||
.tf{border:1px solid var(--hairline-soft);background:#fff;border-radius:var(--radius-md);padding:9px;min-width:0}
|
||
.tf span{display:block;color:var(--stone);font-size:10px;font-weight:950}
|
||
.tf b{display:block;margin-top:3px;font-size:13px;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.tf small{display:block;margin-top:3px;color:var(--stone);font-size:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.composer{border-top:1px solid var(--hairline-soft);background:var(--canvas);padding:12px 18px 14px}
|
||
.composer-inner{max-width:1120px;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:10px;align-items:end}
|
||
.input{min-height:48px;max-height:120px;resize:none;border:1px solid var(--hairline-strong);border-radius:var(--radius-md);padding:13px 14px;font-size:14px;line-height:1.55;outline:none;background:#fff;color:var(--ink);font-family:inherit}
|
||
.input:focus{border-color:var(--blue);box-shadow:0 0 0 3px rgba(66,98,255,.08)}
|
||
.send{height:48px;border:0;border-radius:var(--radius-md);background:#1c1c1e;color:#fff;padding:0 18px;font-weight:950;cursor:pointer}
|
||
.send:disabled{opacity:.45;cursor:not-allowed}
|
||
.empty{padding:40px 20px;text-align:center;color:var(--stone);font-size:13px}
|
||
.empty h2{font-size:24px;color:var(--ink);letter-spacing:-.7px;margin-bottom:8px}
|
||
.loading-dots{display:inline-flex;gap:4px}
|
||
.loading-dots i{width:6px;height:6px;border-radius:50%;background:var(--stone);animation:pulse .9s infinite ease-in-out}
|
||
.loading-dots i:nth-child(2){animation-delay:.15s}
|
||
.loading-dots i:nth-child(3){animation-delay:.3s}
|
||
@keyframes pulse{0%,80%,100%{opacity:.25;transform:translateY(0)}40%{opacity:1;transform:translateY(-3px)}}
|
||
@media(max-width:980px){.chat-shell{grid-template-columns:1fr}.session-pane{display:none}.hero{padding:14px}.messages{padding:14px}.evidence-grid{grid-template-columns:1fr}.brief-grid{grid-template-columns:1fr}.tf-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.composer{padding:10px}.chat-main{height:calc(100vh - 48px)}}
|
||
@media(max-width:520px){.composer-inner{grid-template-columns:1fr}.send{width:100%}.hero{display:block}.status-pill{margin-top:8px}.msg{grid-template-columns:30px minmax(0,1fr)}.avatar{width:30px;height:30px;border-radius:8px}.bubble{padding:12px}}
|
||
</style>
|
||
{% endblock %}
|
||
{% block content %}
|
||
<div class="chat-shell">
|
||
<aside class="session-pane">
|
||
<div class="session-head">
|
||
<div class="session-title">智能问答</div>
|
||
<button class="icon-btn" onclick="newSession()" title="新对话">+</button>
|
||
</div>
|
||
<div class="session-list" id="sessionList"><div class="empty">加载中...</div></div>
|
||
</aside>
|
||
<main class="chat-main">
|
||
<header class="hero">
|
||
<div>
|
||
<h1>Crypto 研究助手</h1>
|
||
<p>结合 AlphaX 现有数据与 Binance 多周期行情,提供 Crypto 研究参考。</p>
|
||
</div>
|
||
<span class="status-pill" id="chatStatus">研究参考</span>
|
||
</header>
|
||
<section class="messages" id="messages"></section>
|
||
<footer class="composer">
|
||
<div class="composer-inner">
|
||
<textarea class="input" id="messageInput" placeholder="问一个加密市场问题,比如:分析 SUI/USDT 现在的技术面,或者解释 DOGE 为什么等回踩。" onkeydown="handleKey(event)"></textarea>
|
||
<button class="send" id="sendBtn" onclick="sendMessage()">发送</button>
|
||
</div>
|
||
</footer>
|
||
</main>
|
||
</div>
|
||
{% endblock %}
|
||
{% block extra_script %}
|
||
<script>
|
||
var state={sessions:[],sessionId:0,messages:[],loading:false};
|
||
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return {'&':'&','<':'<','>':'>','"':'"',"'":'''}[c];});}
|
||
function fixMojibake(v){if(typeof v!=='string'||!/[ÃÂçèéåæäï¼ã]/.test(v))return v;try{var bytes=Uint8Array.from(Array.prototype.map.call(v,function(ch){return ch.charCodeAt(0)&255;}));var fixed=new TextDecoder('utf-8',{fatal:false}).decode(bytes);if(/[\u4e00-\u9fff,。;:!?()《》]/.test(fixed))return fixed;}catch(e){}return v;}
|
||
function deepFix(v){if(typeof v==='string')return fixMojibake(v);if(Array.isArray(v))return v.map(deepFix);if(v&&typeof v==='object'){Object.keys(v).forEach(function(k){v[k]=deepFix(v[k]);});}return v;}
|
||
function short(v,n){v=String(v||'');return v.length>n?v.slice(0,n)+'...':v;}
|
||
function fmtNum(v){v=Number(v||0);if(!v)return'--';if(v>=100)return v.toFixed(2);if(v>=1)return v.toFixed(3);if(v>=0.01)return v.toFixed(4);return v.toFixed(8);}
|
||
function normMessages(items){return (items||[]).map(function(m){m=deepFix(m||{});return {id:m.id,role:m.role,text:m.content_text||'',content:m.content||{},context:m.context||{},created_at:m.created_at,intent:m.intent,symbol:m.symbol};});}
|
||
function renderSessions(){if(!state.sessions.length){sessionList.innerHTML='<div class="empty">暂无对话</div>';return;}sessionList.innerHTML=state.sessions.map(function(s){var active=s.id===state.sessionId?' active':'';return '<div class="session-row'+active+'" onclick="loadSession('+s.id+')"><b>'+esc(s.title||'新对话')+'</b><span>'+esc(short(s.last_message_text||s.summary||'还没有消息',88))+'</span></div>';}).join('');}
|
||
function renderEmpty(){messages.innerHTML='<div class="empty"><h2>问 AlphaX 一个 Crypto 问题</h2><p>直接输入你的问题即可,支持单币技术面、推荐解释、舆情影响和复盘结果。</p></div>';}
|
||
function renderMessages(){if(!state.messages.length){renderEmpty();return;}messages.innerHTML=state.messages.map(renderMessage).join('');messages.scrollTop=messages.scrollHeight;}
|
||
function renderMessage(m){if(m.role==='user'){return '<div class="msg user"><div class="avatar">你</div><div class="bubble"><div class="bubble-text">'+esc(m.text)+'</div></div></div>';}return '<div class="msg"><div class="avatar ai">AI</div><div class="bubble">'+renderAnswer(m)+'</div></div>';}
|
||
function renderProgress(lines){if(!lines||!lines.length)return'';return '<div class="progress-box">'+lines.map(function(line,idx){return '<div class="progress-row"><span>'+esc(line)+'</span>'+(idx===0?'<span class="progress-dots"><i></i><i></i><i></i></span>':'')+'</div>';}).join('')+'</div>';}
|
||
function renderEvidenceList(items){if(!items||!items.length)return '<div class="ev">暂无明确证据,已降级为空态回答。</div>';return items.slice(0,8).map(function(x){if(typeof x==='string')return '<div class="ev">'+esc(x)+'</div>';if(Array.isArray(x))return '<div class="ev">'+esc(x.map(function(v){return typeof v==='string'?v:JSON.stringify(v);}).join(' · '))+'</div>';if(x&&typeof x==='object'){var label=x.label||x.name||x.title||x.reason||x.summary||x.key||'';var value=x.value||x.text||x.detail||x.note||x.signal||x.message||'';var extra=x.timeframe||x.symbol||x.period||x.source||'';var text=(label?label:'证据')+(value?(':'+value):'')+(extra?(' · '+extra):'');return '<div class="ev">'+esc(text||JSON.stringify(x))+'</div>';}return '<div class="ev">'+esc(String(x))+'</div>';}).join('');}
|
||
function renderRecords(items){if(!items||!items.length)return '<span class="record">无直接记录</span>';return items.slice(0,8).map(function(r){if(typeof r==='string')return '<span class="record">'+esc(r)+'</span>';if(r&&typeof r==='object'){var parts=[];if(r.type)parts.push(r.type);if(r.label||r.title||r.name)parts.push(r.label||r.title||r.name);if(r.symbol)parts.push(r.symbol);if(r.status)parts.push(r.status);if(r.timeframe)parts.push(r.timeframe);if(r.created_at||r.detected_at)parts.push((r.created_at||r.detected_at).slice(0,16).replace('T',' '));var text=parts.filter(Boolean).join(' · ');return '<span class="record">'+esc(text||'记录')+'</span>';}return '<span class="record">'+esc(String(r))+'</span>';}).join('');}
|
||
function renderTfGrid(ctx){var tech=(ctx&&ctx.technicals)||{},tfs=tech.timeframes||{},order=['15m','1h','4h','1d'];var has=order.some(function(tf){return tfs[tf]&&tfs[tf].available;});if(!has)return'';return '<div class="tf-grid">'+order.map(function(tf){var x=tfs[tf]||{};if(!x.available)return '<div class="tf"><span>'+tf+'</span><b>无数据</b><small>'+esc(x.reason||'Binance 未返回')+'</small></div>';var trend={uptrend:'上行',rebound:'反弹',weak:'偏弱',downtrend:'下行',sideways:'震荡'}[x.trend]||x.trend||'--';var sub='RSI '+(x.rsi14||'--')+' · 量 '+(x.volume_ratio_20||0)+'x';return '<div class="tf"><span>'+tf+'</span><b>'+esc(trend)+' · $'+fmtNum(x.price)+'</b><small>'+esc(sub)+'</small></div>';}).join('')+'</div>';}
|
||
function styleFor(m,c,ctx){return c.answer_style||({coin_analysis:'technical',recommendation_explain:'decision',market_overview:'market',sentiment:'news',review:'review',restricted:'notice',unsupported:'notice',help:'help'}[m.intent||ctx.intent]||'default');}
|
||
function splitPlainText(text){var raw=String(text||'').replace(/\r\n/g,'\n').trim();if(!raw)return[];var out=[];var current=[];var lines=raw.split('\n');function flush(){var block=current.join(' ').replace(/\s+/g,' ').trim();if(block)out.push(block);current=[];}
|
||
lines.forEach(function(line){var t=line.trim();if(!t){flush();return;}if(/^【[^】]+】/.test(t)||/^(结论|证据|风险|建议|判断|复盘|总结|要点|关注点|结论如下)[::]/.test(t)){flush();out.push(t);return;}var numbered=/^(\d+)[\.、]\s*(.+)$/.exec(t);if(numbered){flush();out.push(numbered[0]);return;}if(/^[-•]\s+/.test(t)){flush();out.push(t);return;}if(current.length&¤t[current.length-1].length+t.length>220){flush();current.push(t);flush();return;}current.push(t);});
|
||
flush();if(!out.length)out.push(raw);return out;}
|
||
function renderPlainTextAnswer(text){var blocks=splitPlainText(text);return '<div class="answer-body">'+blocks.map(function(block){if(/^【[^】]+】/.test(block)||/^(结论|证据|风险|建议|判断|复盘|总结|要点|关注点|结论如下)[::]/.test(block)){return '<div class="answer-block is-title">'+esc(block)+'</div>';}return '<div class="answer-block">'+esc(block)+'</div>';}).join('')+'</div>';}
|
||
function renderEvidenceSection(title,items,empty){return '<div class="mini-section"><h3>'+esc(title)+'</h3><div class="ev-list">'+(items&&items.length?renderEvidenceList(items):'<div class="ev">'+esc(empty||'暂无明确数据。')+'</div>')+'</div></div>';}
|
||
function renderRecordSection(title,items){if(!items||!items.length)return'';return '<div class="mini-section"><h3>'+esc(title)+'</h3><div class="record-list">'+renderRecords(items)+'</div></div>';}
|
||
function renderMarketBrief(ctx){var src=(ctx&&ctx.technical_summary)||{},items=[];if(src.stance)items.push(['状态',src.stance]);if(src.risk_level)items.push(['风险',src.risk_level]);if(src.latest_price)items.push(['价格','$'+fmtNum(src.latest_price)]);if(!items.length)return'';return '<div class="brief-grid">'+items.map(function(x){return '<div class="brief"><span>'+esc(x[0])+'</span><b>'+esc(x[1])+'</b></div>';}).join('')+'</div>';}
|
||
function renderAnswer(m){var c=m.content||{},ctx=m.context||{},answer=String(c.answer||m.text||c.summary||'--');var evidence=Array.isArray(c.evidence)?c.evidence:[];var risks=Array.isArray(c.risk_flags)?c.risk_flags:[];var records=Array.isArray(c.related_records)?c.related_records:[];var style=styleFor(m,c,ctx);var tag=m.intent||ctx.intent||style||'回答';var headOnly='<div class="answer-head"><b>'+esc(c.summary||'研究结论')+'</b><span class="tag">'+esc(tag)+'</span></div>';var head=headOnly+renderPlainTextAnswer(answer);if(style==='notice'||style==='help'||m.intent==='error')return headOnly+renderPlainTextAnswer(answer)+'<div class="notice-box">'+esc(answer)+'</div>';if(style==='technical')return head+renderTfGrid(ctx)+renderEvidenceSection('关键判断',evidence,'暂无明确技术证据。')+(risks.length?renderEvidenceSection('风险提示',risks,''):'')+renderRecordSection('相关记录',records);if(style==='market')return head+renderMarketBrief(ctx)+renderEvidenceSection('市场要点',evidence,'暂无市场要点。');if(style==='decision')return head+renderEvidenceSection('决策依据',evidence,'暂无推荐依据。')+(risks.length?renderEvidenceSection('不成立条件',risks,''):'')+renderRecordSection('推荐记录',records);if(style==='news')return head+renderEvidenceSection('事件解读',evidence,'暂无舆情事件。')+renderRecordSection('新闻记录',records);if(style==='review')return head+renderEvidenceSection('复盘发现',evidence,'暂无复盘样本。')+(risks.length?renderEvidenceSection('需要警惕',risks,''):'')+renderRecordSection('复盘记录',records);return head+renderEvidenceSection('要点',evidence,'暂无明确证据。')+renderRecordSection('相关记录',records);}
|
||
async function init(){try{var d=await (await fetch('/api/chat/bootstrap')).json();state.sessions=(d.sessions&&d.sessions.items)||[];renderSessions();if(state.sessions[0])loadSession(state.sessions[0].id);else renderEmpty();}catch(e){messages.innerHTML='<div class="empty">聊天助手加载失败</div>';}}
|
||
async function refreshSessions(){var d=await (await fetch('/api/chat/sessions?limit=20')).json();state.sessions=d.items||[];renderSessions();}
|
||
async function newSession(){state.sessionId=0;state.messages=[];renderSessions();renderEmpty();messageInput.focus();}
|
||
async function loadSession(id){state.sessionId=id;renderSessions();messages.innerHTML='<div class="empty">加载对话...</div>';try{var d=await (await fetch('/api/chat/sessions/'+id)).json();state.messages=normMessages((d.messages&&d.messages.items)||[]);renderMessages();}catch(e){messages.innerHTML='<div class="empty">读取对话失败</div>';}}
|
||
function handleKey(e){if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();sendMessage();}}
|
||
function appendLoading(){state.messages.push({role:'assistant',text:'',content:{summary:'正在读取数据',answer:'',evidence:[]},context:{},created_at:new Date().toISOString(),intent:'loading'});renderMessages();}
|
||
function removeLoading(){state.messages=state.messages.filter(function(m){return m.intent!=='loading';});}
|
||
async function sendMessage(){var text=messageInput.value.trim();if(!text||state.loading)return;state.loading=true;sendBtn.disabled=true;chatStatus.textContent='分析中';state.messages.push({role:'user',text:text,content:{text:text},created_at:new Date().toISOString()});messageInput.value='';appendLoading();try{var d=deepFix(await (await fetch('/api/chat/send',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({session_id:state.sessionId||0,message:text})})).json());removeLoading();state.sessionId=(d.session&&d.session.id)||state.sessionId;state.messages.push(d.assistant_message);renderMessages();await refreshSessions();}catch(e){removeLoading();state.messages.push({role:'assistant',content:{summary:'回答失败',answer:'这次请求没有完成,请稍后重试。',evidence:[]},context:{},created_at:new Date().toISOString(),intent:'error'});renderMessages();}finally{state.loading=false;sendBtn.disabled=false;chatStatus.textContent='研究参考';}}
|
||
var _renderAnswer=renderAnswer;
|
||
renderAnswer=function(m){
|
||
if(m.intent==='loading'){
|
||
return '<div class="answer-head"><b>正在分析中</b><span class="tag">分析中</span></div>'
|
||
+ '<div class="progress-box">'
|
||
+ '<div class="progress-row"><span>读取 AlphaX 当前数据</span><span class="progress-dots"><i></i><i></i><i></i></span></div>'
|
||
+ '<div class="progress-row"><span>汇总多周期行情与结构</span></div>'
|
||
+ '<div class="progress-row"><span>结合推荐、舆情与复盘</span></div>'
|
||
+ '</div>'
|
||
+ '<div class="notice-box">稍等一下,我正在把不同数据源拼起来,随后会给你结论和依据。</div>';
|
||
}
|
||
return _renderAnswer(m);
|
||
}
|
||
init();
|
||
</script>
|
||
{% endblock %}
|