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.
This commit is contained in:
nepiedg
2026-04-02 10:43:25 +00:00
parent 044586d60a
commit 5a9d6090f3
5 changed files with 246 additions and 9 deletions
+36
View File
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace app\api\model;
use think\Model;
/**
* 用户特殊绑定额度模型(对应 dy_special_binding 表)
*
* 该表用于补充用户级绑定上限、公众号绑定数等特殊能力。
*/
class DySpecialBinding extends Model
{
// 与 acgpmw 保持一致,特殊绑定配置存放在 member 库。
protected $connection = 'dbmember';
protected $name = 'dy_special_binding';
protected $pk = 'id';
protected $autoWriteTimestamp = false;
/**
* 获取当前用户启用中的特殊绑定配置。
*
* @param int $userid 用户ID
* @return self|null
*/
public static function findActiveByUserid(int $userid): ?self
{
return self::where('userid', $userid)
->where('disabled', 0)
->find();
}
}
+36
View File
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace app\api\model;
use think\Model;
/**
* 用户单独平台权限模型(对应 dy_special_platforms 表)
*
* 该表用于覆盖套餐默认平台集合,并补充少量用户级能力开关。
*/
class DySpecialPlatforms extends Model
{
// 与 acgpmw 保持一致,特殊平台权限存放在 member 库。
protected $connection = 'dbmember';
protected $name = 'dy_special_platforms';
protected $pk = 'id';
protected $autoWriteTimestamp = false;
/**
* 获取当前用户启用中的特殊平台配置。
*
* @param int $userid 用户ID
* @return self|null
*/
public static function findActiveByUserid(int $userid): ?self
{
return self::where('userid', $userid)
->where('disabled', 0)
->find();
}
}
+158 -1
View File
@@ -98,7 +98,11 @@ class Member extends Model
// 套餐配置改由模型统一封装,避免业务层散落裸表查询。
$product = ProductList::findByVType((int) $this->v_type);
return $product ? $product->toArray() : null;
if (!$product) {
return null;
}
return $this->buildEffectiveProductInfo($product->toArray());
}
/**
@@ -137,4 +141,157 @@ class Member extends Model
// 日志记录失败不影响登录
}
}
/**
* 构建与 acgpmw `MemberController` 对齐后的套餐信息。
*
* 这里只补齐当前 tp 已实际用到的套餐二次加工逻辑:
* 1. 处理特定版本新增平台
* 2. 处理用户单独平台覆盖
* 3. 处理公众号/微信绑定等特殊额度
* 4. 处理内部账号临时补平台
*
* @param array $productInfo 原始套餐信息
* @return array
*/
private function buildEffectiveProductInfo(array $productInfo): array
{
$productInfo['platforms'] = (string) ($productInfo['platforms'] ?? '');
// 对齐 acgpmw:金钻/钻石新注册账号额外补充 B站 和 B家号。
if ((int) $this->regtime >= 1773158400
&& in_array((int) $this->v_type, [123, 124], true)
&& (int) ($productInfo['video_num'] ?? 0) > 0
) {
$productInfo['platforms'] = self::appendPlatform($productInfo['platforms'], 2);
$productInfo['platforms'] = self::appendPlatform($productInfo['platforms'], 5);
}
// 对齐 acgpmw:用户单独平台权限可直接覆盖套餐平台集合。
$specialPlatforms = DySpecialPlatforms::findActiveByUserid((int) $this->userid);
$productInfo['sora_turntable_type'] = (int) ($specialPlatforms->sora_turntable_type ?? 0);
if ($specialPlatforms) {
$specialPlatformsData = $specialPlatforms->toArray();
if (!empty($specialPlatformsData['platforms'])) {
$productInfo['platforms'] = (string) $specialPlatformsData['platforms'];
}
if (!empty($specialPlatformsData['kword_num'])) {
$productInfo['kword_num'] = $specialPlatformsData['kword_num'];
}
if (!empty($specialPlatformsData['is_video_num']) && (int) ($productInfo['video_num'] ?? 0) < 0) {
$productInfo['video_num'] = 1;
}
}
// 对齐 acgpmw:用户单独绑定额度可覆盖微信/公众号绑定数量。
$specialBinding = DySpecialBinding::findActiveByUserid((int) $this->userid);
if ($specialBinding) {
$specialBindingData = $specialBinding->toArray();
if ((int) ($specialBindingData['wx_num'] ?? 0) > 0) {
$productInfo['wx_num'] = (int) $specialBindingData['wx_num'];
}
if ((int) ($specialBindingData['wxgzh_num'] ?? 0) > 0) {
$productInfo['wxgzh_num'] = (int) $specialBindingData['wxgzh_num'];
}
}
$productInfo['soft_groups_auth'] = $this->resolveSoftGroupsAuth();
// 对齐 acgpmw:内部号在部分版本下临时追加 B家号、B站、公众号。
if ((int) $this->staff_type === 1
&& in_array((int) $productInfo['soft_groups_auth'], [0, 2], true)
&& !$this->hasTitkAuth()
) {
$productInfo['platforms'] = self::appendPlatform($productInfo['platforms'], 2);
$productInfo['platforms'] = self::appendPlatform($productInfo['platforms'], 5);
$productInfo['platforms'] = self::appendPlatform($productInfo['platforms'], 6);
}
return $productInfo;
}
/**
* 计算软件账号等级标识。
*
* 该规则直接按 acgpmw `MemberController` 中的 `soft_groups_auth` 判定对齐。
*
* @return int
*/
private function resolveSoftGroupsAuth(): int
{
$vType = (int) $this->v_type;
$softGroupsAuth = 0;
$softGroupVTypes = [144, 145, 146, 147, 156];
if (in_array($vType, $softGroupVTypes, true)) {
$softGroupsAuth = 1;
}
if (in_array($vType, [149, 152, 157], true)) {
$softGroupsAuth = 2;
}
if (in_array($vType, [161], true)) {
$softGroupsAuth = 3;
}
if (in_array($vType, [162], true)) {
$softGroupsAuth = 4;
}
if (in_array($vType, [169], true)) {
$softGroupsAuth = 6;
}
if (in_array($vType, [170], true)) {
$softGroupsAuth = 7;
}
if (in_array($vType, [171, 172, 173], true)) {
$softGroupsAuth = 8;
}
if (in_array($vType, [176, 177, 178, 179], true)) {
$softGroupsAuth = 9;
}
if (in_array($vType, [180], true)) {
$softGroupsAuth = 10;
}
return $softGroupsAuth;
}
/**
* 判断当前用户是否属于 TikTok 特殊账号版本。
*
* @return bool
*/
private function hasTitkAuth(): bool
{
return in_array((int) $this->v_type, [158, 159, 160, 163, 164, 166], true);
}
/**
* 追加平台到逗号包裹的平台字符串中。
*
* @param string $platforms 平台字符串,如 `,0,1,6,`
* @param int $platform 平台编号
* @return string
*/
private static function appendPlatform(string $platforms, int $platform): string
{
if (strpos($platforms, ',' . $platform . ',') !== false) {
return $platforms;
}
$platformList = [];
$platformText = trim($platforms, ',');
if ($platformText !== '') {
foreach (explode(',', $platformText) as $item) {
if ($item === '') {
continue;
}
$platformList[] = (int) $item;
}
}
$platformList[] = $platform;
$platformList = array_values(array_unique($platformList));
sort($platformList);
return ',' . implode(',', $platformList) . ',';
}
}
+8 -8
View File
@@ -37,13 +37,13 @@ class PlatformService
* 这里在 API 中直接返回前端所需文案,避免小程序自行猜测。
*/
private const PLATFORM_NAME_MAP = [
0 => '音',
1 => '手',
2 => '家号',
3 => '小红',
4 => '视号',
5 => 'B',
6 => '公号',
0 => 'D音',
1 => 'K手',
2 => 'B家号',
3 => '小红',
4 => '视P号',
5 => 'B哩哔哩',
6 => '公Z号',
10 => 'TikTok',
];
@@ -104,7 +104,7 @@ class PlatformService
* 计算当前用户可见平台。
*
* 该逻辑直接对齐 acgpmw `platform::index()`
* 1. 从套餐 `product_list.platforms` 读取平台权限
* 1. 先使用已按 `MemberController` 规则加工后的套餐平台权限
* 2. 若为 146/147 且不在特殊账号名单中,仅允许抖音平台
*
* @param Member $member 当前登录用户
+8
View File
@@ -4,6 +4,7 @@ declare(strict_types=1);
use think\facade\Route;
use app\api\controller\v1\Auth;
use app\api\controller\v1\Platform;
use app\api\controller\v1\PublishPlan;
/**
* 全局路由入口。
@@ -31,3 +32,10 @@ Route::group('api/v1/auth', function () {
Route::group('api/v1/platform', function () {
Route::get('accounts', [Platform::class, 'accounts']);
})->middleware(\app\api\middleware\Auth::class);
// v1 发布计划接口(需登录)
Route::group('api/v1/publish-plan', function () {
Route::get('list', [PublishPlan::class, 'index']);
Route::post('start/:id', [PublishPlan::class, 'start']);
Route::post('stop/:id', [PublishPlan::class, 'stop']);
})->middleware(\app\api\middleware\Auth::class);