From 6b46767d86eb7007cf882cee51de8df805c90d8a Mon Sep 17 00:00:00 2001 From: nepiedg <806669289@qq.com.com> Date: Thu, 2 Apr 2026 07:09:29 +0000 Subject: [PATCH] refactor(member, auth): streamline product info retrieval and enhance dashboard statistics - Updated `getProductInfo` method in `Member` model to use a unified model for fetching product data. - Refactored `logLogin` method to utilize `MemberLoginLog` for logging login attempts. - Introduced `getDashboardStats` method in `AuthService` to gather user-specific statistics, including remaining quotas and counts of authorized accounts, published tasks, and works. - Added new database configuration for Douyin business statistics. --- app/api/model/DyVideoCron.php | 35 ++++++++++++++++++++ app/api/model/DyVideoUser.php | 35 ++++++++++++++++++++ app/api/model/DysVideoLog.php | 54 ++++++++++++++++++++++++++++++ app/api/model/Member.php | 33 ++++++++----------- app/api/model/MemberLoginLog.php | 32 ++++++++++++++++++ app/api/model/ProductList.php | 34 +++++++++++++++++++ app/api/service/AuthService.php | 56 ++++++++++++++++++++++++++++++++ config/database.php | 21 ++++++++++++ 8 files changed, 281 insertions(+), 19 deletions(-) create mode 100644 app/api/model/DyVideoCron.php create mode 100644 app/api/model/DyVideoUser.php create mode 100644 app/api/model/DysVideoLog.php create mode 100644 app/api/model/MemberLoginLog.php create mode 100644 app/api/model/ProductList.php diff --git a/app/api/model/DyVideoCron.php b/app/api/model/DyVideoCron.php new file mode 100644 index 0000000..f13cd06 --- /dev/null +++ b/app/api/model/DyVideoCron.php @@ -0,0 +1,35 @@ +where('status', '<>', 3) + ->count(); + } +} diff --git a/app/api/model/DyVideoUser.php b/app/api/model/DyVideoUser.php new file mode 100644 index 0000000..1f22edb --- /dev/null +++ b/app/api/model/DyVideoUser.php @@ -0,0 +1,35 @@ +where('disabled', 0) + ->count(); + } +} diff --git a/app/api/model/DysVideoLog.php b/app/api/model/DysVideoLog.php new file mode 100644 index 0000000..ba373e8 --- /dev/null +++ b/app/api/model/DysVideoLog.php @@ -0,0 +1,54 @@ +db() + ->name($tableName) + ->where('userid', $userid) + ->where('status', '<=', 1) + ->count(); + } + + /** + * 根据用户ID计算分表名。 + * + * @param int $userid 用户ID + * @return string + */ + private static function resolveTableName(int $userid): string + { + return sprintf('dys_video_log_%d', $userid % 1000); + } +} diff --git a/app/api/model/Member.php b/app/api/model/Member.php index 9d9e0e8..a838135 100644 --- a/app/api/model/Member.php +++ b/app/api/model/Member.php @@ -95,13 +95,10 @@ class Member extends Model */ public function getProductInfo(): ?array { - // 从主库获取套餐信息 - $product = \think\facade\Db::connect('dbbiz') - ->name('product_list') - ->where('v_type', $this->v_type) - ->find(); + // 套餐配置改由模型统一封装,避免业务层散落裸表查询。 + $product = ProductList::findByVType((int) $this->v_type); - return $product; + return $product ? $product->toArray() : null; } /** @@ -126,19 +123,17 @@ class Member extends Model public function logLogin(bool $success, string $loginType = 'password'): void { try { - \think\facade\Db::connect('dbmember') - ->name('member_login_log') - ->insert([ - 'userid' => $this->userid, - 'ip' => request()->ip(), - 'time' => time(), - 'succeed' => $success ? 1 : 0, - 'diqu' => '', - 'login_type' => $loginType, - 'adminid' => 0, - 'v_type' => $this->v_type ?? 0, - ]); - } catch (\Exception $e) { + MemberLoginLog::recordLogin([ + 'userid' => $this->userid, + 'ip' => request()->ip(), + 'time' => time(), + 'succeed' => $success ? 1 : 0, + 'diqu' => '', + 'login_type' => $loginType, + 'adminid' => 0, + 'v_type' => $this->v_type ?? 0, + ]); + } catch (\Throwable $e) { // 日志记录失败不影响登录 } } diff --git a/app/api/model/MemberLoginLog.php b/app/api/model/MemberLoginLog.php new file mode 100644 index 0000000..9e34b31 --- /dev/null +++ b/app/api/model/MemberLoginLog.php @@ -0,0 +1,32 @@ +save($payload); + } +} diff --git a/app/api/model/ProductList.php b/app/api/model/ProductList.php new file mode 100644 index 0000000..8d0331f --- /dev/null +++ b/app/api/model/ProductList.php @@ -0,0 +1,34 @@ +find(); + } +} diff --git a/app/api/service/AuthService.php b/app/api/service/AuthService.php index 8b436f3..f217bdb 100644 --- a/app/api/service/AuthService.php +++ b/app/api/service/AuthService.php @@ -4,6 +4,9 @@ declare(strict_types=1); namespace app\api\service; use app\api\common\Jwt; +use app\api\model\DyVideoCron; +use app\api\model\DyVideoUser; +use app\api\model\DysVideoLog; use app\api\model\Member; /** @@ -155,6 +158,7 @@ class AuthService // 获取套餐信息 $productInfo = $member->getProductInfo(); + $dashboardStats = $this->getDashboardStats($member, $productInfo); return [ 'userid' => $member->userid, @@ -163,14 +167,66 @@ class AuthService 'endtime' => $member->endtime, 'formtypeid' => $member->formtypeid, 'disabled' => $member->disabled, + 'video_num' => $member->video_num, + 'sp_num' => $member->sp_num, 'product' => $productInfo ? [ 'v_type' => $productInfo['v_type'] ?? null, + 'nameu' => $productInfo['nameu'] ?? '', 'video_num' => $productInfo['video_num'] ?? 0, 'account_num' => $productInfo['account_num'] ?? 0, ] : null, + 'stats' => $dashboardStats, ]; } + /** + * 获取首页统计数据。 + * + * 此处按 acgpmw `dyai/controller/index.php::right()` 的首页语义对齐: + * - 账户剩余条数:优先展示用户余额 `member.video_num` + * - 授权账号:统计 `dy_video_user` + * - 发布任务:统计 `dy_video_cron` + * - 发布作品:统计抖音日志分表 `dys_video_log_{userid % 1000}` + * + * 查询失败时返回 null,避免前端把异常误展示为 0。 + * + * @param Member $member 当前登录用户 + * @param array|null $productInfo 当前套餐信息 + * @return array + */ + private function getDashboardStats(Member $member, ?array $productInfo = null): array + { + $isUnlimitedQuota = $productInfo && (int) ($productInfo['video_num'] ?? 0) < 0; + + $stats = [ + 'remaining_quota' => $isUnlimitedQuota ? null : (int) ($member->video_num ?? 0), + 'remaining_quota_unlimited' => $isUnlimitedQuota, + 'published_works_count' => null, + 'authorized_account_count' => null, + 'published_task_count' => null, + ]; + + try { + $stats['authorized_account_count'] = DyVideoUser::countActiveByUserId((int) $member->userid); + } catch (\Throwable $exception) { + // 统计接口需要尽量稳健,单项查询失败时不阻断登录信息返回。 + } + + try { + $stats['published_task_count'] = DyVideoCron::countActiveByUserId((int) $member->userid); + } catch (\Throwable $exception) { + // 这里与 acgpmw 一样只排除 status=3 的任务,其余状态均计入首页统计。 + } + + try { + $stats['published_works_count'] = DysVideoLog::countPublishedByUserId((int) $member->userid); + } catch (\Throwable $exception) { + // 发布作品日志使用分表存储,查询失败时前端按“待接入”兜底展示。 + } + + return $stats; + } + /** * 修改密码 * @param int $userid diff --git a/config/database.php b/config/database.php index 70f38c5..38ed2e3 100644 --- a/config/database.php +++ b/config/database.php @@ -62,6 +62,27 @@ return [ 'fields_cache' => false, ], + // 抖音业务数据库(用于首页发布作品统计分表) + 'dbdouying' => [ + 'type' => 'mysql', + 'hostname' => env('DB_DOUYING_HOSTNAME', 'rm-m5e6936bb24oj5272co.mysql.rds.aliyuncs.com'), + 'database' => env('DB_DOUYING_DATABASE', 'douying'), + 'username' => env('DB_DOUYING_USERNAME', 'contenttpl'), + 'password' => env('DB_DOUYING_PASSWORD', 'QXYxgg123!@#q'), + 'hostport' => env('DB_DOUYING_HOSTPORT', '3306'), + 'params' => [], + 'charset' => env('DB_DOUYING_CHARSET', 'utf8'), + 'prefix' => '', + 'deploy' => 0, + 'rw_separate' => false, + 'master_num' => 1, + 'slave_no' => '', + 'fields_strict' => false, + 'break_reconnect' => false, + 'trigger_sql' => env('APP_DEBUG', true), + 'fields_cache' => false, + ], + // 后台管理数据库 'dbxgg' => [ 'type' => 'mysql',