Initial commit: Telegram Management System
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
Full-stack web application for Telegram management - Frontend: Vue 3 + Vben Admin - Backend: NestJS - Features: User management, group broadcast, statistics 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
779
complete-api-server.js
Normal file
779
complete-api-server.js
Normal file
@@ -0,0 +1,779 @@
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const mysql = require('mysql2/promise');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const bcrypt = require('bcryptjs');
|
||||
|
||||
const app = express();
|
||||
|
||||
// 中间件配置
|
||||
app.use(cors({
|
||||
origin: ['http://localhost:5173', 'http://localhost:3000'],
|
||||
credentials: true
|
||||
}));
|
||||
app.use(express.json({ limit: '50mb' }));
|
||||
app.use(express.urlencoded({ extended: true, limit: '50mb' }));
|
||||
|
||||
// 数据库连接配置
|
||||
const dbConfig = {
|
||||
host: '127.0.0.1',
|
||||
user: 'root',
|
||||
password: '',
|
||||
database: 'tg_manage',
|
||||
acquireTimeout: 60000,
|
||||
timeout: 60000,
|
||||
reconnect: true
|
||||
};
|
||||
|
||||
// JWT配置
|
||||
const JWT_SECRET = 'tg-management-system-jwt-secret-2025';
|
||||
|
||||
// 数据库连接池
|
||||
let pool;
|
||||
async function initDB() {
|
||||
pool = mysql.createPool({
|
||||
...dbConfig,
|
||||
waitForConnections: true,
|
||||
connectionLimit: 10,
|
||||
queueLimit: 0
|
||||
});
|
||||
console.log('📊 数据库连接池初始化成功');
|
||||
}
|
||||
|
||||
// JWT中间件
|
||||
const authenticateToken = (req, res, next) => {
|
||||
const authHeader = req.headers['authorization'];
|
||||
const token = authHeader && authHeader.split(' ')[1];
|
||||
|
||||
if (!token) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
code: 401,
|
||||
msg: '未提供访问令牌'
|
||||
});
|
||||
}
|
||||
|
||||
jwt.verify(token, JWT_SECRET, (err, user) => {
|
||||
if (err) {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
code: 403,
|
||||
msg: '令牌无效或已过期'
|
||||
});
|
||||
}
|
||||
req.user = user;
|
||||
next();
|
||||
});
|
||||
};
|
||||
|
||||
// 统一错误处理
|
||||
const handleError = (error, req, res, next) => {
|
||||
console.error('API错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
code: 500,
|
||||
msg: '服务器内部错误: ' + error.message,
|
||||
data: null
|
||||
});
|
||||
};
|
||||
|
||||
// ==================== 认证相关接口 ====================
|
||||
|
||||
// 登录接口
|
||||
app.post('/auth/login', async (req, res) => {
|
||||
try {
|
||||
const { username, password } = req.body || {};
|
||||
|
||||
if (!username || !password) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
code: 400,
|
||||
msg: '用户名和密码不能为空',
|
||||
data: null
|
||||
});
|
||||
}
|
||||
|
||||
// 简单验证 - 生产环境应该从数据库验证
|
||||
if (username === 'admin' && password === '111111') {
|
||||
const token = jwt.sign(
|
||||
{
|
||||
id: 1,
|
||||
username: 'admin',
|
||||
role: 'admin'
|
||||
},
|
||||
JWT_SECRET,
|
||||
{ expiresIn: '24h' }
|
||||
);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: 200,
|
||||
msg: '登录成功',
|
||||
data: {
|
||||
token,
|
||||
user: {
|
||||
id: 1,
|
||||
username: 'admin',
|
||||
role: 'admin',
|
||||
nickname: '系统管理员'
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res.status(401).json({
|
||||
success: false,
|
||||
code: 401,
|
||||
msg: '用户名或密码错误',
|
||||
data: null
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error, req, res);
|
||||
}
|
||||
});
|
||||
|
||||
// 获取用户信息接口
|
||||
app.get('/auth/user', authenticateToken, (req, res) => {
|
||||
res.json({
|
||||
success: true,
|
||||
code: 200,
|
||||
msg: '获取用户信息成功',
|
||||
data: {
|
||||
id: req.user.id,
|
||||
username: req.user.username,
|
||||
role: req.user.role,
|
||||
nickname: '系统管理员',
|
||||
avatar: null,
|
||||
permissions: ['*']
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ==================== TG账号管理接口 ====================
|
||||
|
||||
// TG账号列表接口
|
||||
app.post('/tgAccount/list', async (req, res) => {
|
||||
try {
|
||||
const connection = await pool.getConnection();
|
||||
|
||||
const page = (req.body && req.body.page) || 1;
|
||||
const size = (req.body && req.body.size) || 10;
|
||||
const phone = (req.body && req.body.phone) || '';
|
||||
const status = req.body && req.body.status;
|
||||
const usageId = req.body && req.body.usageId;
|
||||
|
||||
let whereConditions = [];
|
||||
let params = [];
|
||||
|
||||
if (phone) {
|
||||
whereConditions.push('phone LIKE ?');
|
||||
params.push(`%${phone}%`);
|
||||
}
|
||||
|
||||
if (status !== undefined && status !== null && status !== '') {
|
||||
whereConditions.push('status = ?');
|
||||
params.push(status);
|
||||
}
|
||||
|
||||
if (usageId !== undefined && usageId !== null && usageId !== '') {
|
||||
whereConditions.push('usageId = ?');
|
||||
params.push(usageId);
|
||||
}
|
||||
|
||||
const whereClause = whereConditions.length > 0 ? 'WHERE ' + whereConditions.join(' AND ') : '';
|
||||
|
||||
// 查询总数
|
||||
const [countResult] = await connection.execute(
|
||||
`SELECT COUNT(*) as total FROM accounts ${whereClause}`,
|
||||
params
|
||||
);
|
||||
const total = countResult[0].total;
|
||||
|
||||
// 查询数据
|
||||
const offset = (page - 1) * size;
|
||||
const [rows] = await connection.execute(
|
||||
`SELECT
|
||||
id, phone, firstname, lastname, status, usageId,
|
||||
createdAt, updatedAt, lastOnline, isBan, about
|
||||
FROM accounts
|
||||
${whereClause}
|
||||
ORDER BY id DESC
|
||||
LIMIT ${size} OFFSET ${offset}`,
|
||||
params
|
||||
);
|
||||
|
||||
// 统计数据
|
||||
const [stats] = await connection.execute(
|
||||
`SELECT
|
||||
COUNT(*) as total,
|
||||
SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as active,
|
||||
SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) as inactive,
|
||||
SUM(CASE WHEN isBan = 1 THEN 1 ELSE 0 END) as banned
|
||||
FROM accounts`
|
||||
);
|
||||
|
||||
connection.release();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: 200,
|
||||
data: {
|
||||
list: rows,
|
||||
total: total,
|
||||
page: page,
|
||||
size: size,
|
||||
totalPages: Math.ceil(total / size),
|
||||
stats: stats[0]
|
||||
},
|
||||
msg: '查询成功'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('TG账号列表API错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
code: 500,
|
||||
data: null,
|
||||
msg: '服务器错误: ' + error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// TG账号详情接口
|
||||
app.get('/tgAccount/:id', async (req, res) => {
|
||||
try {
|
||||
const connection = await pool.getConnection();
|
||||
const { id } = req.params;
|
||||
|
||||
const [rows] = await connection.execute(
|
||||
'SELECT * FROM accounts WHERE id = ?',
|
||||
[id]
|
||||
);
|
||||
|
||||
connection.release();
|
||||
|
||||
if (rows.length === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
code: 404,
|
||||
msg: '账号不存在',
|
||||
data: null
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: 200,
|
||||
msg: '获取成功',
|
||||
data: rows[0]
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
handleError(error, req, res);
|
||||
}
|
||||
});
|
||||
|
||||
// 创建TG账号接口
|
||||
app.post('/tgAccount/add', async (req, res) => {
|
||||
try {
|
||||
const connection = await pool.getConnection();
|
||||
const { phone, firstname, lastname, password, usageId } = req.body;
|
||||
|
||||
if (!phone || !usageId) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
code: 400,
|
||||
msg: '手机号和用途不能为空',
|
||||
data: null
|
||||
});
|
||||
}
|
||||
|
||||
const [result] = await connection.execute(
|
||||
`INSERT INTO accounts
|
||||
(phone, firstname, lastname, password, usageId, status, createdAt, updatedAt)
|
||||
VALUES (?, ?, ?, ?, ?, 1, NOW(), NOW())`,
|
||||
[phone, firstname || '', lastname || '', password || '', usageId]
|
||||
);
|
||||
|
||||
connection.release();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: 200,
|
||||
msg: '添加成功',
|
||||
data: { id: result.insertId }
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
if (error.code === 'ER_DUP_ENTRY') {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
code: 400,
|
||||
msg: '手机号已存在',
|
||||
data: null
|
||||
});
|
||||
} else {
|
||||
handleError(error, req, res);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 更新TG账号接口
|
||||
app.put('/tgAccount/:id', async (req, res) => {
|
||||
try {
|
||||
const connection = await pool.getConnection();
|
||||
const { id } = req.params;
|
||||
const { firstname, lastname, usageId, status, about } = req.body;
|
||||
|
||||
await connection.execute(
|
||||
`UPDATE accounts
|
||||
SET firstname = ?, lastname = ?, usageId = ?, status = ?, about = ?, updatedAt = NOW()
|
||||
WHERE id = ?`,
|
||||
[firstname, lastname, usageId, status, about, id]
|
||||
);
|
||||
|
||||
connection.release();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: 200,
|
||||
msg: '更新成功',
|
||||
data: null
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
handleError(error, req, res);
|
||||
}
|
||||
});
|
||||
|
||||
// 删除TG账号接口
|
||||
app.delete('/tgAccount/:id', async (req, res) => {
|
||||
try {
|
||||
const connection = await pool.getConnection();
|
||||
const { id } = req.params;
|
||||
|
||||
await connection.execute('DELETE FROM accounts WHERE id = ?', [id]);
|
||||
|
||||
connection.release();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: 200,
|
||||
msg: '删除成功',
|
||||
data: null
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
handleError(error, req, res);
|
||||
}
|
||||
});
|
||||
|
||||
// 批量操作TG账号接口
|
||||
app.post('/tgAccount/batch', async (req, res) => {
|
||||
try {
|
||||
const connection = await pool.getConnection();
|
||||
const { ids, action } = req.body;
|
||||
|
||||
if (!ids || !Array.isArray(ids) || ids.length === 0) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
code: 400,
|
||||
msg: '请选择要操作的账号',
|
||||
data: null
|
||||
});
|
||||
}
|
||||
|
||||
const placeholders = ids.map(() => '?').join(',');
|
||||
|
||||
switch (action) {
|
||||
case 'enable':
|
||||
await connection.execute(
|
||||
`UPDATE accounts SET status = 1, updatedAt = NOW() WHERE id IN (${placeholders})`,
|
||||
ids
|
||||
);
|
||||
break;
|
||||
case 'disable':
|
||||
await connection.execute(
|
||||
`UPDATE accounts SET status = 0, updatedAt = NOW() WHERE id IN (${placeholders})`,
|
||||
ids
|
||||
);
|
||||
break;
|
||||
case 'delete':
|
||||
await connection.execute(
|
||||
`DELETE FROM accounts WHERE id IN (${placeholders})`,
|
||||
ids
|
||||
);
|
||||
break;
|
||||
default:
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
code: 400,
|
||||
msg: '不支持的操作类型',
|
||||
data: null
|
||||
});
|
||||
}
|
||||
|
||||
connection.release();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: 200,
|
||||
msg: '批量操作成功',
|
||||
data: null
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
handleError(error, req, res);
|
||||
}
|
||||
});
|
||||
|
||||
// ==================== 账号用途管理接口 ====================
|
||||
|
||||
// 账号用途列表接口
|
||||
app.post('/accountUsage/list', async (req, res) => {
|
||||
try {
|
||||
const connection = await pool.getConnection();
|
||||
|
||||
const pageIndex = (req.body && req.body.pageIndex) || 1;
|
||||
const pageSize = (req.body && req.body.pageSize) || 10;
|
||||
const type = (req.body && req.body.type) || '';
|
||||
|
||||
let whereClause = '';
|
||||
let params = [];
|
||||
|
||||
if (type) {
|
||||
whereClause = 'WHERE type LIKE ?';
|
||||
params.push(`%${type}%`);
|
||||
}
|
||||
|
||||
// 查询总数
|
||||
const [countResult] = await connection.execute(
|
||||
`SELECT COUNT(*) as total FROM accounts_usage ${whereClause}`,
|
||||
params
|
||||
);
|
||||
const total = countResult[0].total;
|
||||
|
||||
// 查询数据
|
||||
const offset = (pageIndex - 1) * pageSize;
|
||||
const [rows] = await connection.execute(
|
||||
`SELECT id, type, createdAt, updatedAt
|
||||
FROM accounts_usage
|
||||
${whereClause}
|
||||
ORDER BY id DESC
|
||||
LIMIT ${pageSize} OFFSET ${offset}`,
|
||||
params
|
||||
);
|
||||
|
||||
connection.release();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: '200',
|
||||
message: '查询成功',
|
||||
data: {
|
||||
list: rows,
|
||||
totalRow: total,
|
||||
pageIndex: pageIndex,
|
||||
pageSize: pageSize
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('账号用途API错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
code: '500',
|
||||
message: '服务器错误: ' + error.message,
|
||||
data: null
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 添加账号用途接口
|
||||
app.post('/accountUsage/add', async (req, res) => {
|
||||
try {
|
||||
const connection = await pool.getConnection();
|
||||
const { type } = req.body;
|
||||
|
||||
if (!type) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
code: '400',
|
||||
message: '用途名称不能为空',
|
||||
data: null
|
||||
});
|
||||
}
|
||||
|
||||
const [result] = await connection.execute(
|
||||
'INSERT INTO accounts_usage (type, createdAt, updatedAt) VALUES (?, NOW(), NOW())',
|
||||
[type]
|
||||
);
|
||||
|
||||
connection.release();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: '200',
|
||||
message: '添加成功',
|
||||
data: { id: result.insertId }
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('添加账号用途错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
code: '500',
|
||||
message: '添加失败: ' + error.message,
|
||||
data: null
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 更新账号用途接口
|
||||
app.post('/accountUsage/update', async (req, res) => {
|
||||
try {
|
||||
const connection = await pool.getConnection();
|
||||
const { id, type } = req.body;
|
||||
|
||||
if (!type) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
code: '400',
|
||||
message: '用途名称不能为空',
|
||||
data: null
|
||||
});
|
||||
}
|
||||
|
||||
await connection.execute(
|
||||
'UPDATE accounts_usage SET type = ?, updatedAt = NOW() WHERE id = ?',
|
||||
[type, id]
|
||||
);
|
||||
|
||||
connection.release();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: '200',
|
||||
message: '更新成功',
|
||||
data: null
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('更新账号用途错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
code: '500',
|
||||
message: '更新失败: ' + error.message,
|
||||
data: null
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 删除账号用途接口
|
||||
app.delete('/accountUsage/:id', async (req, res) => {
|
||||
try {
|
||||
const connection = await pool.getConnection();
|
||||
const { id } = req.params;
|
||||
|
||||
await connection.execute('DELETE FROM accounts_usage WHERE id = ?', [id]);
|
||||
|
||||
connection.release();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: '200',
|
||||
message: '删除成功',
|
||||
data: null
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('删除账号用途错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
code: '500',
|
||||
message: '删除失败: ' + error.message,
|
||||
data: null
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ==================== 统计分析接口 ====================
|
||||
|
||||
// 系统概览数据接口
|
||||
app.get('/telegram/statistics/overview', async (req, res) => {
|
||||
try {
|
||||
const connection = await pool.getConnection();
|
||||
|
||||
// 账号统计
|
||||
const [accountStats] = await connection.execute(
|
||||
`SELECT
|
||||
COUNT(*) as totalAccounts,
|
||||
SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as activeAccounts,
|
||||
SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) as inactiveAccounts,
|
||||
SUM(CASE WHEN isBan = 1 THEN 1 ELSE 0 END) as bannedAccounts
|
||||
FROM accounts`
|
||||
);
|
||||
|
||||
// 用途统计
|
||||
const [usageStats] = await connection.execute(
|
||||
'SELECT COUNT(*) as totalUsages FROM accounts_usage'
|
||||
);
|
||||
|
||||
// 在线统计(最近24小时)
|
||||
const [onlineStats] = await connection.execute(
|
||||
`SELECT COUNT(*) as onlineAccounts
|
||||
FROM accounts
|
||||
WHERE lastOnline >= DATE_SUB(NOW(), INTERVAL 24 HOUR)`
|
||||
);
|
||||
|
||||
connection.release();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: 200,
|
||||
msg: '获取成功',
|
||||
data: {
|
||||
accounts: accountStats[0],
|
||||
usages: usageStats[0].totalUsages,
|
||||
online: onlineStats[0].onlineAccounts,
|
||||
timestamp: new Date().toISOString()
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
handleError(error, req, res);
|
||||
}
|
||||
});
|
||||
|
||||
// 账号统计数据接口
|
||||
app.get('/telegram/statistics/account', async (req, res) => {
|
||||
try {
|
||||
const connection = await pool.getConnection();
|
||||
|
||||
// 按用途分组统计
|
||||
const [usageStats] = await connection.execute(
|
||||
`SELECT
|
||||
u.type as usageName,
|
||||
COUNT(a.id) as count,
|
||||
SUM(CASE WHEN a.status = 1 THEN 1 ELSE 0 END) as active,
|
||||
SUM(CASE WHEN a.isBan = 1 THEN 1 ELSE 0 END) as banned
|
||||
FROM accounts_usage u
|
||||
LEFT JOIN accounts a ON u.id = a.usageId
|
||||
GROUP BY u.id, u.type
|
||||
ORDER BY count DESC`
|
||||
);
|
||||
|
||||
// 日活统计(最近7天)
|
||||
const [dailyStats] = await connection.execute(
|
||||
`SELECT
|
||||
DATE(lastOnline) as date,
|
||||
COUNT(*) as count
|
||||
FROM accounts
|
||||
WHERE lastOnline >= DATE_SUB(NOW(), INTERVAL 7 DAY)
|
||||
GROUP BY DATE(lastOnline)
|
||||
ORDER BY date DESC`
|
||||
);
|
||||
|
||||
connection.release();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: 200,
|
||||
msg: '获取成功',
|
||||
data: {
|
||||
usageStats,
|
||||
dailyStats
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
handleError(error, req, res);
|
||||
}
|
||||
});
|
||||
|
||||
// ==================== 菜单权限接口 ====================
|
||||
|
||||
// 获取菜单权限接口
|
||||
app.get('/telegram/permission/menus', authenticateToken, (req, res) => {
|
||||
const menus = [
|
||||
{
|
||||
id: 1,
|
||||
title: '仪表板',
|
||||
path: '/dashboard',
|
||||
icon: 'DashboardOutlined',
|
||||
children: []
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '账号管理',
|
||||
path: '/account-manage',
|
||||
icon: 'UserOutlined',
|
||||
children: [
|
||||
{
|
||||
id: 21,
|
||||
title: 'TG账号列表',
|
||||
path: '/account-manage/list',
|
||||
icon: 'UnorderedListOutlined'
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
title: 'TG账号用途',
|
||||
path: '/account-manage/usage',
|
||||
icon: 'TagsOutlined'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code: 200,
|
||||
msg: '获取菜单成功',
|
||||
data: menus
|
||||
});
|
||||
});
|
||||
|
||||
// ==================== 健康检查接口 ====================
|
||||
|
||||
app.get('/health', (req, res) => {
|
||||
res.json({
|
||||
success: true,
|
||||
code: 200,
|
||||
msg: 'API服务运行正常',
|
||||
data: {
|
||||
timestamp: new Date().toISOString(),
|
||||
uptime: process.uptime()
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 全局错误处理
|
||||
app.use(handleError);
|
||||
|
||||
// 启动服务
|
||||
const PORT = 3002;
|
||||
|
||||
async function startServer() {
|
||||
try {
|
||||
await initDB();
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`🚀 完整版API服务启动成功,端口: ${PORT}`);
|
||||
console.log(`📊 健康检查: GET http://localhost:${PORT}/health`);
|
||||
console.log(`🔐 登录接口: POST http://localhost:${PORT}/auth/login`);
|
||||
console.log(`👤 用户信息: GET http://localhost:${PORT}/auth/user`);
|
||||
console.log(`📱 TG账号列表: POST http://localhost:${PORT}/tgAccount/list`);
|
||||
console.log(`📋 账号用途管理: POST http://localhost:${PORT}/accountUsage/list`);
|
||||
console.log(`📈 系统概览: GET http://localhost:${PORT}/telegram/statistics/overview`);
|
||||
console.log(`📊 账号统计: GET http://localhost:${PORT}/telegram/statistics/account`);
|
||||
console.log(`🏠 菜单权限: GET http://localhost:${PORT}/telegram/permission/menus`);
|
||||
console.log('');
|
||||
console.log('✅ 完整版API服务器已就绪,支持全功能!');
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('❌ 服务启动失败:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
startServer();
|
||||
Reference in New Issue
Block a user