Jelajahi Sumber

refactor(表格组件): 用Tooltip替换Popover实现文本溢出提示

简化表格列渲染逻辑,使用antd的Tooltip组件替代复杂的Popover实现,提高代码可维护性
统一处理文本溢出时的提示效果,删除冗余的截断函数
max_liu 2 minggu lalu
induk
melakukan
fb93058379
2 mengubah file dengan 104 tambahan dan 168 penghapusan
  1. 14 90
      src/pages/PendingToolsList.js
  2. 90 78
      src/pages/ToolsLibraryList.js

+ 14 - 90
src/pages/PendingToolsList.js

@@ -1,9 +1,10 @@
 import React, { useState, useEffect } from "react";
-import { Table, Button, Input, Space, Tag, message, Modal, Popover } from "antd";
+import { Table, Button, Input, Space, Tag, message, Modal, Tooltip } from "antd";
 import { SearchOutlined, EditOutlined, DeleteOutlined, EyeOutlined } from "@ant-design/icons";
 import { useNavigate } from "react-router-dom";
 import { pendingToolsApi } from "../services/api";
 import moment from "moment";
+import { render } from "@testing-library/react";
 
 const { Search } = Input;
 const { confirm } = Modal;
@@ -39,45 +40,18 @@ const PendingToolsList = () => {
     return statusMap[status] || "未知";
   };
 
-  // 文本截断函数
-  const truncateText = (text, maxLength = 150) => {
-    if (!text) return "";
-    return text.length > maxLength ? text.substring(0, maxLength) + "..." : text;
-  };
-
   const columns = [
     {
       title: "工具ID",
       dataIndex: "search_task_id",
       key: "search_task_id",
       width: 150,
-      render: (text) => {
-        const displayText = truncateText(text, 150);
-        const needsTruncation = text && text.length > 150;
-
-        return needsTruncation ? (
-          <Popover
-            content={
-              <div
-                style={{
-                  maxHeight: "calc(100vh - 35px)",
-                  overflowY: "auto",
-                  wordBreak: "break-word",
-                  whiteSpace: "pre-wrap",
-                  maxWidth: 300,
-                }}
-              >
-                {text}
-              </div>
-            }
-            title="完整内容"
-          >
-            <span style={{ cursor: "pointer" }}>{displayText}</span>
-          </Popover>
-        ) : (
-          <span>{displayText}</span>
-        );
-      },
+      ellipsis: true,
+      render: (text) => (
+        <Tooltip title={text}>
+          <span className="cursor-pointer">{text}</span>
+        </Tooltip>
+      ),
     },
     {
       title: "工具名称",
@@ -96,33 +70,12 @@ const PendingToolsList = () => {
       dataIndex: "tools_function_desc",
       key: "tools_function_desc",
       width: 300,
-      render: (text) => {
-        const displayText = truncateText(text, 150);
-        const needsTruncation = text && text.length > 150;
-
-        return needsTruncation ? (
-          <Popover
-            content={
-              <div
-                style={{
-                  maxHeight: "calc(100vh - 35px)",
-                  overflowY: "auto",
-                  wordBreak: "break-word",
-                  whiteSpace: "pre-wrap",
-                  maxWidth: 400,
-                }}
-              >
-                {text}
-              </div>
-            }
-            title="完整描述"
-          >
-            <span style={{ cursor: "pointer" }}>{displayText}</span>
-          </Popover>
-        ) : (
-          <span>{displayText}</span>
-        );
-      },
+      ellipsis: true,
+      render: (text) => (
+        <Tooltip title={text}>
+          <span className="cursor-pointer">{text}</span>
+        </Tooltip>
+      ),
     },
     {
       title: "状态",
@@ -136,35 +89,6 @@ const PendingToolsList = () => {
       dataIndex: "fail_reason",
       key: "fail_reason",
       width: 200,
-      render: (text) => {
-        if (!text) return "-";
-
-        const displayText = truncateText(text, 150);
-        const needsTruncation = text && text.length > 150;
-
-        return needsTruncation ? (
-          <Popover
-            content={
-              <div
-                style={{
-                  maxHeight: "calc(100vh - 35px)",
-                  overflowY: "auto",
-                  wordBreak: "break-word",
-                  whiteSpace: "pre-wrap",
-                  maxWidth: 400,
-                }}
-              >
-                {text}
-              </div>
-            }
-            title="完整失败原因"
-          >
-            <span style={{ cursor: "pointer", color: "#ff4d4f" }}>{displayText}</span>
-          </Popover>
-        ) : (
-          <span style={{ color: text ? "#ff4d4f" : "inherit" }}>{displayText}</span>
-        );
-      },
     },
     {
       title: "创建时间",

+ 90 - 78
src/pages/ToolsLibraryList.js

@@ -1,9 +1,9 @@
-import React, { useState, useEffect } from 'react';
-import { Table, Button, Space, Tag, message, Modal } from 'antd';
-import { EditOutlined, EyeOutlined, SendOutlined } from '@ant-design/icons';
-import { useNavigate } from 'react-router-dom';
-import { toolsLibraryApi } from '../services/api';
-import moment from 'moment';
+import React, { useState, useEffect } from "react";
+import { Table, Button, Space, Tag, message, Modal, Tooltip } from "antd";
+import { EditOutlined, EyeOutlined, SendOutlined } from "@ant-design/icons";
+import { useNavigate } from "react-router-dom";
+import { toolsLibraryApi } from "../services/api";
+import moment from "moment";
 
 const { confirm } = Modal;
 
@@ -19,133 +19,145 @@ const ToolsLibraryList = () => {
 
   const getStatusColor = (status) => {
     const statusMap = {
-      'normal': 'success',
-      'offline': 'default',
+      normal: "success",
+      offline: "default",
     };
-    return statusMap[status] || 'warning';
+    return statusMap[status] || "warning";
   };
 
   const getStatusText = (status) => {
     const statusMap = {
-      'normal': '正常',
-      'offline': '已下线',
+      normal: "正常",
+      offline: "已下线",
     };
     return statusMap[status] || status;
   };
 
   const getCallTypeText = (type) => {
     const typeMap = {
-      'api': 'API调用',
-      'browser_auto_operate': '浏览器自动操作',
+      api: "API调用",
+      browser_auto_operate: "浏览器自动操作",
     };
     return typeMap[type] || type;
   };
 
   const getApiProviderText = (provider) => {
     const providerMap = {
-      'official': '官方',
-      '302ai': '302AI',
-      'official_api': '官方API',
+      official: "官方",
+      "302ai": "302AI",
+      official_api: "官方API",
     };
     return providerMap[provider] || provider;
   };
 
   const columns = [
     {
-      title: '工具ID',
-      dataIndex: 'tools_id',
-      key: 'tools_id',
+      title: "工具ID",
+      dataIndex: "tools_id",
+      key: "tools_id",
       width: 200,
       ellipsis: true,
+      render: (text) => (
+        <Tooltip title={text}>
+          <span className="cursor-pointer">{text}</span>
+        </Tooltip>
+      ),
     },
     {
-      title: '工具名称',
-      dataIndex: 'tools_name',
-      key: 'tools_name',
+      title: "工具名称",
+      dataIndex: "tools_name",
+      key: "tools_name",
       width: 150,
     },
     {
-      title: '工具功能名称',
-      dataIndex: 'tools_function_name',
-      key: 'tools_function_name',
+      title: "工具功能名称",
+      dataIndex: "tools_function_name",
+      key: "tools_function_name",
       width: 200,
     },
     {
-      title: '工具全称',
-      dataIndex: 'tools_full_name',
-      key: 'tools_full_name',
+      title: "工具全称",
+      dataIndex: "tools_full_name",
+      key: "tools_full_name",
       width: 250,
       ellipsis: true,
+      render: (text) => (
+        <Tooltip title={text}>
+          <span className="cursor-pointer">{text}</span>
+        </Tooltip>
+      ),
     },
     {
-      title: '工具描述',
-      dataIndex: 'tools_desc',
-      key: 'tools_desc',
+      title: "工具描述",
+      dataIndex: "tools_desc",
+      key: "tools_desc",
       width: 300,
       ellipsis: true,
+      render: (text) => (
+        <Tooltip title={text}>
+          <span className="cursor-pointer">{text}</span>
+        </Tooltip>
+      ),
     },
     {
-      title: '版本',
-      dataIndex: 'tools_version',
-      key: 'tools_version',
+      title: "版本",
+      dataIndex: "tools_version",
+      key: "tools_version",
       width: 80,
-      render: (version) => (
-        <Tag color="geekblue">{version}</Tag>
-      ),
+      render: (version) => <Tag color="geekblue">{version}</Tag>,
     },
     {
-      title: '状态',
-      dataIndex: 'status',
-      key: 'status',
+      title: "状态",
+      dataIndex: "status",
+      key: "status",
       width: 100,
-      render: (status) => (
-        <Tag color={getStatusColor(status)}>{getStatusText(status)}</Tag>
-      ),
+      render: (status) => <Tag color={getStatusColor(status)}>{getStatusText(status)}</Tag>,
     },
     {
-      title: '调用方式',
-      dataIndex: 'call_type',
-      key: 'call_type',
+      title: "调用方式",
+      dataIndex: "call_type",
+      key: "call_type",
       width: 120,
-      render: (type) => (
-        <Tag color="blue">{getCallTypeText(type)}</Tag>
-      ),
+      render: (type) => <Tag color="blue">{getCallTypeText(type)}</Tag>,
     },
     {
-      title: 'API提供方',
-      dataIndex: 'api_provider',
-      key: 'api_provider',
+      title: "API提供方",
+      dataIndex: "api_provider",
+      key: "api_provider",
       width: 120,
-      render: (provider) => (
-        <Tag color="purple">{getApiProviderText(provider)}</Tag>
-      ),
+      render: (provider) => <Tag color="purple">{getApiProviderText(provider)}</Tag>,
     },
     {
-      title: 'API路径',
-      dataIndex: 'api_url_path',
-      key: 'api_url_path',
+      title: "API路径",
+      dataIndex: "api_url_path",
+      key: "api_url_path",
       width: 200,
       ellipsis: true,
+      render: (text) => (
+        <Tooltip title={text}>
+          <span className="cursor-pointer">{text}</span>
+        </Tooltip>
+      ),
     },
     {
-      title: '创建时间',
-      dataIndex: 'create_time',
-      key: 'create_time',
+      title: "创建时间",
+      dataIndex: "create_time",
+      key: "create_time",
       width: 180,
-      render: (time) => moment(time).format('YYYY-MM-DD HH:mm:ss'),
+      render: (time) => moment(time).format("YYYY-MM-DD HH:mm:ss"),
     },
     {
-      title: '更新时间',
-      dataIndex: 'update_time',
-      key: 'update_time',
+      title: "更新时间",
+      dataIndex: "update_time",
+      key: "update_time",
       width: 180,
-      render: (time) => moment(time).format('YYYY-MM-DD HH:mm:ss'),
+      render: (time) => moment(time).format("YYYY-MM-DD HH:mm:ss"),
     },
     {
-      title: '操作',
-      key: 'action',
+      title: "操作",
+      key: "action",
       width: 200,
-      fixed: 'right',
+      fixed: "right",
       render: (_, record) => (
         <Space size="small">
           <Button
@@ -163,7 +175,7 @@ const ToolsLibraryList = () => {
           >
             编辑
           </Button>
-          {record.status !== 'normal' && (
+          {record.status !== "normal" && (
             <Button
               type="primary"
               size="small"
@@ -192,7 +204,7 @@ const ToolsLibraryList = () => {
         total: response.data.total,
       });
     } catch (error) {
-      message.error('获取数据失败');
+      message.error("获取数据失败");
     } finally {
       setLoading(false);
     }
@@ -204,17 +216,17 @@ const ToolsLibraryList = () => {
 
   const handlePublish = (id) => {
     confirm({
-      title: '确认发布',
-      content: '确定要发布这个工具吗?',
-      okText: '确认',
-      cancelText: '取消',
+      title: "确认发布",
+      content: "确定要发布这个工具吗?",
+      okText: "确认",
+      cancelText: "取消",
       onOk: async () => {
         try {
           await toolsLibraryApi.publish(id);
-          message.success('发布成功');
+          message.success("发布成功");
           fetchData(pagination.current, pagination.pageSize);
         } catch (error) {
-          message.error('发布失败');
+          message.error("发布失败");
         }
       },
     });
@@ -240,4 +252,4 @@ const ToolsLibraryList = () => {
   );
 };
 
-export default ToolsLibraryList;
+export default ToolsLibraryList;