فهرست منبع

增强问答列表组件,添加项目级应用的选择逻辑,优化数据加载和状态管理,同时更新样式以改善用户体验。

刘博博 1 ماه پیش
والد
کامیت
61916485b5
3فایلهای تغییر یافته به همراه188 افزوده شده و 10 حذف شده
  1. 101 9
      src/pages/deepseek/questionAnswer/list/index.tsx
  2. 38 1
      src/pages/layout/components/Header.tsx
  3. 49 0
      src/pages/layout/style.less

+ 101 - 9
src/pages/deepseek/questionAnswer/list/index.tsx

@@ -17,7 +17,7 @@ import {
   Space,
   Row,
   Col,
-  Input, Cascader, Card
+  Input, Cascader, Card, Spin
 } from 'antd';
 import {
   PlusOutlined,
@@ -44,6 +44,7 @@ import IconSvg from "@/assets/public/icon.svg";
 import dayjs from 'dayjs';
 import UpdateNotification from '@/help/components/UpdateNotification';
 import { CURRENT_VERSION } from '@/help/components/UpdateNotification/version';
+import { useLocation } from 'react-router-dom';
 
 const { Header, Footer, Sider, Content } = Layout;
 const { Option } = Select;
@@ -85,6 +86,7 @@ const layoutStyle = {
 };
 const QuestionAnswerList: React.FC = () => {
   const [form] = Form.useForm();
+  const location = useLocation();
 
   interface Item {
     name: string,
@@ -282,14 +284,44 @@ const QuestionAnswerList: React.FC = () => {
   const appTypeApi = {
     fetchAppType: async () => {
       try {
+        // 1. 先请求应用列表,获取项目名称数据
+        const userInfo = LocalStorage.getUserInfo();
+        const userId = (userInfo?.id ?? '1').toString();
+        
+        const appListRes = await apis.fetchTakaiAppList({
+          keyword: '',
+          name: '',
+          pageNumber: 1,
+          pageSize: 1000,
+          typeId: '41',
+          userId: userId,
+          projectId: null
+        });
+        
+        // 提取所有的 projectName 并去重
+        const projectNames = appListRes.rows.map((item: any) => item.projectName).filter(Boolean);
+        const uniqueProjectNames = new Set(projectNames);
+        
+        // 2. 请求应用类型列表
         const res = await apis.fetchTakaiAppTypeList('app_type');
+        
+        // 3. 对比数据,保留所有类型,但标记是否有对应的项目数据
         const list = res.data.map((item: any) => {
           return {
             label: item.dictLabel,
             value: item.dictCode,
           }
         });
-        setAppTypeList(list);
+        
+        // 如果没有项目级应用的数据,过滤掉"项目级应用"类型
+        const filteredList = list.filter((item: any) => {
+          if (item.label === '项目级应用') {
+            return uniqueProjectNames.size > 0;
+          }
+          return true;
+        });
+        
+        setAppTypeList(filteredList);
       } catch (error: any) {
         console.error(error);
       }
@@ -364,15 +396,22 @@ const QuestionAnswerList: React.FC = () => {
   };
 
   const init = async () => {
-    await appApi.fetchList(null, null, true); // 强制刷新
-    await indexApi.fetchIndex(null, null);
     await appTypeApi.fetchAppType();
     await projectApi.fetchProject();
     await appProTypeApi.fetchAppProType();
     await levelTypeApi.fetchLevelAppType();
 
-    // 设置默认选择"全部"
-    form.setFieldsValue({ typeId: '全部' });
+    // 检查是否从导航跳转过来,需要选中"项目级应用"
+    const shouldSelectProjectApp = location.state?.selectProjectApp;
+    
+    if (!shouldSelectProjectApp) {
+      // 默认加载全部数据
+      await appApi.fetchList(null, null, true); // 强制刷新
+      await indexApi.fetchIndex(null, null);
+      // 设置默认选择"全部"
+      form.setFieldsValue({ typeId: '全部' });
+    }
+    // 如果需要选中项目级应用,会在 useEffect 中处理
   }
 
   React.useEffect(() => {
@@ -388,6 +427,48 @@ const QuestionAnswerList: React.FC = () => {
     init();
   }, [page.pageSize, page.pageNumber])
 
+  // 监听 appTypeList 变化,处理从导航跳转过来选中"项目级应用"的逻辑
+  React.useEffect(() => {
+    const shouldSelectProjectApp = location.state?.selectProjectApp;
+    
+    if (shouldSelectProjectApp && appTypeList.length > 0) {
+      // 找到"项目级应用"的配置
+      const projectAppType = appTypeList.find(item => item.label === '项目级应用');
+      
+      if (projectAppType) {
+        const projectAppValue = projectAppType.value;
+        setSelectedType(projectAppValue);
+        form.setFieldsValue({ typeId: projectAppValue });
+        
+        // 如果是项目级应用(value为'41'),显示子面板
+        if (projectAppValue === '41') {
+          setShowSubPanel(true);
+        }
+        
+        // 加载对应的数据
+        appApi.fetchList(projectAppValue, null, true);
+        indexApi.fetchIndex(projectAppValue, null);
+        
+        // 清除 location.state,避免重复触发
+        window.history.replaceState({}, document.title);
+      }
+    }
+  }, [appTypeList, location.state])
+
+  // 监听 selectedType 变化,通知 Header 组件更新选中状态
+  React.useEffect(() => {
+    if (appTypeList.length > 0) {
+      const projectAppType = appTypeList.find(item => item.label === '项目级应用');
+      const isProjectApp = projectAppType && selectedType === projectAppType.value;
+      
+      // 触发自定义事件通知 Header 组件
+      const event = new CustomEvent('projectAppActiveChange', {
+        detail: { isActive: isProjectApp }
+      });
+      window.dispatchEvent(event);
+    }
+  }, [selectedType, appTypeList])
+
   const paginationConfig: PaginationConfig = {
     // 显示数据总量
     showTotal: (total: number) => {
@@ -870,8 +951,17 @@ const QuestionAnswerList: React.FC = () => {
         </div>
       )}
       {
-        list.length
-          ?
+        listLoading ? (
+          <div style={{ 
+            display: 'flex', 
+            justifyContent: 'center', 
+            alignItems: 'center', 
+            minHeight: '400px',
+            padding: '50px 0'
+          }}>
+            <Spin size="large" tip="加载中..." />
+          </div>
+        ) : list.length ? (
           <div className='questionAnswerList'>
             {/*<div style={ { overflow: 'auto' } }>*/}
             {/*  <Flex gap="middle" wrap>*/}
@@ -1138,7 +1228,7 @@ const QuestionAnswerList: React.FC = () => {
               />
             </div>
           </div>
-          :
+        ) : (
           <div>
             {/* {
                     createFlag &&
@@ -1150,9 +1240,11 @@ const QuestionAnswerList: React.FC = () => {
                 } */}
             <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
           </div>
+        )
       }
     </div>
   )
 };
 
 export default observer(QuestionAnswerList);
+

+ 38 - 1
src/pages/layout/components/Header.tsx

@@ -1,5 +1,5 @@
 import * as React from 'react';
-import { Layout, MenuProps, Modal, Dropdown, Select, Button, Tooltip } from 'antd';
+import { Layout, MenuProps, Modal, Dropdown, Select, Button, Tooltip, Menu } from 'antd';
 import { CaretDownOutlined, LogoutOutlined } from '@ant-design/icons';
 import { useNavigate, useLocation } from 'react-router-dom';
 import logoSrc from '@/assets/public/logo.png';
@@ -26,6 +26,22 @@ const Header: React.FC<Props> = (props: Props) => {
     const navigate = useNavigate();
     const location = useLocation();
     const isHelp = location.pathname.startsWith('/help');
+    
+    // 监听是否选中项目级应用
+    const [isProjectAppActive, setIsProjectAppActive] = React.useState(false);
+    
+    React.useEffect(() => {
+        // 监听自定义事件来更新选中状态
+        const handleProjectAppChange = (event: CustomEvent) => {
+            setIsProjectAppActive(event.detail.isActive);
+        };
+        
+        window.addEventListener('projectAppActiveChange' as any, handleProjectAppChange);
+        
+        return () => {
+            window.removeEventListener('projectAppActiveChange' as any, handleProjectAppChange);
+        };
+    }, []);
 
     // const items: MenuProps['items'] = [
     //     // 移除退出登录选项,现在使用独立的登出按钮
@@ -47,6 +63,13 @@ const Header: React.FC<Props> = (props: Props) => {
         }
     };
 
+    const handleProjectAppClick = () => {
+        navigate('/deepseek/questionAnswer', { 
+            state: { selectProjectApp: true },
+            replace: false 
+        });
+    };
+
     return (
         <AntdHeader className='header'>
             <div className='header-logo'>
@@ -58,6 +81,20 @@ const Header: React.FC<Props> = (props: Props) => {
                 >
                     建科•小智应用广场
                 </div>
+                <Button 
+                    type="text" 
+                    onClick={handleProjectAppClick}
+                    style={{ 
+                        marginLeft: '24px',
+                        color: '#1890ff',
+                        fontSize: '14px',
+                        height: '32px',
+                        fontWeight: 500
+                    }}
+                    className={`header-nav-button ${isProjectAppActive ? 'active' : ''}`}
+                >
+                    项目级应用
+                </Button>
                 {/* <Select 
                     className='header-platform-selector'
                     open={open}

+ 49 - 0
src/pages/layout/style.less

@@ -121,6 +121,55 @@
         }
     }
 
+    // 导航按钮样式
+    &-nav-button {
+        color: #000000 !important;
+        transition: all 0.3s ease;
+        position: relative;
+        border-radius: 0 !important;
+        padding-bottom: 2px !important;
+        
+        // 底部下划线(默认隐藏)
+        &::after {
+            content: '';
+            position: absolute;
+            bottom: -20px;
+            left: 50%;
+            transform: translateX(-50%);
+            width: 0;
+            height: 3px;
+            background-color: #1890ff;
+            transition: width 0.3s ease;
+            border-radius: 1.5px;
+        }
+        
+        // 选中状态
+        &.active {
+            color: #000000 !important;
+            font-weight: 600;
+            
+            &::after {
+                width: 100%;
+            }
+        }
+        
+        // 未选中状态的 hover
+        &:not(.active):hover {
+            color: #000000 !important;
+            background: transparent !important;
+            
+            &::after {
+                width: 100%;
+                background-color: rgba(24, 144, 255, 0.5);
+            }
+        }
+        
+        &:not(.active):active {
+            color: #000000 !important;
+            background: transparent !important;
+        }
+    }
+
     &-platform-selector {
         width: 200px;
         margin-left: 20px;