first commit

This commit is contained in:
yanpeng200212
2026-10-08 10:43:59 +08:00
commit 8430ba0452
288 changed files with 29595 additions and 0 deletions
+75
View File
@@ -0,0 +1,75 @@
import { Router } from 'express';
import bcrypt from 'bcryptjs';
import db from '../db.js';
import { auth, sign } from '../middleware.js';
const router = Router();
// 注册
router.post('/register', (req, res) => {
const { username, password, nickname, phone, building } = req.body;
if (!username || !password || !nickname) {
return res.status(400).json({ message: '请填写完整信息' });
}
if (username.length < 3 || password.length < 6) {
return res.status(400).json({ message: '用户名至少3位,密码至少6位' });
}
const exists = db.prepare('SELECT id FROM users WHERE username = ?').get(username);
if (exists) {
return res.status(400).json({ message: '用户名已存在' });
}
const hash = bcrypt.hashSync(password, 10);
const info = db
.prepare('INSERT INTO users (username, password, nickname, phone, building) VALUES (?, ?, ?, ?, ?)')
.run(username, hash, nickname, phone || '', building || '');
const user = db.prepare('SELECT * FROM users WHERE id = ?').get(info.lastInsertRowid);
res.json({ token: sign(user), user: safeUser(user) });
});
// 登录
router.post('/login', (req, res) => {
const { username, password } = req.body;
const user = db.prepare('SELECT * FROM users WHERE username = ?').get(username);
if (!user || !bcrypt.compareSync(password, user.password)) {
return res.status(401).json({ message: '用户名或密码错误' });
}
res.json({ token: sign(user), user: safeUser(user) });
});
// 获取当前用户
router.get('/me', auth, (req, res) => {
const user = db.prepare('SELECT * FROM users WHERE id = ?').get(req.user.id);
if (!user) return res.status(404).json({ message: '用户不存在' });
res.json(safeUser(user));
});
// 更新个人资料
router.put('/me', auth, (req, res) => {
const { nickname, phone, building, bio } = req.body;
db.prepare('UPDATE users SET nickname = ?, phone = ?, building = ?, bio = ? WHERE id = ?')
.run(nickname, phone || '', building || '', bio || '', req.user.id);
const user = db.prepare('SELECT * FROM users WHERE id = ?').get(req.user.id);
res.json(safeUser(user));
});
// 修改密码
router.put('/password', auth, (req, res) => {
const { oldPassword, newPassword } = req.body;
const user = db.prepare('SELECT * FROM users WHERE id = ?').get(req.user.id);
if (!bcrypt.compareSync(oldPassword, user.password)) {
return res.status(400).json({ message: '原密码错误' });
}
if (newPassword.length < 6) {
return res.status(400).json({ message: '新密码至少6位' });
}
const hash = bcrypt.hashSync(newPassword, 10);
db.prepare('UPDATE users SET password = ? WHERE id = ?').run(hash, req.user.id);
res.json({ message: '修改成功' });
});
function safeUser(u) {
const { password, ...rest } = u;
return rest;
}
export default router;
+38
View File
@@ -0,0 +1,38 @@
import { Router } from 'express';
import db from '../db.js';
import { auth } from '../middleware.js';
const router = Router();
// 家政服务列表
router.get('/', auth, (req, res) => {
const items = db
.prepare('SELECT h.*, u.nickname, u.avatar FROM housekeeping h JOIN users u ON h.user_id = u.id ORDER BY h.created_at DESC')
.all();
res.json(items);
});
// 发布家政服务
router.post('/', auth, (req, res) => {
const { title, description, price, phone } = req.body;
if (!title || !description) {
return res.status(400).json({ message: '请填写服务名称和描述' });
}
const info = db
.prepare('INSERT INTO housekeeping (user_id, title, description, price, phone) VALUES (?, ?, ?, ?, ?)')
.run(req.user.id, title, description, price || '', phone || '');
res.json(db.prepare('SELECT * FROM housekeeping WHERE id = ?').get(info.lastInsertRowid));
});
// 删除服务
router.delete('/:id', auth, (req, res) => {
const item = db.prepare('SELECT * FROM housekeeping WHERE id = ?').get(req.params.id);
if (!item) return res.status(404).json({ message: '服务不存在' });
if (item.user_id !== req.user.id && req.user.role !== 'admin') {
return res.status(403).json({ message: '无权删除' });
}
db.prepare('DELETE FROM housekeeping WHERE id = ?').run(req.params.id);
res.json({ message: '删除成功' });
});
export default router;
+28
View File
@@ -0,0 +1,28 @@
import { Router } from 'express';
import db from '../db.js';
import { auth } from '../middleware.js';
const router = Router();
// 物业通知列表
router.get('/', (req, res) => {
const notices = db.prepare('SELECT * FROM notices ORDER BY created_at DESC').all();
res.json(notices);
});
// 发布通知(管理员)
router.post('/', auth, (req, res) => {
if (req.user.role !== 'admin') {
return res.status(403).json({ message: '仅管理员可发布通知' });
}
const { title, content, type } = req.body;
if (!title || !content) {
return res.status(400).json({ message: '请填写标题和内容' });
}
const info = db
.prepare('INSERT INTO notices (title, content, type) VALUES (?, ?, ?)')
.run(title, content, type || '通知');
res.json(db.prepare('SELECT * FROM notices WHERE id = ?').get(info.lastInsertRowid));
});
export default router;
+90
View File
@@ -0,0 +1,90 @@
import { Router } from 'express';
import db from '../db.js';
import { auth } from '../middleware.js';
const router = Router();
// 获取动态列表(含用户信息、是否已点赞)
router.get('/', auth, (req, res) => {
const { category } = req.query;
let sql = `
SELECT p.*, u.nickname, u.avatar,
(SELECT COUNT(*) FROM likes l WHERE l.post_id = p.id) as like_count,
EXISTS(SELECT 1 FROM likes l WHERE l.post_id = p.id AND l.user_id = ?) as liked
FROM posts p JOIN users u ON p.user_id = u.id
`;
const params = [req.user.id];
if (category && category !== '全部') {
sql += ' WHERE p.category = ?';
params.push(category);
}
sql += ' ORDER BY p.created_at DESC';
const posts = db.prepare(sql).all(...params);
res.json(posts.map(p => ({ ...p, images: JSON.parse(p.images || '[]') })));
});
// 发布动态
router.post('/', auth, (req, res) => {
const { content, images, category } = req.body;
if (!content || !content.trim()) {
return res.status(400).json({ message: '内容不能为空' });
}
const info = db
.prepare('INSERT INTO posts (user_id, content, images, category) VALUES (?, ?, ?, ?)')
.run(req.user.id, content, JSON.stringify(images || []), category || '动态');
const post = db.prepare('SELECT * FROM posts WHERE id = ?').get(info.lastInsertRowid);
res.json({ ...post, images: JSON.parse(post.images || '[]') });
});
// 删除动态
router.delete('/:id', auth, (req, res) => {
const post = db.prepare('SELECT * FROM posts WHERE id = ?').get(req.params.id);
if (!post) return res.status(404).json({ message: '动态不存在' });
if (post.user_id !== req.user.id && req.user.role !== 'admin') {
return res.status(403).json({ message: '无权删除' });
}
db.prepare('DELETE FROM comments WHERE post_id = ?').run(req.params.id);
db.prepare('DELETE FROM likes WHERE post_id = ?').run(req.params.id);
db.prepare('DELETE FROM posts WHERE id = ?').run(req.params.id);
res.json({ message: '删除成功' });
});
// 点赞/取消点赞
router.post('/:id/like', auth, (req, res) => {
const post = db.prepare('SELECT id FROM posts WHERE id = ?').get(req.params.id);
if (!post) return res.status(404).json({ message: '动态不存在' });
const existing = db
.prepare('SELECT id FROM likes WHERE post_id = ? AND user_id = ?')
.get(req.params.id, req.user.id);
if (existing) {
db.prepare('DELETE FROM likes WHERE id = ?').run(existing.id);
res.json({ liked: false });
} else {
db.prepare('INSERT INTO likes (post_id, user_id) VALUES (?, ?)').run(req.params.id, req.user.id);
res.json({ liked: true });
}
});
// 获取评论
router.get('/:id/comments', auth, (req, res) => {
const comments = db
.prepare('SELECT c.*, u.nickname, u.avatar FROM comments c JOIN users u ON c.user_id = u.id WHERE c.post_id = ? ORDER BY c.created_at ASC')
.all(req.params.id);
res.json(comments);
});
// 发表评论
router.post('/:id/comments', auth, (req, res) => {
const { content } = req.body;
if (!content || !content.trim()) {
return res.status(400).json({ message: '评论不能为空' });
}
db.prepare('INSERT INTO comments (post_id, user_id, content) VALUES (?, ?, ?)')
.run(req.params.id, req.user.id, content);
const list = db
.prepare('SELECT c.*, u.nickname, u.avatar FROM comments c JOIN users u ON c.user_id = u.id WHERE c.post_id = ? ORDER BY c.created_at ASC')
.all(req.params.id);
res.json(list);
});
export default router;
+50
View File
@@ -0,0 +1,50 @@
import { Router } from 'express';
import db from '../db.js';
import { auth } from '../middleware.js';
const router = Router();
// 二手闲置列表
router.get('/', auth, (req, res) => {
const items = db
.prepare('SELECT s.*, u.nickname, u.avatar FROM secondhand s JOIN users u ON s.user_id = u.id ORDER BY s.created_at DESC')
.all();
res.json(items.map(i => ({ ...i, images: JSON.parse(i.images || '[]') })));
});
// 发布闲置
router.post('/', auth, (req, res) => {
const { title, description, price, images } = req.body;
if (!title || !description) {
return res.status(400).json({ message: '请填写标题和描述' });
}
const info = db
.prepare('INSERT INTO secondhand (user_id, title, description, price, images) VALUES (?, ?, ?, ?, ?)')
.run(req.user.id, title, description, price || 0, JSON.stringify(images || []));
res.json(db.prepare('SELECT * FROM secondhand WHERE id = ?').get(info.lastInsertRowid));
});
// 更新状态(下架/售出)
router.put('/:id', auth, (req, res) => {
const item = db.prepare('SELECT * FROM secondhand WHERE id = ?').get(req.params.id);
if (!item) return res.status(404).json({ message: '物品不存在' });
if (item.user_id !== req.user.id && req.user.role !== 'admin') {
return res.status(403).json({ message: '无权操作' });
}
const { status } = req.body;
db.prepare('UPDATE secondhand SET status = ? WHERE id = ?').run(status, req.params.id);
res.json(db.prepare('SELECT * FROM secondhand WHERE id = ?').get(req.params.id));
});
// 删除闲置
router.delete('/:id', auth, (req, res) => {
const item = db.prepare('SELECT * FROM secondhand WHERE id = ?').get(req.params.id);
if (!item) return res.status(404).json({ message: '物品不存在' });
if (item.user_id !== req.user.id && req.user.role !== 'admin') {
return res.status(403).json({ message: '无权删除' });
}
db.prepare('DELETE FROM secondhand WHERE id = ?').run(req.params.id);
res.json({ message: '删除成功' });
});
export default router;