345 lines
7.6 KiB
TypeScript
345 lines
7.6 KiB
TypeScript
import { Controller, Get, Post, Body, Param, Inject } from '@midwayjs/core';
|
|
import { Context } from '@midwayjs/koa';
|
|
import { PlaybackService } from '../service/playback.service';
|
|
import { WebSocketService } from '../service/websocket.service';
|
|
|
|
@Controller('/api/admin')
|
|
export class AdminController {
|
|
@Inject()
|
|
ctx: Context;
|
|
|
|
@Inject()
|
|
playbackService: PlaybackService;
|
|
|
|
@Inject()
|
|
webSocketService: WebSocketService;
|
|
|
|
/**
|
|
* 验证管理员token
|
|
*/
|
|
private verifyAdminToken(): boolean {
|
|
const token = this.ctx.headers.authorization?.replace('Bearer ', '') || this.ctx.query.token;
|
|
|
|
if (!token) {
|
|
this.ctx.status = 401;
|
|
this.ctx.body = {
|
|
success: false,
|
|
message: '未提供认证token',
|
|
};
|
|
return false;
|
|
}
|
|
|
|
const adminToken = process.env.ADMIN_TOKEN || 'admin123';
|
|
|
|
if (token !== adminToken) {
|
|
this.ctx.status = 403;
|
|
this.ctx.body = {
|
|
success: false,
|
|
message: '无效的认证token',
|
|
};
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 管理员登录(获取token)- 不需要token验证
|
|
*/
|
|
@Post('/login')
|
|
async login(@Body() body: { password: string }) {
|
|
const adminPassword = process.env.ADMIN_PASSWORD || 'admin';
|
|
|
|
if (body.password !== adminPassword) {
|
|
return {
|
|
success: false,
|
|
message: '密码错误',
|
|
data: null,
|
|
};
|
|
}
|
|
|
|
// 返回token(实际生产环境应使用JWT等更安全的方式)
|
|
const token = process.env.ADMIN_TOKEN || 'admin123';
|
|
|
|
return {
|
|
success: true,
|
|
message: '登录成功',
|
|
data: { token },
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 控制播放/暂停
|
|
*/
|
|
@Post('/playback/play')
|
|
async play() {
|
|
if (!this.verifyAdminToken()) {
|
|
return;
|
|
}
|
|
try {
|
|
this.playbackService.play();
|
|
const state = this.playbackService.getState();
|
|
this.webSocketService.broadcastPlaybackState(state);
|
|
return {
|
|
success: true,
|
|
message: '播放命令已发送',
|
|
data: state,
|
|
};
|
|
} catch (error: any) {
|
|
return {
|
|
success: false,
|
|
message: error.message || '播放失败',
|
|
data: null,
|
|
};
|
|
}
|
|
}
|
|
|
|
@Post('/playback/pause')
|
|
async pause() {
|
|
if (!this.verifyAdminToken()) {
|
|
return;
|
|
}
|
|
try {
|
|
this.playbackService.pause();
|
|
const state = this.playbackService.getState();
|
|
this.webSocketService.broadcastPlaybackState(state);
|
|
return {
|
|
success: true,
|
|
message: '暂停命令已发送',
|
|
data: state,
|
|
};
|
|
} catch (error: any) {
|
|
return {
|
|
success: false,
|
|
message: error.message || '暂停失败',
|
|
data: null,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 发送公告
|
|
*/
|
|
@Post('/announcement')
|
|
async sendAnnouncement(@Body() body: { title: string; content: string; duration?: number }) {
|
|
if (!this.verifyAdminToken()) {
|
|
return;
|
|
}
|
|
if (!body.title || !body.content) {
|
|
return {
|
|
success: false,
|
|
message: '标题和内容不能为空',
|
|
data: null,
|
|
};
|
|
}
|
|
|
|
try {
|
|
this.webSocketService.broadcastAnnouncement({
|
|
title: body.title,
|
|
content: body.content,
|
|
duration: body.duration || 5000, // 默认5秒
|
|
});
|
|
|
|
return {
|
|
success: true,
|
|
message: '公告已发送',
|
|
data: null,
|
|
};
|
|
} catch (error: any) {
|
|
return {
|
|
success: false,
|
|
message: error.message || '发送公告失败',
|
|
data: null,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 控制特定用户的音量
|
|
*/
|
|
@Post('/user/:userId/volume')
|
|
async setUserVolume(@Body() body: { volume: number; muted?: boolean }, @Param('userId') userId: string) {
|
|
if (!this.verifyAdminToken()) {
|
|
return;
|
|
}
|
|
|
|
// 确保userId是字符串
|
|
if (typeof userId !== 'string') {
|
|
return {
|
|
success: false,
|
|
message: '无效的用户ID',
|
|
data: null,
|
|
};
|
|
}
|
|
|
|
const volume = body.volume;
|
|
const muted = body.muted;
|
|
|
|
if (volume === undefined || volume < 0 || volume > 1) {
|
|
return {
|
|
success: false,
|
|
message: '音量值必须在0-1之间',
|
|
data: null,
|
|
};
|
|
}
|
|
|
|
console.log(`管理员请求控制用户 ${userId} 的音量:`, { volume, muted });
|
|
|
|
try {
|
|
const success = this.webSocketService.sendVolumeControlToUser(userId, {
|
|
volume,
|
|
muted,
|
|
});
|
|
|
|
if (!success) {
|
|
return {
|
|
success: false,
|
|
message: '用户不在线或连接已断开',
|
|
data: null,
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
message: '音量控制命令已发送',
|
|
data: { volume, muted },
|
|
};
|
|
} catch (error: any) {
|
|
return {
|
|
success: false,
|
|
message: error.message || '设置音量失败',
|
|
data: null,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 控制特定用户的静音状态
|
|
*/
|
|
@Post('/user/:userId/mute')
|
|
async setUserMute(@Body() body: { muted: boolean }, @Param('userId') userId: string) {
|
|
if (!this.verifyAdminToken()) {
|
|
return;
|
|
}
|
|
|
|
// 确保userId是字符串
|
|
if (typeof userId !== 'string') {
|
|
return {
|
|
success: false,
|
|
message: '无效的用户ID',
|
|
data: null,
|
|
};
|
|
}
|
|
|
|
const muted = body.muted;
|
|
|
|
if (typeof muted !== 'boolean') {
|
|
return {
|
|
success: false,
|
|
message: 'muted必须是布尔值',
|
|
data: null,
|
|
};
|
|
}
|
|
|
|
console.log(`管理员请求控制用户 ${userId} 的静音状态:`, muted);
|
|
|
|
try {
|
|
// 静音时音量设为0,取消静音时恢复默认音量0.5(或根据实际情况调整)
|
|
const volume = muted ? 0 : 0.5;
|
|
|
|
const success = this.webSocketService.sendVolumeControlToUser(userId, {
|
|
volume,
|
|
muted,
|
|
});
|
|
|
|
if (!success) {
|
|
return {
|
|
success: false,
|
|
message: '用户不在线或连接已断开',
|
|
data: null,
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
message: muted ? '静音命令已发送' : '取消静音命令已发送',
|
|
data: { muted, volume },
|
|
};
|
|
} catch (error: any) {
|
|
return {
|
|
success: false,
|
|
message: error.message || '设置静音失败',
|
|
data: null,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取当前播放状态
|
|
*/
|
|
@Get('/playback/state')
|
|
async getPlaybackState() {
|
|
if (!this.verifyAdminToken()) {
|
|
return;
|
|
}
|
|
const state = this.playbackService.getState();
|
|
return {
|
|
success: true,
|
|
message: 'OK',
|
|
data: state,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 调整播放进度
|
|
*/
|
|
@Post('/playback/seek')
|
|
async seek(@Body() body: { time: number }) {
|
|
if (!this.verifyAdminToken()) {
|
|
return;
|
|
}
|
|
|
|
if (body.time === undefined || body.time === null) {
|
|
return {
|
|
success: false,
|
|
message: '时间不能为空',
|
|
data: null,
|
|
};
|
|
}
|
|
|
|
try {
|
|
this.playbackService.setCurrentTime(body.time);
|
|
const state = this.playbackService.getState();
|
|
this.webSocketService.broadcastPlaybackState(state);
|
|
return {
|
|
success: true,
|
|
message: 'OK',
|
|
data: state,
|
|
};
|
|
} catch (error: any) {
|
|
return {
|
|
success: false,
|
|
message: error.message || '调整进度失败',
|
|
data: null,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取所有在线用户
|
|
*/
|
|
@Get('/users')
|
|
async getAllUsers() {
|
|
if (!this.verifyAdminToken()) {
|
|
return;
|
|
}
|
|
const users = this.webSocketService.getAllUsers();
|
|
return {
|
|
success: true,
|
|
message: 'OK',
|
|
data: users,
|
|
};
|
|
}
|
|
}
|
|
|