Bladeren bron

feat: enhance Python service integration and improve component definitions

- Updated Weixin and Xiaohongshu adapters to accept an optional Python service URL for better flexibility.
- Enhanced the check for Python service availability to use the provided URL or fallback to the default configuration.
- Added ElCol and ElRow components to TypeScript definitions for Element Plus.
- Updated index.html to refine Content Security Policy for improved security.

These changes improve the adaptability of the publishing process and expand the component libra
Ethanfly 1 dag geleden
bovenliggende
commit
4fe7785be5

+ 39 - 0
check-python-config.js

@@ -0,0 +1,39 @@
+import mysql from 'mysql2/promise';
+
+async function checkConfig() {
+  const connection = await mysql.createConnection({
+    host: '8.136.223.156',
+    port: 6630,
+    user: 'media_manager',
+    password: 'media_manager',
+    database: 'media_manager'
+  });
+
+  try {
+    // 检查 system_config 表
+    const [rows] = await connection.execute(
+      'SELECT * FROM system_config WHERE config_key = "python_publish_service_url"'
+    );
+    
+    console.log('system_config 表中的 Python 服务配置:');
+    console.log(rows);
+
+    // 检查用户是否设置了配置
+    if (rows.length === 0) {
+      console.log('数据库中没有找到 python_publish_service_url 配置');
+      
+      // 插入默认配置
+      await connection.execute(
+        'INSERT INTO system_config (config_key, config_value, description) VALUES (?, ?, ?)',
+        ['python_publish_service_url', 'http://47.96.25.207:5005', 'Python 发布服务地址']
+      );
+      console.log('已插入默认配置: http://47.96.25.207:5005');
+    }
+  } catch (error) {
+    console.error('数据库查询错误:', error.message);
+  } finally {
+    await connection.end();
+  }
+}
+
+checkConfig();

+ 1 - 1
client/index.html

@@ -5,7 +5,7 @@
   <meta charset="UTF-8" />
   <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   <meta http-equiv="Content-Security-Policy"
-    content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' http://localhost:* http://127.0.0.1:* https: ws://localhost:* ws://127.0.0.1:* wss:" />
+    content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' http://localhost:* http://127.0.0.1:* http: https: ws://localhost:* ws://127.0.0.1:* ws: wss:" />
   <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
   <title>智媒通</title>
 </head>

+ 2 - 0
client/src/components.d.ts

@@ -18,6 +18,7 @@ declare module 'vue' {
     ElCascader: typeof import('element-plus/es')['ElCascader']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
+    ElCol: typeof import('element-plus/es')['ElCol']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElContainer: typeof import('element-plus/es')['ElContainer']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
@@ -42,6 +43,7 @@ declare module 'vue' {
     ElProgress: typeof import('element-plus/es')['ElProgress']
     ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
+    ElRow: typeof import('element-plus/es')['ElRow']
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']

+ 35 - 0
pnpm-lock.yaml

@@ -680,89 +680,105 @@ packages:
     resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
     cpu: [arm64]
     os: [linux]
+    libc: [glibc]
 
   '@img/sharp-libvips-linux-arm@1.2.4':
     resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
     cpu: [arm]
     os: [linux]
+    libc: [glibc]
 
   '@img/sharp-libvips-linux-ppc64@1.2.4':
     resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
     cpu: [ppc64]
     os: [linux]
+    libc: [glibc]
 
   '@img/sharp-libvips-linux-riscv64@1.2.4':
     resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
     cpu: [riscv64]
     os: [linux]
+    libc: [glibc]
 
   '@img/sharp-libvips-linux-s390x@1.2.4':
     resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
     cpu: [s390x]
     os: [linux]
+    libc: [glibc]
 
   '@img/sharp-libvips-linux-x64@1.2.4':
     resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
     cpu: [x64]
     os: [linux]
+    libc: [glibc]
 
   '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
     resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
     cpu: [arm64]
     os: [linux]
+    libc: [musl]
 
   '@img/sharp-libvips-linuxmusl-x64@1.2.4':
     resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
     cpu: [x64]
     os: [linux]
+    libc: [musl]
 
   '@img/sharp-linux-arm64@0.34.5':
     resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
     cpu: [arm64]
     os: [linux]
+    libc: [glibc]
 
   '@img/sharp-linux-arm@0.34.5':
     resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
     cpu: [arm]
     os: [linux]
+    libc: [glibc]
 
   '@img/sharp-linux-ppc64@0.34.5':
     resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
     cpu: [ppc64]
     os: [linux]
+    libc: [glibc]
 
   '@img/sharp-linux-riscv64@0.34.5':
     resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
     cpu: [riscv64]
     os: [linux]
+    libc: [glibc]
 
   '@img/sharp-linux-s390x@0.34.5':
     resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
     cpu: [s390x]
     os: [linux]
+    libc: [glibc]
 
   '@img/sharp-linux-x64@0.34.5':
     resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
     cpu: [x64]
     os: [linux]
+    libc: [glibc]
 
   '@img/sharp-linuxmusl-arm64@0.34.5':
     resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
     cpu: [arm64]
     os: [linux]
+    libc: [musl]
 
   '@img/sharp-linuxmusl-x64@0.34.5':
     resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
     cpu: [x64]
     os: [linux]
+    libc: [musl]
 
   '@img/sharp-wasm32@0.34.5':
     resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
@@ -888,36 +904,42 @@ packages:
     engines: {node: '>= 10.0.0'}
     cpu: [arm]
     os: [linux]
+    libc: [glibc]
 
   '@parcel/watcher-linux-arm-musl@2.5.4':
     resolution: {integrity: sha512-kGO8RPvVrcAotV4QcWh8kZuHr9bXi9a3bSZw7kFarYR0+fGliU7hd/zevhjw8fnvIKG3J9EO5G6sXNGCSNMYPQ==}
     engines: {node: '>= 10.0.0'}
     cpu: [arm]
     os: [linux]
+    libc: [musl]
 
   '@parcel/watcher-linux-arm64-glibc@2.5.4':
     resolution: {integrity: sha512-KU75aooXhqGFY2W5/p8DYYHt4hrjHZod8AhcGAmhzPn/etTa+lYCDB2b1sJy3sWJ8ahFVTdy+EbqSBvMx3iFlw==}
     engines: {node: '>= 10.0.0'}
     cpu: [arm64]
     os: [linux]
+    libc: [glibc]
 
   '@parcel/watcher-linux-arm64-musl@2.5.4':
     resolution: {integrity: sha512-Qx8uNiIekVutnzbVdrgSanM+cbpDD3boB1f8vMtnuG5Zau4/bdDbXyKwIn0ToqFhIuob73bcxV9NwRm04/hzHQ==}
     engines: {node: '>= 10.0.0'}
     cpu: [arm64]
     os: [linux]
+    libc: [musl]
 
   '@parcel/watcher-linux-x64-glibc@2.5.4':
     resolution: {integrity: sha512-UYBQvhYmgAv61LNUn24qGQdjtycFBKSK3EXr72DbJqX9aaLbtCOO8+1SkKhD/GNiJ97ExgcHBrukcYhVjrnogA==}
     engines: {node: '>= 10.0.0'}
     cpu: [x64]
     os: [linux]
+    libc: [glibc]
 
   '@parcel/watcher-linux-x64-musl@2.5.4':
     resolution: {integrity: sha512-YoRWCVgxv8akZrMhdyVi6/TyoeeMkQ0PGGOf2E4omODrvd1wxniXP+DBynKoHryStks7l+fDAMUBRzqNHrVOpg==}
     engines: {node: '>= 10.0.0'}
     cpu: [x64]
     os: [linux]
+    libc: [musl]
 
   '@parcel/watcher-win32-arm64@2.5.4':
     resolution: {integrity: sha512-iby+D/YNXWkiQNYcIhg8P5hSjzXEHaQrk2SLrWOUD7VeC4Ohu0WQvmV+HDJokZVJ2UjJ4AGXW3bx7Lls9Ln4TQ==}
@@ -1017,66 +1039,79 @@ packages:
     resolution: {integrity: sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==}
     cpu: [arm]
     os: [linux]
+    libc: [glibc]
 
   '@rollup/rollup-linux-arm-musleabihf@4.55.1':
     resolution: {integrity: sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==}
     cpu: [arm]
     os: [linux]
+    libc: [musl]
 
   '@rollup/rollup-linux-arm64-gnu@4.55.1':
     resolution: {integrity: sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==}
     cpu: [arm64]
     os: [linux]
+    libc: [glibc]
 
   '@rollup/rollup-linux-arm64-musl@4.55.1':
     resolution: {integrity: sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==}
     cpu: [arm64]
     os: [linux]
+    libc: [musl]
 
   '@rollup/rollup-linux-loong64-gnu@4.55.1':
     resolution: {integrity: sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==}
     cpu: [loong64]
     os: [linux]
+    libc: [glibc]
 
   '@rollup/rollup-linux-loong64-musl@4.55.1':
     resolution: {integrity: sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==}
     cpu: [loong64]
     os: [linux]
+    libc: [musl]
 
   '@rollup/rollup-linux-ppc64-gnu@4.55.1':
     resolution: {integrity: sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==}
     cpu: [ppc64]
     os: [linux]
+    libc: [glibc]
 
   '@rollup/rollup-linux-ppc64-musl@4.55.1':
     resolution: {integrity: sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==}
     cpu: [ppc64]
     os: [linux]
+    libc: [musl]
 
   '@rollup/rollup-linux-riscv64-gnu@4.55.1':
     resolution: {integrity: sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==}
     cpu: [riscv64]
     os: [linux]
+    libc: [glibc]
 
   '@rollup/rollup-linux-riscv64-musl@4.55.1':
     resolution: {integrity: sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==}
     cpu: [riscv64]
     os: [linux]
+    libc: [musl]
 
   '@rollup/rollup-linux-s390x-gnu@4.55.1':
     resolution: {integrity: sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==}
     cpu: [s390x]
     os: [linux]
+    libc: [glibc]
 
   '@rollup/rollup-linux-x64-gnu@4.55.1':
     resolution: {integrity: sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==}
     cpu: [x64]
     os: [linux]
+    libc: [glibc]
 
   '@rollup/rollup-linux-x64-musl@4.55.1':
     resolution: {integrity: sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==}
     cpu: [x64]
     os: [linux]
+    libc: [musl]
 
   '@rollup/rollup-openbsd-x64@4.55.1':
     resolution: {integrity: sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==}

+ 22 - 6
server/src/automation/platforms/weixin.ts

@@ -368,10 +368,17 @@ export class WeixinAdapter extends BasePlatformAdapter {
 
   /**
    * 检查 Python 发布服务是否可用
+   * @param pythonServiceUrl 可选的 Python 服务地址,如果不提供则从全局配置读取
    */
-  private async checkPythonServiceAvailable(): Promise<boolean> {
+  private async checkPythonServiceAvailable(pythonServiceUrl?: string): Promise<boolean> {
     try {
-      const pythonUrl = (await getPythonServiceBaseUrl()).replace(/\/$/, '');
+      let pythonUrl = pythonServiceUrl;
+      if (!pythonUrl) {
+        pythonUrl = (await getPythonServiceBaseUrl()).replace(/\/$/, '');
+      } else {
+        pythonUrl = pythonUrl.replace(/\/$/, '');
+      }
+      
       const response = await fetch(`${pythonUrl}/health`, {
         method: 'GET',
         signal: AbortSignal.timeout(3000),
@@ -392,7 +399,8 @@ export class WeixinAdapter extends BasePlatformAdapter {
   private async publishVideoViaPython(
     cookies: string,
     params: PublishParams,
-    onProgress?: (progress: number, message: string) => void
+    onProgress?: (progress: number, message: string) => void,
+    pythonServiceUrl?: string
   ): Promise<PublishResult> {
     logger.info('[Weixin Python] Starting publish via Python service with AI assist...');
     onProgress?.(5, '正在通过 Python 服务发布...');
@@ -409,7 +417,12 @@ export class WeixinAdapter extends BasePlatformAdapter {
 
       // 使用 AI 辅助发布接口
       const extra = (params.extra || {}) as Record<string, unknown>;
-      const pythonUrl = (await getPythonServiceBaseUrl()).replace(/\/$/, '');
+      let pythonUrl = pythonServiceUrl;
+      if (!pythonUrl) {
+        pythonUrl = (await getPythonServiceBaseUrl()).replace(/\/$/, '');
+      } else {
+        pythonUrl = pythonUrl.replace(/\/$/, '');
+      }
       const response = await fetch(`${pythonUrl}/publish/ai-assisted`, {
         method: 'POST',
         headers: {
@@ -453,7 +466,10 @@ export class WeixinAdapter extends BasePlatformAdapter {
     options?: { headless?: boolean }
   ): Promise<PublishResult> {
     // 只使用 Python 服务发布
-    const pythonAvailable = await this.checkPythonServiceAvailable();
+    // 从 params.extra 中获取 Python 服务地址
+    const extra = (params.extra || {}) as Record<string, unknown>;
+    const pythonServiceUrl = extra.pythonServiceUrl as string | undefined;
+    const pythonAvailable = await this.checkPythonServiceAvailable(pythonServiceUrl);
     if (!pythonAvailable) {
       logger.error('[Weixin] Python service not available');
       return {
@@ -464,7 +480,7 @@ export class WeixinAdapter extends BasePlatformAdapter {
 
     logger.info('[Weixin] Using Python service for publishing');
     try {
-      const result = await this.publishVideoViaPython(cookies, params, onProgress);
+      const result = await this.publishVideoViaPython(cookies, params, onProgress, pythonServiceUrl);
 
       // 检查是否需要验证码
       if (!result.success && result.errorMessage?.includes('验证码')) {

+ 21 - 6
server/src/automation/platforms/xiaohongshu.ts

@@ -425,10 +425,16 @@ export class XiaohongshuAdapter extends BasePlatformAdapter {
 
   /**
    * 检查 Python API 服务是否可用
+   * @param pythonServiceUrl 可选的 Python 服务地址,如果不提供则从全局配置读取
    */
-  private async checkPythonServiceAvailable(): Promise<boolean> {
+  private async checkPythonServiceAvailable(pythonServiceUrl?: string): Promise<boolean> {
     try {
-      const pythonUrl = (await getPythonServiceBaseUrl()).replace(/\/$/, '');
+      let pythonUrl = pythonServiceUrl;
+      if (!pythonUrl) {
+        pythonUrl = (await getPythonServiceBaseUrl()).replace(/\/$/, '');
+      } else {
+        pythonUrl = pythonUrl.replace(/\/$/, '');
+      }
       const response = await fetch(`${pythonUrl}/health`, {
         method: 'GET',
         signal: AbortSignal.timeout(3000),
@@ -450,7 +456,8 @@ export class XiaohongshuAdapter extends BasePlatformAdapter {
   private async publishVideoViaApi(
     cookies: string,
     params: PublishParams,
-    onProgress?: (progress: number, message: string) => void
+    onProgress?: (progress: number, message: string) => void,
+    pythonServiceUrl?: string
   ): Promise<PublishResult> {
     logger.info('[Xiaohongshu API] Starting publish via Python API service...');
     onProgress?.(5, '正在通过 API 发布...');
@@ -500,7 +507,12 @@ export class XiaohongshuAdapter extends BasePlatformAdapter {
       });
 
       // 使用 AI 辅助发布接口
-      const pythonUrl = (await getPythonServiceBaseUrl()).replace(/\/$/, '');
+      let pythonUrl = pythonServiceUrl;
+      if (!pythonUrl) {
+        pythonUrl = (await getPythonServiceBaseUrl()).replace(/\/$/, '');
+      } else {
+        pythonUrl = pythonUrl.replace(/\/$/, '');
+      }
       const response = await fetch(`${pythonUrl}/publish/ai-assisted`, {
         method: 'POST',
         headers: {
@@ -540,7 +552,10 @@ export class XiaohongshuAdapter extends BasePlatformAdapter {
     options?: { headless?: boolean }
   ): Promise<PublishResult> {
     // 只使用 Python API 服务
-    const apiAvailable = await this.checkPythonServiceAvailable();
+    // 从 params.extra 中获取 Python 服务地址
+    const extra = (params.extra || {}) as Record<string, unknown>;
+    const pythonServiceUrl = extra.pythonServiceUrl as string | undefined;
+    const apiAvailable = await this.checkPythonServiceAvailable(pythonServiceUrl);
     if (!apiAvailable) {
       logger.error('[Xiaohongshu] Python API service not available');
       return {
@@ -551,7 +566,7 @@ export class XiaohongshuAdapter extends BasePlatformAdapter {
 
     logger.info('[Xiaohongshu] Using Python API service for publishing');
     try {
-      const result = await this.publishVideoViaApi(cookies, params, onProgress);
+      const result = await this.publishVideoViaApi(cookies, params, onProgress, pythonServiceUrl);
 
       // 检查是否需要验证码
       if (!result.success && ((result as any).needCaptcha || result.errorMessage?.includes('验证码'))) {

+ 23 - 2
server/src/services/PythonServiceConfigService.ts

@@ -1,4 +1,5 @@
 import { AppDataSource, SystemConfig } from '../models/index.js';
+import { logger } from '../utils/logger.js';
 
 const FALLBACK_PYTHON_SERVICE_URL =
   process.env.PYTHON_PUBLISH_SERVICE_URL || process.env.XHS_SERVICE_URL || process.env.PYTHON_API_URL || 'http://localhost:5005';
@@ -9,26 +10,46 @@ const CACHE_TTL_MS = 30_000;
 let cached: { url: string; expiresAt: number } | null = null;
 
 export function invalidatePythonServiceBaseUrlCache(): void {
+  logger.info('[PythonServiceConfig] 清除缓存');
   cached = null;
 }
 
 export async function getPythonServiceBaseUrl(): Promise<string> {
   const now = Date.now();
-  if (cached && cached.expiresAt > now) return cached.url;
+  if (cached && cached.expiresAt > now) {
+    logger.info(`[PythonServiceConfig] 使用缓存: ${cached.url}`);
+    return cached.url;
+  }
 
   let fromDb = '';
+  let dbError: any = null;
   try {
+    logger.info('[PythonServiceConfig] 从数据库读取配置');
     if (AppDataSource.isInitialized) {
       const repo = AppDataSource.getRepository(SystemConfig);
       const row = await repo.findOne({ where: { configKey: CONFIG_KEY } });
       fromDb = String(row?.configValue || '').trim();
+      logger.info(`[PythonServiceConfig] 数据库查询结果: ${fromDb || '(空)'}`);
+    } else {
+      logger.warn('[PythonServiceConfig] 数据库未初始化');
     }
-  } catch {
+  } catch (error) {
+    dbError = error;
+    logger.error(`[PythonServiceConfig] 数据库查询失败: ${error}`);
     fromDb = '';
   }
 
   const url = fromDb || FALLBACK_PYTHON_SERVICE_URL;
   cached = { url, expiresAt: now + CACHE_TTL_MS };
+  
+  if (fromDb) {
+    logger.info(`[PythonServiceConfig] 使用数据库配置: ${url}`);
+  } else if (dbError) {
+    logger.warn(`[PythonServiceConfig] 使用后备配置(数据库错误): ${url}`);
+  } else {
+    logger.warn(`[PythonServiceConfig] 使用后备配置(数据库无记录): ${url}`);
+  }
+  
   return url;
 }