report_image_detail.html 8.39 KB
<!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>
* { margin:0;padding:0;box-sizing:border-box; }
body { font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:#f0f2f5;color:#333;padding:20px;max-width:900px;margin:0 auto; }
nav { margin-bottom:16px; }
nav a { color:#3498db;text-decoration:none;font-size:14px; }
.card { background:white;border-radius:8px;padding:24px;box-shadow:0 1px 2px rgba(0,0,0,0.05);margin-bottom:16px; }
.card img { width:100%;border-radius:6px;border:1px solid #eee; }
.meta { margin-top:16px; }
.meta-row { display:flex;align-items:baseline;gap:8px;margin-bottom:8px;font-size:14px;flex-wrap:wrap; }
.meta-label { color:#999;white-space:nowrap;min-width:50px; }
.meta-value { color:#333;word-break:break-all; }
.meta-value.mono { font-family:monospace;font-size:13px;background:#f5f5f5;padding:2px 8px;border-radius:4px; }
.actions { display:flex;gap:8px;margin-top:16px; }
.actions button { flex:1;padding:14px;border-radius:8px;font-size:14px;cursor:pointer; }
.btn-send { border:1px solid #27ae60;background:white;color:#27ae60; }
.btn-delete { border:1px solid #e74c3c;background:white;color:#e74c3c; }
.loading { text-align:center;padding:40px;color:#999; }
.style-badge { display:inline-block;font-size:11px;padding:2px 8px;border-radius:10px;font-weight:500; }
/* send modal */
.modal-overlay { display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);z-index:999;align-items:center;justify-content:center; }
.modal-box { background:white;border-radius:12px;width:92%;max-width:400px;max-height:80%;overflow-y:auto;padding:0; }
.modal-header { padding:14px;border-bottom:1px solid #eee;display:flex;justify-content:space-between;align-items:center; }
.modal-header span { font-weight:600; }
.modal-header button { background:none;border:none;font-size:22px;cursor:pointer; }
.contact-item { padding:14px;border-bottom:1px solid #f5f5f5;cursor:pointer;display:flex;align-items:center;gap:10px; }
</style>
</head>
<body>
<nav><a href="/report-images">← 返回图片列表</a></nav>
<div id="content"><div class="loading">加载中...</div></div>

<div id="sendModal" class="modal-overlay" onclick="closeSendModal()">
  <div class="modal-box" onclick="event.stopPropagation()">
    <div class="modal-header"><span>选择发送对象</span><button onclick="closeSendModal()">×</button></div>
    <div style="padding:8px 12px;"><input type="text" id="contactSearch" placeholder="搜索..." oninput="filterContacts()" style="width:100%;padding:10px;border:1px solid #ddd;border-radius:8px;font-size:14px;margin-bottom:8px;"></div>
    <div id="contactList" style="max-height:400px;overflow-y:auto;"><div style="text-align:center;padding:20px;color:#999;">加载中...</div></div>
  </div>
</div>

<script>
var IMG_ID = {{ image_id }};
var allContacts = [];

function esc(s){return String(s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');}

var STYLE_LABELS={vintage:'复古报纸',swiss:'瑞士',magazine:'编辑杂志','visual-note':'视觉笔记',minimalism:'极简',brutalism:'粗野',memphis:'孟菲斯',bauhaus:'包豪斯',cyberpunk:'赛博朋克','futuristic-ui':'未来界面','pop-art':'波普',isometric:'等距',watercolor:'水彩',vaporwave:'蒸汽波'};
var STYLE_COLORS={vintage:'#8b7355',swiss:'#e02020',magazine:'#1a365d','visual-note':'#e67e22',minimalism:'#333',brutalism:'#0000ff',memphis:'#ff6b9d',bauhaus:'#1d3f8e',cyberpunk:'#00ff41','futuristic-ui':'#00bcd4','pop-art':'#ff5722',isometric:'#607d8b',watercolor:'#9c27b0',vaporwave:'#ff6ac2'};
function styleBadge(s){if(!s)return '';var n=STYLE_LABELS[s]||s,c=STYLE_COLORS[s]||'#999';return ' <span class="style-badge" style="background:'+c+'18;color:'+c+';border:1px solid '+c+'40;">'+n+'</span>';}

async function load(){
  var el = document.getElementById('content');
  try {
    var r = await fetch('/api/report-images');
    var j = await r.json();
    if (!j.ok || !j.data) { el.innerHTML='<div class="loading">加载失败</div>'; return; }
    var img = null;
    for (var i=0;i<j.data.length;i++){ if (j.data[i].id === IMG_ID) { img = j.data[i]; break; } }
    if (!img) { el.innerHTML='<div class="loading">图片不存在</div>'; return; }
    document.title = '🖼 ' + (img.image_path||'').split('/').pop() + ' — ' + (img.chatroom_name||'');
    var filename = (img.image_path||'').split('/').pop();
    var url = '/media/report-image/' + img.id;
    var html = '<div class="card">';
    html += '<img src="'+url+'" alt="日报图片">';
    html += '<div class="meta">';
    html += '<div class="meta-row"><span class="meta-label">文件名</span><span class="meta-value mono">📄 '+esc(filename)+'</span></div>';
    html += '<div class="meta-row"><span class="meta-label">群聊</span><span class="meta-value">'+esc(img.chatroom_name||'')+'</span></div>';
    html += '<div class="meta-row"><span class="meta-label">日期</span><span class="meta-value">'+img.report_date+'</span>'+styleBadge(img.style)+'</div>';
    html += '<div class="meta-row"><span class="meta-label">ID</span><span class="meta-value mono">#'+img.report_id+' · 图片 #'+img.id+'</span></div>';
    if (img.created_at) html += '<div class="meta-row"><span class="meta-label">生成</span><span class="meta-value">'+(img.created_at||'').slice(0,16)+'</span></div>';
    html += '<div class="meta-row"><span class="meta-label"></span><a href="/report/'+img.report_id+'" style="color:#3498db;">查看日报 #'+img.report_id+'</a></div>';
    html += '</div>';
    html += '<div class="actions">';
    html += '<button class="btn-send" onclick="showSendModal()">📤 发送微信</button>';
    html += '<button class="btn-delete" onclick="del()">🗑 删除</button>';
    html += '</div></div>';
    el.innerHTML = html;
  } catch(e) { el.innerHTML='<div class="loading">加载失败: '+esc(e.message)+'</div>'; }
}

function showSendModal(){
  document.getElementById('sendModal').style.display='flex';
  document.getElementById('contactSearch').value='';
  if (!allContacts.length) {
    fetch('/api/sessions').then(function(r){return r.json();}).then(function(j){
      allContacts = (j.data||[]).map(function(s){return {wxid:s.talker,name:s.display_name||s.talker,type:s.talker_type,preview:s.preview||''};});
      renderContacts(allContacts);
    });
  } else { renderContacts(allContacts); }
}

function renderContacts(list){
  var el = document.getElementById('contactList');
  if (!list.length) { el.innerHTML='<div style="text-align:center;padding:20px;color:#999;">无联系人</div>'; return; }
  var html='';
  for (var i=0;i<list.length;i++){
    var c=list[i],color=c.type==='group'?'#27ae60':c.type==='official'?'#e67e22':'#3498db',label=c.type==='group'?'群':c.type==='official'?'号':'人';
    html+='<div class="contact-item" data-wxid="'+esc(c.wxid)+'" data-name="'+esc(c.name)+'" onclick="sendToEl(this)">';
    html+='<div style="width:40px;height:40px;border-radius:8px;background:'+color+';color:white;display:flex;align-items:center;justify-content:center;font-size:16px;flex-shrink:0;">'+(c.name||'?')[0]+'</div>';
    html+='<div style="flex:1;min-width:0;"><div style="font-size:15px;">'+esc(c.name)+'</div><div style="font-size:12px;color:#999;">'+esc(c.preview).slice(0,30)+'</div></div>';
    html+='<span style="font-size:12px;color:#bbb;">'+label+'</span></div>';
  }
  el.innerHTML=html;
}

function filterContacts(){
  var q=document.getElementById('contactSearch').value.trim().toLowerCase();
  if (!q) { renderContacts(allContacts); return; }
  renderContacts(allContacts.filter(function(c){return c.name.toLowerCase().indexOf(q)>=0;}));
}

function closeSendModal(){ document.getElementById('sendModal').style.display='none'; }

async function sendToEl(el){
  var wxid=el.getAttribute('data-wxid'),name=el.getAttribute('data-name');
  if (!confirm('发送给 '+name+'?')) return;
  closeSendModal();
  try {
    var r=await fetch('/api/report-image/'+IMG_ID+'/send',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({to:wxid})});
    var j=await r.json();
    if (j.ok) { alert('发送任务已提交!'); } else { alert('失败: '+(j.error||'')); }
  } catch(e) { alert('错误: '+e.message); }
}

async function del(){
  if (!confirm('确认删除?')) return;
  await fetch('/api/report-image/'+IMG_ID+'/delete',{method:'POST'});
  location.href='/report-images';
}

load();
</script>
</body>
</html>