Ver Fonte

智价云2.0页面修改

hechuanqi há 2 meses atrás
pai
commit
369308c1ea

+ 0 - 1
.husky/commit-msg

@@ -1 +0,0 @@
-npx --no-install max verify-commit $1

+ 3 - 0
.lintstagedrc

@@ -13,5 +13,8 @@
   "*.ts?(x)": [
     "max lint --fix --eslint-only",
     "prettier --cache --parser=typescript --write"
+  ],
+  ".umirc.ts": [
+    "prettier --cache --parser=typescript --write"
   ]
 }

+ 14 - 0
.umirc.ts

@@ -55,6 +55,20 @@ export default defineConfig({
       icon: 'FileTextOutlined',
       component: './PlatformConfig',
     },
+    // 平台维护(平台注册表管理)
+    {
+      name: '平台维护',
+      path: '/platform_manage',
+      icon: 'AppstoreOutlined',
+      component: './PlatformManage',
+    },
+    // 平台账号(仅查看和启用/禁用,账号由心跳上报自动维护)
+    {
+      name: '平台账号',
+      path: '/platform_account',
+      icon: 'UserOutlined',
+      component: './PlatformAccount',
+    },
     // 全局未匹配路由兜底到 404
     {
       path: '*',

+ 17 - 24
src/pages/CollectionTask/index.tsx

@@ -1,22 +1,33 @@
 import ProTable from '@/components/ProTable';
-import { PlatformConstants } from '@/constants/PlatformConstants';
 import {
   AllocateStatusConstants,
   TaskStatusConstants,
 } from '@/constants/StatusConstants';
 import API from '@/services';
 import type { ActionType, ProColumns } from '@ant-design/pro-table';
-import React, { useRef } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
 
 /**
  * 采集任务列表
- * 后端接口:GET /collect_task/index?name=&page=&limit=
+ * 后端接口:GET /collect_task/index?name=&platform=&page=&limit=
  * 任务由定时任务 CollectTaskGenerateTask 自动生成,前端仅展示。
+ * 平台名称由后端 platform_name 字段直接返回,前端不再做编码映射。
  */
 const CollectionTask: React.FC = () => {
   const actionRef = useRef<ActionType>();
   const proTableFormRef = useRef<any>();
   const downloadRef = useRef<any>({});
+  const [platformOptions, setPlatformOptions] = useState<
+    { label: string; value: number }[]
+  >([]);
+
+  useEffect(() => {
+    API.CollectPlatform.selectOptions().then((res: any) => {
+      if (res?.code === 'success') {
+        setPlatformOptions(res.data || []);
+      }
+    });
+  }, []);
 
   const columns: ProColumns[] = [
     {
@@ -36,8 +47,8 @@ const CollectionTask: React.FC = () => {
       dataIndex: 'platform',
       key: 'platform',
       valueType: 'select',
-      valueEnum: PlatformConstants,
-      hideInSearch: true,
+      fieldProps: { options: platformOptions },
+      renderText: (_, record: any) => record?.platform_name ?? '-',
     },
     {
       title: '产品名称',
@@ -56,12 +67,6 @@ const CollectionTask: React.FC = () => {
       key: 'product_brand',
       hideInSearch: true,
     },
-    {
-      title: '最小起购量',
-      dataIndex: 'minimum_order_quantity',
-      key: 'minimum_order_quantity',
-      hideInSearch: true,
-    },
     {
       title: '采集开始时间',
       dataIndex: 'sampling_start_time',
@@ -80,25 +85,13 @@ const CollectionTask: React.FC = () => {
       renderText: (val) =>
         typeof val === 'number' && val < 1e12 ? val * 1000 : val,
     },
-    {
-      title: '最多分配设备数',
-      dataIndex: 'max_equipment_number',
-      hideInSearch: true,
-      key: 'max_equipment_number',
-    },
-    {
-      title: '已分配设备数',
-      dataIndex: 'equipment_number',
-      hideInSearch: true,
-      key: 'equipment_number',
-    },
     {
       title: '当前页/总页',
       dataIndex: 'current_page',
       hideInSearch: true,
       key: 'current_page',
       renderText: (val, record) =>
-        val == null ? '-' : `${val}/${record.total_pages ?? '-'}`,
+        val === null ? '-' : `${val}/${record.total_pages ?? '-'}`,
     },
     {
       title: '已爬取数量',

+ 35 - 41
src/pages/Home/index.tsx

@@ -1,6 +1,15 @@
-import { PlatformConstants } from '@/constants/PlatformConstants';
 import API from '@/services';
-import { Card, Col, DatePicker, Empty, Row, Space, Spin, Table, Tag } from 'antd';
+import {
+  Card,
+  Col,
+  DatePicker,
+  Empty,
+  Row,
+  Space,
+  Spin,
+  Table,
+  Tag,
+} from 'antd';
 import type { ColumnsType } from 'antd/es/table';
 import dayjs, { Dayjs } from 'dayjs';
 import React, { useEffect, useMemo, useState } from 'react';
@@ -12,6 +21,7 @@ interface DashboardRow {
   id?: number;
   statDate?: string;
   platform: string;
+  platform_name?: string;
   totalPages?: number;
   totalCount?: number;
   totalTasks?: number;
@@ -100,9 +110,9 @@ const HomePage: React.FC = () => {
       dataIndex: 'platform',
       key: 'platform',
       width: 140,
-      render: (val) => (
+      render: (_, record) => (
         <span className={styles.platformName}>
-          {(PlatformConstants as any)[val] ?? `平台${val}`}
+          {record.platform_name ?? record.platform}
         </span>
       ),
     },
@@ -124,14 +134,16 @@ const HomePage: React.FC = () => {
       key: 'completionRate',
       align: 'right',
       render: (val) =>
-        val == null ? '-' : (
+        val === null ? (
+          '-'
+        ) : (
           <span
             className={
               Number(val) >= 80
                 ? styles.rateUp
                 : Number(val) >= 50
-                  ? undefined
-                  : styles.rateDown
+                ? undefined
+                : styles.rateDown
             }
           >
             {`${Number(val).toFixed(2)}%`}
@@ -144,12 +156,7 @@ const HomePage: React.FC = () => {
       key: 'totalPages',
       align: 'right',
     },
-    {
-      title: '今日爬取条数',
-      dataIndex: 'totalCount',
-      key: 'totalCount',
-      align: 'right',
-    },
+
     {
       title: '活跃账号',
       dataIndex: 'activeAccounts',
@@ -168,11 +175,7 @@ const HomePage: React.FC = () => {
       key: 'exceptionTotal',
       align: 'right',
       render: (val) =>
-        val > 0 ? (
-          <Tag color="red">{val}</Tag>
-        ) : (
-          <Tag color="green">0</Tag>
-        ),
+        val > 0 ? <Tag color="red">{val}</Tag> : <Tag color="green">0</Tag>,
     },
     {
       title: '异常率',
@@ -180,12 +183,10 @@ const HomePage: React.FC = () => {
       key: 'exceptionRate',
       align: 'right',
       render: (val) =>
-        val == null ? '-' : (
-          <span
-            className={
-              Number(val) <= 5 ? styles.rateUp : styles.rateDown
-            }
-          >
+        val === null ? (
+          '-'
+        ) : (
+          <span className={Number(val) <= 5 ? styles.rateUp : styles.rateDown}>
             {`${Number(val).toFixed(2)}%`}
           </span>
         ),
@@ -221,7 +222,7 @@ const HomePage: React.FC = () => {
       dataIndex: 'platform',
       key: 'platform',
       width: 140,
-      render: (val) => (PlatformConstants as any)[val] ?? `平台${val}`,
+      render: (_, record) => record.platform_name ?? record.platform,
     },
     {
       title: '总任务数',
@@ -241,12 +242,6 @@ const HomePage: React.FC = () => {
       key: 'totalPages',
       align: 'right',
     },
-    {
-      title: '爬取条数',
-      dataIndex: 'totalCount',
-      key: 'totalCount',
-      align: 'right',
-    },
     {
       title: '异常',
       dataIndex: 'exceptionTotal',
@@ -280,17 +275,16 @@ const HomePage: React.FC = () => {
         </Col>
         <Col xs={24} sm={12} md={6}>
           <div className={styles.summaryCard}>
-            <span className={styles.summaryTitle}>今日爬取条数</span>
-            <span className={styles.summaryValue}>{summary.totalCount}</span>
-            <span className={styles.summaryHint}>
-              爬取页数 {summary.totalPages}
-            </span>
+            <span className={styles.summaryTitle}>今日爬取页数</span>
+            <span className={styles.summaryValue}>{summary.totalPages}</span>
           </div>
         </Col>
         <Col xs={24} sm={12} md={6}>
           <div className={styles.summaryCard}>
             <span className={styles.summaryTitle}>今日活跃账号</span>
-            <span className={styles.summaryValue}>{summary.activeAccounts}</span>
+            <span className={styles.summaryValue}>
+              {summary.activeAccounts}
+            </span>
             <span className={styles.summaryHint}>
               回告次数 {summary.reportCount}
             </span>
@@ -316,7 +310,9 @@ const HomePage: React.FC = () => {
       </Row>
 
       <div className={styles.platformPanel}>
-        <div className={styles.panelTitle}>平台数据明细({date.format('YYYY-MM-DD')})</div>
+        <div className={styles.panelTitle}>
+          平台数据明细({date.format('YYYY-MM-DD')})
+        </div>
         <Spin spinning={loading}>
           {list.length ? (
             <Table<DashboardRow>
@@ -349,9 +345,7 @@ const HomePage: React.FC = () => {
         <Spin spinning={trendLoading}>
           {trendData.length ? (
             <Table
-              rowKey={(r: any) =>
-                `${r.statDate || ''}-${r.platform || ''}`
-              }
+              rowKey={(r: any) => `${r.statDate || ''}-${r.platform || ''}`}
               dataSource={trendData}
               columns={trendColumns}
               size="small"

+ 142 - 0
src/pages/PlatformAccount/index.tsx

@@ -0,0 +1,142 @@
+import ProTable from '@/components/ProTable';
+import { ConfigStatusConstants } from '@/constants/StatusConstants';
+import API from '@/services';
+import { guid } from '@/utils/utils';
+import type { ActionType, ProColumns } from '@ant-design/pro-table';
+import { message, Space, Typography } from 'antd';
+import React, { useEffect, useRef, useState } from 'react';
+
+/**
+ * 平台账号列表
+ * 后端接口(CollectPlatformAccountController):
+ * - GET  /collect_platform_account/index?platform=&account_username=&page=&limit=
+ * - POST /collect_platform_account/set_status    启用/禁用账号
+ *
+ * 注意:不提供新增/编辑/删除功能,账号数据由心跳上报自动维护
+ */
+const PlatformAccount: React.FC = () => {
+  const actionRef = useRef<ActionType>();
+  const proTableFormRef = useRef<any>();
+  const [platformOptions, setPlatformOptions] = useState<
+    { label: string; value: number }[]
+  >([]);
+
+  useEffect(() => {
+    API.CollectPlatform.selectOptions().then((res: any) => {
+      if (res?.code === 'success') {
+        setPlatformOptions(res.data || []);
+      }
+    });
+  }, []);
+
+  const columns: ProColumns[] = [
+    {
+      title: 'ID',
+      dataIndex: 'id',
+      key: 'id',
+      hideInSearch: true,
+      width: 80,
+    },
+    {
+      title: '平台',
+      dataIndex: 'platform',
+      key: 'platform',
+      valueType: 'select',
+      fieldProps: { options: platformOptions },
+      renderText: (_, record: any) => record?.platform_name ?? '-',
+    },
+    {
+      title: '账号名称',
+      dataIndex: 'account_username',
+      key: 'account_username',
+    },
+    {
+      title: '状态',
+      dataIndex: 'status',
+      key: 'status',
+      hideInSearch: true,
+      valueType: 'select',
+      valueEnum: ConfigStatusConstants,
+      width: 100,
+    },
+    {
+      title: '最后心跳时间',
+      dataIndex: 'last_heartbeat_time',
+      key: 'last_heartbeat_time',
+      hideInSearch: true,
+      valueType: 'dateTime',
+      renderText: (val) =>
+        typeof val === 'number' && val < 1e12 ? val * 1000 : val ?? '-',
+    },
+    {
+      title: '创建时间',
+      dataIndex: 'insert_time',
+      key: 'insert_time',
+      hideInSearch: true,
+      valueType: 'dateTime',
+      renderText: (val) =>
+        typeof val === 'number' && val < 1e12 ? val * 1000 : val,
+    },
+    {
+      title: '更新时间',
+      dataIndex: 'update_time',
+      key: 'update_time',
+      hideInSearch: true,
+      valueType: 'dateTime',
+      renderText: (val) =>
+        typeof val === 'number' && val < 1e12 ? val * 1000 : val,
+    },
+    {
+      title: '操作',
+      dataIndex: 'option',
+      key: 'option',
+      valueType: 'option',
+      fixed: 'right',
+      width: 100,
+      render: (text, record) => {
+        void text;
+        return (
+          <Space key={guid()}>
+            <Typography.Link
+              style={{ color: record.status === 0 ? 'red' : 'green' }}
+              onClick={async () => {
+                const response = await API.CollectPlatformAccount.setStatus({
+                  id: record.id,
+                  status: record.status === 0 ? 1 : 0,
+                });
+                if (response.code === 'success') {
+                  message.success('操作成功');
+                  actionRef.current?.reload();
+                  return;
+                }
+                throw new Error(response?.msg || '操作失败');
+              }}
+            >
+              {record.status === 0 ? '禁用' : '启用'}
+            </Typography.Link>
+          </Space>
+        );
+      },
+    },
+  ];
+
+  return (
+    <ProTable
+      columns={columns}
+      actionRef={actionRef}
+      formRef={proTableFormRef}
+      request={async (params) => {
+        const res = await API.CollectPlatformAccount.list(params);
+        return {
+          data: res.data?.data || [],
+          total: res.data?.total || 0,
+          success: true,
+        };
+      }}
+      editable={{ type: 'multiple' }}
+      scroll={{ x: '120%' }}
+    />
+  );
+};
+
+export default PlatformAccount;

+ 17 - 13
src/pages/PlatformConfig/index.tsx

@@ -2,14 +2,13 @@ import Modal from '@/components/Modal';
 import ModiyFormModal from '@/components/ModiyFormModal';
 import ProTable from '@/components/ProTable';
 import { ModalTitleMap } from '@/constants/BasicConstants';
-import { PlatformConstants } from '@/constants/PlatformConstants';
 import { ConfigStatusConstants } from '@/constants/StatusConstants';
 import API from '@/services';
 import { guid } from '@/utils/utils';
 import { PlusOutlined } from '@ant-design/icons';
 import type { ActionType, ProColumns } from '@ant-design/pro-table';
 import { Button, message, Space, Typography } from 'antd';
-import React, { useRef } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
 
 /**
  * 平台配置
@@ -27,6 +26,17 @@ const PlatformConfig: React.FC = () => {
   const proTableFormRef = useRef<any>();
   const downloadRef = useRef<any>({});
   const modiyFormModalRef = useRef<any>();
+  const [platformOptions, setPlatformOptions] = useState<
+    { label: string; value: number }[]
+  >([]);
+
+  useEffect(() => {
+    API.CollectPlatform.selectOptions().then((res: any) => {
+      if (res?.code === 'success') {
+        setPlatformOptions(res.data || []);
+      }
+    });
+  }, []);
 
   const flattenConfig = (record: any) => {
     // 将后端返回的 config Map 拍平到 rowData,方便表单回显
@@ -61,12 +71,7 @@ const PlatformConfig: React.FC = () => {
               isRequired: true,
               value: 'platform',
               type: 'select',
-              options: Object?.entries(PlatformConstants)
-                ?.filter(([key]) => Number(key) !== 0)
-                ?.map(([key, value]) => ({
-                  label: value as string,
-                  value: Number(key),
-                })),
+              options: platformOptions,
             },
             {
               label: '休息时长(分钟)',
@@ -128,8 +133,7 @@ const PlatformConfig: React.FC = () => {
       dataIndex: 'platform',
       key: 'platform',
       hideInSearch: true,
-      valueType: 'select',
-      valueEnum: PlatformConstants,
+      renderText: (_, record: any) => record?.platform_name ?? '-',
     },
     {
       title: '休息时长(分钟)',
@@ -185,11 +189,11 @@ const PlatformConfig: React.FC = () => {
         return (
           <Space key={guid()}>
             <Typography.Link
-              style={{ color: record.status == 0 ? 'red' : 'green' }}
+              style={{ color: record.status === 0 ? 'red' : 'green' }}
               onClick={async () => {
                 const response = await API.PlatformConfig.setStatus({
                   id: record.id,
-                  status: record.status == 0 ? 1 : 0,
+                  status: record.status === 0 ? 1 : 0,
                 });
                 if (response.code === 'success') {
                   message.success('操作成功');
@@ -199,7 +203,7 @@ const PlatformConfig: React.FC = () => {
                 throw new Error(response?.msg || '操作失败');
               }}
             >
-              {record.status == 0 ? '禁用' : '启用'}
+              {record.status === 0 ? '禁用' : '启用'}
             </Typography.Link>
             <Typography.Link onClick={() => modiyManage('update', record)}>
               编辑

+ 228 - 0
src/pages/PlatformManage/index.tsx

@@ -0,0 +1,228 @@
+import Modal from '@/components/Modal';
+import ModiyFormModal from '@/components/ModiyFormModal';
+import ProTable from '@/components/ProTable';
+import { ModalTitleMap } from '@/constants/BasicConstants';
+import { ConfigStatusConstants } from '@/constants/StatusConstants';
+import API from '@/services';
+import { guid } from '@/utils/utils';
+import { PlusOutlined } from '@ant-design/icons';
+import type { ActionType, ProColumns } from '@ant-design/pro-table';
+import { Button, message, Space, Typography } from 'antd';
+import React, { useRef } from 'react';
+
+/**
+ * 平台维护
+ * 后端接口(CollectPlatformController):
+ * - GET  /collect_platform/list          平台列表(可选 status 过滤)
+ * - POST /collect_platform/add           新增平台(code + name 必填)
+ * - POST /collect_platform/edit          编辑平台(id 必填)
+ * - POST /collect_platform/set_status    设置平台状态
+ *
+ * VO 字段:id, code, name, sort_order, status, insert_time, update_time
+ * DTO 字段:id, code, name, sortOrder, status
+ */
+const PlatformManage: React.FC = () => {
+  const actionRef = useRef<ActionType>();
+  const proTableFormRef = useRef<any>();
+  const downloadRef = useRef<any>({});
+  const modiyFormModalRef = useRef<any>();
+
+  const modiyManage = (type: 'create' | 'update', data: any = {}) => {
+    const { hide } = Modal.show({
+      title: `${ModalTitleMap[type]}平台`,
+      width: 560,
+      content: (
+        <ModiyFormModal
+          type={type}
+          formOptions={{ labelCol: 8, labelAlign: 'right' }}
+          formList={[
+            {
+              label: '平台编码',
+              isRequired: true,
+              value: 'code',
+              type: 'number',
+              help: '全局唯一编码,创建后不可修改',
+            },
+            {
+              label: '平台名称',
+              isRequired: true,
+              value: 'name',
+              type: 'input',
+            },
+            {
+              label: '排序',
+              isRequired: false,
+              value: 'sort_order',
+              type: 'number',
+              help: '值越小越靠前,默认为 0',
+            },
+          ]}
+          ref={modiyFormModalRef}
+          getDetail={() => ({
+            code: data?.code,
+            name: data?.name,
+            sort_order: data?.sort_order ?? 0,
+          })}
+        />
+      ),
+      onOk: async () => {
+        const formInstance = modiyFormModalRef.current;
+        if (!formInstance) {
+          throw new Error('表单未初始化');
+        }
+        const isFormValid = await formInstance.validateForm();
+        if (!isFormValid) {
+          throw new Error('表单校验未通过');
+        }
+        const values = formInstance.getData();
+        const payload = {
+          code: Number(values.code),
+          name: String(values.name).trim(),
+          sortOrder: Number(values.sort_order ?? 0),
+        };
+        const response =
+          type === 'create'
+            ? await API.CollectPlatform.add(payload)
+            : await API.CollectPlatform.edit({ id: data.id, ...payload });
+        if (response.code === 'success') {
+          message.success(type === 'create' ? '创建成功' : '更新成功');
+          actionRef.current?.reload();
+          return;
+        }
+        throw new Error(response?.msg || '操作失败');
+      },
+      onCancel: () => {
+        hide();
+      },
+    });
+  };
+
+  const columns: ProColumns[] = [
+    {
+      title: 'ID',
+      dataIndex: 'id',
+      key: 'id',
+      hideInSearch: true,
+      width: 80,
+    },
+    {
+      title: '平台编码',
+      dataIndex: 'code',
+      key: 'code',
+      hideInSearch: true,
+      width: 100,
+    },
+    {
+      title: '平台名称',
+      dataIndex: 'name',
+      key: 'name',
+      hideInSearch: true,
+    },
+    {
+      title: '排序',
+      dataIndex: 'sort_order',
+      key: 'sort_order',
+      hideInSearch: true,
+      width: 80,
+      renderText: (_, record: any) => record?.sort_order ?? '-',
+    },
+    {
+      title: '状态',
+      dataIndex: 'status',
+      key: 'status',
+      hideInSearch: true,
+      valueType: 'select',
+      valueEnum: ConfigStatusConstants,
+      width: 100,
+    },
+    {
+      title: '创建时间',
+      dataIndex: 'insert_time',
+      key: 'insert_time',
+      hideInSearch: true,
+      valueType: 'dateTime',
+      renderText: (val) =>
+        typeof val === 'number' && val < 1e12 ? val * 1000 : val,
+    },
+    {
+      title: '更新时间',
+      dataIndex: 'update_time',
+      key: 'update_time',
+      hideInSearch: true,
+      valueType: 'dateTime',
+      renderText: (val) =>
+        typeof val === 'number' && val < 1e12 ? val * 1000 : val,
+    },
+    {
+      title: '操作',
+      dataIndex: 'option',
+      key: 'option',
+      valueType: 'option',
+      fixed: 'right',
+      width: 140,
+      render: (text, record) => {
+        void text;
+        return (
+          <Space key={guid()}>
+            <Typography.Link
+              style={{ color: record.status === 0 ? 'red' : 'green' }}
+              onClick={async () => {
+                const response = await API.CollectPlatform.setStatus({
+                  id: record.id,
+                  status: record.status === 0 ? 1 : 0,
+                });
+                if (response.code === 'success') {
+                  message.success('操作成功');
+                  actionRef.current?.reload();
+                  return;
+                }
+                throw new Error(response?.msg || '操作失败');
+              }}
+            >
+              {record.status === 0 ? '禁用' : '启用'}
+            </Typography.Link>
+            <Typography.Link onClick={() => modiyManage('update', record)}>
+              编辑
+            </Typography.Link>
+          </Space>
+        );
+      },
+    },
+  ];
+
+  return (
+    <ProTable
+      columns={columns}
+      actionRef={actionRef}
+      formRef={proTableFormRef}
+      request={async (params) => {
+        downloadRef.current = params;
+        const res = await API.CollectPlatform.list(params);
+        return {
+          data: res.data || [],
+          total: res.data?.length || 0,
+          success: true,
+        };
+      }}
+      editable={{ type: 'multiple' }}
+      scroll={{ x: '120%' }}
+      noSearch
+      toolbar={{
+        actions: [
+          <Button
+            key="add"
+            type="primary"
+            icon={<PlusOutlined />}
+            onClick={() => {
+              modiyManage('create');
+            }}
+          >
+            新增平台
+          </Button>,
+        ],
+      }}
+    />
+  );
+};
+
+export default PlatformManage;

+ 64 - 0
src/services/collect_platform.ts

@@ -0,0 +1,64 @@
+import BaseAPI from './BaseAPI';
+
+/**
+ * 平台注册表 Service
+ * 后端接口(CollectPlatformController):
+ * - GET  /platform/select_options     平台下拉选项(仅启用状态)
+ * - GET  /platform/list               平台列表(可选 status 过滤)
+ * - POST /platform/add                新增平台
+ * - POST /platform/edit               编辑平台
+ * - POST /platform/set_status         设置平台状态
+ */
+class CollectPlatformAPI extends BaseAPI {
+  constructor() {
+    super(``);
+  }
+
+  /** 平台下拉选项(仅启用平台,返回 [{value, label}]) */
+  selectOptions() {
+    return this._get({ path: `/platform/select_options` }).then((data) => {
+      return data;
+    });
+  }
+
+  /** 查询平台列表(status 可选:0=启用,1=禁用,不传=全部) */
+  list(data?: any) {
+    return this._get({ path: `/platform/list`, data }).then((data) => {
+      return data;
+    });
+  }
+
+  /** 新增平台(code + name 必填) */
+  add(data: {
+    code: number;
+    name: string;
+    sortOrder?: number;
+    status?: number;
+  }) {
+    return this._post({ path: `/platform/add`, data }).then((data) => {
+      return data;
+    });
+  }
+
+  /** 编辑平台(id 必填) */
+  edit(data: {
+    id: number;
+    code?: number;
+    name?: string;
+    sortOrder?: number;
+    status?: number;
+  }) {
+    return this._post({ path: `/platform/edit`, data }).then((data) => {
+      return data;
+    });
+  }
+
+  /** 设置平台状态(0=启用,1=禁用) */
+  setStatus(data: { id: number; status: number }) {
+    return this._post({ path: `/platform/set_status`, data }).then((data) => {
+      return data;
+    });
+  }
+}
+
+export default new CollectPlatformAPI();

+ 33 - 0
src/services/collect_platform_account.ts

@@ -0,0 +1,33 @@
+import BaseAPI from './BaseAPI';
+
+/**
+ * 平台账号 Service
+ * 后端接口(CollectPlatformAccountController):
+ * - GET  /collect_platform_account/index        账号分页列表(支持 platform、account_username 筛选)
+ * - POST /collect_platform_account/set_status   启用/禁用账号
+ *
+ * 注意:不提供新增/编辑/删除接口,账号数据由心跳上报自动维护
+ */
+class CollectPlatformAccountAPI extends BaseAPI {
+  constructor() {
+    super(``);
+  }
+
+  /** 账号分页列表 */
+  list(data?: any) {
+    return this._get({
+      path: `/collect_platform_account/index`,
+      data,
+    }).then((data) => data);
+  }
+
+  /** 启用/禁用账号(0=正常,1=禁用) */
+  setStatus(data: { id: number; status: number }) {
+    return this._post({
+      path: `/collect_platform_account/set_status`,
+      data,
+    }).then((data) => data);
+  }
+}
+
+export default new CollectPlatformAccountAPI();

+ 5 - 1
src/services/index.ts

@@ -1,11 +1,15 @@
-import Login from './login';
+import CollectPlatform from './collect_platform';
+import CollectPlatformAccount from './collect_platform_account';
 import CollectTask from './collect_task';
 import Dashboard from './dashboard';
+import Login from './login';
 import PlatformConfig from './platform_config';
 
 export default {
   Login,
   CollectTask,
+  CollectPlatform,
+  CollectPlatformAccount,
   Dashboard,
   PlatformConfig,
 };