feat(platform): add endpoint to retrieve platform accounts for a user
- Introduced `getPlatformAccountsByUserId` method in `DyVideoUser` model to fetch active platform accounts for a specified user. - Added new API route for accessing platform accounts under `v1/platform/accounts`, requiring user authentication.
This commit is contained in:
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\api\service;
|
||||
|
||||
use app\api\model\DyVideoUser;
|
||||
use app\api\model\DyVideoUserTitk;
|
||||
use app\api\model\Member;
|
||||
|
||||
/**
|
||||
* 平台账号管理服务。
|
||||
*
|
||||
* 本服务只补齐小程序“平台账号管理”页面所需的最基础只读能力,
|
||||
* 关键查询与状态语义按 acgpmw `dyai/controller/platform.php` 的
|
||||
* `index()` / `get_zhanghu_list()` 对齐,不擅自扩展解绑、授权等高风险动作。
|
||||
*/
|
||||
class PlatformService
|
||||
{
|
||||
/**
|
||||
* 平台映射按 acgpmw `data/other/platforms_py.php` 对齐。
|
||||
*/
|
||||
private const PLATFORM_KEY_MAP = [
|
||||
0 => 'douyin',
|
||||
1 => 'kuaishou',
|
||||
2 => 'baijiahao',
|
||||
3 => 'xiaohongshu',
|
||||
4 => 'shipinhao',
|
||||
5 => 'bilibili',
|
||||
6 => 'gongzhonghao',
|
||||
10 => 'tiktok',
|
||||
];
|
||||
|
||||
/**
|
||||
* 页面展示名称。
|
||||
*
|
||||
* acgpmw 模板内部会通过 `$this->platform_info[$platform]` 展示中文平台名,
|
||||
* 这里在 API 中直接返回前端所需文案,避免小程序自行猜测。
|
||||
*/
|
||||
private const PLATFORM_NAME_MAP = [
|
||||
0 => '抖音',
|
||||
1 => '快手',
|
||||
2 => '百家号',
|
||||
3 => '小红书',
|
||||
4 => '视频号',
|
||||
5 => 'B站',
|
||||
6 => '公众号',
|
||||
10 => 'TikTok',
|
||||
];
|
||||
|
||||
/**
|
||||
* 获取平台账号管理页列表数据。
|
||||
*
|
||||
* @param int $userid 当前登录用户ID
|
||||
* @param int|null $platform 当前筛选平台;为空时返回全部可见平台
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getAccountList(int $userid, ?int $platform = null): array
|
||||
{
|
||||
$member = Member::findByUserid($userid);
|
||||
if (!$member) {
|
||||
throw new \Exception('用户不存在', 4006);
|
||||
}
|
||||
|
||||
$productInfo = $member->getProductInfo();
|
||||
$availablePlatforms = $this->resolveAvailablePlatforms($member, $productInfo);
|
||||
|
||||
if (empty($availablePlatforms)) {
|
||||
throw new \Exception('暂无平台管理权限', 4004);
|
||||
}
|
||||
|
||||
if ($platform !== null && !in_array($platform, $availablePlatforms, true)) {
|
||||
throw new \Exception('当前套餐暂无该平台权限', 4004);
|
||||
}
|
||||
|
||||
$targetPlatform = $platform;
|
||||
$accounts = DyVideoUser::getPlatformAccountsByUserId($userid, $targetPlatform);
|
||||
|
||||
$accountItems = [];
|
||||
foreach ($accounts as $account) {
|
||||
$accountPlatform = (int) $account->platform;
|
||||
|
||||
if (!in_array($accountPlatform, $availablePlatforms, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$accountItems[] = $this->buildAccountItem($account->toArray());
|
||||
}
|
||||
|
||||
$platformTabs = $this->buildPlatformTabs($availablePlatforms, $userid);
|
||||
$summary = $this->buildSummary($accountItems);
|
||||
|
||||
return [
|
||||
'filters' => [
|
||||
'current_platform' => $targetPlatform,
|
||||
'platforms' => $platformTabs,
|
||||
],
|
||||
'summary' => $summary,
|
||||
'list' => $accountItems,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算当前用户可见平台。
|
||||
*
|
||||
* 该逻辑直接对齐 acgpmw `platform::index()`:
|
||||
* 1. 从套餐 `product_list.platforms` 读取平台权限
|
||||
* 2. 若为 146/147 且不在特殊账号名单中,仅允许抖音平台
|
||||
*
|
||||
* @param Member $member 当前登录用户
|
||||
* @param array|null $productInfo 套餐信息
|
||||
* @return array<int>
|
||||
*/
|
||||
private function resolveAvailablePlatforms(Member $member, ?array $productInfo): array
|
||||
{
|
||||
$platformText = trim((string) ($productInfo['platforms'] ?? ''), ',');
|
||||
if ($platformText === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$platforms = array_values(array_filter(array_map('intval', explode(',', $platformText)), static function ($item) {
|
||||
return array_key_exists($item, self::PLATFORM_NAME_MAP);
|
||||
}));
|
||||
|
||||
$specialAccounts = $this->loadSpecialAccounts();
|
||||
$isRestrictedVType = in_array((int) $member->v_type, [146, 147], true);
|
||||
$isSpecialAccount = in_array((int) $member->userid, $specialAccounts, true);
|
||||
|
||||
if ($isRestrictedVType && !$isSpecialAccount) {
|
||||
return [0];
|
||||
}
|
||||
|
||||
return $platforms;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建前端平台筛选项。
|
||||
*
|
||||
* @param array<int> $platforms 当前用户可见平台
|
||||
* @param int $userid 当前用户ID
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private function buildPlatformTabs(array $platforms, int $userid): array
|
||||
{
|
||||
$tabs = [
|
||||
[
|
||||
'id' => null,
|
||||
'name' => '全部平台',
|
||||
'key' => 'all',
|
||||
'count' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
$allCount = 0;
|
||||
foreach ($platforms as $platform) {
|
||||
$count = DyVideoUser::where('userid', $userid)
|
||||
->where('disabled', 0)
|
||||
->where('platform', $platform)
|
||||
->count();
|
||||
|
||||
$allCount += (int) $count;
|
||||
$tabs[] = [
|
||||
'id' => $platform,
|
||||
'name' => self::PLATFORM_NAME_MAP[$platform] ?? ('平台' . $platform),
|
||||
'key' => self::PLATFORM_KEY_MAP[$platform] ?? ('platform_' . $platform),
|
||||
'count' => (int) $count,
|
||||
];
|
||||
}
|
||||
|
||||
$tabs[0]['count'] = $allCount;
|
||||
|
||||
return $tabs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把数据库记录转换为前端可直接渲染的账号卡片。
|
||||
*
|
||||
* 状态字段解释按 acgpmw `get_zhanghu_list()` 三列展示对齐:
|
||||
* - `is_endauth` => 账号授权状态
|
||||
* - `aa_endauth` => 数据授权状态
|
||||
* - `browser` => 异常状态
|
||||
*
|
||||
* @param array $account dy_video_user 单条记录
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function buildAccountItem(array $account): array
|
||||
{
|
||||
$platform = (int) ($account['platform'] ?? 0);
|
||||
$countryName = '';
|
||||
|
||||
if ($platform === 10) {
|
||||
$titkInfo = DyVideoUserTitk::findByVuid((int) $account['id']);
|
||||
$countryName = (string) ($titkInfo->country_name ?? '');
|
||||
}
|
||||
|
||||
$accountAuth = (int) ($account['is_endauth'] ?? 0) === 1
|
||||
? $this->buildStatusBlock('授权到期', 'danger', '请重新完成平台授权')
|
||||
: $this->buildStatusBlock('授权正常', 'success', '当前账号授权可用');
|
||||
|
||||
$dataAuth = (int) ($account['aa_endauth'] ?? 0) === 1
|
||||
? $this->buildStatusBlock('授权到期', 'danger', '请重新完成数据授权')
|
||||
: $this->buildStatusBlock('授权正常', 'success', '当前数据授权可用');
|
||||
|
||||
$exceptionStatus = (int) ($account['browser'] ?? 0) === 1
|
||||
? $this->buildStatusBlock('发布异常', 'warning', '发布链路存在异常,需要人工处理')
|
||||
: $this->buildStatusBlock('使用正常', 'success', '当前账号发布链路正常');
|
||||
|
||||
return [
|
||||
'id' => (int) $account['id'],
|
||||
'platform' => $platform,
|
||||
'platform_name' => self::PLATFORM_NAME_MAP[$platform] ?? ('平台' . $platform),
|
||||
'platform_key' => self::PLATFORM_KEY_MAP[$platform] ?? ('platform_' . $platform),
|
||||
'nickname' => (string) ($account['dy_nickname'] ?? ''),
|
||||
'avatar' => (string) ($account['dy_avatar'] ?? ''),
|
||||
'intro' => (string) ($account['dy_intro'] ?? ''),
|
||||
'phone' => (string) ($account['info_shouji'] ?? ''),
|
||||
'country_name' => $countryName,
|
||||
'proviceid' => (int) ($account['proviceid'] ?? 0),
|
||||
'is_lanv' => (int) ($account['is_lanv'] ?? 0) === 1,
|
||||
'is_qyh' => (int) ($account['is_qyh'] ?? 0) === 1,
|
||||
'account_status' => $accountAuth,
|
||||
'data_status' => $dataAuth,
|
||||
'exception_status' => $exceptionStatus,
|
||||
'status_overview' => $this->buildOverviewStatus($accountAuth, $dataAuth, $exceptionStatus),
|
||||
'display_code' => '#P' . (int) $account['id'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建单个状态块。
|
||||
*
|
||||
* @param string $text 显示文案
|
||||
* @param string $tone 视觉色调:success / warning / danger
|
||||
* @param string $hint 补充说明
|
||||
* @return array<string, string>
|
||||
*/
|
||||
private function buildStatusBlock(string $text, string $tone, string $hint): array
|
||||
{
|
||||
return [
|
||||
'text' => $text,
|
||||
'tone' => $tone,
|
||||
'hint' => $hint,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 汇总账号卡片主状态,便于列表页用一个醒目标记表示当前账号健康度。
|
||||
*
|
||||
* @param array $accountAuth 账号授权状态
|
||||
* @param array $dataAuth 数据授权状态
|
||||
* @param array $exceptionStatus 异常状态
|
||||
* @return array<string, string>
|
||||
*/
|
||||
private function buildOverviewStatus(array $accountAuth, array $dataAuth, array $exceptionStatus): array
|
||||
{
|
||||
if ($accountAuth['tone'] === 'danger' || $dataAuth['tone'] === 'danger') {
|
||||
return $this->buildStatusBlock('需重新授权', 'danger', '账号授权或数据授权已到期');
|
||||
}
|
||||
|
||||
if ($exceptionStatus['tone'] === 'warning') {
|
||||
return $this->buildStatusBlock('存在异常', 'warning', '当前账号发布链路异常');
|
||||
}
|
||||
|
||||
return $this->buildStatusBlock('状态正常', 'success', '账号与发布状态均正常');
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计当前筛选结果。
|
||||
*
|
||||
* @param array<int, array<string, mixed>> $items 列表项
|
||||
* @return array<string, int>
|
||||
*/
|
||||
private function buildSummary(array $items): array
|
||||
{
|
||||
$summary = [
|
||||
'total' => count($items),
|
||||
'need_reauth_count' => 0,
|
||||
'browser_exception_count' => 0,
|
||||
'normal_count' => 0,
|
||||
];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$needReauth = $item['account_status']['tone'] === 'danger' || $item['data_status']['tone'] === 'danger';
|
||||
$hasBrowserException = $item['exception_status']['tone'] === 'warning';
|
||||
|
||||
if ($needReauth) {
|
||||
$summary['need_reauth_count']++;
|
||||
}
|
||||
|
||||
if ($hasBrowserException) {
|
||||
$summary['browser_exception_count']++;
|
||||
}
|
||||
|
||||
if (!$needReauth && !$hasBrowserException) {
|
||||
$summary['normal_count']++;
|
||||
}
|
||||
}
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载 acgpmw 的特殊账号名单。
|
||||
*
|
||||
* 这里优先读取基线项目 `/root/work/acgpmw/data/other/tw_special_account.php`,
|
||||
* 保证 146/147 套餐用户的平台权限限制与原系统保持一致;
|
||||
* 若文件不存在,则退回空数组,接口仍可工作。
|
||||
*
|
||||
* @return array<int>
|
||||
*/
|
||||
private function loadSpecialAccounts(): array
|
||||
{
|
||||
$specialAccountFile = '/root/work/acgpmw/data/other/tw_special_account.php';
|
||||
|
||||
if (!is_file($specialAccountFile)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$accounts = require $specialAccountFile;
|
||||
|
||||
return is_array($accounts)
|
||||
? array_values(array_map('intval', $accounts))
|
||||
: [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user