hechuanqi 1 місяць тому
батько
коміт
acf6568034

+ 1 - 0
src/constants/StatusConstants.ts

@@ -3,6 +3,7 @@ export const TaskStatusConstants = {
   0: '未开始',
   1: '进行中',
   2: '已完成',
+  3: '已取消',
 };
 
 // 兼容历史引用

+ 21 - 2
src/pages/CollectionTask/index.tsx

@@ -9,7 +9,7 @@ import React, { useEffect, useRef, useState } from 'react';
 
 /**
  * 采集任务列表
- * 后端接口:GET /collect_task/index?name=&platform=&page=&limit=
+ * 后端接口:GET /collect_task/index?name=&platform=&startDate=&endDate=&page=&limit=
  * 任务由定时任务 CollectTaskGenerateTask 自动生成,前端仅展示。
  * 平台名称由后端 platform_name 字段直接返回,前端不再做编码映射。
  */
@@ -50,6 +50,13 @@ const CollectionTask: React.FC = () => {
       fieldProps: { options: platformOptions },
       renderText: (_, record: any) => record?.platform_name ?? '-',
     },
+    {
+      title: '采集日期',
+      dataIndex: 'date_range',
+      key: 'date_range',
+      valueType: 'dateRange',
+      hideInTable: true,
+    },
     {
       title: '产品名称',
       dataIndex: 'product_name',
@@ -111,7 +118,6 @@ const CollectionTask: React.FC = () => {
       key: 'status',
       valueType: 'select',
       valueEnum: TaskStatusConstants,
-      hideInSearch: true,
     },
     {
       title: '分配状态',
@@ -130,6 +136,19 @@ const CollectionTask: React.FC = () => {
       formRef={proTableFormRef}
       request={async (params) => {
         downloadRef.current = params;
+        // 将 date_range 展开为后端期望的 startDate / endDate 顶层参数
+        const dateRange = (params as any)?.date_range;
+        if (dateRange && Array.isArray(dateRange) && dateRange.length === 2) {
+          const fmt = (v: any) => {
+            if (!v) return '';
+            return typeof v === 'string'
+              ? v
+              : v.format?.('YYYY-MM-DD') ?? String(v);
+          };
+          (params as any).startDate = fmt(dateRange[0]);
+          (params as any).endDate = fmt(dateRange[1]);
+        }
+        delete (params as any).date_range;
         const res = await API.CollectTask.collectTask(params);
         return {
           data: res.data?.data || [],

+ 32 - 2
src/pages/PlatformAccount/index.tsx

@@ -1,3 +1,4 @@
+import Modal from '@/components/Modal';
 import ProTable from '@/components/ProTable';
 import { ConfigStatusConstants } from '@/constants/StatusConstants';
 import API from '@/services';
@@ -10,7 +11,8 @@ import React, { useEffect, useRef, useState } from 'react';
  * 平台账号列表
  * 后端接口(CollectPlatformAccountController):
  * - GET  /collect_platform_account/index?platform=&account_username=&page=&limit=
- * - POST /collect_platform_account/set_status    启用/禁用账号
+ * - POST /collect_platform_account/set_status       启用/禁用账号
+ * - POST /collect_platform_account/handle_exceptions 处理异常
  *
  * 注意:不提供新增/编辑/删除功能,账号数据由心跳上报自动维护
  */
@@ -92,7 +94,7 @@ const PlatformAccount: React.FC = () => {
       key: 'option',
       valueType: 'option',
       fixed: 'right',
-      width: 100,
+      width: 180,
       render: (text, record) => {
         void text;
         return (
@@ -114,6 +116,34 @@ const PlatformAccount: React.FC = () => {
             >
               {record.status === 0 ? '禁用' : '启用'}
             </Typography.Link>
+            <Typography.Link
+              onClick={() => {
+                Modal.show({
+                  title: '处理异常',
+                  content: (
+                    <p>
+                      确认要处理账号 <b>{record.account_username}</b> 的异常吗?
+                      <br />
+                      此操作将清空该账号的异常计数。
+                    </p>
+                  ),
+                  onOk: async () => {
+                    const response =
+                      await API.CollectPlatformAccount.handleException({
+                        id: record.id,
+                      });
+                    if (response.code === 'success') {
+                      message.success('异常处理成功');
+                      actionRef.current?.reload();
+                      return;
+                    }
+                    throw new Error(response?.msg || '操作失败');
+                  },
+                });
+              }}
+            >
+              处理异常
+            </Typography.Link>
           </Space>
         );
       },

+ 41 - 1
src/pages/PlatformConfig/index.tsx

@@ -20,6 +20,8 @@ import React, { useEffect, useRef, useState } from 'react';
  *
  * 备注:后端 config 为统一 JSON 配置,约定 key:
  *       rest_duration(休息时长,分钟)、daily_max_pages(每日最大页数/条数,0=不限)
+ *       login_exception_limit(登录异常次数上限,0=不限)
+ *       total_exception_limit(总异常次数上限,0=不限)
  */
 const PlatformConfig: React.FC = () => {
   const actionRef = useRef<ActionType>();
@@ -45,6 +47,8 @@ const PlatformConfig: React.FC = () => {
       platform: record?.platform,
       rest_duration: cfg.rest_duration ?? 0,
       daily_max_pages: cfg.daily_max_pages ?? 0,
+      login_exception_limit: cfg.login_exception_limit ?? 0,
+      total_exception_limit: cfg.total_exception_limit ?? 0,
       status: record?.status,
     };
   };
@@ -54,6 +58,8 @@ const PlatformConfig: React.FC = () => {
     return {
       rest_duration: Number(values.rest_duration ?? 0),
       daily_max_pages: Number(values.daily_max_pages ?? 0),
+      login_exception_limit: Number(values.login_exception_limit ?? 0),
+      total_exception_limit: Number(values.total_exception_limit ?? 0),
     };
   };
 
@@ -86,6 +92,20 @@ const PlatformConfig: React.FC = () => {
               type: 'number',
               help: '0 表示不限制',
             },
+            {
+              label: '登录异常次数上限',
+              isRequired: true,
+              value: 'login_exception_limit',
+              type: 'number',
+              help: '超过此次数则不允许拉取任务,0 表示不限制',
+            },
+            {
+              label: '总异常次数上限',
+              isRequired: true,
+              value: 'total_exception_limit',
+              type: 'number',
+              help: '超过此次数则不允许拉取任务,0 表示不限制',
+            },
           ]}
           ref={modiyFormModalRef}
           getDetail={() => flattenConfig(data)}
@@ -152,6 +172,26 @@ const PlatformConfig: React.FC = () => {
           ? '不限'
           : record?.config?.daily_max_pages ?? '-',
     },
+    {
+      title: '登录异常次数上限',
+      dataIndex: ['config', 'login_exception_limit'],
+      key: 'login_exception_limit',
+      hideInSearch: true,
+      renderText: (_, record: any) =>
+        record?.config?.login_exception_limit === 0
+          ? '不限'
+          : record?.config?.login_exception_limit ?? '-',
+    },
+    {
+      title: '总异常次数上限',
+      dataIndex: ['config', 'total_exception_limit'],
+      key: 'total_exception_limit',
+      hideInSearch: true,
+      renderText: (_, record: any) =>
+        record?.config?.total_exception_limit === 0
+          ? '不限'
+          : record?.config?.total_exception_limit ?? '-',
+    },
     {
       title: '状态',
       dataIndex: 'status',
@@ -231,7 +271,7 @@ const PlatformConfig: React.FC = () => {
       editable={{
         type: 'multiple',
       }}
-      scroll={{ x: '150%' }}
+      scroll={{ x: '200%' }}
       noSearch
       toolbar={{
         actions: [

+ 11 - 2
src/services/collect_platform_account.ts

@@ -3,8 +3,9 @@ import BaseAPI from './BaseAPI';
 /**
  * 平台账号 Service
  * 后端接口(CollectPlatformAccountController):
- * - GET  /collect_platform_account/index        账号分页列表(支持 platform、account_username 筛选)
- * - POST /collect_platform_account/set_status   启用/禁用账号
+ * - GET  /collect_platform_account/index            账号分页列表(支持 platform、account_username 筛选)
+ * - POST /collect_platform_account/set_status       启用/禁用账号
+ * - POST /collect_platform_account/handle_exception 处理异常(针对某个账号清空异常计数)
  *
  * 注意:不提供新增/编辑/删除接口,账号数据由心跳上报自动维护
  */
@@ -28,6 +29,14 @@ class CollectPlatformAccountAPI extends BaseAPI {
       data,
     }).then((data) => data);
   }
+
+  /** 处理异常(针对某个账号清空异常计数) */
+  handleException(data: { id: number }) {
+    return this._post({
+      path: `/collect_platform_account/handle_exceptions`,
+      data,
+    }).then((data) => data);
+  }
 }
 
 export default new CollectPlatformAccountAPI();

+ 4 - 4
src/services/collect_task.ts

@@ -3,10 +3,10 @@ import BaseAPI from './BaseAPI';
 /**
  * 采集任务 Service
  * 后端接口:
- * - GET  /collect_task/index?name=&page=&limit=    任务分页列表
- * - GET  /collect_task/pull?platform=&username=     拉取任务(爬虫端)
- * - POST /collect_task/heartbeat                    心跳上报(爬虫端)
- * - POST /collect_task/report                       任务回告(爬虫端)
+ * - GET  /collect_task/index?name=&platform=&startDate=&endDate=&page=&limit=    任务分页列表
+ * - GET  /collect_task/pull?platform=&username=                                  拉取任务(爬虫端)
+ * - POST /collect_task/heartbeat                                                 心跳上报(爬虫端)
+ * - POST /collect_task/report                                                    任务回告(爬虫端)
  */
 class CollectTask extends BaseAPI {
   constructor() {