<!DOCTYPE html>
<html lang="zh‑CN">
<head>
<meta charset="UTF‑8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🦆鹅鸭杀记录本</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,sans-serif}
body{
color:#4a3f2f;
padding:16px;
max-width:100%;
background:
radial-gradient(circle at 20% 20%, rgba(255,255,255,0.85) 0 8%, transparent 9%),
radial-gradient(circle at 80% 10%, rgba(255,255,255,0.75) 0 6%, transparent 7%),
linear-gradient(135deg,#fff7e8,#ffe4c4,#ffdab9);
background-attachment:fixed;
min-height:100vh;
}
body::before{
content:"";
position:fixed;
inset:0;
background-image:url("https://picsum.photos/id/237/1920/1080");
background-size:cover;
background-position:center;
opacity:0.18;
z-index:-1;
}
h2{margin-bottom:10px;color:#6b4226;font-size:22px}
button{cursor:pointer;padding:8px 10px;border:none;border-radius:8px;font-size:15px}
.btn-clear-all{background:#dc3545;color:#fff;margin-bottom:8px;width:100%}
.btn-new-round{background:#208050;color:#fff;margin-bottom:12px;width:100%}
.btn-fold{background:#304058;color:#fff;margin-bottom:12px;width:100%}
.btn-copy-log{background:#4466bb;color:#fff;margin-bottom:8px;width:100%}
.top-status-wrap{margin-bottom:14px;}
.top-title{font-size:18px;font-weight:bold;margin:8px 0 6px;color:#5a3820}
.drag-container{
display:grid;
grid-template-columns:repeat(auto-fill,minmax(130px,1fr));
grid-auto-rows:48px;
gap:8px;
min-height:80px;
padding:10px;
border-radius:10px;
background:rgba(255,255,255,0.65);
border:1px solid rgba(180,140,100,0.35);
margin-bottom:12px;
}
.drag-item{
padding:6px 8px;
border-radius:6px;
display:flex;
align-items:center;
font-size:14px;
cursor:move;
border:1px solid rgba(130,90,60,0.25);
user-select:none;
background:rgba(255,255,255,0.8);
position:relative;
transition:transform 0.15s;
}
.drag-item:hover{
transform:scale(1.03);
}
.drag-item.sus-low{border-color:#e6bc20;}
.drag-item.sus-high{border-color:#d63030;}
.drag-item .mark-tag{
position:absolute;
top:2px;
right:4px;
font-size:10px;
pointer-events:none;
}
.drag-item .love-tag{color:#ff88aa;}
.drag-item .note-tag{color:#ffdd77;}
.drag-item.camp-duck{background:rgba(180,60,60,0.85);color:#fff;border-color:#913c3c;}
.drag-item.camp-neutral{background:rgba(160,90,180,0.85);color:#fff;border-color:#7c4ea8;}
.drag-item.dead-item{opacity:0.75;}
.stat-bar{
background:rgba(255,255,255,0.65);
border:1px solid rgba(180,140,100,0.35);
padding:12px;
border-radius:10px;
margin-bottom:8px;
font-size:15px;
line-height:1.7;
color:#4a3f2f;
}
.config-area{
background:rgba(255,255,255,0.65);
border:1px solid rgba(180,140,100,0.35);
padding:10px 12px;
border-radius:8px;
margin-bottom:12px;
font-size:13px;
color:#5a3820;
}
.blacklist-area{
background:rgba(255,255,255,0.65);
border:1px solid rgba(180,140,100,0.35);
padding:10px 12px;
border-radius:8px;
margin-bottom:12px;
font-size:13px;
color:#5a3820;
}
.death-log-area{
background:rgba(255,255,255,0.65);
border:1px solid rgba(180,140,100,0.35);
padding:10px 12px;
border-radius:8px;
margin-bottom:12px;
font-size:13px;
color:#5a3820;
}
.paste-area{padding:12px;border:1px dashed rgba(150,110,70,0.45);border-radius:10px;margin-bottom:12px;background:rgba(255,255,255,0.6);}
textarea{width:100%;background:#fff;color:#4a3f2f;border:1px solid rgba(130,90,60,0.25);border-radius:8px;padding:8px;font-size:15px}
.input-bar{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:12px}
input,select{padding:8px;background:#fff;color:#4a3f2f;border:1px solid rgba(130,90,60,0.25);border-radius:8px;font-size:15px;flex:1;min-width:90px}
.col-wrap{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-bottom:12px;transition:all 0.3s;}
.col-wrap.hidden{display:none;}
@media (max-width:640px){
.col-wrap{grid-template-columns:1fr;}
}
.col-goose{border:1px solid #287038;border-radius:10px;padding:10px;background:rgba(27,44,32,0.08);}
.col-duck{border:1px solid #882b2b;border-radius:10px;padding:10px;background:rgba(44,27,27,0.08);}
.col-neutral{border:1px solid #603480;border-radius:10px;padding:10px;background:rgba(36,27,48,0.08);}
.col-title{font-weight:bold;margin-bottom:8px;font-size:16px}
.title-goose{color:#287038;}
.title-duck{color:#882b2b;}
.title-neutral{color:#603480;}
.box-scroll{
max-height:320px;
overflow-y:auto;
-webkit-overflow-scrolling:touch;
overflow-x:hidden;
}
.player-item{padding:10px;border-radius:8px;margin:8px 0;border:1px solid rgba(130,90,60,0.25);background:rgba(255,255,255,0.7);}
.player-item.dead{opacity:0.45;text-decoration:line-through;}
.row-edit{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}
.btn-del{background:#444;color:#ddd}
.btn-save{background:#238636;color:#fff}
.btn-kill{background:#992c2c;color:#fff}
.btn-alive{background:#236386;color:#fff}
.ai-panel{margin-top:12px;padding:12px;background:rgba(255,255,255,0.65);border-radius:10px;border:1px solid rgba(180,140,100,0.35);color:#4a3f2f;}
.ai-panel h3{color:#6b4226;margin-bottom:8px;font-size:17px}
#aiResult{
margin-top:6px;
line-height:1.7;
color:#4a3f2f;
font-size:14px;
white-space:pre-wrap;
word-wrap:break-word;
overflow-wrap:break-word;
max-height:320px;
overflow-y:auto;
overflow-x:hidden;
}
.modal-mask{
position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.7);display:none;align-items:center;justify-content:center;z-index:999;
}
.modal-box{
background:#fff;padding:16px;border-radius:10px;max-width:320px;width:90%;color:#4a3f2f;
}
#deathLogList{max-height:140px;overflow-y:auto;margin:6px 0;}
.tip-copy{font-size:12px;color:#6b4226;margin:6px 0;}
</style>
</head>
<body>
<h2>🦆鹅鸭杀 玩家记录本</h2>
<button class="btn-clear-all" onclick="clearAll()">🔄全部清空(全部归零)</button>
<button class="btn-new-round" onclick="newRound()">🆕开启新对局(保留配置)</button>
<button class="btn-fold" onclick="toggleFold()">📦折叠/展开下方阵营列表</button>
<button class="btn-copy-log" onclick="copyReplayLog()">📋一键复制复盘文本</button>
<div class="tip-copy">复制成功后直接粘贴微信群复盘;手机浏览器权限不足会复制失败</div>
<div class="config-area">
<div>⚙本局人数配置</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:6px;">
<label>鸭子数量:<input type="number" id="cfgDuck" value="3" min="0" max="12" style="width:60px"/></label>
<label>中立数量:<input type="number" id="cfgNeu" value="2" min="0" max="12" style="width:60px"/></label>
</div>
</div>
<div class="blacklist-area">
<div>🚫本局不存在角色(勾选+自定义)</div>
<div style="display:flex;flex-wrap:wrap;gap:8px;margin:4px 0 6px;">
<label><input type="checkbox" value="猎鹰" onchange="render()">猎鹰</label>
<label><input type="checkbox" value="老鹰" onchange="render()">老鹰</label>
<label><input type="checkbox" value="鹈鹕" onchange="render()">鹈鹕</label>
<label><input type="checkbox" value="秃鹫" onchange="render()">秃鹫</label>
<label><input type="checkbox" value="鸽子" onchange="render()">鸽子</label>
</div>
<input id="banCustom" placeholder="自定义禁用角色,逗号隔开" style="width:100%" onchange="render()"/>
</div>
<div class="death-log-area">
<div>☠尸体记录</div>
<div style="display:flex;gap:6px;flex-wrap:wrap;margin:4px 0;">
<select id="logDeadMan">
<option value="">选择死者</option>
<option value="未知">未知</option>
</select>
<select id="logFinder">
<option value="">选择发现人</option>
<option value="未知">未知</option>
</select>
<input id="logRound" placeholder="回合,例:第2轮">
<button onclick="addDeathLog()">添加记录</button>
</div>
<div id="deathLogList"></div>
</div>
<div class="top-status-wrap">
<div class="top-title">🟢 现存人员(拖拽到死亡框直接置死亡)</div>
<div id="aliveBox" class="drag-container"></div>
<div class="top-title">💀 已死亡人员(拖拽回存活框直接复活)</div>
<div id="deadBox" class="drag-container"></div>
</div>
<div class="stat-bar" id="statBar">
总:0人|🟢存活:0 💀死亡:0|🦢好鹅:0 🦆坏鸭:0 🎭中立:0 ❓未标记:0
</div>
<div class="paste-area">
<div>📷iPhone操作:相册打开截图 → 长按图片拷贝文字,粘贴到下方框,批量导入玩家(默认无阵营、存活)</div>
<textarea id="pasteText" rows="4" placeholder="粘贴识别出来的全部玩家名字,一行一个"></textarea>
<button style="margin-top:8px;width:100%" onclick="batchAdd()">粘贴文本批量添加玩家</button>
</div>
<div class="input-bar">
<input id="nameInput" placeholder="玩家名字">
<select id="campSelect" onchange="onMainCampChange()">
<option value="">阵营标记</option>
<option value="鹅">好鹅阵营</option>
<option value="鸭子">坏鸭阵营</option>
<option value="中立">中立阵营</option>
</select>
<select id="roleSelect">
<option value="">怀疑身份</option>
</select>
<select id="aliveSelect">
<option value="alive">活着</option>
<option value="dead">死亡</option>
</select>
<button onclick="addPlayer()">添加</button>
</div>
<div class="col-wrap" id="colWrap">
<div class="col-goose">
<div class="col-title title-goose">🦢 好鹅阵营 / 未标记</div>
<div id="boxGoose" class="box-scroll"></div>
</div>
<div class="col-duck">
<div class="col-title title-duck">🦆 坏鸭阵营</div>
<div id="boxDuck" class="box-scroll"></div>
</div>
<div class="col-neutral">
<div class="col-title title-neutral">🎭 中立阵营</div>
<div id="boxNeutral" class="box-scroll"></div>
</div>
</div>
<div class="ai-panel">
<h3>📊简易AI分析</h3>
<button onclick="runAiAnalyse()">执行分析</button>
<div id="aiResult">点击执行分析,生成场上推理参考</div>
</div>
<div class="modal-mask" id="noteModal" onclick="closeNoteModal()">
<div class="modal-box" onclick="event.stopPropagation()">
<div id="modalName" style="font-weight:bold;margin-bottom:6px;"></div>
<div id="modalNote"></div>
<button onclick="closeNoteModal()" style="width:100%;margin-top:10px;">关闭</button>
</div>
</div>
<script>
const roleLib = {
"鹅":["侦探","加拿大鹅","士兵","复仇者","探测员","星届行者","模仿者","正义使者","清醒梦者","生存主义者","科学家","网红","肉汁","观鸟者","警长","说客","跟踪者","通灵者","预言家","验尸官","追踪者","冒险家","政治家","恋人","流浪儿童","锁匠"],
"鸭子":["专业杀手","丧葬者","传教士","刺客","剑客","寄生者","宿主","小丑","巫医","忍者","派对狂","爆炸王","走失小鸭","超能力者","身份窃贼","连环杀手","间谍","隐形者","静语者","默剧演员","变形者","狙击手","食鸟鸭","术士"],
"中立":["呆呆鸟","决斗呆呆鸟","喜鹊","布谷鸟","渡鸦","猎鹰","老鹰","鸽子","鹈鹕","秃鹫"]
};
let list = [];
let dragSrcEl = null;
let foldState = false;
let deathLogs = [];
function refreshDeathSelectOptions(){
const selDead = document.getElementById("logDeadMan");
const selFinder = document.getElementById("logFinder");
selDead.innerHTML = `<option value="">选择死者</option><option value="未知">未知</option>`;
selFinder.innerHTML = `<option value="">选择发现人</option><option value="未知">未知</option>`;
list.forEach(p=>{
selDead.innerHTML += `<option value="${p.name}">${p.name}</option>`;
selFinder.innerHTML += `<option value="${p.name}">${p.name}</option>`;
})
}
function toggleFold(){
foldState = !foldState;
const wrap = document.getElementById("colWrap");
wrap.classList.toggle("hidden",foldState);
}
function updateStat(){
const total = list.length;
const alive = list.filter(x=>x.status==='alive').length;
const dead = list.filter(x=>x.status==='dead').length;
const g = list.filter(x=>x.camp==="鹅").length;
const d = list.filter(x=>x.camp==="鸭子").length;
const n = list.filter(x=>x.camp==="中立").length;
const unknown = list.filter(x=>!x.camp).length;
document.getElementById('statBar').innerText =
`总:${total}人|🟢存活:${alive} 💀死亡:${dead}|🦢好鹅:${g} 🦆坏鸭:${d} 🎭中立:${n} ❓未标记:0`;
}
function renderDeathLog(){
const box = document.getElementById("deathLogList");
if(deathLogs.length===0){box.innerHTML="<div style='color:#888'>暂无尸体记录</div>";return;}
box.innerHTML = deathLogs.map((item,idx)=>{
return `<div>${item.round}|死者:${item.deadMan}|发现:${item.finder} <button style="font-size:11px;padding:2px 4px" onclick="delDeathLog(${idx})">删除</button></div>`
}).join("");
}
function addDeathLog(){
const dMan = document.getElementById("logDeadMan").value.trim();
const finder = document.getElementById("logFinder").value.trim();
const round = document.getElementById("logRound").value.trim();
if(!dMan)return;
deathLogs.push({deadMan:dMan,finder:finder||"未知",round:round||"未知回合"});
document.getElementById("logRound").value="";
renderDeathLog();
}
function delDeathLog(idx){
deathLogs.splice(idx,1);
renderDeathLog();
}
let modalOpenForIndex = null;
function openNoteModal(idx){
modalOpenForIndex = idx;
const p = list[idx];
document.getElementById("modalName").innerText = p.name;
document.getElementById("modalNote").innerText = p.note ? "备注:"+p.note : "暂无备注";
document.getElementById("noteModal").style.display="flex";
}
function closeNoteModal(){
document.getElementById("noteModal").style.display="none";
modalOpenForIndex=null;
}
function renderTopPanel(){
const aliveBox = document.getElementById('aliveBox');
const deadBox = document.getElementById('deadBox');
aliveBox.innerHTML = '';
deadBox.innerHTML = '';
list.forEach((p,i)=>{
const div = document.createElement('div');
div.className = 'drag-item';
div.draggable = true;
div.dataset.index = i;
div.innerText = p.name + (p.role?"【"+p.role+"】":"");
if(p.suspect === "low") div.classList.add("sus-low");
if(p.suspect === "high") div.classList.add("sus-high");
if(p.note){
const noteSpan = document.createElement("span");
noteSpan.className = "mark-tag note-tag";
noteSpan.innerText = "📝";
div.appendChild(noteSpan);
}
if(p.isLover){
const loveSpan = document.createElement("span");
loveSpan.className = "mark-tag love-tag";
loveSpan.innerText = "❤️";
div.appendChild(loveSpan);
}
if(p.camp === "鸭子") div.classList.add("camp-duck");
if(p.camp === "中立") div.classList.add("camp-neutral");
if(p.status === 'dead'){
div.classList.add('dead-item');
deadBox.appendChild(div);
}else{
aliveBox.appendChild(div);
}
div.addEventListener('dragstart',handleDragStart);
})
aliveBox.addEventListener("dragover",e=>e.preventDefault());
aliveBox.addEventListener("drop",function(e){
e.preventDefault();
if(!dragSrcEl) return;
const idx = Number(dragSrcEl.dataset.index);
if(list[idx].status !== "alive"){
list[idx].status = "alive";
render();
}
dragSrcEl=null;
})
deadBox.addEventListener("dragover",e=>e.preventDefault());
deadBox.addEventListener("drop",function(e){
e.preventDefault();
if(!dragSrcEl) return;
const idx = Number(dragSrcEl.dataset.index);
if(list[idx].status !== "dead"){
list[idx].status = "dead";
render();
}
dragSrcEl=null;
})
}
function handleDragStart(e){
dragSrcEl = this;
e.dataTransfer.effectAllowed = 'move';
}
function fillRoleSelect(selDom,campVal,selectedVal){
selDom.innerHTML = `<option value="">怀疑身份</option>`;
if(!campVal) return;
const arr = roleLib[campVal]||[];
arr.forEach(r=>{
selDom.innerHTML += `<option value="${r}" ${r===selectedVal?'selected':''}>${r}</option>`;
})
}
function onMainCampChange(){
const c = document.getElementById('campSelect').value;
fillRoleSelect(document.getElementById('roleSelect'),c,"");
}
function quickKill(idx){
list[idx].status = "dead";
render();
}
function quickAlive(idx){
list[idx].status = "alive";
render();
}
function render(){
renderTopPanel();
renderDeathLog();
refreshDeathSelectOptions();
let htmlGoose='',htmlDuck='',htmlNeutral='';
list.forEach((p,i)=>{
const deadClass = p.status === 'dead' ? 'dead' : '';
let itemHtml = '<div class="player-item '+deadClass+'">';
itemHtml += '<div>名字:'+p.name+'|身份:'+(p.role||"未知")+'|状态:'+(p.status==='dead'?'💀死亡':'🟢活着')+'</div>';
itemHtml += `<div>备注:<input value="${p.note||''}" id="editNote${i}" placeholder="简短备注"></div>`;
itemHtml += `<div><label><input type="checkbox" id="excludeDuck${i}" ${p.excludeDuck?'checked':''}>排除鸭子嫌疑</label></div>`;
itemHtml += `<div><label><input type="checkbox" id="isLover${i}" ${p.isLover?'checked':''}>标记为恋人</label></div>`;
itemHtml += `<div>怀疑等级:
<select id="susSel${i}">
<option value="none" ${p.suspect==="none"||!p.suspect?"selected":""}>无怀疑</option>
<option value="low" ${p.suspect==="low"?"selected":""}>轻度怀疑</option>
<option value="high" ${p.suspect==="high"?"selected":""}>高度怀疑</option>
</select>
</div>`;
itemHtml += '<div class="row-edit">';
itemHtml += '<input value="'+p.name+'" id="editName'+i+'" placeholder="修改名字">';
itemHtml += '<select id="editCamp'+i+'" onchange="onEditCampChange('+i+')">';
itemHtml += '<option value="">阵营标记</option>';
itemHtml += '<option value="鹅" '+(p.camp==='鹅'?'selected':'')+'>好鹅阵营</option>';
itemHtml += '<option value="鸭子" '+(p.camp==='鸭子'?'selected':'')+'>坏鸭阵营</option>';
itemHtml += '<option value="中立" '+(p.camp==='中立'?'selected':'')+'>中立阵营</option>';
itemHtml += '</select>';
itemHtml += '<select id="editRole'+i+'"><option value="">怀疑身份</option></select>';
itemHtml += '<select id="editStatus'+i+'">';
itemHtml += '<option value="alive" '+(p.status==='alive'?'selected':'')+'>活着</option>';
itemHtml += '<option value="dead" '+(p.status==='dead'?'selected':'')+'>死亡</option>';
itemHtml += '</select>';
itemHtml += '<button class="btn-kill" onclick="quickKill('+i+')">💀置死亡</button>';
itemHtml += '<button class="btn-alive" onclick="quickAlive('+i+')">💚置存活</button>';
itemHtml += '<button class="btn-save" onclick="saveEdit('+i+')">保存修改</button>';
itemHtml += '<button class="btn-del" onclick="remove('+i+')">删除</button>';
itemHtml += '</div></div>';
if(p.camp === "鸭子"){
htmlDuck += itemHtml;
}else if(p.camp === "中立"){
htmlNeutral += itemHtml;
}else{
htmlGoose += itemHtml;
}
})
document.getElementById('boxGoose').innerHTML = htmlGoose;
document.getElementById('boxDuck').innerHTML = htmlDuck;
document.getElementById('boxNeutral').innerHTML = htmlNeutral;
list.forEach((p,i)=>{
const sel = document.getElementById('editRole'+i);
if(sel) fillRoleSelect(sel,p.camp,p.role);
})
updateStat();
}
function onEditCampChange(idx){
const campVal = document.getElementById('editCamp'+idx).value;
fillRoleSelect(document.getElementById('editRole'+idx), campVal, "");
}
function addPlayer(){
const name = document.getElementById('nameInput').value.trim();
const camp = document.getElementById('campSelect').value;
const role = document.getElementById('roleSelect').value;
const status = document.getElementById('aliveSelect').value;
if(!name)return;
list.push({name,camp,role,status,note:"",excludeDuck:false,isLover:false,suspect:"none"});
document.getElementById('nameInput').value='';
document.getElementById('campSelect').value="";
document.getElementById('roleSelect').innerHTML=`<option value="">怀疑身份</option>`;
render();
}
function saveEdit(idx){
const newName = document.getElementById('editName'+idx).value.trim();
const newCamp = document.getElementById('editCamp'+idx).value;
const newRole = document.getElementById('editRole'+idx).value;
const newStatus = document.getElementById('editStatus'+idx).value;
const newNote = document.getElementById('editNote'+idx).value.trim();
const excludeDuck = document.getElementById('excludeDuck'+idx).checked;
const isLover = document.getElementById('isLover'+idx).checked;
const suspect = document.getElementById("susSel"+idx).value;
if(!newName) return;
list[idx].name = newName;
list[idx].camp = newCamp;
list[idx].role = newRole;
list[idx].status = newStatus;
list[idx].note = newNote;
list[idx].excludeDuck = excludeDuck;
list[idx].isLover = isLover;
list[idx].suspect = suspect;
render();
}
function remove(idx){
list.splice(idx,1);
render();
}
function batchAdd(){
const text = document.getElementById('pasteText').value;
const lines = text.split(/[\n\r]+/).map(s=>s.trim()).filter(s=>s.length>1&&s.length<22);
lines.forEach(name=>{
list.push({name:name,camp:"",role:"",status:"alive",note:"",excludeDuck:false,isLover:false,suspect:"none"})
})
document.getElementById('pasteText').value="";
render();
}
function newRound(){
list = [];
deathLogs = [];
render();
document.getElementById('aiResult').innerText = "点击执行分析,生成场上推理参考";
document.getElementById('pasteText').value = "";
}
function clearAll(){
list = [];
deathLogs = [];
document.getElementById("cfgDuck").value=3;
document.getElementById("cfgNeu").value=2;
document.getElementById("banCustom").value="";
document.querySelectorAll(".blacklist-area input").forEach(cb=>cb.checked=false);
render();
document.getElementById('aiResult').innerText = "点击执行分析,生成场上推理参考";
document.getElementById('pasteText').value = "";
}
function runAiAnalyse(){
if(list.length===0){
document.getElementById("aiResult").innerText = "请先录入玩家信息!";
return;
}
const theoDuck = Number(document.getElementById("cfgDuck").value)||0;
const theoNeutral = Number(document.getElementById("cfgNeu").value)||0;
let countGoose = list.filter(x=>x.camp==="鹅").length;
let countDuck = list.filter(x=>x.camp==="鸭子").length;
let countNeutral = list.filter(x=>x.camp==="中立").length;
let unKnow = list.filter(x=>!x.camp).length;
let aliveTotal = list.filter(x=>x.status==='alive').length;
let deadTotal = list.filter(x=>x.status==='dead').length;
const total = list.length;
const hideDuck = Math.max(0,theoDuck-countDuck);
const hideNeu = Math.max(0,theoNeutral-countNeutral);
const excludeList = list.filter(p=>p.excludeDuck).map(p=>p.name);
const loverList = list.filter(p=>p.isLover).map(p=>p.name);
const blkInputs = document.querySelectorAll(".blacklist-area input:checked");
const banCheckRoles = Array.from(blkInputs).map(el=>el.value);
const banCustomStr = document.getElementById("banCustom").value.trim();
let banCustomArr = banCustomStr ? banCustomStr.split(",").map(s=>s.trim()).filter(s=>s) : [];
const banRoles = [...banCheckRoles,...banCustomArr];
let output = `【鹅鸭杀复盘记录】
总录入玩家:${total}人
存活:${aliveTotal}人|已死亡:${deadTotal}人
已标记好鹅:${countGoose}|坏鸭:${countDuck}|中立:${countNeutral}
未判定阵营:${unKnow}人
【潜藏身份估算(按你填写配置)】
本局设置:坏鸭${theoDuck},中立${theoNeutral}
👉推测场上还藏坏鸭:${hideDuck}只
👉推测场上还藏中立:${hideNeu}个
${excludeList.length>0?"✅已排除鸭子嫌疑:"+excludeList.join("、"):"✅暂无排除鸭子嫌疑人员"}
${loverList.length>0?"❤️标记恋人:"+loverList.join("、")+";恋人胜负跟随绑定对象":"❤️暂无标记恋人"}
${banRoles.length>0?"🚫本局不存在角色:"+banRoles.join("、"):"🚫未勾选禁用角色"}
☠尸体记录:
${deathLogs.length>0 ? deathLogs.map(d=>`${d.round}|死者${d.deadMan}|发现人${d.finder}`).join("\n"):"无尸体记录"}
玩家明细:
${list.map(p=>`${p.status==='dead'?'💀':'🟢'}${p.name}|阵营:${p.camp||"未标记"}|怀疑身份:${p.role||"无"}|怀疑等级:${p.suspect==="low"?"轻度":p.suspect==="high"?"高度":"无"}|备注:${p.note||"无"}`).join("\n")}
提示:
1.潜藏数量基于你手动填写本局配置计算;
2.恋人属于特殊双阵营角色,胜负跟随绑定对象;
3.仅统计你手动填写的数据,仅供参考。`
document.getElementById("aiResult").innerText = output;
}
async function copyReplayLog(){
runAiAnalyse();
const text = document.getElementById("aiResult").innerText;
try{
await navigator.clipboard.writeText(text);
alert("✅复盘文本已经复制!直接粘贴到聊天框");
}catch(e){
alert("⚠️浏览器复制权限失败,请手动长按AI结果框复制文字");
}
}
render();
</script>
</body>
</html>