系统概述
“还活着么签到系统”是一个轻量级的单页HTML应用,专为个人安全签到设计。用户通过每日签到向紧急联系人确认自身安全状态,当连续多日未签到时,系统会模拟向紧急联系人发送短信通知。所有数据存储在浏览器本地,无需后端支持,开箱即用。
该系统特别适合需要定期确认安全的独居人士、户外工作者或特殊职业人群使用,也可作为个人健康安全管理的简单工具。
技术特点
- 纯前端实现 – 单HTML文件,无需服务器端支持
- 本地数据存储 – 使用localStorage保存所有数据
- 响应式设计 – 适配手机和PC浏览器
- 模拟短信通知 – 可扩展为真实短信服务
- 轻量简洁 – 文件体积小,加载速度快
功能特点
🏠 用户注册
- 手机号注册验证(11位数字)
- 数据本地存储,保护用户隐私
👨👩👧 紧急联系人设置
- 设置亲属或朋友为紧急联系人
- 支持填写关系说明(如:父亲、母亲、配偶等)
- 联系人不能是自己,确保安全机制有效
✅ 每日签到
- 简洁的签到按钮,一键完成签到
- 显示当天签到状态和签到时间
- 签到记录本地保存
📊 签到历史
- 查看所有历史签到记录
- 按日期排序,最新记录置顶
- 清晰的日期和时间显示
📱 安全提醒机制
- 连续3天未签到触发短信通知
- 模拟向紧急联系人发送提醒短信
- 可扩展为真实阿里云短信服务
⚙️ 系统配置
- 预留阿里云短信服务配置界面
- 支持AccessKey ID、Secret、签名和模板代码配置
- 界面显示配置状态
使用说明
首次使用
- 打开系统页面
- 将HTML文件保存在任意位置
- 用浏览器打开该文件
- 注册账号
- 输入11位手机号完成注册
- 系统会自动跳转到紧急联系人设置
- 设置紧急联系人
- 填写联系人姓名、手机号和关系
- 联系人手机号不能与注册手机号相同
- 建议填写直系亲属信息
日常使用
- 每日签到
- 每日访问系统页面
- 点击”今日签到”按钮
- 系统记录签到时间和日期
- 查看签到历史
- 在签到页面下方查看历史记录
- 了解自己的签到习惯
- 安全机制
- 如果连续3天未签到
- 系统会模拟发送短信给紧急联系人
- 提示联系人关注用户安全状态
技术实现
数据存储
// 数据存储在localStorage中
let userData = {
phone: '',
emergencyContact: {
name: '',
phone: '',
relationship: ''
},
checkInHistory: [],
lastCheckInDate: null
};
// 保存数据
localStorage.setItem('checkInData', JSON.stringify(userData));
签到逻辑
- 检查当日是否已签到
- 记录签到时间和日期
- 更新最后签到日期
- 刷新界面显示
安全提醒
- 定时检查连续未签到天数
- 连续3天未签到触发提醒
- 模拟短信发送流程
- 提供真实短信接口扩展点
部署方式
最简单部署
- 保存HTML文件到本地
- 用浏览器直接打开文件
- 开始使用
Web服务器部署
- 将HTML文件上传到任意Web服务器
- 通过URL访问页面
- 支持多设备访问(数据在各设备独立)
静态托管服务
- GitHub Pages
- Netlify
- Vercel
- 云存储静态网站托管
扩展开发
添加后端支持
对于需要数据持久化或多用户支持的场景,可扩展后端功能:
// 示例:添加API调用
async function saveToServer(data) {
const response = await fetch('https://api.example.com/checkin', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
});
return response.json();
}
// 替换localStorage调用
// localStorage.setItem('checkInData', JSON.stringify(userData));
// 改为:
// saveToServer(userData);
集成真实短信服务
- 注册阿里云短信服务
- 获取AccessKey ID和Secret
- 配置短信签名和模板
- 替换模拟发送函数为真实API调用
// 真实短信发送示例
async function sendRealSMS(contactPhone, message) {
// 调用阿里云短信API
// 实现真实短信发送逻辑
}
添加多语言支持
- 创建语言包对象
- 根据用户选择切换语言
- 更新界面文本显示
增加数据导出功能
- 添加导出按钮
- 将签到历史导出为CSV或PDF
- 支持打印功能
注意事项
隐私安全
- 本地存储:所有数据仅保存在用户浏览器中,更换设备或清除缓存会丢失数据
- 手机号处理:界面显示时会自动隐藏中间4位保护隐私
- 联系人信息:建议告知联系人被设置为紧急联系人
使用限制
- 数据持久性:本地存储不适合长期重要数据备份
- 多设备同步:不支持多设备间数据同步
- 短信功能:当前为模拟发送,需要真实功能需自行集成
浏览器兼容性
- 支持所有现代浏览器(Chrome、Firefox、Safari、Edge)
- 需要启用JavaScript
- 建议使用最新版本浏览器
定制建议
界面定制
- 修改CSS样式调整颜色和布局
- 添加品牌Logo和名称
- 调整响应式断点适应不同设备
功能增强
- 添加签到提醒(浏览器通知)
- 支持多个紧急联系人
- 添加签到备注功能
- 实现数据备份到云端
安全加强
- 添加登录密码保护
- 实现数据加密存储
- 添加操作日志记录
免责声明
本系统为个人开发项目,仅供学习和个人使用。系统提供的安全提醒功能为模拟实现,不能替代真实的安全保障措施。用户应对自身安全负责,建议结合其他安全措施使用。
对于因使用本系统造成的任何直接或间接损失,开发者不承担任何责任。
效果预览
![图片[1]-最近较火的还活着么签到系统HTML源码-QQ沐编程](https://www.qqmu.com/wp-content/uploads/2026/01/huozhem.jpg)
源代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>活着么签到系统-QQ沐编程qqmu.com</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
body {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
width: 100%;
max-width: 500px;
background: white;
border-radius: 16px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.header {
background: #4a6bdf;
color: white;
padding: 25px 20px;
text-align: center;
}
.header h1 {
font-size: 24px;
font-weight: 600;
}
.form-container {
padding: 25px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: #333;
}
.form-group input {
width: 100%;
padding: 14px;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 16px;
transition: border-color 0.3s;
}
.form-group input:focus {
border-color: #4a6bdf;
outline: none;
box-shadow: 0 0 0 2px rgba(74, 107, 223, 0.2);
}
.btn {
width: 100%;
padding: 14px;
background: #4a6bdf;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: background 0.3s;
}
.btn:hover {
background: #3a5bce;
}
.btn:disabled {
background: #b0b0b0;
cursor: not-allowed;
}
.view {
display: none;
}
.view.active {
display: block;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.user-info {
background: #f9f9f9;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
}
.user-info p {
margin-bottom: 8px;
color: #555;
}
.user-info span {
font-weight: 500;
color: #333;
}
.checkin-status {
text-align: center;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
font-weight: 500;
}
.checked-in {
background: #e8f5e9;
color: #2e7d32;
}
.not-checked-in {
background: #fff3e0;
color: #ef6c00;
}
.history {
margin-top: 25px;
}
.history h3 {
margin-bottom: 15px;
color: #333;
padding-bottom: 8px;
border-bottom: 1px solid #eee;
}
.history-list {
max-height: 200px;
overflow-y: auto;
}
.history-item {
padding: 12px 15px;
background: #f9f9f9;
border-radius: 8px;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
}
.history-date {
color: #555;
}
.history-time {
color: #888;
font-size: 14px;
}
.alert {
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
font-size: 14px;
}
.alert-warning {
background: #fff3e0;
color: #ef6c00;
border-left: 4px solid #ff9800;
}
.alert-info {
background: #e3f2fd;
color: #1565c0;
border-left: 4px solid #2196f3;
}
.sms-config {
background: #f9f9f9;
padding: 15px;
border-radius: 8px;
margin-top: 20px;
font-size: 14px;
}
.sms-config h4 {
margin-bottom: 10px;
color: #333;
}
.sms-config p {
margin-bottom: 8px;
color: #555;
}
[url=home.php?mod=space&uid=945662]@media[/url] (max-width: 600px) {
.container {
border-radius: 12px;
}
.header {
padding: 20px 15px;
}
.form-container {
padding: 20px 15px;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>活着么签到系统</h1>
</div>
<!-- 注册视图 -->
<div id="register-view" class="view active">
<div class="form-container">
<h2>手机号注册</h2>
<div class="alert alert-info">
请输入您的手机号进行注册,注册后需要设置紧急联系人才能开始签到
</div>
<div class="form-group">
<label for="phone">手机号</label>
<input type="tel" id="phone" placeholder="请输入11位手机号" pattern="[0-9]{11}" required>
</div>
<button id="register-btn" class="btn">注册</button>
</div>
</div>
<!-- 紧急联系人视图 -->
<div id="emergency-contact-view" class="view">
<div class="form-container">
<h2>设置紧急联系人</h2>
<div class="alert alert-warning">
紧急联系人不能是自己,建议填写直系亲属信息
</div>
<div class="form-group">
<label for="contact-name">联系人姓名</label>
<input type="text" id="contact-name" placeholder="请输入联系人姓名" required>
</div>
<div class="form-group">
<label for="contact-phone">联系人手机号</label>
<input type="tel" id="contact-phone" placeholder="请输入11位手机号" pattern="[0-9]{11}" required>
</div>
<div class="form-group">
<label for="relationship">与您的关系</label>
<input type="text" id="relationship" placeholder="例如:父亲、母亲、配偶等" required>
</div>
<button id="set-contact-btn" class="btn">完成设置</button>
</div>
</div>
<!-- 主视图 -->
<div id="main-view" class="view">
<div class="form-container">
<h2>每日打卡</h2>
<div class="user-info">
<p>手机号: <span id="user-phone"></span></p>
<p>紧急联系人: <span id="emergency-contact"></span> (<span id="contact-relationship"></span>)</p>
</div>
<div id="checkin-status" class="checkin-status not-checked-in">
今日尚未签到,请点击下方按钮签到
</div>
<button id="checkin-btn" class="btn">今日签到</button>
<div class="history">
<h3>签到历史</h3>
<div id="history-list" class="history-list">
<!-- 签到历史将在这里显示 -->
</div>
</div>
<div class="sms-config">
<h4>阿里云短信服务配置</h4>
<p>AccessKey ID: <span id="access-key-id">已配置</span></p>
<p>AccessKey Secret: <span id="access-key-secret">已配置</span></p>
<p>签名: <span id="sms-sign">已配置</span></p>
<p>模板代码: <span id="template-code">已配置</span></p>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// 初始化数据
let userData = {
phone: '',
emergencyContact: {
name: '',
phone: '',
relationship: ''
},
checkInHistory: [],
lastCheckInDate: null
};
// 从localStorage加载数据
function loadData() {
const savedData = localStorage.getItem('checkInData');
if (savedData) {
userData = JSON.parse(savedData);
updateUI();
}
}
// 保存数据到localStorage
function saveData() {
localStorage.setItem('checkInData', JSON.stringify(userData));
}
// 更新UI
function updateUI() {
if (userData.phone && !userData.emergencyContact.name) {
showView('emergency-contact-view');
} else if (userData.phone && userData.emergencyContact.name) {
showView('main-view');
updateMainView();
} else {
showView('register-view');
}
}
// 显示指定视图
function showView(viewId) {
document.querySelectorAll('.view').forEach(view => {
view.classList.remove('active');
});
document.getElementById(viewId).classList.add('active');
}
// 更新主视图
function updateMainView() {
document.getElementById('user-phone').textContent = userData.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
document.getElementById('emergency-contact').textContent = userData.emergencyContact.name;
document.getElementById('contact-relationship').textContent = userData.emergencyContact.relationship;
// 更新签到状态
const today = new Date().toISOString().split('T')[0];
const hasCheckedIn = userData.checkInHistory.some(record => record.date === today);
const checkinStatus = document.getElementById('checkin-status');
const checkinBtn = document.getElementById('checkin-btn');
if (hasCheckedIn) {
checkinStatus.textContent = `您今天已于 ${userData.checkInHistory.find(r => r.date === today).time} 签到成功!`;
checkinStatus.className = 'checkin-status checked-in';
checkinBtn.textContent = '今日已签到';
checkinBtn.disabled = true;
} else {
checkinStatus.textContent = '今日尚未签到,请点击下方按钮签到';
checkinStatus.className = 'checkin-status not-checked-in';
checkinBtn.textContent = '今日签到';
checkinBtn.disabled = false;
}
// 更新签到历史
const historyList = document.getElementById('history-list');
historyList.innerHTML = '';
if (userData.checkInHistory.length === 0) {
historyList.innerHTML = '<div class="history-item">暂无签到记录</div>';
} else {
// 按日期降序排列
const sortedHistory = [...userData.checkInHistory].sort((a, b) => new Date(b.date) - new Date(a.date));
sortedHistory.forEach(record => {
const item = document.createElement('div');
item.className = 'history-item';
item.innerHTML = `
<div>
<div class="history-date">${record.date}</div>
</div>
<div class="history-time">${record.time}</div>
`;
historyList.appendChild(item);
});
}
// 检查连续未签到天数
checkConsecutiveMissedDays();
}
// 检查连续未签到天数
function checkConsecutiveMissedDays() {
if (!userData.lastCheckInDate) return;
const lastCheckIn = new Date(userData.lastCheckInDate);
const today = new Date();
today.setHours(0, 0, 0, 0);
const diffTime = Math.abs(today - lastCheckIn);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
if (diffDays >= 3) {
// 模拟发送短信
sendSMSNotification(diffDays);
}
}
// 模拟发送短信通知
function sendSMSNotification(daysMissed) {
// 在实际应用中,这里会调用阿里云短信API
console.log(`正在发送短信通知紧急联系人 ${userData.emergencyContact.name} (${userData.emergencyContact.phone})`);
console.log(`短信内容: 您的亲属 ${userData.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')} 已连续 ${daysMissed} 天未签到,请及时联系确认安全。`);
alert(`模拟短信发送成功!\n\n已向紧急联系人 ${userData.emergencyContact.name} (${userData.emergencyContact.phone}) 发送通知:\n"您的亲属已连续 ${daysMissed} 天未签到,请及时联系确认安全。"`);
// 重置计数器(在实际应用中,可能需要更复杂的逻辑)
userData.lastCheckInDate = new Date().toISOString().split('T')[0];
saveData();
}
// 注册按钮点击事件
document.getElementById('register-btn').addEventListener('click', function() {
const phone = document.getElementById('phone').value;
if (!/^\d{11}$/.test(phone)) {
alert('请输入有效的11位手机号!');
return;
}
userData.phone = phone;
saveData();
updateUI();
});
// 设置紧急联系人按钮点击事件
document.getElementById('set-contact-btn').addEventListener('click', function() {
const name = document.getElementById('contact-name').value;
const phone = document.getElementById('contact-phone').value;
const relationship = document.getElementById('relationship').value;
if (!name || !/^\d{11}$/.test(phone) || !relationship) {
alert('请填写完整的紧急联系人信息!');
return;
}
if (phone === userData.phone) {
alert('紧急联系人不能是自己!');
return;
}
userData.emergencyContact = {
name,
phone,
relationship
};
saveData();
updateUI();
});
// 签到按钮点击事件
document.getElementById('checkin-btn').addEventListener('click', function() {
const today = new Date().toISOString().split('T')[0];
const now = new Date();
const time = now.toTimeString().split(' ')[0].substring(0, 5);
// 检查今天是否已经签到
const hasCheckedIn = userData.checkInHistory.some(record => record.date === today);
if (hasCheckedIn) {
alert('您今天已经签到过了!');
return;
}
// 添加签到记录
userData.checkInHistory.push({
date: today,
time: time
});
// 更新最后签到日期
userData.lastCheckInDate = today;
saveData();
updateUI();
alert('签到成功!');
});
// 初始化应用
loadData();
// 每天检查一次连续未签到情况(在实际应用中,这应该在后端完成)
setInterval(checkConsecutiveMissedDays, 24 * 60 * 60 * 1000);
});
</script>
</body>
</html>
© 版权声明
本站资源来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!
THE END












