Files
mini_tp/app/api/service/PlatformService.php
T
nepiedg 5a9d6090f3 feat(member): enhance product info processing and add new utility methods
- Updated `getProductInfo` method to return processed product information using `buildEffectiveProductInfo`.
- Introduced new private methods for building effective product info, resolving software account levels, and checking special TikTok account status.
- Refactored platform string handling with `appendPlatform` method to ensure unique and sorted platform entries.
- Updated platform name mappings in `PlatformService` for consistency with new naming conventions.
2026-04-02 10:43:25 +00:00

326 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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 => 'D音',
1 => 'K手',
2 => 'B家号',
3 => '小红薯',
4 => '视P号',
5 => 'B哩哔哩',
6 => '公Z号',
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. 先使用已按 `MemberController` 规则加工后的套餐平台权限
* 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))
: [];
}
}