ソースを参照

refactor: remove bilibili and kuaishou platforms, keep 4 platforms

删除 bilibili(B站) 和 kuaishou(快手) 两个平台:移除适配器文件、shared PlatformType 枚举值与 PLATFORMS 配置、HeadlessBrowserService/PublishService/AccountService/BrowserLoginService 等所有引用、孤儿图标 svg;新增 database/migrations/delete_bilibili_kuaishou_and_related.sql 清理历史数据并缩减 platform 枚举。保留 douyin/weixin_video/xiaohongshu/baijiahao 四个平台实现及 toutiao/qie/dayuhao 占位。前端 AVAILABLE_PLATFORM_TYPES 本就只有这 4 个。
Ethanfly 4 週間 前
コミット
8a5aaaec60

+ 0 - 4
client/src/assets/platforms/bilibili.svg

@@ -1,4 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
-  <rect x="1" y="1" width="22" height="22" rx="6" fill="#60a5fa"/>
-  <text x="12" y="15" text-anchor="middle" font-size="10" font-family="Arial, Helvetica, sans-serif" fill="#ffffff">B</text>
-</svg>

+ 0 - 4
client/src/assets/platforms/kuaishou.svg

@@ -1,4 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
-  <rect x="1" y="1" width="22" height="22" rx="6" fill="#f59e0b"/>
-  <text x="12" y="15" text-anchor="middle" font-size="9" font-family="Arial, Helvetica, sans-serif" fill="#ffffff">KS</text>
-</svg>

+ 2 - 68
client/src/components/BrowserTab.vue

@@ -301,7 +301,7 @@ const isAdminMode = computed(() => !!props.tab.browserData?.isAdminMode);
 const hasValidAccountInfo = computed(() => {
 const hasValidAccountInfo = computed(() => {
   if (!accountInfo.value) return false;
   if (!accountInfo.value) return false;
   const defaultNames = [
   const defaultNames = [
-    '抖音账号', '小红书账号', '快手账号', '视频号账号', 'B站账号', 
+    '抖音账号', '小红书账号', '视频号账号',
     '头条账号', '百家号账号', '企鹅号账号', '大鱼号账号'
     '头条账号', '百家号账号', '企鹅号账号', '大鱼号账号'
   ];
   ];
   return accountInfo.value.accountName && !defaultNames.includes(accountInfo.value.accountName);
   return accountInfo.value.accountName && !defaultNames.includes(accountInfo.value.accountName);
@@ -647,7 +647,7 @@ async function handleAILoginSuccess(currentScreenshot: string) {
   
   
   // 检查是否成功提取到有效的账号信息(排除默认值)
   // 检查是否成功提取到有效的账号信息(排除默认值)
   const defaultNames = [
   const defaultNames = [
-    '抖音账号', '小红书账号', '快手账号', '视频号账号', 'B站账号', 
+    '抖音账号', '小红书账号', '视频号账号',
     '头条账号', '百家号账号', '企鹅号账号', '大鱼号账号', '未知账号'
     '头条账号', '百家号账号', '企鹅号账号', '大鱼号账号', '未知账号'
   ];
   ];
   const isValidAccountInfo = extractedAccountInfo && 
   const isValidAccountInfo = extractedAccountInfo && 
@@ -1800,11 +1800,6 @@ function isLoggedInByUrl(): boolean {
       /creator\.douyin\.com\/login/,        // 登录页
       /creator\.douyin\.com\/login/,        // 登录页
       /passport\.douyin\.com/,              // 护照登录
       /passport\.douyin\.com/,              // 护照登录
     ],
     ],
-    kuaishou: [
-      /passport\.kuaishou/,
-      /login\.kuaishou/,
-      /cp\.kuaishou\.com\/?$/,              // 快手创作者根路径
-    ],
     xiaohongshu: [
     xiaohongshu: [
       /creator\.xiaohongshu\.com\/?$/,      // 小红书根路径(会重定向到登录页)
       /creator\.xiaohongshu\.com\/?$/,      // 小红书根路径(会重定向到登录页)
       /creator\.xiaohongshu\.com\/login/,   // 登录页
       /creator\.xiaohongshu\.com\/login/,   // 登录页
@@ -1814,11 +1809,6 @@ function isLoggedInByUrl(): boolean {
       /channels\.weixin\.qq\.com\/login\.html/,   // 登录页
       /channels\.weixin\.qq\.com\/login\.html/,   // 登录页
       /channels\.weixin\.qq\.com\/platform\/login/, // iframe 登录页
       /channels\.weixin\.qq\.com\/platform\/login/, // iframe 登录页
     ],
     ],
-    bilibili: [
-      /passport\.bilibili/,
-      /login\.bilibili/,
-      /member\.bilibili\.com\/?$/,          // B站创作者根路径
-    ],
     toutiao: [/passport\.toutiao/],
     toutiao: [/passport\.toutiao/],
     baijiahao: [
     baijiahao: [
       /baijiahao\.baidu\.com\/?$/,          // 百家号根路径
       /baijiahao\.baidu\.com\/?$/,          // 百家号根路径
@@ -1839,10 +1829,6 @@ function isLoggedInByUrl(): boolean {
       /creator\.douyin\.com\/creator-micro\/home/,  // 主要判断条件
       /creator\.douyin\.com\/creator-micro\/home/,  // 主要判断条件
       /creator\.douyin\.com\/creator-micro/,        // creator-micro 下的其他页面也算
       /creator\.douyin\.com\/creator-micro/,        // creator-micro 下的其他页面也算
     ],
     ],
-    kuaishou: [
-      /cp\.kuaishou\.com\/article/,
-      /cp\.kuaishou\.com\/profile/,
-    ],
     xiaohongshu: [
     xiaohongshu: [
       /creator\.xiaohongshu\.com\/new\/home/,       // 主要判断条件
       /creator\.xiaohongshu\.com\/new\/home/,       // 主要判断条件
       /creator\.xiaohongshu\.com\/new\//,           // /new/ 下的其他页面也算
       /creator\.xiaohongshu\.com\/new\//,           // /new/ 下的其他页面也算
@@ -1851,10 +1837,6 @@ function isLoggedInByUrl(): boolean {
       /channels\.weixin\.qq\.com\/platform(?!\/login)/,        // 主要判断条件(排除 iframe 登录页)
       /channels\.weixin\.qq\.com\/platform(?!\/login)/,        // 主要判断条件(排除 iframe 登录页)
       /channels\.weixin\.qq\.com\/mp\//,                       // 新版视频号后台(mp 路径)
       /channels\.weixin\.qq\.com\/mp\//,                       // 新版视频号后台(mp 路径)
     ],
     ],
-    bilibili: [
-      /member\.bilibili\.com\/platform/,
-      /space\.bilibili\.com\/\d+/,
-    ],
     toutiao: [
     toutiao: [
       /mp\.toutiao\.com\/profile/,
       /mp\.toutiao\.com\/profile/,
     ],
     ],
@@ -1876,13 +1858,11 @@ function isLoggedInByUrl(): boolean {
       /douyin\.com/,
       /douyin\.com/,
       /bytedance\.com/,        // 字节跳动相关域名(活动弹窗等)
       /bytedance\.com/,        // 字节跳动相关域名(活动弹窗等)
     ],
     ],
-    kuaishou: [/kuaishou\.com/],
     xiaohongshu: [
     xiaohongshu: [
       /xiaohongshu\.com/,
       /xiaohongshu\.com/,
       /xhslink\.com/,
       /xhslink\.com/,
     ],
     ],
     weixin_video: [/channels\.weixin\.qq\.com/],
     weixin_video: [/channels\.weixin\.qq\.com/],
-    bilibili: [/bilibili\.com/],
     toutiao: [/toutiao\.com/],
     toutiao: [/toutiao\.com/],
     baijiahao: [/baidu\.com/, /baijiahao\.baidu\.com/],
     baijiahao: [/baidu\.com/, /baijiahao\.baidu\.com/],
   };
   };
@@ -1998,11 +1978,6 @@ function isOnLoginPage(): boolean {
       /creator\.douyin\.com\/login/,
       /creator\.douyin\.com\/login/,
       /passport\.douyin\.com/,
       /passport\.douyin\.com/,
     ],
     ],
-    kuaishou: [
-      /passport\.kuaishou/,
-      /login\.kuaishou/,
-      /cp\.kuaishou\.com\/?$/,              // 快手创作者根路径
-    ],
     xiaohongshu: [
     xiaohongshu: [
       /creator\.xiaohongshu\.com\/?$/,      // 小红书创作者根路径(会重定向到登录页)
       /creator\.xiaohongshu\.com\/?$/,      // 小红书创作者根路径(会重定向到登录页)
       /creator\.xiaohongshu\.com\/login/,   // 小红书登录页
       /creator\.xiaohongshu\.com\/login/,   // 小红书登录页
@@ -2012,11 +1987,6 @@ function isOnLoginPage(): boolean {
       /channels\.weixin\.qq\.com\/login\.html/,   // 视频号登录页
       /channels\.weixin\.qq\.com\/login\.html/,   // 视频号登录页
       /channels\.weixin\.qq\.com\/platform\/login/, // 视频号 iframe 登录页
       /channels\.weixin\.qq\.com\/platform\/login/, // 视频号 iframe 登录页
     ],
     ],
-    bilibili: [
-      /passport\.bilibili/,
-      /login\.bilibili/,
-      /member\.bilibili\.com\/?$/,          // B站创作者根路径
-    ],
     toutiao: [/passport\.toutiao/],
     toutiao: [/passport\.toutiao/],
     baijiahao: [
     baijiahao: [
       /baijiahao\.baidu\.com\/?$/,          // 百家号根路径
       /baijiahao\.baidu\.com\/?$/,          // 百家号根路径
@@ -3308,22 +3278,6 @@ async function extractAccountInfoFromPage(): Promise<{
           return result;
           return result;
         })()
         })()
       `,
       `,
-      kuaishou: `
-        (function() {
-          const result = { accountId: '', accountName: '', avatarUrl: '', fansCount: 0, worksCount: 0 };
-          
-          const avatarEl = document.querySelector('.user-avatar img, [class*="avatar"] img');
-          if (avatarEl) result.avatarUrl = avatarEl.src || '';
-          
-          const nameEl = document.querySelector('.user-name, [class*="userName"], [class*="nickname"]');
-          if (nameEl) result.accountName = nameEl.textContent?.trim() || '';
-          
-          const uidMatch = document.cookie.match(/userId=([^;]+)/);
-          if (uidMatch) result.accountId = 'kuaishou_' + uidMatch[1];
-          
-          return result;
-        })()
-      `,
       baijiahao: `
       baijiahao: `
         (function() {
         (function() {
           const result = { accountId: '', accountName: '', avatarUrl: '', fansCount: 0, worksCount: 0 };
           const result = { accountId: '', accountName: '', avatarUrl: '', fansCount: 0, worksCount: 0 };
@@ -3463,22 +3417,6 @@ async function extractAccountInfoFromPage(): Promise<{
           return result;
           return result;
         })()
         })()
       `,
       `,
-      bilibili: `
-        (function() {
-          const result = { accountId: '', accountName: '', avatarUrl: '', fansCount: 0, worksCount: 0 };
-          
-          const avatarEl = document.querySelector('.user-avatar img, [class*="avatar"] img');
-          if (avatarEl) result.avatarUrl = avatarEl.src || '';
-          
-          const nameEl = document.querySelector('.user-name, [class*="userName"], [class*="nickname"]');
-          if (nameEl) result.accountName = nameEl.textContent?.trim() || '';
-          
-          const uidMatch = document.cookie.match(/DedeUserID=([^;]+)/);
-          if (uidMatch) result.accountId = 'bilibili_' + uidMatch[1];
-          
-          return result;
-        })()
-      `,
       weixin_video: `
       weixin_video: `
         (function() {
         (function() {
           const result = { accountId: '', accountName: '', avatarUrl: '', fansCount: 0, worksCount: 0 };
           const result = { accountId: '', accountName: '', avatarUrl: '', fansCount: 0, worksCount: 0 };
@@ -3877,10 +3815,8 @@ function checkHasLoginCookie(cookies: Electron.Cookie[]): boolean {
   // 注意:只检查真正表示已登录的 cookie,不要包含通用 cookie
   // 注意:只检查真正表示已登录的 cookie,不要包含通用 cookie
   const platformCookieNames: Record<string, string[]> = {
   const platformCookieNames: Record<string, string[]> = {
     douyin: ['sessionid', 'passport_csrf_token', 'sid_guard'],
     douyin: ['sessionid', 'passport_csrf_token', 'sid_guard'],
-    kuaishou: ['passToken', 'userId'],
     xiaohongshu: ['web_session', 'xsecappid'],
     xiaohongshu: ['web_session', 'xsecappid'],
     weixin_video: ['wxuin', 'pass_ticket'],
     weixin_video: ['wxuin', 'pass_ticket'],
-    bilibili: ['SESSDATA', 'bili_jct'],
     toutiao: ['sessionid', 'sso_uid'],
     toutiao: ['sessionid', 'sso_uid'],
     baijiahao: ['BDUSS', 'STOKEN'],  // BAIDUID 是通用 Cookie,不能用于判断登录
     baijiahao: ['BDUSS', 'STOKEN'],  // BAIDUID 是通用 Cookie,不能用于判断登录
     qie: ['uin', 'skey'],
     qie: ['uin', 'skey'],
@@ -4172,9 +4108,7 @@ async function setPresetCookies(cookieDataStr: string) {
     const platformDomainMap: Record<string, string> = {
     const platformDomainMap: Record<string, string> = {
       douyin: '.douyin.com',
       douyin: '.douyin.com',
       xiaohongshu: '.xiaohongshu.com',
       xiaohongshu: '.xiaohongshu.com',
-      kuaishou: '.kuaishou.com',
       weixin_video: '.qq.com',
       weixin_video: '.qq.com',
-      bilibili: '.bilibili.com',
       baijiahao: '.baidu.com',
       baijiahao: '.baidu.com',
       toutiao: '.toutiao.com',
       toutiao: '.toutiao.com',
     };
     };

+ 0 - 1
client/src/utils/format.ts

@@ -125,7 +125,6 @@ export function formatDuration(seconds: number | string | undefined): string {
 export const platformColors: Record<string, string> = {
 export const platformColors: Record<string, string> = {
   xiaohongshu: '#E91E63',
   xiaohongshu: '#E91E63',
   douyin: '#374151',
   douyin: '#374151',
-  kuaishou: '#F59E0B',
   weixin: '#10B981',
   weixin: '#10B981',
   weixin_video: '#10B981',
   weixin_video: '#10B981',
   shipinhao: '#10B981',
   shipinhao: '#10B981',

+ 0 - 4
client/src/views/Accounts/index.vue

@@ -805,10 +805,6 @@ onMounted(async () => {
     background: linear-gradient(135deg, #fe2c55, #ff5c7c);
     background: linear-gradient(135deg, #fe2c55, #ff5c7c);
   }
   }
 
 
-  &.kuaishou {
-    background: linear-gradient(135deg, #ff5000, #ff7733);
-  }
-
   &.weixin_video,
   &.weixin_video,
   &.shipinhao {
   &.shipinhao {
     background: linear-gradient(135deg, #07c160, #2dc76d);
     background: linear-gradient(135deg, #07c160, #2dc76d);

+ 0 - 4
client/src/views/Analytics/Account/index.vue

@@ -363,8 +363,6 @@ import { useTaskQueueStore } from '@/stores/taskQueue';
 import iconDefaultUrl from '@/assets/platforms/default.svg?url';
 import iconDefaultUrl from '@/assets/platforms/default.svg?url';
 import douyinIconUrl from '@/assets/platforms/douyin.svg?url';
 import douyinIconUrl from '@/assets/platforms/douyin.svg?url';
 import xhsIconUrl from '@/assets/platforms/xiaohongshu.svg?url';
 import xhsIconUrl from '@/assets/platforms/xiaohongshu.svg?url';
-import bilibiliIconUrl from '@/assets/platforms/bilibili.svg?url';
-import kuaishouIconUrl from '@/assets/platforms/kuaishou.svg?url';
 import weixinVideoIconUrl from '@/assets/platforms/weixin_video.svg?url';
 import weixinVideoIconUrl from '@/assets/platforms/weixin_video.svg?url';
 import baijiahaoIconUrl from '@/assets/platforms/baijiahao.svg?url';
 import baijiahaoIconUrl from '@/assets/platforms/baijiahao.svg?url';
 const route = useRoute();
 const route = useRoute();
@@ -411,8 +409,6 @@ const iconDefault = iconDefaultUrl;
 const platformIcons: Record<string, string> = {
 const platformIcons: Record<string, string> = {
   douyin: douyinIconUrl,
   douyin: douyinIconUrl,
   xiaohongshu: xhsIconUrl,
   xiaohongshu: xhsIconUrl,
-  bilibili: bilibiliIconUrl,
-  kuaishou: kuaishouIconUrl,
   weixin: weixinVideoIconUrl,
   weixin: weixinVideoIconUrl,
   weixin_video: weixinVideoIconUrl,
   weixin_video: weixinVideoIconUrl,
   baijiahao: baijiahaoIconUrl,
   baijiahao: baijiahaoIconUrl,

+ 0 - 2
client/src/views/Analytics/Overview/index.vue

@@ -269,8 +269,6 @@ function getPlatformTagType(platform: PlatformType) {
   const typeMap: Record<string, 'primary' | 'success' | 'warning' | 'danger' | 'info'> = {
   const typeMap: Record<string, 'primary' | 'success' | 'warning' | 'danger' | 'info'> = {
     douyin: 'danger',
     douyin: 'danger',
     xiaohongshu: 'danger',
     xiaohongshu: 'danger',
-    bilibili: 'primary',
-    kuaishou: 'warning',
     weixin: 'success',
     weixin: 'success',
   };
   };
   return typeMap[platform] || 'info';
   return typeMap[platform] || 'info';

+ 0 - 4
client/src/views/Analytics/Platform/index.vue

@@ -155,8 +155,6 @@ import request from '@/api/request';
 import iconDefaultUrl from '@/assets/platforms/default.svg?url';
 import iconDefaultUrl from '@/assets/platforms/default.svg?url';
 import douyinIconUrl from '@/assets/platforms/douyin.svg?url';
 import douyinIconUrl from '@/assets/platforms/douyin.svg?url';
 import xhsIconUrl from '@/assets/platforms/xiaohongshu.svg?url';
 import xhsIconUrl from '@/assets/platforms/xiaohongshu.svg?url';
-import bilibiliIconUrl from '@/assets/platforms/bilibili.svg?url';
-import kuaishouIconUrl from '@/assets/platforms/kuaishou.svg?url';
 import weixinVideoIconUrl from '@/assets/platforms/weixin_video.svg?url';
 import weixinVideoIconUrl from '@/assets/platforms/weixin_video.svg?url';
 import baijiahaoIconUrl from '@/assets/platforms/baijiahao.svg?url';
 import baijiahaoIconUrl from '@/assets/platforms/baijiahao.svg?url';
 
 
@@ -186,8 +184,6 @@ const iconDefault = iconDefaultUrl;
 const platformIcons: Record<string, string> = {
 const platformIcons: Record<string, string> = {
   douyin: douyinIconUrl,
   douyin: douyinIconUrl,
   xiaohongshu: xhsIconUrl,
   xiaohongshu: xhsIconUrl,
-  bilibili: bilibiliIconUrl,
-  kuaishou: kuaishouIconUrl,
   weixin: weixinVideoIconUrl,
   weixin: weixinVideoIconUrl,
   weixin_video: weixinVideoIconUrl,
   weixin_video: weixinVideoIconUrl,
   baijiahao: baijiahaoIconUrl,
   baijiahao: baijiahaoIconUrl,

+ 0 - 1
client/src/views/Analytics/index.vue

@@ -264,7 +264,6 @@ async function loadData() {
 const platformColors: Record<string, string> = {
 const platformColors: Record<string, string> = {
   xiaohongshu: '#E91E63',
   xiaohongshu: '#E91E63',
   douyin: '#374151',
   douyin: '#374151',
-  kuaishou: '#F59E0B',
   weixin: '#10B981',
   weixin: '#10B981',
   weixin_video: '#10B981',
   weixin_video: '#10B981',
   shipinhao: '#10B981',
   shipinhao: '#10B981',

+ 0 - 2
client/src/views/Publish/index.vue

@@ -538,8 +538,6 @@ const PLATFORM_PUBLISH_REQUIREMENTS: Record<string, {
   xiaohongshu: { requireTitle: true, requireDescription: true, requireVideo: true, showTags: true },
   xiaohongshu: { requireTitle: true, requireDescription: true, requireVideo: true, showTags: true },
   weixin_video: { requireTitle: true, requireDescription: false, requireVideo: true, showTags: true },
   weixin_video: { requireTitle: true, requireDescription: false, requireVideo: true, showTags: true },
   baijiahao: { requireTitle: true, requireDescription: true, requireVideo: false, showTags: true },
   baijiahao: { requireTitle: true, requireDescription: true, requireVideo: false, showTags: true },
-  kuaishou: { requireTitle: true, requireDescription: false, requireVideo: true, showTags: true },
-  bilibili: { requireTitle: true, requireDescription: false, requireVideo: true, showTags: true },
 };
 };
 
 
 // 只要任一选中平台要求某字段,就显示必填
 // 只要任一选中平台要求某字段,就显示必填

+ 44 - 0
database/migrations/delete_bilibili_kuaishou_and_related.sql

@@ -0,0 +1,44 @@
+-- 删除 platform=bilibili(快手?否:B站) 和 platform=kuaishou(快手) 的所有数据,
+-- 并缩减 platform_accounts.platform 枚举(移除 'bilibili'、'kuaishou' 两个值)
+-- 执行顺序:先删各关联表数据(评论/作品日统计/作品/发布结果/账号级统计),最后删 platform_accounts,再 ALTER 枚举
+-- 说明:多数关联表对 platform_accounts 有 ON DELETE CASCADE,显式删除仅为清晰与安全兜底
+-- !!! 执行前请备份数据库;本脚本不可逆 !!!
+-- 执行日期: 2026-06-23
+
+USE media_manager;
+
+-- 1. 删除评论(comments.platform 为 VARCHAR;account_id 外键为 CASCADE,此处按 platform 显式删)
+DELETE FROM comments
+WHERE platform IN ('bilibili', 'kuaishou');
+
+-- 2. 删除作品每日统计(先于 works 删除,避免外键 CASCADE 时序问题;CASCADE 也会自动删)
+DELETE FROM work_day_statistics
+WHERE work_id IN (SELECT id FROM works WHERE platform IN ('bilibili', 'kuaishou'));
+
+-- 3. 删除作品(work_day_statistics 已在上一步清理;accountId 外键 CASCADE 也会处理残留)
+DELETE FROM works
+WHERE platform IN ('bilibili', 'kuaishou');
+
+-- 4. 删除发布结果(publish_results.platform 为 VARCHAR;account_id CASCADE 也会删)
+DELETE FROM publish_results
+WHERE platform IN ('bilibili', 'kuaishou');
+
+-- 5. 删除账号级数据统计(analytics_data 无 platform 列,按 account_id 子查询;account_id CASCADE 也会删)
+DELETE FROM analytics_data
+WHERE account_id IN (SELECT id FROM platform_accounts WHERE platform IN ('bilibili', 'kuaishou'));
+
+-- 6. 删除账号每日统计(user_day_statistics 无 platform 列,按 account_id 子查询;account_id CASCADE 也会删)
+DELETE FROM user_day_statistics
+WHERE account_id IN (SELECT id FROM platform_accounts WHERE platform IN ('bilibili', 'kuaishou'));
+
+-- 7. 删除平台账号(核心;上述关联表已显式清理,CASCADE 也会兜底)
+DELETE FROM platform_accounts
+WHERE platform IN ('bilibili', 'kuaishou');
+
+-- 8. 缩减 platform_accounts.platform 枚举:移除 'bilibili'、'kuaishou'
+--    新枚举与 database/schema.sql 保持一致(7 值)
+ALTER TABLE platform_accounts
+MODIFY COLUMN platform ENUM('douyin','weixin_video','xiaohongshu','toutiao','baijiahao','qie','dayuhao') NOT NULL;
+
+-- 提示:publish_tasks.target_accounts (JSON) 可能仍引用已删除的 bilibili/kuaishou 账号 id,
+-- 这些历史任务的 target_accounts 会存在悬空引用,但不影响新任务,可按需手动清理或保留为历史记录。

+ 1 - 1
database/schema.sql

@@ -69,7 +69,7 @@ CREATE TABLE IF NOT EXISTS account_groups (
 CREATE TABLE IF NOT EXISTS platform_accounts (
 CREATE TABLE IF NOT EXISTS platform_accounts (
     id INT PRIMARY KEY AUTO_INCREMENT,
     id INT PRIMARY KEY AUTO_INCREMENT,
     user_id INT NOT NULL,
     user_id INT NOT NULL,
-    platform ENUM('douyin','kuaishou','weixin_video','xiaohongshu','bilibili','toutiao','baijiahao','qie','dayuhao') NOT NULL,
+    platform ENUM('douyin','weixin_video','xiaohongshu','toutiao','baijiahao','qie','dayuhao') NOT NULL,
     account_name VARCHAR(100),
     account_name VARCHAR(100),
     account_id VARCHAR(100),
     account_id VARCHAR(100),
     avatar_url VARCHAR(500),
     avatar_url VARCHAR(500),

+ 0 - 2
scripts/check-publish-flow.mjs

@@ -5,8 +5,6 @@ const platformFiles = [
   'server/src/automation/platforms/weixin.ts',
   'server/src/automation/platforms/weixin.ts',
   'server/src/automation/platforms/baijiahao.ts',
   'server/src/automation/platforms/baijiahao.ts',
   'server/src/automation/platforms/douyin.ts',
   'server/src/automation/platforms/douyin.ts',
-  'server/src/automation/platforms/bilibili.ts',
-  'server/src/automation/platforms/kuaishou.ts',
 ];
 ];
 
 
 const lifecycleOffenders = [];
 const lifecycleOffenders = [];

+ 0 - 4
server/src/ai/index.ts

@@ -936,10 +936,6 @@ export class QwenAIService {
 - "粉丝 X" 或 "粉丝 X/500" 表示粉丝数量
 - "粉丝 X" 或 "粉丝 X/500" 表示粉丝数量
 - 侧边栏有"笔记管理"、"数据看板"等入口
 - 侧边栏有"笔记管理"、"数据看板"等入口
 - 如果看到类似ID格式的字符串(字母+数字组合),很可能就是小红书号`,
 - 如果看到类似ID格式的字符串(字母+数字组合),很可能就是小红书号`,
-      kuaishou: `
-快手平台常见的账号信息位置:
-- 页面顶部显示用户信息
-- 侧边栏有创作者中心入口`,
       weixin_video: `
       weixin_video: `
 视频号平台常见的账号信息位置和格式:
 视频号平台常见的账号信息位置和格式:
 - 页面顶部显示账号名称(如"轻尘网络")
 - 页面顶部显示账号名称(如"轻尘网络")

+ 0 - 440
server/src/automation/platforms/bilibili.ts

@@ -1,440 +0,0 @@
-/// <reference lib="dom" />
-import path from 'path';
-import { BasePlatformAdapter } from './base.js';
-import type {
-  AccountProfile,
-  PublishParams,
-  PublishResult,
-  DateRange,
-  AnalyticsData,
-  CommentData,
-} from './base.js';
-import type { PlatformType, QRCodeInfo, LoginStatusResult } from '@media-manager/shared';
-import { logger } from '../../utils/logger.js';
-import { aiService } from '../../ai/index.js';
-
-// 服务器根目录(用于构造绝对路径)
-const SERVER_ROOT = path.resolve(process.cwd());
-
-/**
- * B站平台适配器
- */
-export class BilibiliAdapter extends BasePlatformAdapter {
-  readonly platform: PlatformType = 'bilibili';
-  readonly loginUrl = 'https://member.bilibili.com/';
-  readonly publishUrl = 'https://member.bilibili.com/platform/upload/video/frame';
-  
-  protected getCookieDomain(): string {
-    return '.bilibili.com';
-  }
-  
-  async getQRCode(): Promise<QRCodeInfo> {
-    try {
-      await this.initBrowser();
-      
-      if (!this.page) throw new Error('Page not initialized');
-      
-      await this.page.goto('https://passport.bilibili.com/login');
-      await this.waitForSelector('.login-scan-img img', 30000);
-      
-      const qrcodeImg = await this.page.$('.login-scan-img img');
-      const qrcodeUrl = await qrcodeImg?.getAttribute('src');
-      
-      if (!qrcodeUrl) {
-        throw new Error('Failed to get QR code');
-      }
-      
-      return {
-        qrcodeUrl,
-        qrcodeKey: `bilibili_${Date.now()}`,
-        expireTime: Date.now() + 180000,
-      };
-    } catch (error) {
-      logger.error('Bilibili getQRCode error:', error);
-      throw error;
-    }
-  }
-  
-  async checkQRCodeStatus(_qrcodeKey: string): Promise<LoginStatusResult> {
-    try {
-      if (!this.page) {
-        return { status: 'expired', message: '二维码已过期' };
-      }
-      
-      const currentUrl = this.page.url();
-      
-      if (currentUrl.includes('member.bilibili.com')) {
-        const cookies = await this.getCookies();
-        await this.closeBrowser();
-        return { status: 'confirmed', message: '登录成功', cookies };
-      }
-      
-      return { status: 'waiting', message: '等待扫码' };
-    } catch (error) {
-      logger.error('Bilibili checkQRCodeStatus error:', error);
-      return { status: 'error', message: '检查状态失败' };
-    }
-  }
-  
-  async checkLoginStatus(cookies: string): Promise<boolean> {
-    try {
-      await this.initBrowser();
-      await this.setCookies(cookies);
-      
-      if (!this.page) throw new Error('Page not initialized');
-      
-      await this.page.goto('https://member.bilibili.com/platform/home');
-      await this.page.waitForLoadState('networkidle');
-      
-      const avatar = await this.page.$('.user-avatar');
-      await this.closeBrowser();
-      
-      return !!avatar;
-    } catch (error) {
-      logger.error('Bilibili checkLoginStatus error:', error);
-      await this.closeBrowser();
-      return false;
-    }
-  }
-  
-  async getAccountInfo(cookies: string): Promise<AccountProfile> {
-    try {
-      await this.initBrowser();
-      await this.setCookies(cookies);
-      
-      if (!this.page) throw new Error('Page not initialized');
-      
-      await this.page.goto('https://member.bilibili.com/platform/home');
-      await this.page.waitForLoadState('networkidle');
-      
-      const accountName = await this.page.$eval('.user-name', el => el.textContent?.trim() || '');
-      const avatarUrl = await this.page.$eval('.user-avatar img', el => el.getAttribute('src') || '');
-      
-      await this.closeBrowser();
-      
-      return {
-        accountId: '',
-        accountName,
-        avatarUrl,
-        fansCount: 0,
-        worksCount: 0,
-      };
-    } catch (error) {
-      logger.error('Bilibili getAccountInfo error:', error);
-      await this.closeBrowser();
-      throw error;
-    }
-  }
-  
-  async publishVideo(
-    cookies: string,
-    params: PublishParams,
-    onProgress?: (progress: number, message: string) => void,
-    onCaptchaRequired?: (captchaInfo: { taskId: string; type: 'sms' | 'image'; phone?: string; imageBase64?: string }) => Promise<string>,
-    options?: { headless?: boolean }
-  ): Promise<PublishResult> {
-    const useHeadless = options?.headless ?? true;
-
-    try {
-      await this.initBrowser({ headless: useHeadless });
-      await this.setCookies(cookies);
-
-      if (!this.page) throw new Error('Page not initialized');
-
-      onProgress?.(5, '正在打开上传页面...');
-
-      await this.page.goto(this.publishUrl, {
-        waitUntil: 'domcontentloaded',
-        timeout: 60000,
-      });
-
-      await this.page.waitForTimeout(3000);
-
-      // 检查是否需要登录
-      const currentUrl = this.page.url();
-      if (currentUrl.includes('passport') || currentUrl.includes('login')) {
-        await this.closeBrowser();
-        return {
-          success: false,
-          errorMessage: '账号登录已过期,请重新登录',
-        };
-      }
-
-      onProgress?.(10, '正在上传视频...');
-
-      // 上传视频 - 优先使用 AI 截图分析找到上传入口
-      let uploadTriggered = false;
-
-      // 方法1: AI 截图分析找到上传入口
-      logger.info('[Bilibili Publish] Using AI to find upload entry...');
-      try {
-        const screenshot = await this.screenshotBase64();
-        const guide = await aiService.getPageOperationGuide(screenshot, 'bilibili', '找到视频上传入口并点击上传按钮');
-        logger.info(`[Bilibili Publish] AI analysis result:`, guide);
-
-        if (guide.hasAction && guide.targetSelector) {
-          logger.info(`[Bilibili Publish] AI suggested selector: ${guide.targetSelector}`);
-          try {
-            const [fileChooser] = await Promise.all([
-              this.page.waitForEvent('filechooser', { timeout: 10000 }),
-              this.page.click(guide.targetSelector),
-            ]);
-            await fileChooser.setFiles(params.videoPath);
-            uploadTriggered = true;
-            logger.info('[Bilibili Publish] Upload triggered via AI selector');
-          } catch (e) {
-            logger.warn(`[Bilibili Publish] AI selector click failed: ${e}`);
-          }
-        }
-      } catch (e) {
-        logger.warn(`[Bilibili Publish] AI analysis failed: ${e}`);
-      }
-
-      // 方法2: 尝试点击常见的上传区域触发 file chooser
-      if (!uploadTriggered) {
-        logger.info('[Bilibili Publish] Trying common upload selectors...');
-        const uploadSelectors = [
-          // B站常见上传区域选择器
-          '[class*="upload-area"]',
-          '[class*="upload-btn"]',
-          '[class*="bcc-upload"]',
-          '[class*="video-upload"]',
-          '[class*="upload-container"]',
-          '.upload-trigger',
-          '.video-uploader',
-          'div[class*="uploader"]',
-          'button:has-text("上传")',
-          'div:has-text("上传视频"):not(:has(div))',
-          'span:has-text("点击上传")',
-          '[class*="upload-select"]',
-          '.bili-upload',
-        ];
-        
-        for (const selector of uploadSelectors) {
-          if (uploadTriggered) break;
-          try {
-            const element = this.page.locator(selector).first();
-            if (await element.count() > 0 && await element.isVisible()) {
-              logger.info(`[Bilibili Publish] Trying selector: ${selector}`);
-              const [fileChooser] = await Promise.all([
-                this.page.waitForEvent('filechooser', { timeout: 5000 }),
-                element.click(),
-              ]);
-              await fileChooser.setFiles(params.videoPath);
-              uploadTriggered = true;
-              logger.info(`[Bilibili Publish] Upload triggered via selector: ${selector}`);
-            }
-          } catch (e) {
-            // 继续尝试下一个选择器
-          }
-        }
-      }
-
-      // 方法3: 直接设置 file input
-      if (!uploadTriggered) {
-        logger.info('[Bilibili Publish] Trying file input method...');
-        const fileInputs = await this.page.$$('input[type="file"]');
-        logger.info(`[Bilibili Publish] Found ${fileInputs.length} file inputs`);
-        for (const fileInput of fileInputs) {
-          try {
-            const accept = await fileInput.getAttribute('accept');
-            if (!accept || accept.includes('video') || accept.includes('*')) {
-              await fileInput.setInputFiles(params.videoPath);
-              uploadTriggered = true;
-              logger.info('[Bilibili Publish] Upload triggered via file input');
-              break;
-            }
-          } catch (e) {
-            logger.warn(`[Bilibili Publish] File input method failed: ${e}`);
-          }
-        }
-      }
-
-      if (!uploadTriggered) {
-        // 截图调试
-        try {
-          if (this.page) {
-            const screenshotPath = `uploads/debug/bilibili_no_upload_${Date.now()}.png`;
-            await this.page.screenshot({ path: screenshotPath, fullPage: true });
-            logger.info(`[Bilibili Publish] Screenshot saved: ${screenshotPath}`);
-          }
-        } catch {}
-        throw new Error('未找到上传入口');
-      }
-
-      // 等待上传完成
-      onProgress?.(20, '视频上传中...');
-      const maxWaitTime = 300000; // 5分钟
-      const startTime = Date.now();
-
-      while (Date.now() - startTime < maxWaitTime) {
-        // 检查上传进度
-        const progressText = await this.page.locator('[class*="progress"]').first().textContent().catch(() => '');
-        if (progressText) {
-          const match = progressText.match(/(\d+)%/);
-          if (match) {
-            const progress = parseInt(match[1]);
-            onProgress?.(20 + Math.floor(progress * 0.4), `视频上传中: ${progress}%`);
-          }
-        }
-
-        // 检查上传完成
-        const uploadSuccess = await this.page.locator('.upload-success, [class*="success"], [class*="complete"]').count();
-        if (uploadSuccess > 0) {
-          logger.info('[Bilibili Publish] Video upload completed');
-          break;
-        }
-
-        await this.page.waitForTimeout(2000);
-      }
-
-      onProgress?.(60, '正在填写视频信息...');
-
-      // 填写标题
-      const titleInput = this.page.locator('.video-title input, input[placeholder*="标题"]').first();
-      if (await titleInput.count() > 0) {
-        await titleInput.fill(params.title);
-      }
-
-      // 填写简介
-      if (params.description) {
-        const descInput = this.page.locator('textarea[placeholder*="简介"], .desc-input textarea').first();
-        if (await descInput.count() > 0) {
-          await descInput.fill(params.description);
-        }
-      }
-
-      // 选择分区
-      try {
-        const typeBtn = this.page.locator('.type-btn, [class*="select-type"]').first();
-        if (await typeBtn.count() > 0) {
-          await typeBtn.click();
-          await this.page.waitForTimeout(500);
-          // 默认选择生活区
-          const lifeCategory = this.page.locator('[data-tid="160"], :has-text("生活")').first();
-          if (await lifeCategory.count() > 0) {
-            await lifeCategory.click();
-          }
-        }
-      } catch {
-        logger.warn('[Bilibili Publish] Failed to select category');
-      }
-
-      onProgress?.(80, '正在发布...');
-
-      // 点击发布
-      const submitBtn = this.page.locator('.submit-add, button:has-text("投稿"), [class*="submit"]').first();
-      if (await submitBtn.count() > 0) {
-        await submitBtn.click();
-      } else {
-        throw new Error('未找到发布按钮');
-      }
-
-      // 等待发布结果
-      onProgress?.(90, '等待发布完成...');
-      const publishMaxWait = 120000; // 2分钟
-      const publishStartTime = Date.now();
-      let aiCheckCounter = 0;
-
-      while (Date.now() - publishStartTime < publishMaxWait) {
-        await this.page.waitForTimeout(3000);
-
-        // 检查成功提示
-        const successHint = await this.page.locator('.success-hint, [class*="success"]:has-text("成功")').count();
-        if (successHint > 0) {
-          onProgress?.(100, '发布成功!');
-          return await this.finishPublishSuccess();
-        }
-
-        // 检查错误提示
-        const errorHint = await this.page.locator('[class*="error"], [class*="fail"]').first().textContent().catch(() => '');
-        if (errorHint && (errorHint.includes('失败') || errorHint.includes('错误'))) {
-          throw new Error(`发布失败: ${errorHint}`);
-        }
-
-        // AI 辅助检测(每 3 次循环)
-        aiCheckCounter++;
-        if (aiCheckCounter >= 3) {
-          aiCheckCounter = 0;
-          const aiStatus = await this.aiAnalyzePublishStatus();
-          if (aiStatus) {
-            logger.info(`[Bilibili Publish] AI status: ${aiStatus.status}, confidence: ${aiStatus.confidence}%`);
-
-            if (aiStatus.status === 'success' && aiStatus.confidence >= 70) {
-              onProgress?.(100, '发布成功!');
-              return await this.finishPublishSuccess();
-            }
-
-            if (aiStatus.status === 'failed' && aiStatus.confidence >= 70) {
-              throw new Error(aiStatus.errorMessage || 'AI 检测到发布失败');
-            }
-
-            if (aiStatus.status === 'need_captcha' && onCaptchaRequired) {
-              const imageBase64 = await this.screenshotBase64();
-              try {
-                const captchaCode = await onCaptchaRequired({
-                  taskId: `bilibili_captcha_${Date.now()}`,
-                  type: 'image',
-                  imageBase64,
-                });
-                if (captchaCode) {
-                  const guide = await this.aiGetPublishOperationGuide('需要输入验证码');
-                  if (guide?.hasAction && guide.targetSelector) {
-                    await this.page.fill(guide.targetSelector, captchaCode);
-                  }
-                }
-              } catch {
-                logger.error('[Bilibili Publish] Captcha handling failed');
-              }
-            }
-
-            if (aiStatus.status === 'need_action' && aiStatus.nextAction) {
-              const guide = await this.aiGetPublishOperationGuide(aiStatus.pageDescription);
-              if (guide?.hasAction) {
-                await this.aiExecuteOperation(guide);
-              }
-            }
-          }
-        }
-      }
-
-      // 超时,AI 最终检查
-      const finalAiStatus = await this.aiAnalyzePublishStatus();
-      if (finalAiStatus?.status === 'success') {
-        onProgress?.(100, '发布成功!');
-        return await this.finishPublishSuccess();
-      }
-
-      throw new Error('发布超时,请手动检查是否发布成功');
-
-    } catch (error) {
-      logger.error('Bilibili publishVideo error:', error);
-      await this.closeBrowser();
-      return {
-        success: false,
-        errorMessage: error instanceof Error ? error.message : '发布失败',
-      };
-    }
-  }
-  
-  async getComments(_cookies: string, videoId: string): Promise<CommentData[]> {
-    logger.info(`Bilibili getComments for video ${videoId}`);
-    return [];
-  }
-  
-  async replyComment(_cookies: string, commentId: string, content: string): Promise<boolean> {
-    logger.info(`Bilibili replyComment ${commentId}: ${content}`);
-    return true;
-  }
-  
-  async getAnalytics(_cookies: string, _dateRange: DateRange): Promise<AnalyticsData> {
-    return {
-      fansCount: 0,
-      fansIncrease: 0,
-      viewsCount: 0,
-      likesCount: 0,
-      commentsCount: 0,
-      sharesCount: 0,
-    };
-  }
-}

+ 0 - 6
server/src/automation/platforms/index.ts

@@ -1,15 +1,11 @@
 import type { PlatformType } from '@media-manager/shared';
 import type { PlatformType } from '@media-manager/shared';
 import { BasePlatformAdapter } from './base.js';
 import { BasePlatformAdapter } from './base.js';
 import { DouyinAdapter } from './douyin.js';
 import { DouyinAdapter } from './douyin.js';
-import { KuaishouAdapter } from './kuaishou.js';
-import { BilibiliAdapter } from './bilibili.js';
 import { XiaohongshuAdapter } from './xiaohongshu.js';
 import { XiaohongshuAdapter } from './xiaohongshu.js';
 import { WeixinAdapter } from './weixin.js';
 import { WeixinAdapter } from './weixin.js';
 
 
 export { BasePlatformAdapter } from './base.js';
 export { BasePlatformAdapter } from './base.js';
 export { DouyinAdapter } from './douyin.js';
 export { DouyinAdapter } from './douyin.js';
-export { KuaishouAdapter } from './kuaishou.js';
-export { BilibiliAdapter } from './bilibili.js';
 export { XiaohongshuAdapter } from './xiaohongshu.js';
 export { XiaohongshuAdapter } from './xiaohongshu.js';
 export { WeixinAdapter } from './weixin.js';
 export { WeixinAdapter } from './weixin.js';
 
 
@@ -18,8 +14,6 @@ export { WeixinAdapter } from './weixin.js';
  */
  */
 const adapterRegistry = new Map<PlatformType, new () => BasePlatformAdapter>([
 const adapterRegistry = new Map<PlatformType, new () => BasePlatformAdapter>([
   ['douyin', DouyinAdapter],
   ['douyin', DouyinAdapter],
-  ['kuaishou', KuaishouAdapter],
-  ['bilibili', BilibiliAdapter],
   ['xiaohongshu', XiaohongshuAdapter],
   ['xiaohongshu', XiaohongshuAdapter],
   ['weixin_video', WeixinAdapter],
   ['weixin_video', WeixinAdapter],
 ]);
 ]);

+ 0 - 421
server/src/automation/platforms/kuaishou.ts

@@ -1,421 +0,0 @@
-import path from 'path';
-import { BasePlatformAdapter } from './base.js';
-import type {
-  AccountProfile,
-  PublishParams,
-  PublishResult,
-  DateRange,
-  AnalyticsData,
-  CommentData,
-} from './base.js';
-import type { PlatformType, QRCodeInfo, LoginStatusResult } from '@media-manager/shared';
-import { logger } from '../../utils/logger.js';
-import { aiService } from '../../ai/index.js';
-
-// 服务器根目录(用于构造绝对路径)
-const SERVER_ROOT = path.resolve(process.cwd());
-
-/**
- * 快手平台适配器
- */
-export class KuaishouAdapter extends BasePlatformAdapter {
-  readonly platform: PlatformType = 'kuaishou';
-  readonly loginUrl = 'https://cp.kuaishou.com/';
-  readonly publishUrl = 'https://cp.kuaishou.com/article/publish/video';
-  
-  protected getCookieDomain(): string {
-    return '.kuaishou.com';
-  }
-  
-  async getQRCode(): Promise<QRCodeInfo> {
-    try {
-      await this.initBrowser();
-      
-      if (!this.page) throw new Error('Page not initialized');
-      
-      await this.page.goto(this.loginUrl);
-      await this.waitForSelector('.qrcode-img', 30000);
-      
-      const qrcodeImg = await this.page.$('.qrcode-img');
-      const qrcodeUrl = await qrcodeImg?.getAttribute('src');
-      
-      if (!qrcodeUrl) {
-        throw new Error('Failed to get QR code');
-      }
-      
-      return {
-        qrcodeUrl,
-        qrcodeKey: `kuaishou_${Date.now()}`,
-        expireTime: Date.now() + 300000,
-      };
-    } catch (error) {
-      logger.error('Kuaishou getQRCode error:', error);
-      throw error;
-    }
-  }
-  
-  async checkQRCodeStatus(_qrcodeKey: string): Promise<LoginStatusResult> {
-    try {
-      if (!this.page) {
-        return { status: 'expired', message: '二维码已过期' };
-      }
-      
-      const currentUrl = this.page.url();
-      
-      if (currentUrl.includes('/profile') || currentUrl.includes('/article')) {
-        const cookies = await this.getCookies();
-        await this.closeBrowser();
-        return { status: 'confirmed', message: '登录成功', cookies };
-      }
-      
-      return { status: 'waiting', message: '等待扫码' };
-    } catch (error) {
-      logger.error('Kuaishou checkQRCodeStatus error:', error);
-      return { status: 'error', message: '检查状态失败' };
-    }
-  }
-  
-  async checkLoginStatus(cookies: string): Promise<boolean> {
-    try {
-      await this.initBrowser();
-      await this.setCookies(cookies);
-      
-      if (!this.page) throw new Error('Page not initialized');
-      
-      await this.page.goto('https://cp.kuaishou.com/profile');
-      await this.page.waitForLoadState('networkidle');
-      
-      const needLogin = await this.page.$('.login-btn');
-      await this.closeBrowser();
-      
-      return !needLogin;
-    } catch (error) {
-      logger.error('Kuaishou checkLoginStatus error:', error);
-      await this.closeBrowser();
-      return false;
-    }
-  }
-  
-  async getAccountInfo(cookies: string): Promise<AccountProfile> {
-    try {
-      await this.initBrowser();
-      await this.setCookies(cookies);
-      
-      if (!this.page) throw new Error('Page not initialized');
-      
-      await this.page.goto('https://cp.kuaishou.com/profile');
-      await this.page.waitForLoadState('networkidle');
-      
-      const accountName = await this.page.$eval('.user-name', el => el.textContent?.trim() || '');
-      const avatarUrl = await this.page.$eval('.avatar img', el => el.getAttribute('src') || '');
-      
-      await this.closeBrowser();
-      
-      return {
-        accountId: '',
-        accountName,
-        avatarUrl,
-        fansCount: 0,
-        worksCount: 0,
-      };
-    } catch (error) {
-      logger.error('Kuaishou getAccountInfo error:', error);
-      await this.closeBrowser();
-      throw error;
-    }
-  }
-  
-  async publishVideo(
-    cookies: string,
-    params: PublishParams,
-    onProgress?: (progress: number, message: string) => void,
-    onCaptchaRequired?: (captchaInfo: { taskId: string; type: 'sms' | 'image'; phone?: string; imageBase64?: string }) => Promise<string>,
-    options?: { headless?: boolean }
-  ): Promise<PublishResult> {
-    const useHeadless = options?.headless ?? true;
-
-    try {
-      await this.initBrowser({ headless: useHeadless });
-      await this.setCookies(cookies);
-
-      if (!this.page) throw new Error('Page not initialized');
-
-      onProgress?.(5, '正在打开上传页面...');
-
-      await this.page.goto(this.publishUrl, {
-        waitUntil: 'domcontentloaded',
-        timeout: 60000,
-      });
-
-      await this.page.waitForTimeout(3000);
-
-      // 检查是否需要登录
-      const currentUrl = this.page.url();
-      if (currentUrl.includes('login') || currentUrl.includes('passport')) {
-        await this.closeBrowser();
-        return {
-          success: false,
-          errorMessage: '账号登录已过期,请重新登录',
-        };
-      }
-
-      onProgress?.(10, '正在上传视频...');
-
-      // 上传视频 - 优先使用 AI 截图分析找到上传入口
-      let uploadTriggered = false;
-
-      // 方法1: AI 截图分析找到上传入口
-      logger.info('[Kuaishou Publish] Using AI to find upload entry...');
-      try {
-        const screenshot = await this.screenshotBase64();
-        const guide = await aiService.getPageOperationGuide(screenshot, 'kuaishou', '找到视频上传入口并点击上传按钮');
-        logger.info(`[Kuaishou Publish] AI analysis result:`, guide);
-
-        if (guide.hasAction && guide.targetSelector) {
-          logger.info(`[Kuaishou Publish] AI suggested selector: ${guide.targetSelector}`);
-          try {
-            const [fileChooser] = await Promise.all([
-              this.page.waitForEvent('filechooser', { timeout: 10000 }),
-              this.page.click(guide.targetSelector),
-            ]);
-            await fileChooser.setFiles(params.videoPath);
-            uploadTriggered = true;
-            logger.info('[Kuaishou Publish] Upload triggered via AI selector');
-          } catch (e) {
-            logger.warn(`[Kuaishou Publish] AI selector click failed: ${e}`);
-          }
-        }
-      } catch (e) {
-        logger.warn(`[Kuaishou Publish] AI analysis failed: ${e}`);
-      }
-
-      // 方法2: 尝试点击常见的上传区域触发 file chooser
-      if (!uploadTriggered) {
-        logger.info('[Kuaishou Publish] Trying common upload selectors...');
-        const uploadSelectors = [
-          // 快手常见上传区域选择器
-          '[class*="upload-area"]',
-          '[class*="upload-btn"]',
-          '[class*="upload-video"]',
-          '[class*="video-upload"]',
-          '[class*="drag-upload"]',
-          '.upload-trigger',
-          '.video-uploader',
-          'div[class*="uploader"]',
-          'button:has-text("上传")',
-          'div:has-text("上传视频"):not(:has(div))',
-          'span:has-text("点击上传")',
-          '[class*="add-video"]',
-          '.kwai-upload',
-        ];
-        
-        for (const selector of uploadSelectors) {
-          if (uploadTriggered) break;
-          try {
-            const element = this.page.locator(selector).first();
-            if (await element.count() > 0 && await element.isVisible()) {
-              logger.info(`[Kuaishou Publish] Trying selector: ${selector}`);
-              const [fileChooser] = await Promise.all([
-                this.page.waitForEvent('filechooser', { timeout: 5000 }),
-                element.click(),
-              ]);
-              await fileChooser.setFiles(params.videoPath);
-              uploadTriggered = true;
-              logger.info(`[Kuaishou Publish] Upload triggered via selector: ${selector}`);
-            }
-          } catch (e) {
-            // 继续尝试下一个选择器
-          }
-        }
-      }
-
-      // 方法3: 直接设置 file input
-      if (!uploadTriggered) {
-        logger.info('[Kuaishou Publish] Trying file input method...');
-        const fileInputs = await this.page.$$('input[type="file"]');
-        logger.info(`[Kuaishou Publish] Found ${fileInputs.length} file inputs`);
-        for (const fileInput of fileInputs) {
-          try {
-            const accept = await fileInput.getAttribute('accept');
-            if (!accept || accept.includes('video') || accept.includes('*')) {
-              await fileInput.setInputFiles(params.videoPath);
-              uploadTriggered = true;
-              logger.info('[Kuaishou Publish] Upload triggered via file input');
-              break;
-            }
-          } catch (e) {
-            logger.warn(`[Kuaishou Publish] File input method failed: ${e}`);
-          }
-        }
-      }
-
-      if (!uploadTriggered) {
-        // 截图调试
-        try {
-          if (this.page) {
-            const screenshotPath = `uploads/debug/kuaishou_no_upload_${Date.now()}.png`;
-            await this.page.screenshot({ path: screenshotPath, fullPage: true });
-            logger.info(`[Kuaishou Publish] Screenshot saved: ${screenshotPath}`);
-          }
-        } catch {}
-        throw new Error('未找到上传入口');
-      }
-
-      // 等待上传完成
-      onProgress?.(20, '视频上传中...');
-      const maxWaitTime = 300000; // 5分钟
-      const startTime = Date.now();
-
-      while (Date.now() - startTime < maxWaitTime) {
-        const progressText = await this.page.locator('[class*="progress"]').first().textContent().catch(() => '');
-        if (progressText) {
-          const match = progressText.match(/(\d+)%/);
-          if (match) {
-            const progress = parseInt(match[1]);
-            onProgress?.(20 + Math.floor(progress * 0.4), `视频上传中: ${progress}%`);
-          }
-        }
-
-        const uploadSuccess = await this.page.locator('.upload-success, [class*="success"], [class*="complete"]').count();
-        if (uploadSuccess > 0) {
-          logger.info('[Kuaishou Publish] Video upload completed');
-          break;
-        }
-
-        await this.page.waitForTimeout(2000);
-      }
-
-      onProgress?.(60, '正在填写视频信息...');
-
-      // 填写标题
-      const titleInput = this.page.locator('.title-input, input[placeholder*="标题"]').first();
-      if (await titleInput.count() > 0) {
-        await titleInput.fill(params.title);
-      }
-
-      // 填写描述
-      if (params.description) {
-        const descInput = this.page.locator('.desc-input, textarea[placeholder*="描述"]').first();
-        if (await descInput.count() > 0) {
-          await descInput.fill(params.description);
-        }
-      }
-
-      onProgress?.(80, '正在发布...');
-
-      // 点击发布
-      const publishBtn = this.page.locator('.publish-btn, button:has-text("发布")').first();
-      if (await publishBtn.count() > 0) {
-        await publishBtn.click();
-      } else {
-        throw new Error('未找到发布按钮');
-      }
-
-      // 等待发布结果
-      onProgress?.(90, '等待发布完成...');
-      const publishMaxWait = 120000; // 2分钟
-      const publishStartTime = Date.now();
-      let aiCheckCounter = 0;
-
-      while (Date.now() - publishStartTime < publishMaxWait) {
-        await this.page.waitForTimeout(3000);
-
-        // 检查成功提示
-        const successHint = await this.page.locator('.publish-success, [class*="success"]:has-text("成功")').count();
-        if (successHint > 0) {
-          onProgress?.(100, '发布成功!');
-          return await this.finishPublishSuccess();
-        }
-
-        // 检查错误提示
-        const errorHint = await this.page.locator('[class*="error"], [class*="fail"]').first().textContent().catch(() => '');
-        if (errorHint && (errorHint.includes('失败') || errorHint.includes('错误'))) {
-          throw new Error(`发布失败: ${errorHint}`);
-        }
-
-        // AI 辅助检测(每 3 次循环)
-        aiCheckCounter++;
-        if (aiCheckCounter >= 3) {
-          aiCheckCounter = 0;
-          const aiStatus = await this.aiAnalyzePublishStatus();
-          if (aiStatus) {
-            logger.info(`[Kuaishou Publish] AI status: ${aiStatus.status}, confidence: ${aiStatus.confidence}%`);
-
-            if (aiStatus.status === 'success' && aiStatus.confidence >= 70) {
-              onProgress?.(100, '发布成功!');
-              return await this.finishPublishSuccess();
-            }
-
-            if (aiStatus.status === 'failed' && aiStatus.confidence >= 70) {
-              throw new Error(aiStatus.errorMessage || 'AI 检测到发布失败');
-            }
-
-            if (aiStatus.status === 'need_captcha' && onCaptchaRequired) {
-              const imageBase64 = await this.screenshotBase64();
-              try {
-                const captchaCode = await onCaptchaRequired({
-                  taskId: `kuaishou_captcha_${Date.now()}`,
-                  type: 'image',
-                  imageBase64,
-                });
-                if (captchaCode) {
-                  const guide = await this.aiGetPublishOperationGuide('需要输入验证码');
-                  if (guide?.hasAction && guide.targetSelector) {
-                    await this.page.fill(guide.targetSelector, captchaCode);
-                  }
-                }
-              } catch {
-                logger.error('[Kuaishou Publish] Captcha handling failed');
-              }
-            }
-
-            if (aiStatus.status === 'need_action' && aiStatus.nextAction) {
-              const guide = await this.aiGetPublishOperationGuide(aiStatus.pageDescription);
-              if (guide?.hasAction) {
-                await this.aiExecuteOperation(guide);
-              }
-            }
-          }
-        }
-      }
-
-      // 超时,AI 最终检查
-      const finalAiStatus = await this.aiAnalyzePublishStatus();
-      if (finalAiStatus?.status === 'success') {
-        onProgress?.(100, '发布成功!');
-        return await this.finishPublishSuccess();
-      }
-
-      throw new Error('发布超时,请手动检查是否发布成功');
-
-    } catch (error) {
-      logger.error('Kuaishou publishVideo error:', error);
-      await this.closeBrowser();
-      return {
-        success: false,
-        errorMessage: error instanceof Error ? error.message : '发布失败',
-      };
-    }
-  }
-  
-  async getComments(_cookies: string, videoId: string): Promise<CommentData[]> {
-    logger.info(`Kuaishou getComments for video ${videoId} - no implementation`);
-    return [];
-  }
-  
-  async replyComment(_cookies: string, commentId: string, content: string): Promise<boolean> {
-    logger.info(`Kuaishou replyComment ${commentId}: ${content}`);
-    return true;
-  }
-  
-  async getAnalytics(_cookies: string, _dateRange: DateRange): Promise<AnalyticsData> {
-    return {
-      fansCount: 0,
-      fansIncrease: 0,
-      viewsCount: 0,
-      likesCount: 0,
-      commentsCount: 0,
-      sharesCount: 0,
-    };
-  }
-}

+ 1 - 1
server/src/models/entities/PlatformAccount.ts

@@ -25,7 +25,7 @@ export class PlatformAccount {
 
 
   @Column({
   @Column({
     type: 'enum',
     type: 'enum',
-    enum: ['douyin', 'kuaishou', 'weixin_video', 'xiaohongshu', 'bilibili', 'toutiao', 'baijiahao', 'qie', 'dayuhao'],
+    enum: ['douyin', 'weixin_video', 'xiaohongshu', 'toutiao', 'baijiahao', 'qie', 'dayuhao'],
   })
   })
   platform!: PlatformType;
   platform!: PlatformType;
 
 

+ 0 - 8
server/src/services/AccountService.ts

@@ -920,10 +920,8 @@ export class AccountService {
     try {
     try {
       const domainMap: Record<string, string> = {
       const domainMap: Record<string, string> = {
         douyin: '.douyin.com',
         douyin: '.douyin.com',
-        kuaishou: '.kuaishou.com',
         xiaohongshu: '.xiaohongshu.com',
         xiaohongshu: '.xiaohongshu.com',
         weixin_video: '.qq.com',
         weixin_video: '.qq.com',
-        bilibili: '.bilibili.com',
         toutiao: '.toutiao.com',
         toutiao: '.toutiao.com',
         baijiahao: '.baidu.com',
         baijiahao: '.baidu.com',
         qie: '.qq.com',
         qie: '.qq.com',
@@ -1034,10 +1032,8 @@ export class AccountService {
     // 获取平台对应的域名
     // 获取平台对应的域名
     const domainMap: Record<string, string> = {
     const domainMap: Record<string, string> = {
       douyin: '.douyin.com',
       douyin: '.douyin.com',
-      kuaishou: '.kuaishou.com',
       xiaohongshu: '.xiaohongshu.com',
       xiaohongshu: '.xiaohongshu.com',
       weixin_video: '.qq.com',
       weixin_video: '.qq.com',
-      bilibili: '.bilibili.com',
       toutiao: '.toutiao.com',
       toutiao: '.toutiao.com',
       baijiahao: '.baidu.com',
       baijiahao: '.baidu.com',
       qie: '.qq.com',
       qie: '.qq.com',
@@ -1110,10 +1106,8 @@ export class AccountService {
     // 各平台用于标识用户的 Cookie 名称(按优先级排序)
     // 各平台用于标识用户的 Cookie 名称(按优先级排序)
     const platformCookieNames: Record<string, string[]> = {
     const platformCookieNames: Record<string, string[]> = {
       douyin: ['passport_uid', 'uid_tt', 'ttwid', 'sessionid_ss'],
       douyin: ['passport_uid', 'uid_tt', 'ttwid', 'sessionid_ss'],
-      kuaishou: ['userId', 'passToken', 'did'],
       xiaohongshu: ['customerClientId', 'web_session', 'xsecappid'],
       xiaohongshu: ['customerClientId', 'web_session', 'xsecappid'],
       weixin_video: ['wxuin', 'pass_ticket', 'uin'],
       weixin_video: ['wxuin', 'pass_ticket', 'uin'],
-      bilibili: ['DedeUserID', 'SESSDATA', 'bili_jct'],
       toutiao: ['sso_uid', 'sessionid', 'passport_uid'],
       toutiao: ['sso_uid', 'sessionid', 'passport_uid'],
       baijiahao: ['BDUSS', 'STOKEN', 'BAIDUID'],
       baijiahao: ['BDUSS', 'STOKEN', 'BAIDUID'],
       qie: ['uin', 'skey', 'p_uin'],
       qie: ['uin', 'skey', 'p_uin'],
@@ -1189,8 +1183,6 @@ export class AccountService {
     'xiaohongshu': 'xhs_',
     'xiaohongshu': 'xhs_',
     'weixin_video': 'sph_',
     'weixin_video': 'sph_',
     'baijiahao': 'bjh_',
     'baijiahao': 'bjh_',
-    'kuaishou': 'ks_',
-    'bilibili': 'bili_',
     'toutiao': 'tt_',
     'toutiao': 'tt_',
     'qie': 'qie_',
     'qie': 'qie_',
     'dayuhao': 'dyh_',
     'dayuhao': 'dyh_',

+ 1 - 15
server/src/services/BrowserLoginService.ts

@@ -52,16 +52,6 @@ const PLATFORM_CONFIG: Record<string, {
     cookieDomain: '.douyin.com',
     cookieDomain: '.douyin.com',
     loginCookies: ['sessionid', 'sessionid_ss', 'passport_csrf_token'],
     loginCookies: ['sessionid', 'sessionid_ss', 'passport_csrf_token'],
   },
   },
-  kuaishou: {
-    loginUrl: 'https://cp.kuaishou.com/',
-    successIndicators: ['/article/publish', '/profile'],
-    cookieDomain: '.kuaishou.com',
-  },
-  bilibili: {
-    loginUrl: 'https://member.bilibili.com/platform/home',
-    successIndicators: ['/platform/home', '/platform/upload'],
-    cookieDomain: '.bilibili.com',
-  },
   xiaohongshu: {
   xiaohongshu: {
     loginUrl: 'https://creator.xiaohongshu.com/',
     loginUrl: 'https://creator.xiaohongshu.com/',
     successIndicators: ['/creator/home', '/publish'],
     successIndicators: ['/creator/home', '/publish'],
@@ -795,7 +785,7 @@ class BrowserLoginService extends EventEmitter {
       const isValidAccountId = (id: string): boolean => {
       const isValidAccountId = (id: string): boolean => {
         if (!id) return false;
         if (!id) return false;
         // 检查是否是时间戳格式(纯数字或以平台前缀+数字结尾)
         // 检查是否是时间戳格式(纯数字或以平台前缀+数字结尾)
-        const timestampPattern = /^(weixin_video_|douyin_|xiaohongshu_|kuaishou_|bilibili_|baijiahao_|weixin_)?\d{10,}$/;
+        const timestampPattern = /^(weixin_video_|douyin_|xiaohongshu_|baijiahao_|weixin_)?\d{10,}$/;
         return !timestampPattern.test(id);
         return !timestampPattern.test(id);
       };
       };
 
 
@@ -1299,10 +1289,6 @@ class BrowserLoginService extends EventEmitter {
               finalAccountId = rawId.startsWith('douyin_') ? rawId : `douyin_${rawId}`;
               finalAccountId = rawId.startsWith('douyin_') ? rawId : `douyin_${rawId}`;
             } else if (platform === 'xiaohongshu') {
             } else if (platform === 'xiaohongshu') {
               finalAccountId = rawId.startsWith('xiaohongshu_') ? rawId : `xiaohongshu_${rawId}`;
               finalAccountId = rawId.startsWith('xiaohongshu_') ? rawId : `xiaohongshu_${rawId}`;
-            } else if (platform === 'kuaishou') {
-              finalAccountId = rawId.startsWith('kuaishou_') ? rawId : `kuaishou_${rawId}`;
-            } else if (platform === 'bilibili') {
-              finalAccountId = rawId.startsWith('bilibili_') ? rawId : `bilibili_${rawId}`;
             } else {
             } else {
               finalAccountId = rawId.startsWith(`${platform}_`) ? rawId : `${platform}_${rawId}`;
               finalAccountId = rawId.startsWith(`${platform}_`) ? rawId : `${platform}_${rawId}`;
             }
             }

+ 0 - 120
server/src/services/HeadlessBrowserService.ts

@@ -341,8 +341,6 @@ class HeadlessBrowserService {
   private getPlatformReferer(platform: PlatformType): string {
   private getPlatformReferer(platform: PlatformType): string {
     const referers: Record<string, string> = {
     const referers: Record<string, string> = {
       douyin: 'https://creator.douyin.com/',
       douyin: 'https://creator.douyin.com/',
-      bilibili: 'https://member.bilibili.com/',
-      kuaishou: 'https://cp.kuaishou.com/',
       baijiahao: 'https://baijiahao.baidu.com/',
       baijiahao: 'https://baijiahao.baidu.com/',
     };
     };
     return referers[platform] || '';
     return referers[platform] || '';
@@ -820,12 +818,6 @@ class HeadlessBrowserService {
         case 'douyin':
         case 'douyin':
           accountInfo = await this.fetchDouyinAccountInfo(page, context, cookies);
           accountInfo = await this.fetchDouyinAccountInfo(page, context, cookies);
           break;
           break;
-        case 'bilibili':
-          accountInfo = await this.fetchBilibiliAccountInfo(page, context, cookies);
-          break;
-        case 'kuaishou':
-          accountInfo = await this.fetchKuaishouAccountInfo(page, context, cookies);
-          break;
         case 'xiaohongshu':
         case 'xiaohongshu':
           accountInfo = await this.fetchXiaohongshuAccountInfo(page, context, cookies);
           accountInfo = await this.fetchXiaohongshuAccountInfo(page, context, cookies);
           break;
           break;
@@ -1346,108 +1338,6 @@ class HeadlessBrowserService {
   }
   }
 
 
   /**
   /**
-   * 获取B站账号信息
-   */
-  private async fetchBilibiliAccountInfo(
-    page: Page,
-    _context: BrowserContext,
-    cookies: CookieData[]
-  ): Promise<AccountInfo> {
-    let accountId = `bilibili_${Date.now()}`;
-    let accountName = 'B站账号';
-    let avatarUrl = '';
-    let fansCount: number | undefined;
-    let worksCount = 0;
-
-    try {
-      const uidCookie = cookies.find(c => c.name === 'DedeUserID');
-      if (uidCookie?.value) {
-        accountId = `bilibili_${uidCookie.value}`;
-      }
-
-      await page.goto('https://member.bilibili.com/platform/home', {
-        waitUntil: 'domcontentloaded',
-        timeout: 30000,
-      });
-
-      await page.waitForTimeout(3000);
-
-      // 获取用户名
-      const nameEl = await page.$('[class*="nickname"], .user-name, .uname');
-      if (nameEl) {
-        const text = await nameEl.textContent();
-        if (text?.trim()) {
-          accountName = text.trim();
-        }
-      }
-
-      // 获取头像
-      const avatarEl = await page.$('[class*="avatar"] img, .user-face img');
-      if (avatarEl) {
-        const src = await avatarEl.getAttribute('src');
-        if (src) {
-          avatarUrl = src;
-        }
-      }
-    } catch (error) {
-      logger.warn('Failed to fetch Bilibili account info:', error);
-    }
-
-    return { accountId, accountName, avatarUrl, fansCount, worksCount };
-  }
-
-  /**
-   * 获取快手账号信息
-   */
-  private async fetchKuaishouAccountInfo(
-    page: Page,
-    _context: BrowserContext,
-    cookies: CookieData[]
-  ): Promise<AccountInfo> {
-    let accountId = `kuaishou_${Date.now()}`;
-    let accountName = '快手账号';
-    let avatarUrl = '';
-    let fansCount: number | undefined;
-    let worksCount = 0;
-
-    try {
-      const uidCookie = cookies.find(c => c.name === 'userId' || c.name === 'kuaishou.server.web_st');
-      if (uidCookie?.value) {
-        accountId = `kuaishou_${uidCookie.value.slice(0, 20)}`;
-      }
-
-      await page.goto('https://cp.kuaishou.com/profile', {
-        waitUntil: 'domcontentloaded',
-        timeout: 30000,
-      });
-
-      await page.waitForTimeout(3000);
-
-      // 获取用户名
-      const nameEl = await page.$('[class*="nickname"], [class*="userName"]');
-      if (nameEl) {
-        const text = await nameEl.textContent();
-        if (text?.trim()) {
-          accountName = text.trim();
-        }
-      }
-
-      // 获取头像
-      const avatarEl = await page.$('[class*="avatar"] img');
-      if (avatarEl) {
-        const src = await avatarEl.getAttribute('src');
-        if (src) {
-          avatarUrl = src;
-        }
-      }
-    } catch (error) {
-      logger.warn('Failed to fetch Kuaishou account info:', error);
-    }
-
-    return { accountId, accountName, avatarUrl, fansCount, worksCount };
-  }
-
-  /**
    * 获取微信视频号账号信息
    * 获取微信视频号账号信息
    */
    */
   private async fetchWeixinVideoAccountInfo(
   private async fetchWeixinVideoAccountInfo(
@@ -2775,14 +2665,6 @@ class HeadlessBrowserService {
         homeUrl: 'https://creator.douyin.com/creator-micro/home',
         homeUrl: 'https://creator.douyin.com/creator-micro/home',
         loginIndicators: ['login', 'passport', 'sso'],
         loginIndicators: ['login', 'passport', 'sso'],
       },
       },
-      bilibili: {
-        homeUrl: 'https://member.bilibili.com/platform/home',
-        loginIndicators: ['passport.bilibili.com', 'login'],
-      },
-      kuaishou: {
-        homeUrl: 'https://cp.kuaishou.com/profile',
-        loginIndicators: ['passport.kuaishou.com', 'login'],
-      },
       xiaohongshu: {
       xiaohongshu: {
         homeUrl: 'https://creator.xiaohongshu.com/',
         homeUrl: 'https://creator.xiaohongshu.com/',
         loginIndicators: ['login', 'passport'],
         loginIndicators: ['login', 'passport'],
@@ -3140,9 +3022,7 @@ class HeadlessBrowserService {
     const platformNames: Record<string, string> = {
     const platformNames: Record<string, string> = {
       douyin: '抖音',
       douyin: '抖音',
       xiaohongshu: '小红书',
       xiaohongshu: '小红书',
-      kuaishou: '快手',
       weixin_video: '视频号',
       weixin_video: '视频号',
-      bilibili: 'B站',
       toutiao: '头条',
       toutiao: '头条',
       baijiahao: '百家号',
       baijiahao: '百家号',
     };
     };

+ 0 - 4
server/src/services/PublishService.ts

@@ -13,8 +13,6 @@ import { wsManager } from '../websocket/index.js';
 import { DouyinAdapter } from '../automation/platforms/douyin.js';
 import { DouyinAdapter } from '../automation/platforms/douyin.js';
 import { XiaohongshuAdapter } from '../automation/platforms/xiaohongshu.js';
 import { XiaohongshuAdapter } from '../automation/platforms/xiaohongshu.js';
 import { WeixinAdapter } from '../automation/platforms/weixin.js';
 import { WeixinAdapter } from '../automation/platforms/weixin.js';
-import { KuaishouAdapter } from '../automation/platforms/kuaishou.js';
-import { BilibiliAdapter } from '../automation/platforms/bilibili.js';
 import { BaijiahaoAdapter } from '../automation/platforms/baijiahao.js';
 import { BaijiahaoAdapter } from '../automation/platforms/baijiahao.js';
 import { BasePlatformAdapter } from '../automation/platforms/base.js';
 import { BasePlatformAdapter } from '../automation/platforms/base.js';
 import { logger } from '../utils/logger.js';
 import { logger } from '../utils/logger.js';
@@ -46,8 +44,6 @@ export class PublishService {
     this.adapterFactories.set('douyin', () => new DouyinAdapter());
     this.adapterFactories.set('douyin', () => new DouyinAdapter());
     this.adapterFactories.set('xiaohongshu', () => new XiaohongshuAdapter());
     this.adapterFactories.set('xiaohongshu', () => new XiaohongshuAdapter());
     this.adapterFactories.set('weixin_video', () => new WeixinAdapter() as BasePlatformAdapter);
     this.adapterFactories.set('weixin_video', () => new WeixinAdapter() as BasePlatformAdapter);
-    this.adapterFactories.set('kuaishou', () => new KuaishouAdapter());
-    this.adapterFactories.set('bilibili', () => new BilibiliAdapter());
     this.adapterFactories.set('baijiahao', () => new BaijiahaoAdapter());
     this.adapterFactories.set('baijiahao', () => new BaijiahaoAdapter());
   }
   }
 
 

+ 0 - 1
server/src/services/WorkDayStatisticsService.ts

@@ -334,7 +334,6 @@ export class WorkDayStatisticsService {
   private platformNameMap: Record<string, string> = {
   private platformNameMap: Record<string, string> = {
     xiaohongshu: '小红书',
     xiaohongshu: '小红书',
     douyin: '抖音',
     douyin: '抖音',
-    kuaishou: '快手',
     weixin: '视频号',
     weixin: '视频号',
     weixin_video: '视频号',
     weixin_video: '视频号',
     shipinhao: '视频号',
     shipinhao: '视频号',

+ 0 - 2
server/src/utils/cookieParser.ts

@@ -10,10 +10,8 @@ export type CookieData = {
 // Domain map used by different platforms
 // Domain map used by different platforms
 const domainMap: Record<string, string> = {
 const domainMap: Record<string, string> = {
   douyin: '.douyin.com',
   douyin: '.douyin.com',
-  kuaishou: '.kuaishou.com',
   xiaohongshu: '.xiaohongshu.com',
   xiaohongshu: '.xiaohongshu.com',
   weixin_video: '.qq.com',
   weixin_video: '.qq.com',
-  bilibili: '.bilibili.com',
   toutiao: '.toutiao.com',
   toutiao: '.toutiao.com',
   baijiahao: '.baidu.com',
   baijiahao: '.baidu.com',
   qie: '.qq.com',
   qie: '.qq.com',

+ 0 - 4
server/src/utils/workCoverCache.ts

@@ -57,10 +57,6 @@ function getCoverReferer(platform: PlatformType): string {
       return 'https://creator.xiaohongshu.com/';
       return 'https://creator.xiaohongshu.com/';
     case 'douyin':
     case 'douyin':
       return 'https://creator.douyin.com/';
       return 'https://creator.douyin.com/';
-    case 'kuaishou':
-      return 'https://cp.kuaishou.com/';
-    case 'bilibili':
-      return 'https://member.bilibili.com/';
     default:
     default:
       return 'https://www.baidu.com/';
       return 'https://www.baidu.com/';
   }
   }

+ 0 - 32
shared/src/constants/platforms.ts

@@ -41,22 +41,6 @@ export const PLATFORMS: Record<PlatformType, PlatformInfo> = {
     maxVideoDuration: 900,
     maxVideoDuration: 900,
     supported: true,
     supported: true,
   },
   },
-  kuaishou: {
-    type: 'kuaishou',
-    name: '快手',
-    nameEn: 'Kuaishou',
-    icon: 'kuaishou',
-    color: '#FF4906',
-    loginUrl: 'https://cp.kuaishou.com/',
-    creatorUrl: 'https://cp.kuaishou.com/',
-    maxTitleLength: 50,
-    maxDescriptionLength: 500,
-    maxTags: 10,
-    supportedVideoFormats: ['mp4', 'mov'],
-    maxVideoSize: 4096,
-    maxVideoDuration: 600,
-    supported: false,
-  },
   weixin_video: {
   weixin_video: {
     type: 'weixin_video',
     type: 'weixin_video',
     name: '视频号',
     name: '视频号',
@@ -89,22 +73,6 @@ export const PLATFORMS: Record<PlatformType, PlatformInfo> = {
     maxVideoDuration: 900,
     maxVideoDuration: 900,
     supported: true,
     supported: true,
   },
   },
-  bilibili: {
-    type: 'bilibili',
-    name: 'B站',
-    nameEn: 'Bilibili',
-    icon: 'bilibili',
-    color: '#00A1D6',
-    loginUrl: 'https://member.bilibili.com/',
-    creatorUrl: 'https://member.bilibili.com/platform/home',
-    maxTitleLength: 80,
-    maxDescriptionLength: 2000,
-    maxTags: 12,
-    supportedVideoFormats: ['mp4', 'flv'],
-    maxVideoSize: 8192,
-    maxVideoDuration: 14400,
-    supported: false,
-  },
   toutiao: {
   toutiao: {
     type: 'toutiao',
     type: 'toutiao',
     name: '头条号',
     name: '头条号',

+ 1 - 3
shared/src/types/platform.ts

@@ -1,12 +1,10 @@
 /**
 /**
  * 支持的平台类型
  * 支持的平台类型
  */
  */
-export type PlatformType = 
+export type PlatformType =
   | 'douyin'       // 抖音
   | 'douyin'       // 抖音
-  | 'kuaishou'     // 快手
   | 'weixin_video' // 视频号
   | 'weixin_video' // 视频号
   | 'xiaohongshu'  // 小红书
   | 'xiaohongshu'  // 小红书
-  | 'bilibili'     // B站
   | 'toutiao'      // 头条号
   | 'toutiao'      // 头条号
   | 'baijiahao'    // 百家号
   | 'baijiahao'    // 百家号
   | 'qie'          // 企鹅号
   | 'qie'          // 企鹅号