You've already forked think-plugs-recorder
180 lines
8.2 KiB
HTML
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> |