feat: Modal 小屏滚动 + 数据看板视频播放 + Docker Alpine 化

- 数据看板作者视频播放接口从 /api/video/stream 改为 /api/Video/play(后端只有 Play action,之前笔误导致 404)
- 全局 Modal 小屏适配:body max-height + 自定义 10px 深色滚动条,兼容 full-modal 和登录页 login-modal
- Docker 镜像换 Alpine + 内置 ffmpeg,避开 Ubuntu apt 网络问题
- 新增 .dockerignore 排除 node_modules / logs / videos / db 等构建噪音
- 移除已废弃的 DyQrCodeService(旧扫码登录)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
yuming
2026-07-03 18:03:57 +08:00
parent 30060fe29c
commit e6c5587637
12 changed files with 411 additions and 289 deletions
+1 -64
View File
@@ -25,11 +25,8 @@ namespace dy.net.Controllers
private readonly DouyinFollowService douyinFollowService;
private readonly DouyinCookieService douyinCookieService;
private readonly DouyinHttpClientService httpClientService;
private readonly DyQrCodeService _qrCodeService;
public ConfigController(DouyinCookieService dyCookieService, DouyinCommonService commonService, DouyinQuartzJobService quartzJobService, DouyinFollowService douyinFollowService, DouyinCookieService douyinCookieService, DouyinHttpClientService httpClientService, DyQrCodeService qrCodeService)
public ConfigController(DouyinCookieService dyCookieService, DouyinCommonService commonService, DouyinQuartzJobService quartzJobService, DouyinFollowService douyinFollowService, DouyinCookieService douyinCookieService, DouyinHttpClientService httpClientService)
{
this.dyCookieService = dyCookieService;
this.commonService = commonService;
@@ -37,7 +34,6 @@ namespace dy.net.Controllers
this.douyinFollowService = douyinFollowService;
this.douyinCookieService = douyinCookieService;
this.httpClientService = httpClientService;
_qrCodeService = qrCodeService;
}
@@ -487,64 +483,5 @@ namespace dy.net.Controllers
}
}
/// <summary>
/// 获取抖音扫码登录二维码
/// </summary>
[AllowAnonymous]
[HttpGet("qrcode")]
public async Task<IActionResult> GetQrCode()
{
try
{
var (token, qrBase64) = await _qrCodeService.GetQrCodeAsync();
return Ok(new { code = 0, data = new { token, qrBase64 } });
}
catch (Exception ex)
{
return Ok(new { code = -1, error = ex.Message });
}
}
/// <summary>
/// 轮询扫码状态(前端每2秒调一次)
/// status: 1=待扫码, 2=已扫码待确认, 3=登录成功, -1=已过期
/// </summary>
[AllowAnonymous]
[HttpGet("qrstatus")]
public async Task<IActionResult> GetQrStatus([FromQuery] string token)
{
try
{
var (status, cookies, secUserId) = await _qrCodeService.CheckStatusAsync(token);
return Ok(new { code = 0, data = new { status, cookies, secUserId } });
}
catch (Exception ex)
{
Serilog.Log.Error($"查询扫码状态失败: {ex.Message}");
return Ok(new { code = -1, error = ex.Message });
}
}
/// <summary>
/// 扫码成功后,将 Cookie 绑定到指定账号
/// </summary>
[HttpPost("qrbind")]
public async Task<IActionResult> BindQrCode([FromQuery] string token, [FromQuery] string id)
{
try
{
var (cookies, secUserId) = _qrCodeService.GetSessionResult(token);
if (string.IsNullOrEmpty(cookies))
return Ok(new { code = -1, error = "扫码尚未完成或已过期" });
var result = await douyinCookieService.FastResetCookie(id, cookies);
_qrCodeService.RemoveSession(token);
return Ok(new { code = result ? 0 : -1, secUserId });
}
catch (Exception ex)
{
return Ok(new { code = -1, error = ex.Message });
}
}
}
}