{"record":{"id":"7e8745be6f90972d","repo":"yikart/AiToEarn","slug":"error-7e8745","errorCode":null,"errorMessage":"插件未安装或未就绪","messagePattern":"插件未安装或未就绪","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"project/aitoearn-web/src/store/plugin/plats/douyin/index.ts","lineNumber":48,"sourceCode":"  SubCommentListParams,\n} from '../types'\nimport type { DouyinDirectMessageResponse, DouyinInteractionResponse } from './types'\nimport { PlatType } from '@/app/config/platConfig'\nimport { getHomeFeedList, homeFeedCursor } from './homeFeed'\nimport { getWorkDetail, getWorkDetailFromListItem } from './workDetail'\n\n/**\n * 抖音平台交互类\n */\nclass DouyinPlatformInteraction implements IPlatformInteraction {\n  readonly platformType = PlatType.Douyin\n\n  /**\n   * 检查插件是否可用\n   */\n  private checkPlugin(): void {\n    if (!window.AIToEarnPlugin) {\n      throw new Error('插件未安装或未就绪')\n    }\n  }\n\n  /**\n   * 重置首页列表游标缓存\n   * 用于刷新列表时清除缓存\n   */\n  resetHomeFeedCursor(): void {\n    homeFeedCursor.reset()\n  }\n\n  /**\n   * 点赞/取消点赞作品（自动化方案）\n   * 使用自动化方案避免 API 风控\n   * @param workId 作品ID\n   * @param isLike true=点赞，false=取消点赞\n   */\n  async likeWork(workId: string, isLike: boolean): Promise<LikeResult> {","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-web/src/store/plugin/plats/douyin/index.ts#L30-L66","documentation":"The Douyin interaction adapter's private checkPlugin() guard throws '插件未安装或未就绪' when `window.AIToEarnPlugin` is undefined. All Douyin plugin actions (likeWork, commentWork, favoriteWork, sendDirectMessage) call it first because every DOM automation depends on the content script injected by the Aitoearn browser extension.","triggerScenarios":"Calling any Douyin interaction method (like, comment, favorite, DM) in a page where the Aitoearn browser extension is not installed, disabled, not yet injected its content script, or running in an environment without the plugin (SSR/non-browser window).","commonSituations":"User browses douyin.com without the extension installed; extension just updated/disabled and page not reloaded; content script failed to inject on the tab; accessing the page in incognito where extensions are blocked.","solutions":["Install/enable the Aitoearn browser extension and reload the douyin.com tab so the content script injects window.AIToEarnPlugin.","Before calling actions, check `typeof window !== 'undefined' && !!window.AIToEarnPlugin` and prompt the user with an install guide instead of letting the error throw.","Check the plugin status store (Status.NOT_INSTALLED / READY) and gate interaction buttons on READY state.","Verify incognito/site access permissions for the extension on douyin.com (chrome://extensions → site access)."],"exampleFix":"// before\nawait pluginManager.get('douyin').likeWork(params)\n\n// after\nif (!window.AIToEarnPlugin) {\n  showInstallPluginGuide()\n  return\n}\nawait pluginManager.get('douyin').likeWork(params)","handlingStrategy":"type-guard","validationCode":"const isPluginAvailable = () =>\n  typeof window !== 'undefined' && !!window.AIToEarnPlugin\nif (!isPluginAvailable()) {\n  showPluginInstallGuide()\n  return\n}","typeGuard":"function hasDouyinPlugin(w: Window): w is Window & { AIToEarnPlugin: NonNullable<Window['AIToEarnPlugin']> } {\n  return typeof w.AIToEarnPlugin !== 'undefined'\n}","tryCatchPattern":"try {\n  await pluginManager.get('douyin').likeWork(params)\n}\ncatch (e) {\n  if (e.message === '插件未安装或未就绪') {\n    openPluginInstallDialog()\n    return\n  }\n  throw e\n}","preventionTips":["Check window.AIToEarnPlugin before any plugin call, ideally once via a hook (usePluginReady)","Gate interaction UI on plugin store Status.READY","Prompt reload after extension install/update since content scripts inject on page load","Verify extension site access includes douyin.com and is enabled outside incognito restrictions"],"tags":["browser-extension","plugin","douyin","content-script"],"backgroundTag":"browser-extension-not-installed","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}