// server.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const path = require('path');
const db = require('./db'); // 引入数据库连接
const userRoutes = require('./routes/user'); // 用户路由

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware
app.use(cors());
app.use(bodyParser.json());
app.use(express.static('public')); // 提供静态文件服务

// 使用用户路由
app.use('/api/users', userRoutes);

// 根路由，返回 HTML 页面
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

// 启动服务器
app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});// routes/user.js
const express = require('express');
const router = express.Router();
const db = require('../db');
const bcrypt = require('bcrypt');

// 用户注册
router.post('/register', async (req, res) => {
    const { username, password } = req.body;
    const hashedPassword = await bcrypt.hash(password, 10); // 加密密码
    const sql = 'INSERT INTO users (username, password) VALUES (?, ?)';

    db.query(sql, [username, hashedPassword], (err, result) => {
        if (err) {
            return res.status(500).json({ message: 'Error registering user' });
        }
        res.status(201).json({ message: 'User registered successfully' });
    });
});

// 用户登录
router.post('/login', (req, res) => {
    const { username, password } = req.body;
    const sql = 'SELECT * FROM users WHERE username = ?';

    db.query(sql, [username], async (err, results) => {
        if (err) {
            return res.status(500).json({ message: 'Error logging in' });
        }
        if (results.length > 0) {
            const user = results[0];
            const match = await bcrypt.compare(password, user.password);
            if (match) {
                res.status(200).json({ message: 'Login successful' });
            } else {
                res.status(401).json({ message: 'Invalid credentials' });
            }
        } else {
            res.status(401).json({ message: 'Invalid credentials' });
        }
    });
});

module.exports = router;<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>User Auth</title>
    <style>
        body { font-family: Arial, sans-serif; }
        .form-container { max-width: 300px; margin: auto; }
        .hidden { display: none; }
        .error-message { color: red; }
    </style>
</head>
<body>
    <div class="form-container">
        <h2>User Registration</h2>
        <form id="registerForm">
            <input type="text" id="registerUsername" placeholder="Username" required>
            <input type="password" id="registerPassword" placeholder="Password" required>
            <button type="submit">Register</button>
        </form>
        <p class="error-message hidden" id="registerError"></p>
        
        <h2>User Login</h2>
        <form id="loginForm">
            <input type="text" id="loginUsername" placeholder="Username" required>
            <input type="password" id="loginPassword" placeholder="Password" required>
            <button type="submit">Login</button>
        </form>
        <p class="error-message hidden" id="loginError"></p>
    </div>

    <script>
        document.getElementById('registerForm').addEventListener('submit', async (event) => {
            event.preventDefault();
            const username = document.getElementById('registerUsername').value;
            const password = document.getElementById('registerPassword').value;

            const response = await fetch('/api/users/register', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ username, password })
            });

            const data = await response.json();
            if (response.ok) {
                alert(data.message);
                document.getElementById('registerForm').reset();
                document.getElementById('registerError').classList.add('hidden');
            } else {
                document.getElementById('registerError').textContent = data.message;
                document.getElementById('registerError').classList.remove('hidden');
            }
        });

        document.getElementById('loginForm').addEventListener('submit', async (event) => {
            event.preventDefault();
            const username = document.getElementById('loginUsername').value;
            const password = document.getElementById('loginPassword').value;

            const response = await fetch('/api/users/login', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ username, password })
            });

            const data = await response.json();
            if (response.ok) {
                alert(data.message);
                document.getElementById('loginForm').reset();
                document.getElementById('loginError').classList.add('hidden');
            } else {
                document.getElementById('loginError').textContent = data.message;
                document.getElementById('loginError').classList.remove('hidden');
            }
        });
    </script>
</body>
</html>登录成功后，进行新的页面，1、添加获取标签接口路由

2、添加数据库查询标签接口数据

3、页面ajax获取标签数据，根据标签跟新标签并渲染