Files
think-plugs-recorder/view/recorder/components/data_readers.html
2025-08-13 10:39:09 +08:00

180 lines
8.2 KiB
HTML

<div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 1.5; color: #262626;">
<div class="recorder-readers {$options.css_class|default=''}" style="background: #ffffff; border: 1px solid #e6e6e6; border-radius: 6px; padding: 15px;">
{if isset($readers) && !empty($readers)}
<div style="margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid #f0f0f0;">
<h5 style="margin: 0; color: #333; font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 6px;">
<i class="layui-icon layui-icon-username" style="color: #1890ff; font-size: 16px;"></i>
读取用户 ({$readers|count})
</h5>
</div>
<div style="display: flex; flex-direction: column; gap: 12px;">
{volist name="readers" id="reader"}
<div class="recorder-reader recorder-slide-in" data-user-id="{$reader.user_id}"
style="display: flex; align-items: flex-start; padding: 12px; background: #fafafa; border-radius: 6px; border-left: 3px solid #1890ff; transition: all 0.3s ease; cursor: pointer;"
onmouseover="this.style.background='#f0f9ff'; this.style.borderLeftColor='#40a9ff'; this.style.transform='translateX(2px)';"
onmouseout="this.style.background='#fafafa'; this.style.borderLeftColor='#1890ff'; this.style.transform='translateX(0)';">
<div style="width: 36px; height: 36px; background: linear-gradient(135deg, #1890ff, #40a9ff); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-right: 12px; color: #ffffff; flex-shrink: 0; box-shadow: 0 2px 4px rgba(24, 144, 255, 0.2);">
<i class="layui-icon layui-icon-username" style="font-size: 16px;"></i>
</div>
<div style="flex: 1; min-width: 0;">
<div style="font-size: 14px; font-weight: 600; color: #333; margin-bottom: 6px;">{$reader.user_nickname}</div>
<div style="display: flex; flex-wrap: wrap; gap: 12px; font-size: 12px; color: #666; margin-bottom: 4px;">
<span style="display: flex; align-items: center; color: #1890ff; font-weight: 500;">
<i class="layui-icon layui-icon-read" style="font-size: 12px; margin-right: 2px;"></i>
读取 {$reader.read_count} 次
</span>
{if $reader.first_read_at != $reader.last_read_at}
<span style="display: flex; align-items: center;">
<i class="layui-icon layui-icon-time" style="font-size: 12px; margin-right: 2px;"></i>
最后: {$reader.last_read_at_relative}
</span>
{else/}
<span style="display: flex; align-items: center;">
<i class="layui-icon layui-icon-time" style="font-size: 12px; margin-right: 2px;"></i>
{$reader.first_read_at_relative}
</span>
{/if}
</div>
<div style="color: #999; font-size: 11px; line-height: 1.4;">
<small>
首次: {$reader.first_read_at_formatted}
{if $reader.first_read_at != $reader.last_read_at}
| 最后: {$reader.last_read_at_formatted}
{/if}
</small>
</div>
</div>
</div>
{/volist}
</div>
{else}
<div style="text-align: center; padding: 50px 20px; color: #999;">
<i class="layui-icon layui-icon-face-cry" style="font-size: 48px; margin-bottom: 12px; color: #ddd; display: block;"></i>
<p style="margin: 0; font-size: 14px;">暂无用户读取过此数据</p>
</div>
{/if}
</div>
</div>
<style>
@keyframes recorderSlideIn {
from { opacity: 0; transform: translateX(-20px); }
to { opacity: 1; transform: translateX(0); }
}
.recorder-slide-in {
animation: recorderSlideIn 0.3s ease-in-out;
}
@media (max-width: 768px) {
.recorder-readers {
padding: 12px !important;
}
.recorder-reader {
padding: 10px !important;
flex-direction: column !important;
text-align: center !important;
}
.recorder-reader > div:first-child {
margin-right: 0 !important;
margin-bottom: 8px !important;
}
.recorder-reader > div:last-child > div:nth-child(2) {
flex-direction: column !important;
gap: 4px !important;
}
}
</style>
<script>
(function() {
'use strict';
// 读取用户点击处理
document.addEventListener('click', function(e) {
var reader = e.target.closest('.recorder-reader');
if (reader) {
// 移除其他选中状态
document.querySelectorAll('.recorder-reader.selected').forEach(function(el) {
el.classList.remove('selected');
el.style.background = '#fafafa';
el.style.borderLeftColor = '#1890ff';
});
// 添加选中状态
reader.classList.add('selected');
reader.style.background = '#e6f7ff';
reader.style.borderLeftColor = '#40a9ff';
// 触发自定义事件
var event = new CustomEvent('recorderReaderSelect', {
detail: {
userId: reader.dataset.userId,
element: reader
}
});
document.dispatchEvent(event);
}
});
// 为新添加的元素添加动画
function addAnimation() {
var readers = document.querySelectorAll('.recorder-reader:not(.animated)');
readers.forEach(function(reader, index) {
reader.style.animationDelay = (index * 100) + 'ms';
reader.classList.add('recorder-slide-in', 'animated');
});
}
// 初始化动画
setTimeout(addAnimation, 100);
// 响应式处理
function handleResize() {
var isMobile = window.innerWidth <= 768;
var readers = document.querySelectorAll('.recorder-reader');
readers.forEach(function(reader) {
if (isMobile) {
reader.style.padding = '10px';
reader.style.flexDirection = 'column';
reader.style.textAlign = 'center';
var avatar = reader.querySelector('div:first-child');
if (avatar) {
avatar.style.marginRight = '0';
avatar.style.marginBottom = '8px';
}
var details = reader.querySelector('div:last-child > div:nth-child(2)');
if (details) {
details.style.flexDirection = 'column';
details.style.gap = '4px';
}
} else {
reader.style.padding = '12px';
reader.style.flexDirection = 'row';
reader.style.textAlign = 'left';
var avatar = reader.querySelector('div:first-child');
if (avatar) {
avatar.style.marginRight = '12px';
avatar.style.marginBottom = '0';
}
var details = reader.querySelector('div:last-child > div:nth-child(2)');
if (details) {
details.style.flexDirection = 'row';
details.style.gap = '12px';
}
}
});
}
window.addEventListener('resize', handleResize);
handleResize();
})();
</script>