Browse Source

添加登录功能和邀请者信息传递功能

master
Default User 1 month ago
parent
commit
7b460ccbf8
  1. 13
      certificate.html
  2. 44
      invite.html
  3. 202
      login.html
  4. 150
      server.js

13
certificate.html

@ -948,6 +948,19 @@
const sessionId = getSessionId(); const sessionId = getSessionId();
urlEncodedData.append('sessionId', sessionId); urlEncodedData.append('sessionId', sessionId);
// 从URL参数中获取邀请者信息
const urlParams = new URLSearchParams(window.location.search);
const inviter = urlParams.get('inviter');
const inviterPhone = urlParams.get('inviterPhone');
// 添加邀请者信息
if (inviter) {
urlEncodedData.append('inviter', inviter);
}
if (inviterPhone) {
urlEncodedData.append('inviterPhone', inviterPhone);
}
// 发送数据到服务器 // 发送数据到服务器
fetch('/submit', { fetch('/submit', {
method: 'POST', method: 'POST',

44
invite.html

@ -154,6 +154,14 @@
</head> </head>
<body> <body>
<div class="container"> <div class="container">
<div class="user-info" style="background-color: #f8f9fa; border-radius: 8px; padding: 15px; margin-bottom: 20px;">
<h3 style="font-size: 16px; color: #333; margin-bottom: 10px;">登录信息</h3>
<div id="userInfo" style="font-size: 14px; color: #666;">
<p>姓名:<span id="userName">未登录</span></p>
<p>电话:<span id="userPhone">未登录</span></p>
</div>
</div>
<div class="header"> <div class="header">
<h1>生成邀请二维码</h1> <h1>生成邀请二维码</h1>
<p>创建一个二维码,邀请他人填写合格证信息</p> <p>创建一个二维码,邀请他人填写合格证信息</p>
@ -187,11 +195,42 @@
</div> </div>
<script> <script>
// 加载用户信息
function loadUserInfo() {
const userInfo = localStorage.getItem('userInfo');
if (userInfo) {
try {
const user = JSON.parse(userInfo);
document.getElementById('userName').textContent = user.name || user.userName;
document.getElementById('userPhone').textContent = user.phoneNumber || '未提供';
} catch (error) {
console.error('解析用户信息失败:', error);
}
}
}
// 生成邀请二维码 // 生成邀请二维码
function generateInviteQR() { function generateInviteQR() {
// 生成包含会话ID的URL // 生成包含会话ID的URL
const sessionId = 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); const sessionId = 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
const inviteUrl = `http://8.137.125.67:3008/certificate.html?sessionId=${encodeURIComponent(sessionId)}`;
// 获取用户信息
const userInfo = localStorage.getItem('userInfo');
let inviterName = '';
let inviterPhone = '';
if (userInfo) {
try {
const user = JSON.parse(userInfo);
inviterName = user.name || user.userName;
inviterPhone = user.phoneNumber || '';
} catch (error) {
console.error('解析用户信息失败:', error);
}
}
// 构建邀请URL,包含会话ID和邀请者信息
const inviteUrl = `http://8.137.125.67:3008/certificate.html?sessionId=${encodeURIComponent(sessionId)}&inviter=${encodeURIComponent(inviterName)}&inviterPhone=${encodeURIComponent(inviterPhone)}`;
// 使用Google Charts API生成二维码 // 使用Google Charts API生成二维码
const qrCodeUrl = `https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=${encodeURIComponent(inviteUrl)}`; const qrCodeUrl = `https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=${encodeURIComponent(inviteUrl)}`;
@ -203,8 +242,9 @@
alert('邀请二维码生成成功!\n\n请将此二维码分享给需要填写信息的人。\n\n对方填写完成后,您可以通过相同的二维码查看和导出信息。'); alert('邀请二维码生成成功!\n\n请将此二维码分享给需要填写信息的人。\n\n对方填写完成后,您可以通过相同的二维码查看和导出信息。');
} }
// 页面加载时自动生成二维码 // 页面加载时自动生成二维码并加载用户信息
window.onload = function() { window.onload = function() {
loadUserInfo();
generateInviteQR(); generateInviteQR();
}; };
</script> </script>

202
login.html

@ -0,0 +1,202 @@
<!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;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.container {
max-width: 400px;
width: 90%;
background-color: white;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
padding: 24px;
}
.header {
text-align: center;
margin-bottom: 24px;
}
.header h1 {
font-size: 24px;
font-weight: 600;
color: #28a745;
margin-bottom: 8px;
}
.header p {
font-size: 14px;
color: #666;
}
.form-group {
margin-bottom: 16px;
}
.form-group label {
display: block;
margin-bottom: 6px;
font-size: 14px;
font-weight: 500;
color: #333;
}
.form-group input {
width: 100%;
padding: 12px;
border: 1px solid #ced4da;
border-radius: 4px;
font-size: 14px;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
.form-group input:focus {
outline: none;
border-color: #28a745;
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
}
.btn {
width: 100%;
padding: 12px;
border: none;
border-radius: 4px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.15s ease-in-out;
}
.btn-primary {
background-color: #28a745;
color: white;
}
.btn-primary:hover {
background-color: #218838;
}
.error-message {
background-color: #f8d7da;
color: #721c24;
padding: 12px;
border-radius: 4px;
margin-bottom: 16px;
font-size: 14px;
display: none;
}
.success-message {
background-color: #d4edda;
color: #155724;
padding: 12px;
border-radius: 4px;
margin-bottom: 16px;
font-size: 14px;
display: none;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>登录</h1>
<p>请输入您的用户名和密码</p>
</div>
<div class="error-message" id="errorMessage"></div>
<div class="success-message" id="successMessage"></div>
<form id="loginForm">
<div class="form-group">
<label for="userName">用户名</label>
<input type="text" id="userName" name="userName" required>
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary">登录</button>
</form>
</div>
<script>
// 显示错误信息
function showError(message) {
const errorElement = document.getElementById('errorMessage');
const successElement = document.getElementById('successMessage');
errorElement.textContent = message;
errorElement.style.display = 'block';
successElement.style.display = 'none';
}
// 显示成功信息
function showSuccess(message) {
const errorElement = document.getElementById('errorMessage');
const successElement = document.getElementById('successMessage');
successElement.textContent = message;
successElement.style.display = 'block';
errorElement.style.display = 'none';
}
// 表单提交处理
document.getElementById('loginForm').addEventListener('submit', function(e) {
e.preventDefault();
const userName = document.getElementById('userName').value.trim();
const password = document.getElementById('password').value;
// 验证输入
if (!userName || !password) {
showError('请输入用户名和密码');
return;
}
// 发送登录请求
fetch('/login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
userName: userName,
password: password
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 登录成功,保存用户信息到本地存储
localStorage.setItem('userInfo', JSON.stringify(data.user));
// 跳转到邀请页面
window.location.href = 'invite.html';
} else {
showError(data.error || '登录失败,请重试');
}
})
.catch(error => {
console.error('登录失败:', error);
showError('网络错误,请重试');
});
});
</script>
</body>
</html>

150
server.js

@ -76,6 +76,138 @@ const server = http.createServer(async (req, res) => {
return; return;
} }
// 登录接口
if (req.method === 'POST' && req.url === '/login') {
try {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', async () => {
try {
// 解析表单数据
const formData = new URLSearchParams(body);
const userName = formData.get('userName');
const password = formData.get('password');
console.log('接收到的登录请求:', { userName });
// 验证输入
if (!userName || !password) {
res.writeHead(400, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type'
});
res.end(JSON.stringify({
success: false,
error: '请输入用户名和密码'
}));
return;
}
// 连接到userlogin数据库
const userloginPool = mysql.createPool({
...dbConfig,
database: 'userlogin'
});
// 验证用户名和密码
const [loginRows] = await userloginPool.execute(
'SELECT * FROM login WHERE userName = ? AND password = ?',
[userName, password]
);
if (loginRows.length === 0) {
res.writeHead(401, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type'
});
res.end(JSON.stringify({
success: false,
error: '用户名或密码错误'
}));
return;
}
const loginInfo = loginRows[0];
const managerId = loginInfo.managerId;
// 获取用户详细信息
const [personnelRows] = await userloginPool.execute(
'SELECT * FROM personnel WHERE managerId = ?',
[managerId]
);
let userInfo = {
userName: loginInfo.userName,
projectName: loginInfo.projectName,
managerId: loginInfo.managerId
};
if (personnelRows.length > 0) {
const personnelInfo = personnelRows[0];
userInfo = {
...userInfo,
name: personnelInfo.name,
phoneNumber: personnelInfo.phoneNumber,
managercompany: personnelInfo.managercompany,
managerdepartment: personnelInfo.managerdepartment,
organization: personnelInfo.organization,
alias: personnelInfo.alias
};
}
console.log('登录成功,用户信息:', userInfo);
// 返回成功响应
res.writeHead(200, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type'
});
res.end(JSON.stringify({
success: true,
user: userInfo
}));
// 关闭临时连接池
await userloginPool.end();
} catch (error) {
console.error('处理登录请求失败:', error.message);
res.writeHead(500, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type'
});
res.end(JSON.stringify({
success: false,
error: '登录失败,请重试'
}));
}
});
} catch (error) {
console.error('登录请求处理失败:', error.message);
res.writeHead(500, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type'
});
res.end(JSON.stringify({
success: false,
error: '登录失败,请重试'
}));
}
return;
}
// 处理GET请求,获取最新的合格证信息 // 处理GET请求,获取最新的合格证信息
if (req.method === 'GET' && req.url.startsWith('/getLatestCertificate')) { if (req.method === 'GET' && req.url.startsWith('/getLatestCertificate')) {
try { try {
@ -88,10 +220,10 @@ const server = http.createServer(async (req, res) => {
// 从数据库获取对应会话的最新合格证信息 // 从数据库获取对应会话的最新合格证信息
let query, params; let query, params;
if (sessionId) { if (sessionId) {
query = 'SELECT company as subjectName, phoneNumber as contact, productName, grossWeight as weight, commitBasis as basis, origin, DATE_FORMAT(issueDate, "%Y-%m-%d") as date, signature, qrCodeUrl FROM certificate WHERE sessionId = ? ORDER BY id DESC LIMIT 1'; query = 'SELECT company as subjectName, phoneNumber as contact, productName, grossWeight as weight, commitBasis as basis, origin, DATE_FORMAT(issueDate, "%Y-%m-%d") as date, signature, qrCodeUrl, inviter, inviter_phone as inviterPhone FROM certificate WHERE sessionId = ? ORDER BY id DESC LIMIT 1';
params = [sessionId]; params = [sessionId];
} else { } else {
query = 'SELECT company as subjectName, phoneNumber as contact, productName, grossWeight as weight, commitBasis as basis, origin, DATE_FORMAT(issueDate, "%Y-%m-%d") as date, signature, qrCodeUrl FROM certificate WHERE sessionId IS NULL ORDER BY id DESC LIMIT 1'; query = 'SELECT company as subjectName, phoneNumber as contact, productName, grossWeight as weight, commitBasis as basis, origin, DATE_FORMAT(issueDate, "%Y-%m-%d") as date, signature, qrCodeUrl, inviter, inviter_phone as inviterPhone FROM certificate WHERE sessionId IS NULL ORDER BY id DESC LIMIT 1';
params = []; params = [];
} }
@ -147,7 +279,9 @@ const server = http.createServer(async (req, res) => {
origin: formData.get('origin'), origin: formData.get('origin'),
date: now, date: now,
signature: formData.get('signature'), signature: formData.get('signature'),
sessionId: sessionId sessionId: sessionId,
inviter: formData.get('inviter'),
inviterPhone: formData.get('inviterPhone')
}; };
console.log('接收到的表单数据:', { console.log('接收到的表单数据:', {
@ -159,7 +293,9 @@ const server = http.createServer(async (req, res) => {
origin: certificate.origin, origin: certificate.origin,
date: certificate.date.toISOString(), date: certificate.date.toISOString(),
hasSignature: !!certificate.signature, hasSignature: !!certificate.signature,
sessionId: sessionId sessionId: sessionId,
inviter: certificate.inviter,
inviterPhone: certificate.inviterPhone
}); });
// 处理手写签名,上传到OSS // 处理手写签名,上传到OSS
@ -218,8 +354,8 @@ const server = http.createServer(async (req, res) => {
// 插入数据到数据库 // 插入数据到数据库
await pool.execute( await pool.execute(
'INSERT INTO certificate (company, phoneNumber, productName, grossWeight, commitBasis, origin, issueDate, signature, sessionId, qrCodeUrl) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', 'INSERT INTO certificate (company, phoneNumber, productName, grossWeight, commitBasis, origin, issueDate, signature, sessionId, qrCodeUrl, inviter, inviter_phone) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
[certificate.subjectName, certificate.contact, certificate.productName, certificate.weight, certificate.basis, certificate.origin, certificate.date, signatureUrl, certificate.sessionId, qrCodeUrl] [certificate.subjectName, certificate.contact, certificate.productName, certificate.weight, certificate.basis, certificate.origin, certificate.date, signatureUrl, certificate.sessionId, qrCodeUrl, certificate.inviter, certificate.inviterPhone]
); );
console.log('数据插入数据库成功'); console.log('数据插入数据库成功');
@ -229,6 +365,8 @@ const server = http.createServer(async (req, res) => {
...certificate, ...certificate,
signature: signatureUrl, signature: signatureUrl,
qrCodeUrl: qrCodeUrl, qrCodeUrl: qrCodeUrl,
inviter: certificate.inviter,
inviterPhone: certificate.inviterPhone,
// 格式化日期为YYYY-MM-DD格式 // 格式化日期为YYYY-MM-DD格式
date: certificate.date.toISOString().split('T')[0] date: certificate.date.toISOString().split('T')[0]
}; };

Loading…
Cancel
Save