Browse Source

Merge remote-tracking branch 'origin/dev/permission' into dev/permission

huiqi 3 months ago
parent
commit
636a0ddb58

+ 140 - 0
src/pages/deepseek/questionAnswer/info/README.md

@@ -0,0 +1,140 @@
+# 提示词模板配置系统
+
+## 概述
+
+这个配置系统用于管理问答应用中的提示词模板,避免在代码中硬编码长文本,提高代码的可维护性和可扩展性。
+
+## 文件结构
+
+```
+src/pages/deepseek/questionAnswer/info/
+├── promptTemplates.ts    # 提示词模板配置文件
+├── index.tsx            # 主组件文件
+└── README.md           # 说明文档
+```
+
+## 使用方法
+
+### 1. 基本使用
+
+```typescript
+import { DEFAULT_PROMPT_TEMPLATE, getPromptTemplate } from './promptTemplates';
+
+// 使用默认模板
+const defaultPrompt = DEFAULT_PROMPT_TEMPLATE;
+
+// 使用特定模板
+const chatPrompt = getPromptTemplate('CHAT_ASSISTANT');
+```
+
+### 2. 在组件中使用
+
+```typescript
+import { DEFAULT_PROMPT_TEMPLATE } from './promptTemplates';
+
+// 在FormItem中使用
+<FormItem 
+  name='prompt'
+  initialValue={DEFAULT_PROMPT_TEMPLATE}
+  rules={[{ required: true, message: '提示词不能为空' }]}
+>
+  <TextArea placeholder="提示词" rows={50} />
+</FormItem>
+```
+
+### 3. 添加新的提示词模板
+
+在 `promptTemplates.ts` 中添加新的模板:
+
+```typescript
+export const PROMPT_TEMPLATES = {
+  // 现有模板...
+  
+  // 新增模板
+  CUSTOM_ASSISTANT: `你是一个自定义助手,请根据以下要求提供服务:
+
+用户需求: {{用户}}
+参考文档: {{知识}}
+
+请按照要求完成任务。`
+};
+```
+
+### 4. 验证和格式化
+
+```typescript
+import { 
+  validatePromptTemplate, 
+  formatPromptTemplate 
+} from './promptTemplates';
+
+// 验证模板是否包含必要占位符
+const isValid = validatePromptTemplate(template);
+
+// 格式化模板(替换占位符)
+const formattedPrompt = formatPromptTemplate(
+  template, 
+  '知识库内容', 
+  '用户输入'
+);
+```
+
+## 模板类型
+
+| 类型 | 描述 | 用途 |
+|------|------|------|
+| `KNOWLEDGE_RETRIEVAL_ASSISTANT` | 知识检索助手 | 基于知识库内容回答问题 |
+| `CHAT_ASSISTANT` | 聊天助手 | 提供友好的对话服务 |
+| `DOCUMENT_SUMMARY` | 文档总结 | 提取文档关键信息 |
+| `CODE_ASSISTANT` | 代码助手 | 提供代码解决方案 |
+| `TRANSLATION_ASSISTANT` | 翻译助手 | 多语言翻译服务 |
+
+## 占位符说明
+
+- `{{知识}}`: 知识库内容占位符
+- `{{用户}}`: 用户输入占位符
+
+## 最佳实践
+
+1. **保持模板简洁**: 避免在模板中包含过多的逻辑判断
+2. **使用占位符**: 统一使用 `{{知识}}` 和 `{{用户}}` 占位符
+3. **添加描述**: 为每个模板添加清晰的描述
+4. **验证模板**: 使用 `validatePromptTemplate` 验证模板格式
+5. **版本控制**: 对模板的修改进行版本控制
+
+## 扩展功能
+
+### 动态模板选择
+
+可以添加一个下拉选择器让用户选择不同的提示词模板:
+
+```typescript
+import { 
+  getAvailableTemplateTypes, 
+  PROMPT_TEMPLATE_DESCRIPTIONS 
+} from './promptTemplates';
+
+const templateTypes = getAvailableTemplateTypes();
+
+<Select 
+  placeholder="选择提示词模板"
+  onChange={(value) => setSelectedTemplate(value)}
+>
+  {templateTypes.map(type => (
+    <Option key={type} value={type}>
+      {PROMPT_TEMPLATE_DESCRIPTIONS[type]}
+    </Option>
+  ))}
+</Select>
+```
+
+### 模板预览
+
+可以添加模板预览功能,让用户在应用前查看模板内容。
+
+## 注意事项
+
+1. 修改模板后需要重新测试应用功能
+2. 确保所有模板都包含必要的占位符
+3. 保持模板的向后兼容性
+4. 定期审查和更新模板内容

+ 124 - 103
src/pages/deepseek/questionAnswer/info/index.tsx

@@ -5,9 +5,9 @@ import './style.less';
 import {
     Button, Input, Form, Divider, Splitter, Select, InputNumber, InputNumberProps,
     Radio, Switch, Row, Col, Slider, Space, RadioChangeEvent,
-    Spin, message
+    Spin, message, Typography, Tooltip
 } from 'antd';
-import { PlusCircleOutlined, MinusCircleOutlined } from '@ant-design/icons';
+import { PlusCircleOutlined, MinusCircleOutlined, ArrowLeftOutlined, InfoCircleOutlined } from '@ant-design/icons';
 import { apis } from '@/apis';
 import router from '@/router';
 import LocalStorage from '@/LocalStorage';
@@ -50,7 +50,7 @@ const QuestionAnswerInfo: React.FC = () => {
                     <InputNumber
                         min={0}
                         max={1}
-                        style={{ margin: '0 16px', width: '100px' }}
+                        className='form-input-number-small'
                         step={0.01}
                         value={topPValue}
                         onChange={onChange}
@@ -85,7 +85,7 @@ const QuestionAnswerInfo: React.FC = () => {
                     <InputNumber
                         min={0}
                         max={1}
-                        style={{ margin: '0 16px', width: '100px' }}
+                        className='form-input-number-small'
                         step={0.01}
                         value={tempValue}
                         onChange={onChange}
@@ -422,7 +422,7 @@ const QuestionAnswerInfo: React.FC = () => {
                             name='name'
                             rules={[{ required: true, message: '问答应用名称不能为空' }]}
                         >
-                            <Input placeholder="应用名称" style={{ width: 646, padding: 8 }} />
+                            <Input placeholder="请输入问答应用名称" className='form-input-large' />
                         </FormItem>
 
                         <FormItem
@@ -430,8 +430,8 @@ const QuestionAnswerInfo: React.FC = () => {
                             name='typeId'
                         >
                             <Select
-                                style={{ width: '300px', height: '48px' }}
-                                placeholder='请选应用类型'
+                                className='questionAnswerInfo-content-title'
+                                placeholder='请选择问答应用类型'
                                 onChange={handleAppChange}
                                 allowClear={true}
                             >
@@ -453,7 +453,7 @@ const QuestionAnswerInfo: React.FC = () => {
                                 rules={[{ required: true, message: '项目类型不能为空' }]}
                             >
                                 <Select
-                                    style={{ width: '300px', height: '48px' }}
+                                    className='questionAnswerInfo-content-title'
                                     placeholder='请选择项目类型'
                                     value={selectedAppProId}
                                     onChange={(value) => setSelectedAppProId(value)}
@@ -475,56 +475,81 @@ const QuestionAnswerInfo: React.FC = () => {
                             <TextArea
                                 showCount
                                 maxLength={500}
-                                placeholder="请输入描述"
-                                style={{ height: 120, resize: 'none', width: 646 }}
+                                placeholder="请输入当前应用的描述"
+                                className='form-textarea-large'
                             />
                         </FormItem>
 
-                        <div>
+                        <div className='preset-questions'>
                             <h4>添加预设问题</h4>
                             <div>
                                 {
                                     inputs.map(input => (
-                                        <div key={input.id} style={{ paddingTop: '10px' }}>
+                                        <div key={input.id} className='question-item'>
                                             <label>问题 {input.id}</label>
                                             <Input
-                                                style={{ width: 300, paddingTop: 8, marginLeft: 20 }}
+                                                className='question-input'
                                                 type="text"
                                                 value={input.value}
                                                 onChange={e => handleChange(input.id, e.target.value)}
                                             />
-                                            <PlusCircleOutlined style={{ marginLeft: 20 }} onClick={addInput} />
-                                            <MinusCircleOutlined style={{ marginLeft: 20 }} onClick={delInput} />
+                                            <div className='question-actions'>
+                                                <PlusCircleOutlined className='question-icon' onClick={addInput} />
+                                                <MinusCircleOutlined className='question-icon' onClick={delInput} />
+                                            </div>
                                         </div>
                                     ))}
                             </div>
                         </div>
-                        <br />
-                        <Button type='primary' onClick={() => {
-                            form.validateFields(['name', 'desc', 'appProId']).then(async (values) => {
-                                setStep(2);
-                                setInputs(inputs);
-                            }).catch((error) => {
-                                console.error(error);
-                            });
-                        }} >
-                            下一步
-                        </Button>
+                        
+                        <div style={{ display: 'flex', gap: '12px', marginTop: '24px', paddingTop: '24px', borderTop: '1px solid #f0f0f0' }}>
+                            <Button
+                                className='btn-cancel'
+                                onClick={() => {
+                                    router.navigate({ pathname: '/deepseek/questionAnswer' });
+                                }}
+                            >
+                                返回
+                            </Button>
+                            <Button 
+                                type='primary' 
+                                onClick={() => {
+                                    form.validateFields(['name', 'desc', 'appProId']).then(async (values) => {
+                                        setStep(2);
+                                        setInputs(inputs);
+                                    }).catch((error) => {
+                                        console.error(error);
+                                    });
+                                }}
+                            >
+                                下一步
+                            </Button>
+                        </div>
                     </div>
 
                     <div style={{ display: step === 2 ? 'block' : 'none' }} className='questionAnswerInfo-content'>
-                        <div style={{ paddingBottom: '10px', display: 'flex', justifyContent: 'flex-end' }}>
+                        <div className='flex-between padding-bottom-16'>
                             <div>
                                 <Button
-                                    style={{ background: '#f5f5f5' }}
+                                    className='btn-back'
+                                    icon={<ArrowLeftOutlined />}
                                     onClick={() => {
                                         setStep(1);
                                     }}
                                 >
                                     上一步
                                 </Button>
-                                {
-                                    createFlag &&
+                            </div>
+                            <div style={{ display: 'flex', gap: '12px' }}>
+                                <Button
+                                    className='btn-cancel'
+                                    onClick={() => {
+                                        router.navigate({ pathname: '/deepseek/questionAnswer' });
+                                    }}
+                                >
+                                    取消
+                                </Button>
+                                {createFlag && (
                                     <Button
                                         type='primary'
                                         onClick={() => {
@@ -618,45 +643,63 @@ const QuestionAnswerInfo: React.FC = () => {
                                             });
                                         }}
                                     >提交应用</Button>
-                                }
+                                )}
                             </div>
                         </div>
-                        <Splitter style={{ height: '100%', boxShadow: '0 0 10px rgba(0, 0, 0, 0.1)' }}>
-                            <Splitter.Panel defaultSize="40%">
-                                <div style={{ width: '100%', height: '100%' }}>
-                                    <h2>Prompt编写</h2>
-                                    <div style={{ paddingTop: '20px' }}>
-                                        <TextArea
-                                            autoSize
-                                            readOnly
-                                            placeholder="编写Prompt过程中可以引入2项变量:{{知识}} 代表知识库中检索到的知识内容, {{用户}}代表用户输入的内容。您可以在编写Prompt过程中将变量拼接在合适的位置。插入:{{知识}} 插入:{{用户}}"
-                                            style={{ width: '100%', height: '300px' }}
-                                        />
+                        <div className='section-title'>
+                            Prompt编写与参数配置
+                            <Tooltip 
+                                title="Prompt用于对大模型的回复做出一些列指令和约束。这段Prompt不会被用户看到。" 
+                                placement="right"
+                                overlayStyle={{ fontSize: '12px' }}
+                            >
+                                <InfoCircleOutlined style={{ marginLeft: '8px', color: '#999', fontSize: '14px' }} />
+                            </Tooltip>
+                        </div>
+                        <Splitter style={{ border: '1px solid #f0f0f0', borderRadius: '6px' }}>
+                            <Splitter.Panel defaultSize="65%">
+                                <div className='prompt'>
+                                    <div className='prompt-info'>
+                                        <div className='prompt-info-text'>
+                                            <Typography.Paragraph style={{ fontSize: '12px', lineHeight: '1.6', color: '#999', margin: 0 }}>
+                                                编写Prompt过程中可以引入2项变量:
+                                                <span className='variable-highlight'>{'{{知识}}'}</span> 
+                                                代表知识库中检索到的知识内容, 
+                                                <span className='variable-highlight'>{'{{用户}}'}</span>
+                                                代表用户输入的内容。您可以在编写Prompt过程中将变量拼接在合适的位置。
+                                                <br />
+                                                插入:
+                                                <span className='variable-highlight'>{'{{知识}}'}</span>,
+                                                插入:
+                                                <span className='variable-highlight'>{'{{用户}}'}</span>。
+                                            </Typography.Paragraph>
+                                        </div>
                                     </div>
-                                    <Divider plain></Divider>
-                                    <div >
+                                    <Divider style={{ margin: '0' }} />
+                                    <div className='prompt-editor-area'>
                                         <FormItem name='prompt'
-                                            initialValue={`你是一位知识检索助手,你必须并且只能从我发送的众多知识片段中寻找能够解决用户输入问题的最优答案,并且在执行任务的过程中严格执行规定的要求。
-
+                                            initialValue={
+                                                `你是一位知识检索助手,你必须并且只能从我发送的众多知识片段中寻找能够解决用户输入问题的最优答案,并且在执行任务的过程中严格执行规定的要求。 \n
 知识片段如下:
 {{知识}}
 
 规定要求:
-- 找到答案就仅使用知识片段中的原文回答用户的提问;
-- 找不到答案就用自身知识并且告诉用户该信息不是来自文档;
+- 找到答案就仅使用知识片段中的原文回答用户的提问;- 找不到答案就用自身知识并且告诉用户该信息不是来自文档;
 - 所引用的文本片段中所包含的示意图占位符必须进行返回,占位符格式参考:【示意图序号_编号】
-  - 严禁输出任何知识片段中不存在的示意图占位符;
-  - 输出的内容必须删除其中包含的任何图注、序号等信息。例如:“进入登录页面(图1.1)”需要从文字中删除图序,回复效果为:“进入登录页面”;“如图所示1.1”,回复效果为:“如图所示”;
-- 格式规范
-  - 文档中会出现包含表格的情况,表格是以图片标识符的形式呈现,表格中缺失数据时候返回空单元格;
-  - 如果需要用到表格中的数据,以代码块语法输出表格中的数据;
-  - 避免使用代码块语法回复信息;
-  - 回复的开头语不要输出诸如:“我想”,“我认为”,“think”等相关语义的文本。
+- 严禁输出任何知识片段中不存在的示意图占位符;
+- 输出的内容必须删除其中包含的任何图注、序号等信息。例如:“进入登录页面(图1.1)”需要从文字中删除图序,回复效果为:“进入登录页面”;“如图所示1.1”,回复效果为:“如图所示”;
+
+格式规范:
+- 文档中会出现包含表格的情况,表格是以图片标识符的形式呈现,表格中缺失数据时候返回空单元格;
+- 如果需要用到表格中的数据,以代码块语法输出表格中的数据;
+- 避免使用代码块语法回复信息;
+- 回复的开头语不要输出诸如:“我想”,“我认为”,“think”等相关语义的文本。
 
 严格执行规定要求,不要复述问题,直接开始回答。
 
 用户输入问题:
-{{用户}}`}
+{{用户}}`
+                                            }
                                             rules={[{ required: true, message: '提示词不能为空' }]}>
                                             <TextArea
                                                 placeholder="提示词"
@@ -665,19 +708,15 @@ const QuestionAnswerInfo: React.FC = () => {
                                         </FormItem>
                                     </div>
                                 </div>
-
                             </Splitter.Panel>
-                            <Splitter.Panel defaultSize="60%">
-                                <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', background: '#f5f5f5', width: '100%', height: '100%' }}>
-                                    <div style={{ width: '50%', height: '100%' }}>
-                                        <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', paddingTop: '50px', fontSize: '16px' }}>
+                            <Splitter.Panel defaultSize="35%">
+                                <div className='flex-center-container'>
+                                    <div className='half-width'>
+                                        <div className='flex-center-top'>
                                             欢迎使用 {name}
                                         </div>
 
-                                        <div style={{
-                                            display: 'flex', justifyContent: 'center', alignItems: 'center',
-                                            paddingTop: '20px'
-                                        }}>
+                                        <div className='flex-center padding-top-20'>
                                             <FormItem
                                                 label='引用知识库'
                                                 name='knowledge_ids'
@@ -686,7 +725,7 @@ const QuestionAnswerInfo: React.FC = () => {
                                                     // mode='multiple'
                                                     // maxCount={MAX_COUNT}
                                                     // suffixIcon={suffix}
-                                                    style={{ width: '300px', height: '48px' }}
+                                                    className='questionAnswerInfo-content-title'
                                                     placeholder='请选择知识库'
                                                 >
                                                     {
@@ -699,7 +738,7 @@ const QuestionAnswerInfo: React.FC = () => {
                                                 </Select>
                                             </FormItem>
                                         </div>
-                                        <div style={{display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
+                                        <div className='flex-center'>
                                             <FormItem
                                                 label='调用模型'
                                                 name="model"
@@ -707,7 +746,7 @@ const QuestionAnswerInfo: React.FC = () => {
                                                 <Select
                                                     placeholder='请选择模型'
                                                     allowClear={true}
-                                                    style={{width: '300px', height: '48px'}}
+                                                    className='questionAnswerInfo-content-title'
                                                     onChange={(value) => {
                                                         if (value === 'Qwen3-30B') {
                                                             setIsDeepThinkVisible(true);
@@ -722,26 +761,20 @@ const QuestionAnswerInfo: React.FC = () => {
 
                                             </FormItem>
                                             </div>
-                                            <div style={{
-                                                display: isDeepThinkVisible  ? 'flex' : 'none',
-                                                justifyContent: 'center',
-                                                alignItems: 'center'
+                                            <div className='flex-center' style={{
+                                                display: isDeepThinkVisible  ? 'flex' : 'none'
                                             }}>
                                                 <FormItem
                                                     label='深度思考'
                                                     name='isDeepThink'
                                                     rules={[{ required: true, message: '请选择是否深度思考' }]}>
-                                                    <Radio.Group buttonStyle="solid" style={{width: '300px'}}>
+                                                    <Radio.Group buttonStyle="solid" className='form-control-width'>
                                                         <Radio.Button value='Y'>是</Radio.Button>
                                                         <Radio.Button value='N'>否</Radio.Button>
                                                     </Radio.Group>
                                                 </FormItem>
                                             </div>
-                                            <div style={{
-                                                display: 'flex',
-                                                justifyContent: 'center',
-                                                alignItems: 'center'
-                                            }}>
+                                            <div className='flex-center'>
                                                 <FormItem
                                                     label='max token'
                                                     name='max_token'
@@ -754,14 +787,10 @@ const QuestionAnswerInfo: React.FC = () => {
 
                                             {
                                                 !isVisible &&
-                                                <div style={{
-                                                    display: 'flex',
-                                                    justifyContent: 'center',
-                                                    alignItems: 'center'
-                                                }}>
+                                                <div className='flex-center'>
                                                     <a onClick={() => {
                                                         setIsVisible(!isVisible);
-                                                    }} className='questionAnswerInfo-content-title'>
+                                                    }} className='link-more-settings'>
                                                         更多设置
                                                     </a>
                                                 </div>
@@ -772,28 +801,20 @@ const QuestionAnswerInfo: React.FC = () => {
                                             <div style={{display: isVisible ? 'block' : 'none', paddingTop: '20px'}}>
                                                 {isVisibleCus &&
                                                     <Space style={{width: '100%'}} direction="vertical">
-                                                        <div style={{
-                                                            display: 'flex',
-                                                            justifyContent: 'center',
-                                                            alignItems: 'center'
-                                                        }}>
+                                                        <div className='flex-center'>
                                                             <FormItem
                                                                 label='Top-p'
                                                                 name='topP'
-                                                                style={{width: '300px'}}
+                                                                className='form-control-width'
                                                             >
                                                                 <TopPDecimalStep/>
                                                             </FormItem>
                                                         </div>
-                                                        <div style={{
-                                                            display: 'flex',
-                                                            justifyContent: 'center',
-                                                            alignItems: 'center'
-                                                        }}>
+                                                        <div className='flex-center'>
                                                             <FormItem
                                                                 label='Temperature'
                                                                 name='temperature'
-                                                                style={{width: '300px'}}
+                                                                className='form-control-width'
                                                             >
                                                                 <TempDecimalStep/>
                                                             </FormItem>
@@ -811,7 +832,7 @@ const QuestionAnswerInfo: React.FC = () => {
                                                         name='param_desc'
                                                         rules={[{required: true, message: '回答风格不能为空'}]}>
                                                         <Radio.Group buttonStyle="solid"
-                                                                     className='questionAnswerInfo-content-title'>
+                                                                     className='form-control-width'>
                                                             <Radio.Button onClick={() => {
                                                                 handleRedioClick('strict')
                                                             }} value='strict'>严谨</Radio.Button>
@@ -840,7 +861,7 @@ const QuestionAnswerInfo: React.FC = () => {
                                                     <FormItem
                                                         label='展示引用知识'
                                                         name='show_recall_result'
-                                                        className='questionAnswerInfo-content-title'>
+                                                        className='form-control-width'>
                                                         <Switch onChange={onChangeShow}/>
                                                     </FormItem>
                                                 </div>
@@ -870,7 +891,7 @@ const QuestionAnswerInfo: React.FC = () => {
                                                     justifyContent: 'center',
                                                     alignItems: 'center'
                                                 }}>
-                                                    <div className='questionAnswerInfo-content-title'>重排方式</div>
+                                                    <div className='section-title'>重排方式</div>
                                                 </div>
                                                 <div style={{
                                                     display: 'flex',
@@ -881,7 +902,7 @@ const QuestionAnswerInfo: React.FC = () => {
                                                         label='Rerank模型'
                                                         name='rerank_status'
                                                         valuePropName='checked'
-                                                        className='questionAnswerInfo-content-title'
+                                                        className='form-control-width'
                                                     >
                                                         <Switch onChange={onChangeModel}/>
                                                     </FormItem>
@@ -897,7 +918,7 @@ const QuestionAnswerInfo: React.FC = () => {
                                                             name='rerank_model_name'
                                                         >
                                                             <Select
-                                                                style={{width: '300px', height: '48px'}}
+                                                                className='questionAnswerInfo-content-title'
                                                                 placeholder='请选择模型'
                                                                 // defaultValue={'rerank'}
                                                             >
@@ -916,7 +937,7 @@ const QuestionAnswerInfo: React.FC = () => {
                                                         name='slice_config_type'
                                                         rules={[{required: true, message: '召回方式不能为空'}]}>
                                                         <Select
-                                                            style={{width: '300px', height: '48px'}}
+                                                            className='questionAnswerInfo-content-title'
                                                             placeholder='请选择'
                                                             onChange={onChangeCount}>
                                                             <Option value="fixed">手动设置</Option>
@@ -951,7 +972,7 @@ const QuestionAnswerInfo: React.FC = () => {
                                                     >
                                                         <TextArea
                                                             rows={4}
-                                                            className='questionAnswerInfo-content-title'
+                                                            className='form-textarea-large'
                                                             placeholder="请输入内容"
                                                         />
                                                     </FormItem>

+ 96 - 0
src/pages/deepseek/questionAnswer/info/promptTemplates.ts

@@ -0,0 +1,96 @@
+// 提示词模板配置文件
+export const PROMPT_TEMPLATES = {
+  // 知识检索助手提示词模板
+  KNOWLEDGE_RETRIEVAL_ASSISTANT: `你是一位知识检索助手,你必须并且只能从我发送的众多知识片段中寻找能够解决用户输入问题的最优答案,并且在执行任务的过程中严格执行规定的要求。
+
+知识片段如下:
+{{知识}} 
+
+规定要求:
+- 找到答案就仅使用知识片段中的原文回答用户的提问;
+- 找不到答案就用自身知识并且告诉用户该信息不是来自文档;
+- 所引用的文本片段中所包含的示意图占位符必须进行返回,占位符格式参考:【示意图序号_编号】
+  - 严禁输出任何知识片段中不存在的示意图占位符;
+  - 输出的内容必须删除其中包含的任何图注、序号等信息。例如:"进入登录页面(图1.1)"需要从文字中删除图序,回复效果为:"进入登录页面";"如图所示1.1",回复效果为:"如图所示";
+
+格式规范:
+  - 文档中会出现包含表格的情况,表格是以图片标识符的形式呈现,表格中缺失数据时候返回空单元格;
+  - 如果需要用到表格中的数据,以代码块语法输出表格中的数据;
+  - 避免使用代码块语法回复信息;
+  - 回复的开头语不要输出诸如:"我想","我认为","think"等相关语义的文本。
+
+严格执行规定要求,不要复述问题,直接开始回答。
+
+用户输入的问题:
+{{用户}} `,
+
+  // 可以添加更多提示词模板
+  CHAT_ASSISTANT: `你是一个友好的聊天助手,请根据用户的问题提供有帮助的回答。
+
+用户问题: {{用户}}`,
+
+  // 文档总结助手
+  DOCUMENT_SUMMARY: `请对以下文档内容进行总结,提取关键信息:
+
+文档内容:
+{{知识}}
+
+用户要求:
+{{用户}}`,
+
+  // 代码助手
+  CODE_ASSISTANT: `你是一个专业的代码助手,请根据用户的需求提供代码解决方案。
+
+用户需求: {{用户}}
+
+相关文档: {{知识}}`,
+
+  // 翻译助手
+  TRANSLATION_ASSISTANT: `你是一个专业的翻译助手,请将用户提供的内容翻译成目标语言。
+
+原文内容: {{用户}}
+
+参考文档: {{知识}}`
+};
+
+// 提示词模板类型定义
+export type PromptTemplateType = keyof typeof PROMPT_TEMPLATES;
+
+// 获取提示词模板的函数
+export const getPromptTemplate = (templateType: PromptTemplateType): string => {
+  return PROMPT_TEMPLATES[templateType];
+};
+
+// 默认提示词模板
+export const DEFAULT_PROMPT_TEMPLATE = PROMPT_TEMPLATES.KNOWLEDGE_RETRIEVAL_ASSISTANT;
+
+// 提示词模板描述
+export const PROMPT_TEMPLATE_DESCRIPTIONS = {
+  KNOWLEDGE_RETRIEVAL_ASSISTANT: '知识检索助手 - 基于知识库内容回答问题',
+  CHAT_ASSISTANT: '聊天助手 - 提供友好的对话服务',
+  DOCUMENT_SUMMARY: '文档总结 - 提取文档关键信息',
+  CODE_ASSISTANT: '代码助手 - 提供代码解决方案',
+  TRANSLATION_ASSISTANT: '翻译助手 - 多语言翻译服务'
+};
+
+// 验证提示词模板是否包含必要的占位符
+export const validatePromptTemplate = (template: string): boolean => {
+  const requiredPlaceholders = ['{{知识}}', '{{用户}}'];
+  return requiredPlaceholders.every(placeholder => template.includes(placeholder));
+};
+
+// 格式化提示词模板(替换占位符)
+export const formatPromptTemplate = (
+  template: string, 
+  knowledge: string = '', 
+  userInput: string = ''
+): string => {
+  return template
+    .replace(/\{\{知识\}\}/g, knowledge)
+    .replace(/\{\{用户\}\}/g, userInput);
+};
+
+// 获取所有可用的模板类型
+export const getAvailableTemplateTypes = (): PromptTemplateType[] => {
+  return Object.keys(PROMPT_TEMPLATES) as PromptTemplateType[];
+};

+ 411 - 7
src/pages/deepseek/questionAnswer/info/style.less

@@ -1,18 +1,422 @@
+// 主容器样式
 .questionAnswerInfo {
   width: 100%;
   height: 100%;
   background: #FFFFFF;
   border-radius: @border-radius-base;
+  
+  // 内容区域
+  &-content {
+    width: 100%;
+    height: 100%;
+    background: #FFFFFF;
+    padding: 16px 20px;
+    
+    // 标题样式
+    &-title {
+      width: 100%;
+      max-width: 646px;
+      height: 48px;
+    }
+  }
 }
 
-.questionAnswerInfo-content {
+// 通用布局样式
+.flex {
+  &-center {
+    &-container {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      background: #f5f5f5;
+      width: 100%;
+      height: 100%;
+    }
+    
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    
+    &-top {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      padding-top: 50px;
+      font-size: 16px;
+    }
+  }
+  
+  &-between {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+  }
+  
+  &-end {
+    display: flex;
+    justify-content: flex-end;
+  }
+}
+
+// 按钮样式
+.btn {
+  &-cancel {
+    background: #f5f5f5;
+    border: none;
+    color: #000000;
+    transition: all 0.3s ease;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    
+    &:hover {
+      background: #e8e8e8;
+      color: #000000;
+      box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
+      transform: translateY(-1px);
+    }
+    
+    &:active {
+      background: #dcdcdc;
+      color: #000000;
+      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
+      transform: translateY(0);
+    }
+    
+    &:focus {
+      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    }
+  }
+  
+  &-back {
+    background: #ffffff;
+    border: 1px solid #f0f0f0;
+    color: #595959;
+    transition: all 0.3s ease;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    
+    &:hover {
+      background: #fafafa;
+      border-color: #40a9ff;
+      color: #40a9ff;
+      box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
+      transform: translateY(-1px);
+    }
+    
+    &:active {
+      background: #f0f0f0;
+      border-color: #1890ff;
+      color: #1890ff;
+      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
+      transform: translateY(0);
+    }
+    
+    &:focus {
+      border-color: #40a9ff;
+      box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
+    }
+  }
+}
+
+// 表单样式
+.form {
+  &-control {
+    &-width {
+      width: 100%;
+      max-width: 646px;
+    }
+    
+    &-height {
+      height: 48px;
+    }
+  }
+  
+  &-input {
+    &-large {
+      width: 100%;
+      max-width: 646px;
+      padding: 8px;
+    }
+    
+    &-number-small {
+      margin: 0 16px;
+      width: 100px;
+    }
+  }
+  
+  &-textarea {
+    &-large {
+      height: 120px;
+      resize: none;
+      width: 100%;
+      max-width: 646px;
+    }
+  }
+}
+
+// 文本区域样式
+.textarea {
+  &-full-width {
+    width: 100%;
+  }
+  
+  &-fixed-height {
+    height: 300px;
+  }
+}
+
+// 预设问题区域样式
+.preset-questions {
+  margin: 24px 0;
+  
+  h4 {
+    margin-bottom: 16px;
+    color: #262626;
+  }
+  
+  .question-item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 12px;
+    flex-wrap: wrap;
+    gap: 12px;
+    
+    label {
+      min-width: 60px;
+      color: #595959;
+      flex-shrink: 0;
+    }
+    
+    .question-input {
+      flex: 1;
+      min-width: 200px;
+      max-width: 400px;
+      margin: 0;
+    }
+    
+    .question-actions {
+      display: flex;
+      gap: 8px;
+      flex-shrink: 0;
+      
+      .question-icon {
+        margin: 0;
+        font-size: 18px;
+        color: @primary-color;
+        cursor: pointer;
+        transition: all 0.3s ease;
+        
+        &:hover {
+          color: @primary-color;
+          transform: scale(1.1);
+        }
+      }
+    }
+  }
+}
+
+// 问题输入框样式(保留向后兼容)
+.question-input {
+  width: 100%;
+  max-width: 300px;
+  padding-top: 8px;
+  margin-left: 20px;
+}
+
+.link-more-settings {
+  color: @primary-color;
+  cursor: pointer;
+  text-decoration: none;
+  
+  &:hover {
+    text-decoration: underline;
+  }
+}
+
+// 标题和链接样式
+.section-title {
+  font-size: 14px;
+  font-weight: 500;
+  color: #262626;
+  margin-bottom: 12px;
+}
+
+// Prompt编辑器布局样式
+.prompt {
   width: 100%;
   height: 100%;
-  background: #FFFFFF;
-  padding: 10px;
+  display: flex;
+  flex-direction: column;
+  // 滚动条
+  overflow-y: auto;
+
+  // 提示词模板显示区域
+  &-info {
+    padding: 16px 20px 10px 20px;
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-start;
+    
+    &-text {
+      // 说明文本
+        
+      .variable-highlight {
+        color: #1890ff;
+        font-weight: 500;
+        padding: 2px 6px;
+        border-radius: 4px;
+        font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
+        margin: 0 2px;
+      }
+    }
+  }
+
+  // 提示词编辑区域
+  &-editor-area {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    
+    .ant-form-item {
+      margin-bottom: 0;
+      height: 100%;
+      
+      .ant-form-item-control {
+        height: 100%;
+        
+        .ant-form-item-control-input {
+          height: 100%;
+          
+          .ant-form-item-control-input-content {
+            height: 100%;
+            
+            .ant-input {
+              height: 100%;
+              border: 1px solid #f0f0f0;
+              border-radius: 8px;
+              padding: 16px;
+              font-size: 14px;
+              line-height: 1.6;
+              resize: none;
+              
+              &:focus {
+                border-color: #1890ff;
+                box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
+              }
+              
+              &::placeholder {
+                color: #bfbfbf;
+                font-style: italic;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+.half-width {
+  width: 50%;
+  height: 100%;
 }
 
-.questionAnswerInfo-content-title {
-  width: 300px;
-  height: 48px;
-}
+// 间距样式
+.padding {
+  &-top {
+    &-10 {
+      padding-top: 10px;
+    }
+    
+    &-20 {
+      padding-top: 20px;
+    }
+  }
+  
+  &-bottom {
+    &-10 {
+      padding-bottom: 10px;
+    }
+
+    &-12 {
+      padding-bottom: 12px;
+    }
+
+    &-16 {
+      padding-bottom: 16px;
+    }
+  }
+}
+
+// 响应式设计
+@media (max-width: 768px) {
+  .questionAnswerInfo {
+    &-content {
+      &-title {
+        max-width: 100%;
+      }
+    }
+  }
+  
+  .form {
+    &-control-width,
+    &-input-large,
+    &-textarea-large {
+      max-width: 100%;
+    }
+  }
+  
+  .question-input {
+    max-width: 100%;
+    margin-left: 0;
+  }
+  
+  .half-width {
+    width: 100%;
+  }
+  
+  .preset-questions {
+    .question-item {
+      flex-direction: column;
+      align-items: flex-start;
+      gap: 8px;
+      
+      label {
+        min-width: auto;
+      }
+      
+      .question-input {
+        width: 100%;
+        max-width: 100%;
+        min-width: auto;
+      }
+      
+      .question-actions {
+        align-self: flex-end;
+      }
+    }
+  }
+}
+
+@media (max-width: 480px) {
+  .questionAnswerInfo {
+    &-content {
+      padding: 16px;
+    }
+  }
+  
+  .form {
+    &-input-large,
+    &-textarea-large {
+      padding: 6px;
+    }
+  }
+  
+  .preset-questions {
+    .question-item {
+      .question-actions {
+        align-self: center;
+        width: 100%;
+        justify-content: center;
+      }
+    }
+  }
+}

+ 98 - 43
src/pages/deepseek/questionAnswer/list/index.tsx

@@ -16,7 +16,8 @@ import {
   Form,
   Space,
   Row,
-  Col
+  Col,
+  Input
 } from 'antd';
 import {
   PlusOutlined,
@@ -25,7 +26,11 @@ import {
   DeleteOutlined,
   StepForwardOutlined,
   SearchOutlined,
-  ReloadOutlined
+  ReloadOutlined,
+  BookOutlined,
+  TeamOutlined,
+  AppstoreOutlined,
+  EditOutlined
 } from '@ant-design/icons';
 import { apis } from '@/apis';
 import './style.less';
@@ -124,7 +129,7 @@ const QuestionAnswerList : React.FC = () => {
   const [ projectList, setProjectList ] = React.useState<ProjectTypeList>( [] );
   const [ appProjectList, setAppProjectList ] = React.useState<AppTypeList>( [] );
   const [ showSubPanel, setShowSubPanel ] = React.useState( false );
-  const [ selectedType, setSelectedType ] = React.useState<number | null>( null );
+  const [ selectedType, setSelectedType ] = React.useState<string | null>( '全部' );
   const wrapperRef = React.useRef<HTMLDivElement>( null );
   const selectRef = React.useRef<any>( null );
   const [ levelTypeList, setLevelTypeList ] = React.useState<AppTypeList>( [] );
@@ -298,6 +303,9 @@ const QuestionAnswerList : React.FC = () => {
     await projectApi.fetchProject();
     await appProTypeApi.fetchAppProType();
     await levelTypeApi.fetchLevelAppType();
+    
+    // 设置默认选择"全部"
+    form.setFieldsValue({ typeId: '全部' });
   }
   
   React.useEffect( () => {
@@ -347,6 +355,7 @@ const QuestionAnswerList : React.FC = () => {
   const handleClickReset = async () => {
     form.resetFields();
     setShowSubPanel( false );
+    setSelectedType( '全部' ); // 重置为"全部"
     page.pageNumber = 1;
     page.pageSize = 10;
     await appApi.fetchList( null, null );
@@ -368,9 +377,8 @@ const QuestionAnswerList : React.FC = () => {
   }, [] );
   
   
-  const handleAppTypeChange = ( value : number ) => {
-    console.log( value, 'sssss' );
-    if ( value === 41 ) {
+  const handleAppTypeChange = ( value : string ) => {
+    if ( value === '41' ) {
       // 如果是项目级应用,切换面板状态
       // setShowSubPanel(prev => !prev);
       setShowSubPanel( true );
@@ -380,9 +388,20 @@ const QuestionAnswerList : React.FC = () => {
     }
     setSelectedType( value );
     form.setFieldsValue( { typeId: value } );
+    
+    // 自动提交逻辑
+    if (value === '全部') {
+      // 全部选项,传递null给后端
+      appApi.fetchList( null, null );
+      indexApi.fetchIndex( null, null );
+    } else {
+      // 其他选项,传递对应的typeId
+      appApi.fetchList( value, null );
+      indexApi.fetchIndex( value, null );
+    }
   };
   
-  const handleAppProTypeChange = ( value : number ) => {
+  const handleAppProTypeChange = ( value : string ) => {
     console.log( value, 'valuevalue' );
     
     setSelectedType( value );
@@ -391,7 +410,6 @@ const QuestionAnswerList : React.FC = () => {
   
   return (
       <div>
-        
         <div style={ { padding: '16px 20px' , display: 'flex' } }>
           <Form
               form={ form }
@@ -400,30 +418,52 @@ const QuestionAnswerList : React.FC = () => {
               style={{ flex: 1 }}
           >
             <div>
-              {/* 主选择器 */ }
+              {/* 主选择器 - 修改为按钮组形式 */}
               <FormItem
-                  // label="应用类型"
                   name="typeId"
                   style={ { marginBottom: 0 } }
               >
-                <Select
-                    ref={ selectRef }
-                    // style={ { width: 200 } }
-                    placeholder="请选择应用类型"
-                    onChange={ handleAppTypeChange }
-                    value={ selectedType }
-                    allowClear
-                >
-                  { appTypeList.map( item => (
-                      <Option key={ item.value } value={ item.value }>
-                        { item.label }
-                      </Option>
-                  ) ) }
-                </Select>
+                <div className="filter-button-group">
+                  {/* 全部按钮 */}
+                  <Button
+                    key="全部"
+                    type={selectedType === '全部' ? 'primary' : 'default'}
+                    size="small"
+                    onClick={() => handleAppTypeChange('全部')}
+                  >
+                    全部
+                  </Button>
+                  {/* 动态应用类型按钮 */}
+                  {appTypeList.map(item => {
+                    // 根据label匹配对应的图标
+                    let icon = null;
+                    const isSelected = selectedType === item.value;
+                    
+                    if (item.label === '专业知识') {
+                      icon = <BookOutlined style={{ fontSize: '14px', marginRight: '0' }} />;
+                    } else if (item.label === '职能管理') {
+                      icon = <TeamOutlined style={{ fontSize: '14px', marginRight: '0' }} />;
+                    } else if (item.label === '项目级应用') {
+                      icon = <AppstoreOutlined style={{ fontSize: '14px', marginRight: '0' }} />;
+                    }
+                    
+                    return (
+                      <Button
+                        key={item.value}
+                        type={isSelected ? 'primary' : 'default'}
+                        size="small"
+                        onClick={() => handleAppTypeChange(item.value)}
+                      >
+                        {icon}
+                        {item.label}
+                      </Button>
+                    );
+                  })}
+                </div>
               </FormItem>
               
               {/* 子选项面板 */ }
-              { showSubPanel && selectedType === 41 && (
+              { showSubPanel && selectedType === '41' && (
                   
                   <FormItem
                       label='类型'
@@ -434,7 +474,12 @@ const QuestionAnswerList : React.FC = () => {
                         placeholder='请选择'
                         allowClear
                         // style={ { width: 200 } }
-                        // onChange={handleAppProTypeChange}
+                        onChange={(value) => {
+                          // 项目类型选择器自动提交逻辑
+                          const currentProjectId = form.getFieldValue('projectId');
+                          appApi.fetchList(value, currentProjectId);
+                          indexApi.fetchIndex(value, currentProjectId);
+                        }}
                     >
                       {
                         appProjectList.map( ( item, index ) => {
@@ -464,6 +509,13 @@ const QuestionAnswerList : React.FC = () => {
                   // style={ { width: '200px' } }
                   placeholder='请选择项目'
                   allowClear
+                  onChange={(value) => {
+                    // 项目选择器自动提交逻辑
+                    const currentTypeId = form.getFieldValue('typeId');
+                    const typeId = currentTypeId === '全部' ? null : currentTypeId;
+                    appApi.fetchList(typeId, value);
+                    indexApi.fetchIndex(typeId, value);
+                  }}
               >
                 {
                   projectList.map( ( item, index ) => {
@@ -478,21 +530,22 @@ const QuestionAnswerList : React.FC = () => {
             
             <FormItem>
               <Space size={ 12 }>
-                <Button
-                    // style={ { marginRight: 16 } }
+                <Tooltip title="重置">
+                  <Button
+                    shape="circle"
+                    icon={ <ReloadOutlined /> }
+                    onClick={ handleClickReset }
+                  />
+                </Tooltip>
+                <Tooltip title="查询">
+                  <Button
                     type='primary'
+                    shape="circle"
                     onClick={ handleClickSearch }
                     icon={ <SearchOutlined /> }
-                >
-                  查询
-                </Button>
-                <Button
-                    icon={ <ReloadOutlined /> }
-                    onClick={ handleClickReset }>
-                  重置
-                </Button>
+                  />
+                </Tooltip>
               </Space>
-            
             </FormItem>
             
             {/* {
@@ -574,7 +627,8 @@ const QuestionAnswerList : React.FC = () => {
                                       <Image
                                           width={ 32 }
                                           height={ 32 }
-                                          src={ IconSvg }
+                                          src={IconSvg}
+                                          preview={false}
                                       />
                                     </div>
                                     {/*<div style={ { overflow: 'auto' } }>*/ }
@@ -672,17 +726,18 @@ const QuestionAnswerList : React.FC = () => {
                                           {
                                               updateFlag &&
                                               <a
+                                                  className="action-button"
                                                   style={ { marginRight: 16 } }
                                                   onClick={ () => {
                                                 router.navigate( { pathname: '/deepseek/questionAnswer/modify' }, { state: { id: item.appId } } );
                                               } }>
-                                                <SettingOutlined /> 编辑
+                                                <EditOutlined /> 编辑
                                               </a>
                                           }
                                           
                                           {
                                               deleteFlag &&
-                                              <a className='text-error' onClick={ () => {
+                                              <a className='delete-button' onClick={ () => {
                                                 Modal.confirm( {
                                                   title: '删除',
                                                   content: `确定删除应用: ` + item.name + ` 吗?`,
@@ -701,7 +756,7 @@ const QuestionAnswerList : React.FC = () => {
                                     
                                     {
                                         createFlag && item.status === '5' &&
-                                        <a style={ { marginLeft: 16 } } onClick={ () => {
+                                        <a className="action-button" style={ { marginLeft: 16 } } onClick={ () => {
                                           Modal.confirm( {
                                             title: '提交审核',
                                             content: `确认提交审核应用: ` + item.name + `吗?`,
@@ -745,14 +800,14 @@ const QuestionAnswerList : React.FC = () => {
               </div>
               :
               <div>
-                {
+                {/* {
                     createFlag &&
                     <Button type='primary'
                             icon={ <PlusOutlined /> }
                             onClick={ () => {
                               router.navigate( { pathname: '/deepseek/questionAnswer/create' } );
                             } }>创建问答应用</Button>
-                }
+                } */}
                 <Empty image={ Empty.PRESENTED_IMAGE_SIMPLE } />
               </div>
         }

+ 165 - 10
src/pages/deepseek/questionAnswer/list/style.less

@@ -9,7 +9,6 @@
 .applicationList {
   width: 100%;
   min-height: 600px;
-  //padding-top: 10px;
 }
 
 .card{
@@ -18,10 +17,38 @@
   border-radius: @border-radius-large;
   min-height: 200px;
   overflow: auto;
+  
+  // 默认状态下操作按钮颜色
+  .action-button {
+    color: #999 !important;
+    transition: color 0.3s ease;
+    
+    &:hover {
+      color: @primary-color !important;
+    }
+  }
+  
+  .delete-button {
+    color: #999 !important;
+    transition: color 0.3s ease;
+    
+    &:hover {
+      color: @error-color !important;
+    }
+  }
 }
 .card:hover{
   box-shadow: 0 0 8px rgba(0,0,0,.1);
   border: 1px solid @primary-color ;
+  
+  // 悬停状态下操作按钮颜色
+  .action-button {
+    color: @primary-color !important;
+  }
+  
+  .delete-button {
+    color: @error-color !important;
+  }
 }
 
 .desc {
@@ -30,22 +57,14 @@
   font-weight: 300; /* 细体字 */
   line-height: 20px;
   transition: all 0.3s;
-  //margin-bottom: 16px;
 }
 
-.info-head {
-  width: 100%;
-  height: 35%;
-}
+
 
 .ant-select-selector {
   border-radius: 4px !important;
   background: #fff !important;
   height: 32px !important;
-  
-  //.ant-select-selection-item {
-  //  //margin-right: 8px !important;
-  //}
 }
 
 .ant-select-dropdown {
@@ -58,3 +77,139 @@
     background-color: rgba(0, 123, 255, 0.1);
   }
 }
+
+
+
+// 按钮组筛选样式
+.filter-button-group {
+  display: flex;
+  gap: 8px;
+  flex-wrap: wrap;
+  
+  .ant-btn {
+    border-radius: 16px;
+    height: 32px;
+    padding: 0 16px;
+    font-size: 14px;
+    font-weight: 400;
+    border: 1px solid #d9d9d9;
+    background-color: #fff;
+    color: #000;
+    transition: all 0.3s ease;
+    display: flex;
+    align-items: center;
+    
+    &:hover {
+      transform: translateY(-1px);
+      box-shadow: 0 2px 8px rgba(24, 144, 255, 0.2);
+      border-color: #40a9ff;
+      color: #40a9ff;
+    }
+    
+    // 所有选中状态的按钮都使用统一的蓝色主题
+    &.ant-btn-primary {
+      background-color: #1890ff !important;
+      border-color: #1890ff !important;
+      color: #fff !important;
+      font-weight: 500 !important;
+      
+      &:hover {
+        background-color: #40a9ff !important;
+        border-color: #40a9ff !important;
+        color: #fff !important;
+      }
+    }
+    
+    // 全部按钮特殊样式 - 未选中时
+    &:first-child:not(.ant-btn-primary) {
+      background-color: #f5f5f5;
+      border-color: #d9d9d9;
+      color: #666;
+      
+      &:hover {
+        background-color: #e6f7ff;
+        border-color: #40a9ff;
+        color: #40a9ff;
+      }
+    }
+    
+    // 图标样式优化
+    .anticon {
+      font-size: 14px;
+      margin-right: 4px;
+      transition: color 0.3s ease;
+      color: #666; // 默认颜色
+    }
+    
+    // 悬停时图标颜色变化
+    &:hover .anticon {
+      color: #40a9ff !important;
+    }
+    
+    // 选中状态时图标颜色
+    &.ant-btn-primary .anticon {
+      color: #fff !important;
+    }
+    
+    // 选中状态悬停时图标颜色
+    &.ant-btn-primary:hover .anticon {
+      color: #fff !important;
+    }
+    
+    // 全部按钮未选中时图标颜色
+    &:first-child:not(.ant-btn-primary) .anticon {
+      color: #666;
+    }
+    
+    // 全部按钮悬停时图标颜色
+    &:first-child:not(.ant-btn-primary):hover .anticon {
+      color: #40a9ff;
+    }
+  }
+}
+
+// 响应式处理
+@media (max-width: 768px) {
+  .filter-button-group {
+    gap: 6px;
+    
+    .ant-btn {
+      font-size: 12px;
+      padding: 0 12px;
+      height: 28px;
+    }
+  }
+}
+
+@media (max-width: 480px) {
+  .filter-button-group {
+    gap: 4px;
+    
+    .ant-btn {
+      font-size: 11px;
+      padding: 0 8px;
+      height: 24px;
+      border-radius: 12px;
+    }
+  }
+}
+
+// 圆形按钮样式优化
+.ant-btn-circle {
+  width: 32px;
+  height: 32px;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  transition: all 0.3s ease;
+  
+  &:hover {
+    transform: translateY(-1px);
+    box-shadow: 0 2px 8px rgba(24, 144, 255, 0.2);
+  }
+  
+  .anticon {
+    font-size: 14px;
+  }
+}

+ 1 - 1
src/pages/layout/components/Breadcrumb.tsx

@@ -58,7 +58,7 @@ const Breadcrumb: React.FC<Props> = (props: Props) => {
     };
 
     const items = routerMatchList.map((item, index) => {
-        const color = (index === 0 || index < routerMatchList.length - 1) ? '#8C8C8C' : '#595959';
+        const color = (index === 0 || index < routerMatchList.length - 1) ? '#595959' : '#1a1a1a';
         return {
             key: index,
             title: <Link

+ 26 - 26
src/pages/layout/components/Header.tsx

@@ -1,6 +1,6 @@
 import * as React from 'react';
-import { Layout, MenuProps, Modal, Dropdown, Select } from 'antd';
-import { CaretDownOutlined, PoweroffOutlined } from '@ant-design/icons';
+import { Layout, MenuProps, Modal, Dropdown, Select, Button, Tooltip } from 'antd';
+import { CaretDownOutlined, LogoutOutlined } from '@ant-design/icons';
 import logoSrc from '@/assets/public/logo.png';
 import router from '@/router';
 import LocalStorage from '@/LocalStorage';
@@ -22,26 +22,9 @@ const Header: React.FC<Props> = (props: Props) => {
         currentMenuType
     } = props;
 
-    const items: MenuProps['items'] = [
-        {
-            key: 'logout',
-            label: (
-                <a onClick={(e) => {
-                    e.preventDefault(); // 阻止默认行为
-                    Modal.confirm({
-                        title: '提示',
-                        content: '确定退出平台吗?',
-                        async onOk() {
-                            await onClickLogout();
-                        }
-                    });
-                }}>
-                    <PoweroffOutlined style={{ marginRight: 5 }} />
-                    退出登录
-                </a>
-            ),
-        }
-    ];
+    // const items: MenuProps['items'] = [
+    //     // 移除退出登录选项,现在使用独立的登出按钮
+    // ];
 
     const fruits = [
         { id: 1, name: 'DeepSeek' },
@@ -63,7 +46,8 @@ const Header: React.FC<Props> = (props: Props) => {
                 <div className='header-logo-text'>
                     建科•小智开放平台
                 </div>
-                <Select style={{ width: 200, marginLeft: 20 }}
+                <Select 
+                    className='header-platform-selector'
                     open={open}
                     value={currentMenuType}
                     onChange={onSelectChange}
@@ -78,7 +62,7 @@ const Header: React.FC<Props> = (props: Props) => {
                     ))}
                 </Select>
             </div>
-            <Dropdown menu={{ items }}>
+            <div className='header-user-section'>
                 <div className='header-operation'>
                     <div className='header-operation-picture'>
                         {userName.slice(0, 1)}
@@ -86,9 +70,25 @@ const Header: React.FC<Props> = (props: Props) => {
                     <div className='header-operation-name'>
                         {userName}
                     </div>
-                    <CaretDownOutlined className='header-operation-down' />
+                        {/* <CaretDownOutlined className='header-operation-down' /> */}
                 </div>
-            </Dropdown>
+                <Tooltip title="退出登录" placement="bottom">
+                    <Button
+                        type="text"
+                        icon={<LogoutOutlined />}
+                        className='header-logout-btn'
+                        onClick={() => {
+                            Modal.confirm({
+                                title: '提示',
+                                content: '确定退出平台吗?',
+                                async onOk() {
+                                    await onClickLogout();
+                                }
+                            });
+                        }}
+                    />
+                </Tooltip>
+            </div>
         </AntdHeader>
     );
 };

+ 176 - 80
src/pages/layout/style.less

@@ -1,8 +1,3 @@
-//.ant-layout {
-//    background: #f5f7fa; // 统一的浅灰色背景
-//}
-
-
 .header {
     width: 100%;
     height: 64px;
@@ -17,83 +12,216 @@
     top: 0;
     left: 0;
     z-index: 1000;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 
-
-    &-nav {
+    // 用户区域样式
+    &-user-section {
         display: flex;
         align-items: center;
-        gap: 40px;
-        margin-left: 40px;
+        gap: 8px;
+    }
 
-        &-item {
-            color: #666;
-            font-weight: 500;
-            position: relative;
-            transition: color 0.3s;
 
-            &:hover {
-                color: @primary-color;
-            }
 
-            &.active {
-                color: @primary-color;
-
-                &::after {
-                    content: '';
-                    position: absolute;
-                    bottom: -22px;
-                    left: 0;
-                    right: 0;
-                    height: 2px;
-                    background: @primary-color;
-                }
-            }
+    // 登出按钮样式
+    &-logout-btn {
+        color: #666;
+        border: none;
+        padding: 4px 8px;
+        border-radius: 6px;
+        transition: all 0.3s ease;
+        
+        &:hover {
+            color: #ff4d4f;
+            background: rgba(255, 77, 79, 0.1);
+        }
+        
+        &:active {
+            color: #cf1322;
+            background: rgba(255, 77, 79, 0.2);
         }
     }
 
-    &-logo {
+    // 用户操作区域样式优化
+    &-operation {
         display: flex;
         align-items: center;
         cursor: pointer;
-        margin-right: 40px;
+        padding: 4px 8px; // 增加点击区域
+        border-radius: 6px;
+        transition: background-color 0.3s ease;
 
         &-picture {
             width: 30px;
             height: 30px;
-            margin-right: 10px;
+            background: @primary-color;
+            border-radius: 50%;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            margin-right: 8px;
+            color: #FFFFFF;
         }
 
-        &-text {
-            font-size: 16px;
+        &-name {
             font-weight: 500;
+            color: @primary-color;
         }
     }
 
-    &-operation {
+    // &-nav {
+    //     display: flex;
+    //     align-items: center;
+    //     gap: 40px;
+    //     margin-left: 40px;
+
+    //     &-item {
+    //         color: #666;
+    //         font-weight: 500;
+    //         position: relative;
+    //         transition: color 0.3s;
+
+    //         &:hover {
+    //             color: @primary-color;
+    //         }
+
+    //         &.active {
+    //             color: @primary-color;
+
+    //             &::after {
+    //                 content: '';
+    //                 position: absolute;
+    //                 bottom: -22px;
+    //                 left: 0;
+    //                 right: 0;
+    //                 height: 2px;
+    //                 background: @primary-color;
+    //             }
+    //         }
+    //     }
+    // }
+
+    &-logo {
         display: flex;
         align-items: center;
         cursor: pointer;
+        margin-right: 40px;
 
         &-picture {
             width: 30px;
             height: 30px;
-            background: @primary-color;
-            border-radius: 50%;
-            display: flex;
-            justify-content: center;
-            align-items: center;
             margin-right: 10px;
-            color: #FFFFFF;
         }
 
-        &-name {
+        &-text {
+            font-size: 18px;
             font-weight: 500;
-            color: @primary-color;
-            margin-right: 10px;
+            color: #000000;
+            margin-right: 24px;
         }
+    }
 
-        &-down {
-            color: @primary-color !important;
+    &-platform-selector {
+        width: 200px;
+        margin-left: 20px;
+        
+        // 基础样式
+        .ant-select-selector {
+            border: 1px solid #e8e8e8;
+            border-radius: 6px;
+            background: #fafafa;
+            
+            &:hover {
+                border-color: #1890ff;
+                background: #fff;
+            }
+        }
+    }
+}
+
+// 响应式处理
+@media (max-width: 1200px) {
+    .header {
+        
+        // 优化logo区域在中等屏幕下的显示
+        &-logo {
+            margin-right: 20px;
+            
+            &-text {
+                font-size: 16px; // 稍微减小字体
+                margin-right: 16px; // 减少右边距
+            }
+        }
+        
+        // 优化Select组件在中等屏幕下的显示
+        .ant-select {
+            width: 160px !important; // 减小Select宽度
+        }
+    }
+}
+
+@media (max-width: 768px) {
+    .header {
+        padding: 0 16px;
+        
+        &-logo {
+            margin-right: 12px;
+            
+            &-text {
+                font-size: 14px; // 进一步减小字体
+                margin-right: 12px; // 进一步减少右边距
+                white-space: nowrap; // 防止换行
+                overflow: hidden; // 隐藏溢出内容
+                text-overflow: ellipsis; // 显示省略号
+                max-width: 120px; // 限制最大宽度
+            }
+        }
+        
+        // 优化Select组件在移动端的显示
+        .ant-select {
+            width: 120px !important; // 进一步减小Select宽度
+            margin-left: 8px !important; // 减少左边距
+        }
+        
+        &-operation {
+            padding: 2px 4px;
+            
+            &-name {
+                display: none; // 在移动端隐藏用户名
+            }
+        }
+        
+        &-logout-btn {
+            padding: 2px 4px;
+        }
+    }
+}
+
+// 超小屏幕优化
+@media (max-width: 480px) {
+    .header {
+        padding: 0 12px;
+        
+        &-logo {
+            margin-right: 8px;
+            
+            &-text {
+                font-size: 12px; // 最小字体
+                margin-right: 8px;
+                max-width: 80px; // 进一步限制宽度
+            }
+            
+            &-picture {
+                width: 24px; // 减小logo尺寸
+                height: 24px;
+                margin-right: 6px;
+            }
+        }
+        
+        // 超小屏幕下的Select组件优化
+        .ant-select {
+            width: 80px !important; // 最小宽度
+            margin-left: 4px !important; // 最小边距
         }
     }
 }
@@ -142,7 +270,6 @@
 
 
 .main-content {
-    //max-height: calc(100vh - 64px);
     padding-bottom: 40px;
     display: flex;
     flex-direction: column;
@@ -160,7 +287,7 @@
         background: #fff;
         position: sticky;
         top: 0;
-        z-index: 10;
+        z-index: 999;
     }
 
     .breadcrumb {
@@ -266,35 +393,4 @@
     }
 }
 
-//.deepseek {
-//    .ant-card-cover {
-//        background: #f0f5ff;
-//    }
-//
-//    .option-icon {
-//        color: #1890ff;
-//    }
-//
-//    .select-button {
-//        background: #1890ff;
-//        border-color: #1890ff;
-//    }
-//
-//}
-//
-//.zhipu {
-//    .ant-card-cover {
-//        background: #f9f0ff;
-//    }
-//
-//    .option-icon {
-//        color: #722ed1;
-//    }
-//
-//    .select-button {
-//        background: #722ed1;
-//        border-color: #722ed1;
-//    }
-//
-//}
 

+ 1 - 1
src/router.tsx

@@ -44,7 +44,7 @@ const routerList: RouteObject[] = [
                 path: '/deepseek/questionAnswer',
                 handle: {
                     menuLevel: 1,
-                    breadcrumbName: '问答应用',
+                    breadcrumbName: '问答广场',
                 },
                 children: [
                     {

+ 40 - 0
src/style/global.less

@@ -92,3 +92,43 @@ ul li {
 //.ant-form-item {
 //    margin-bottom: 16px !important;
 //}
+
+// 全局按钮样式
+.ant-btn-primary {
+  background: #1890ff;
+  border: 1px solid #1890ff;
+  color: #ffffff;
+  transition: all 0.3s ease;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  
+  &:hover {
+    background: #40a9ff;
+    border-color: #40a9ff;
+    color: #ffffff;
+    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
+    transform: translateY(-1px);
+  }
+  
+  &:active {
+    background: #096dd9;
+    border-color: #096dd9;
+    color: #ffffff;
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
+    transform: translateY(0);
+  }
+  
+  &:focus {
+    background: #1890ff;
+    border-color: #1890ff;
+    color: #ffffff;
+    box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
+  }
+  
+  &:disabled {
+    background: #f5f5f5;
+    border-color: #d9d9d9;
+    color: rgba(0, 0, 0, 0.25);
+    box-shadow: none;
+    transform: none;
+  }
+}