3 changed files with 486 additions and 5 deletions
@ -0,0 +1,428 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="zh-CN"> |
|||
<head> |
|||
<meta charset="UTF-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
|||
<title>二维码合集</title> |
|||
<style> |
|||
* { |
|||
margin: 0; |
|||
padding: 0; |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
body { |
|||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; |
|||
background-color: #f5f5f5; |
|||
color: #333; |
|||
-webkit-overflow-scrolling: touch; |
|||
overflow-x: hidden; |
|||
position: relative; |
|||
touch-action: manipulation; |
|||
} |
|||
|
|||
html, body { |
|||
height: 100%; |
|||
overflow: hidden; |
|||
overscroll-behavior: none; |
|||
} |
|||
|
|||
.container { |
|||
max-width: 480px; |
|||
margin: 0 auto; |
|||
background-color: white; |
|||
height: 100%; |
|||
overflow-y: auto; |
|||
-webkit-overflow-scrolling: touch; |
|||
position: relative; |
|||
padding: 20px; |
|||
} |
|||
|
|||
.header { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
padding: 16px; |
|||
background-color: #28a745; |
|||
color: white; |
|||
position: sticky; |
|||
top: 0; |
|||
z-index: 100; |
|||
margin: -20px -20px 20px; |
|||
} |
|||
|
|||
.header h1 { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
} |
|||
|
|||
.header-actions { |
|||
display: flex; |
|||
gap: 12px; |
|||
} |
|||
|
|||
.more-btn { |
|||
background: none; |
|||
border: none; |
|||
color: white; |
|||
font-size: 18px; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.filter-section { |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.filter-section h3 { |
|||
font-size: 16px; |
|||
color: #333; |
|||
margin-bottom: 10px; |
|||
} |
|||
|
|||
.filter-buttons { |
|||
display: flex; |
|||
flex-wrap: wrap; |
|||
gap: 8px; |
|||
} |
|||
|
|||
.filter-btn { |
|||
padding: 8px 12px; |
|||
border: 1px solid #ddd; |
|||
border-radius: 16px; |
|||
background-color: white; |
|||
color: #666; |
|||
font-size: 14px; |
|||
cursor: pointer; |
|||
transition: all 0.3s; |
|||
} |
|||
|
|||
.filter-btn.active { |
|||
background-color: #28a745; |
|||
color: white; |
|||
border-color: #28a745; |
|||
} |
|||
|
|||
.qr-section { |
|||
margin-bottom: 30px; |
|||
} |
|||
|
|||
.qr-section h3 { |
|||
font-size: 16px; |
|||
color: #333; |
|||
margin-bottom: 15px; |
|||
padding-bottom: 8px; |
|||
border-bottom: 1px solid #f0f0f0; |
|||
} |
|||
|
|||
.qr-grid { |
|||
display: grid; |
|||
grid-template-columns: repeat(2, 1fr); |
|||
gap: 15px; |
|||
} |
|||
|
|||
.qr-item { |
|||
background-color: #f8f9fa; |
|||
border-radius: 8px; |
|||
padding: 12px; |
|||
text-align: center; |
|||
} |
|||
|
|||
.qr-item img { |
|||
max-width: 100%; |
|||
max-height: 150px; |
|||
margin-bottom: 10px; |
|||
border-radius: 4px; |
|||
} |
|||
|
|||
.qr-info { |
|||
font-size: 12px; |
|||
color: #666; |
|||
} |
|||
|
|||
.qr-info p { |
|||
margin-bottom: 4px; |
|||
} |
|||
|
|||
.qr-info .name { |
|||
font-weight: 500; |
|||
color: #333; |
|||
} |
|||
|
|||
.empty-state { |
|||
text-align: center; |
|||
padding: 40px 20px; |
|||
color: #999; |
|||
} |
|||
|
|||
.empty-state img { |
|||
max-width: 100px; |
|||
margin-bottom: 15px; |
|||
opacity: 0.5; |
|||
} |
|||
|
|||
.action-buttons { |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 15px; |
|||
margin-top: 30px; |
|||
} |
|||
|
|||
.btn { |
|||
padding: 15px; |
|||
border: none; |
|||
border-radius: 8px; |
|||
font-size: 16px; |
|||
font-weight: 500; |
|||
cursor: pointer; |
|||
text-align: center; |
|||
transition: background-color 0.3s; |
|||
} |
|||
|
|||
.btn-primary { |
|||
background-color: #28a745; |
|||
color: white; |
|||
} |
|||
|
|||
.btn-primary:hover { |
|||
background-color: #218838; |
|||
} |
|||
|
|||
.btn-secondary { |
|||
background-color: #6c757d; |
|||
color: white; |
|||
} |
|||
|
|||
.btn-secondary:hover { |
|||
background-color: #5a6268; |
|||
} |
|||
|
|||
.footer { |
|||
text-align: center; |
|||
margin-top: 40px; |
|||
padding: 20px 0; |
|||
font-size: 14px; |
|||
color: #999; |
|||
border-top: 1px solid #f0f0f0; |
|||
} |
|||
|
|||
@media (max-width: 480px) { |
|||
.container { |
|||
max-width: 100%; |
|||
padding: 15px; |
|||
} |
|||
|
|||
.header { |
|||
margin: -15px -15px 15px; |
|||
} |
|||
|
|||
.header h1 { |
|||
font-size: 16px; |
|||
} |
|||
|
|||
.qr-grid { |
|||
grid-template-columns: 1fr; |
|||
} |
|||
|
|||
.qr-item img { |
|||
max-height: 200px; |
|||
} |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
<div class="container"> |
|||
<div class="header"> |
|||
<h1>二维码合集</h1> |
|||
<div class="header-actions"> |
|||
<button class="more-btn">•••</button> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="filter-section"> |
|||
<h3>筛选</h3> |
|||
<div class="filter-buttons"> |
|||
<button class="filter-btn active" data-filter="all">全部</button> |
|||
<button class="filter-btn" data-filter="me">我的二维码</button> |
|||
<button class="filter-btn" data-filter="others">他人二维码</button> |
|||
</div> |
|||
</div> |
|||
|
|||
<div id="qrCollection"> |
|||
<div class="empty-state"> |
|||
<img src="https://api.qrserver.com/v1/create-qr-code/?size=100x100&data=empty" alt="空状态"> |
|||
<p>暂无二维码</p> |
|||
<p style="font-size: 14px; margin-top: 5px;">请先生成邀请二维码</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="action-buttons"> |
|||
<button class="btn btn-primary" onclick="window.location.href='invite.html'">生成邀请二维码</button> |
|||
<button class="btn btn-secondary" onclick="window.location.href='certificate.html'">返回主页面</button> |
|||
</div> |
|||
|
|||
<div class="footer"> |
|||
技术支持:四川又鸟蛋贸易有限公司 |
|||
</div> |
|||
</div> |
|||
|
|||
<script> |
|||
// 加载用户信息 |
|||
function loadUserInfo() { |
|||
const userInfo = localStorage.getItem('userInfo'); |
|||
if (userInfo) { |
|||
try { |
|||
return JSON.parse(userInfo); |
|||
} catch (error) { |
|||
console.error('解析用户信息失败:', error); |
|||
return null; |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
// 加载二维码合集 |
|||
async function loadQrCollection() { |
|||
const user = loadUserInfo(); |
|||
const qrCollectionElement = document.getElementById('qrCollection'); |
|||
|
|||
try { |
|||
// 从服务器获取二维码合集 |
|||
const response = await fetch('/getQrCollection'); |
|||
const data = await response.json(); |
|||
|
|||
if (data.success && data.qrCodes && data.qrCodes.length > 0) { |
|||
// 渲染二维码合集 |
|||
renderQrCollection(data.qrCodes, user); |
|||
} else { |
|||
// 显示空状态 |
|||
qrCollectionElement.innerHTML = ` |
|||
<div class="empty-state"> |
|||
<img src="https://api.qrserver.com/v1/create-qr-code/?size=100x100&data=empty" alt="空状态"> |
|||
<p>暂无二维码</p> |
|||
<p style="font-size: 14px; margin-top: 5px;">请先生成邀请二维码</p> |
|||
</div> |
|||
`; |
|||
} |
|||
} catch (error) { |
|||
console.error('获取二维码合集失败:', error); |
|||
qrCollectionElement.innerHTML = ` |
|||
<div class="empty-state"> |
|||
<img src="https://api.qrserver.com/v1/create-qr-code/?size=100x100&data=error" alt="错误状态"> |
|||
<p>加载失败</p> |
|||
<p style="font-size: 14px; margin-top: 5px;">请稍后重试</p> |
|||
</div> |
|||
`; |
|||
} |
|||
} |
|||
|
|||
// 渲染二维码合集 |
|||
function renderQrCollection(qrCodes, currentUser) { |
|||
const qrCollectionElement = document.getElementById('qrCollection'); |
|||
|
|||
// 按邀请者分组 |
|||
const groupedQrCodes = {}; |
|||
qrCodes.forEach(qrCode => { |
|||
const inviterName = qrCode.inviter || '未知邀请者'; |
|||
if (!groupedQrCodes[inviterName]) { |
|||
groupedQrCodes[inviterName] = []; |
|||
} |
|||
groupedQrCodes[inviterName].push(qrCode); |
|||
}); |
|||
|
|||
// 生成HTML |
|||
let html = ''; |
|||
Object.keys(groupedQrCodes).forEach(inviterName => { |
|||
const inviterQrCodes = groupedQrCodes[inviterName]; |
|||
|
|||
html += ` |
|||
<div class="qr-section"> |
|||
<h3>${inviterName}</h3> |
|||
<div class="qr-grid"> |
|||
`; |
|||
|
|||
inviterQrCodes.forEach(qrCode => { |
|||
// 生成二维码 |
|||
const qrCodeUrl = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(qrCode.url)}`; |
|||
|
|||
html += ` |
|||
<div class="qr-item"> |
|||
<img src="${qrCodeUrl}" alt="邀请二维码"> |
|||
<div class="qr-info"> |
|||
<p class="name">${qrCode.inviter || '未知'}</p> |
|||
<p>${qrCode.inviterProjectName || '无职位'}</p> |
|||
<p>${qrCode.createdAt || ''}</p> |
|||
</div> |
|||
</div> |
|||
`; |
|||
}); |
|||
|
|||
html += ` |
|||
</div> |
|||
</div> |
|||
`; |
|||
}); |
|||
|
|||
qrCollectionElement.innerHTML = html; |
|||
} |
|||
|
|||
// 筛选二维码 |
|||
function filterQrCodes(filter) { |
|||
const user = loadUserInfo(); |
|||
const qrCollectionElement = document.getElementById('qrCollection'); |
|||
|
|||
// 更新筛选按钮状态 |
|||
document.querySelectorAll('.filter-btn').forEach(btn => { |
|||
btn.classList.remove('active'); |
|||
if (btn.dataset.filter === filter) { |
|||
btn.classList.add('active'); |
|||
} |
|||
}); |
|||
|
|||
// 重新加载并筛选二维码 |
|||
fetch('/getQrCollection') |
|||
.then(response => response.json()) |
|||
.then(data => { |
|||
if (data.success && data.qrCodes && data.qrCodes.length > 0) { |
|||
let filteredQrCodes = data.qrCodes; |
|||
|
|||
if (filter === 'me' && user) { |
|||
filteredQrCodes = data.qrCodes.filter(qrCode => |
|||
qrCode.inviter === (user.name || user.userName) |
|||
); |
|||
} else if (filter === 'others' && user) { |
|||
filteredQrCodes = data.qrCodes.filter(qrCode => |
|||
qrCode.inviter !== (user.name || user.userName) |
|||
); |
|||
} |
|||
|
|||
if (filteredQrCodes.length > 0) { |
|||
renderQrCollection(filteredQrCodes, user); |
|||
} else { |
|||
qrCollectionElement.innerHTML = ` |
|||
<div class="empty-state"> |
|||
<img src="https://api.qrserver.com/v1/create-qr-code/?size=100x100&data=empty" alt="空状态"> |
|||
<p>暂无二维码</p> |
|||
</div> |
|||
`; |
|||
} |
|||
} |
|||
}) |
|||
.catch(error => { |
|||
console.error('筛选二维码失败:', error); |
|||
}); |
|||
} |
|||
|
|||
// 页面加载时加载二维码合集 |
|||
window.onload = function() { |
|||
loadQrCollection(); |
|||
|
|||
// 绑定筛选按钮事件 |
|||
document.querySelectorAll('.filter-btn').forEach(btn => { |
|||
btn.addEventListener('click', function() { |
|||
filterQrCodes(this.dataset.filter); |
|||
}); |
|||
}); |
|||
}; |
|||
</script> |
|||
</body> |
|||
</html> |
|||
Loading…
Reference in new issue