';
foreach ($rows as $r) {
$kind = (string)$r['kind'];
$key = (string)$r['oss_key'];
$mime = isset($r['mime']) ? (string)$r['mime'] : '';
$full = fb_attach_url($key);
$name = fb_attach_label($r);
$sizeH = fb_size_h($r['size']);
if ($kind === 'video') {
$html .= '
'
. ''
. '' . e($name) . ''
. '' . e($sizeH) . ''
. ''
. ''
. '';
} else {
// 缩略图(列表/正文)与灯箱显示图分开取尺寸,避免灯箱里加载原图
$thumb = fb_attach_thumb_url($key, $compact ? 360 : 640, $mime);
$view = fb_attach_thumb_url($key, 1600, $mime);
$html .= '
'
. ''
. '
'
. '';
}
}
return $html . '
';
}
/** 附件展示名(回退为「图片/视频 + 序号」) */
function fb_attach_label(array $r) {
$n = isset($r['orig_name']) ? trim((string)$r['orig_name']) : '';
if ($n !== '') { return fb_excerpt($n, 40); }
return ((string)$r['kind'] === 'video') ? '视频' : '图片';
}
/** 人类可读大小 */
function fb_size_h($bytes) {
$b = (int)$bytes;
if ($b < 1024) { return $b . ' B'; }
if ($b < 1048576) { return round($b / 1024, 1) . ' KB'; }
return round($b / 1048576, 1) . ' MB';
}
/** 统计某主题附件数(列表页标记用) */
function fb_attach_count_map(PDO $pdo, array $threadIds) {
$ids = [];
foreach ($threadIds as $i) { $i = (int)$i; if ($i > 0) { $ids[] = $i; } }
if (!$ids) { return []; }
$in = implode(',', array_fill(0, count($ids), '?'));
$st = $pdo->prepare("SELECT thread_id, COUNT(*) c FROM attachments WHERE thread_id IN ($in) GROUP BY thread_id");
$st->execute($ids);
$out = [];
foreach ($st->fetchAll() as $r) { $out[(int)$r['thread_id']] = (int)$r['c']; }
return $out;
}
/**
* 清理过期附件:先删 OSS 对象,成功后再删库记录(失败则留待下次重试)。
* @return int 已清理条数
*/
function fb_attach_cleanup(PDO $pdo, $days = null, $limit = 200) {
$days = $days === null ? (int)fb_upload_cfg('retention_days', 365) : (int)$days;
if ($days <= 0) { return 0; }
$cut = time() - $days * 86400;
$st = $pdo->prepare('SELECT id, oss_key FROM attachments WHERE created_at < ? ORDER BY created_at ASC LIMIT ' . (int)$limit);
$st->execute([$cut]);
$rows = $st->fetchAll();
$del = $pdo->prepare('DELETE FROM attachments WHERE id = ?');
$n = 0;
foreach ($rows as $r) {
if (fb_attach_delete($r['oss_key'])) {
$del->execute([(int)$r['id']]);
$n++;
}
}
return $n;
}