feat: 将本地独有功能移植到 upstream 最新版本

基于 upstream/master (c5922f9) 新建分支,移植以下功能:
1. 扫码登录(DyQrCodeService + ConfigController 3个接口)
2. 视频预览组件(VideoPlayer.vue)
3. 下载配置服务(DownloadConfigService + AppConfig 6个扩展字段)
4. Gitea CI/CD(.gitea/workflows/deploy.yml)
5. 生产 Dockerfile(Dockerfile.prod,含中国镜像源配置)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
yuming
2026-07-02 20:58:08 +08:00
parent c5922f9b08
commit 30060fe29c
9 changed files with 1086 additions and 1 deletions
+63 -1
View File
@@ -25,10 +25,11 @@ 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)
public ConfigController(DouyinCookieService dyCookieService, DouyinCommonService commonService, DouyinQuartzJobService quartzJobService, DouyinFollowService douyinFollowService, DouyinCookieService douyinCookieService, DouyinHttpClientService httpClientService, DyQrCodeService qrCodeService)
{
this.dyCookieService = dyCookieService;
this.commonService = commonService;
@@ -36,6 +37,7 @@ namespace dy.net.Controllers
this.douyinFollowService = douyinFollowService;
this.douyinCookieService = douyinCookieService;
this.httpClientService = httpClientService;
_qrCodeService = qrCodeService;
}
@@ -484,5 +486,65 @@ namespace dy.net.Controllers
return ApiResult.Fail("文件不存在");
}
}
/// <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 });
}
}
}
}