<template>
  <div class="ai_main">
      <div class="main_ai_content" @scroll="handleUserScroll">
          <div class="main_ai_weclome" >
            <h1>HI~我是慧教研大数据精准分析AI助教</h1>
            <p>您身边的智能助教，专注于成绩数据分析与教学改进建议，为您提供精准解读与决策支持，快来体验吧~</p>
          </div>
          <div class="main_ai_list" v-if="isShowQuickList">
            <div class="main_ai_list_title">
              您可以这样问:
            </div>
            <div class="main_ai_list_content">
                <span class="list_item_tag" v-for="(value,index) in quickList" :key="'list_quick_'+index" @click="quickAsk(value.title)">
                {{value.title}}
                </span>
            </div>
          </div>
         <!-- 显示对话历史 -->
          <div class="chat_history" v-if="chatHistory.length > 0 ">
            <div   v-for="(message, index) in chatHistory" 
              :key="index" 
              :class="['message_item', message.role]"
            >
              <div class="message_user" v-if="message.role === 'user'">
                
              </div>
              <div v-else class="message_avatar"> 
                <div class="avatar_icon">
                </div>
                <div class="avatar_name"> 
                  <div class="name_text">
                    deepseek-v4-pro
                    <span v-if="loading">正在思考中,请稍后<i class="el-icon-loading"></i></span>
                    <span v-else>回答完成</span>
                  </div>
                </div>
              </div>
              <div class="user_message_content" v-if="message.role === 'user'">
                <div class="content_user" >
                  {{message.content}}
                </div>
              </div>
              <div class="assistant_message_content" v-else>
                <div class="content_text"  v-html="FormatContent(message.content, message.role)"></div>
              </div>
            </div>
          </div>
      </div>
      <div class="page_jg_20"></div>
      <div class="main_ai_input">
        <el-input
          type="textarea"
          :rows="4"
          :maxlength="1000"
          placeholder="解读交给我，有问必答"
          v-model="inputContent"
          @keydown.native.enter="handleEnter"
          >
        </el-input>
        <div class="chat_model" >
          <i class="iconfont icon_deepseek"></i>
          deepseek-v4-pro
        </div>
        <div class="input_button" @click="StopMessage" v-if="loading" title="点击可停止思考">
          <i class="el-icon-loading"></i>
        </div>
        <div class="input_button" @click="SendMessage" v-else>
          <i class="iconfont icon_shangjiantou"></i>
        </div>
        <!-- <div class="file_button" @click="OpenMessage()">
          <i class="iconfont icon_folder_upload"></i>
        </div> -->
      </div>
      <div class="main_ai_message">
        内容由ai生成，仅供参考
      </div>
      <div class="page_jg_10"></div>
    </div>
</template>
<script>
import MarkdownIt from 'markdown-it';
export default {
  name: "AiRobot",
  components: {

  },
  props: {
    

   isShowQuickList:{
     type:Boolean,
     default:true
   },//默认显示快捷列表
    
    
  },
  data() {
    return {
      inputContent:'',//输入框
      chatHistory:[],//聊天历史记录
      loading:false,//加载动画
      apiKey:process.env.VUE_APP_DEEPSEEK_API_KEY || 'sk-85322fa189f24dd7aae324c5ff6a236a',// 从环境变量获取API密钥
      quickList:[
        {
          title:'分数段如何助力教学问题诊断?',
        },
        {
          title:'平均分波动背后，教学调整方向在哪?',
        },
        {
          title:'标准差在成绩分析里怎么用?能看出啥教学问题?',
        },
        {
          title:'怎样通过名次段洞察学生学习走势?',
        },
        {
          title:'等级分布在教学分层决策中的应用?',
        },
        {
          title:'借助得分率，怎样精准定位学生知识薄弱点?',
        },
        {
          title:'超均分指标，如何指导教学资源分配?',
        },
        {
          title:'运用难度指标，怎样科学把控教学深度?',
        },
        {
          title:'用n%名段，如何精准规划教学?',
        },
        {
          title:'信度指标能帮助我们排查教学中的哪些隐患?',
        },
        {
          title:'在教学质量评估中，标准差能为教师教学的精准度提供哪些数据?',
        },
        {
          title:'借助标准分，如何横向比较学生不同学科的学习表现?',
        },
        {
          title:'优秀率的波动能反映出教学在培养尖子生方面的哪些问题?',
        },
        {
          title:'历次平均分变化，能为教学调整提供哪些线索?',
        },
        {
          title:'历次标准分变化，对教学评价体系有何调整意义?',
        },
        {
          title:'区分度指标，怎样助力实现个性化教学?',
        },
        {
          title:'通过对比不同学科的 n% 名段，能发现学生学科学习的哪些不均衡问题?',
        },
        {
          title:'如何借助四分位盒须图分析成绩离散问题?',
        },
        {
          title:'通过分析历次标准分，怎样判断教学是否有效提升了学生在整体中的竞争力?',
        },
        {
          title:'从赋分等级分布能看出哪些教学问题？'
        }
      ],//快捷提问列表
      currentStreamingMessageIndex: 0,//当前正在流式传输的消息序号
      abortController: null,//用于取消请求的控制器
      isUserScrolling: false,//是否正在用户滚动页面

    };
  },
  watch: {
    
  },
  mounted()
  {

  },
  methods: 
  {
    //停止消息
    StopMessage()
    {
        // 取消当前正在进行的请求
        if (this.abortController) {
            this.abortController.abort();
            this.abortController = null;
        }
        
        // 结束流式传输消息
        this.finishStreamingMessage();
        
        // 停止加载状态
        this.loading = false;
        this.$emit('StopMessage');
        // 如果当前有正在流式传输的消息，将其标记为完成
        if (this.currentStreamingMessageIndex >= 0 && 
            this.currentStreamingMessageIndex < this.chatHistory.length) {
            this.$set(this.chatHistory[this.currentStreamingMessageIndex], 'isStreaming', false);
            this.currentStreamingMessageIndex = -1;
        }
    },

    //打开消息提醒
    OpenMessage()
    {
        this.$message({
          message: '上传文件功能暂未开放,敬请期待！',
          type: 'warning'
        });
    },
    // 发送消息
    async SendMessage()
    {
      // 确保 inputContent 是字符串类型
      const content = this.inputContent !== null && this.inputContent !== undefined ? 
        String(this.inputContent) : '';
      
      if (!content.trim()) 
      {
        this.$message({
          message: '您还未输入内容哦！',
          type: 'warning'
        });
        return;
      }
     
      
      const userMessage = this.inputContent.trim();
      this.addMessage('user', userMessage);
      this.inputContent = '';
      this.loading = true;
      
      try {
        const response = await this.callDeepSeekAPI(userMessage);
        const aiResponse = response.data.choices[0].message.content;

        console.log('AI 返回的消息:', aiResponse);
        this.addMessage('assistant', aiResponse);
      } catch (error) {
        console.error('API调用失败:', error);
        let errorMessage = '抱歉，AI助手暂时无法回答您的问题。';
        if (error.response) {
          switch (error.response.status) {
            case 401:
              errorMessage = 'API密钥无效，请检查配置。';
              break;
            case 429:
              errorMessage = '请求过于频繁，请稍后再试。';
              break;
            case 500:
              errorMessage = '服务器内部错误，请稍后再试。';
              break;
            default:
              errorMessage = `请求失败: ${error.response.data.message || '未知错误'}`;
          }
        }
        // this.addMessage('assistant', errorMessage);
      } finally {
        this.loading = false;
      }
    },

    // 设置输入框内容
    SetInputContent(content)
    {
      if(content)
      {
        this.inputContent = content;
        // 如果需要自动发送，可以调用发送方法
        this.SendMessage();
        this.inputContent = '';
      }
      
    },

    // 快捷提问
    quickAsk(question) {
      this.inputContent = question;
      this.SendMessage();
    },

    // 调用DeepSeek API(流式)
    async callDeepSeekAPI(message) {
      const apiUrl = 'https://api.deepseek.com/chat/completions';
      // 创建AbortController用于取消请求
      this.abortController = new AbortController();
      
      // 构建消息历史（只保留最近几条以控制token使用）
      const recentMessages = this.chatHistory.slice(-6); // 保留最近6轮对话
      const messages = [
        {
          role: "system", //用户角色信息
          content:"你是中学数学辅导老师，请针对下面的知识点，给中学生输出一份知识点解读。要求：1、语言通俗易懂，不要堆砌晦涩公式，适合学生预习复习看；2、结构分为三块：【是什么】：简单讲这个知识点到底在学什么，核心概念；【学了能干什么】：这个知识点考试用来解决什么类型题目；【注意易错点】：考试最容易踩坑、丢分的地方，2‑4条；3、输出简洁精炼，不要长篇大论，文本适合前端页面直接展示，不要markdown复杂格式，不要多余开场白；4、语气亲和，面向高中生，不要太学术晦涩。"
        },
        ...recentMessages
          .filter(msg => !msg.isStreaming) // 过滤掉仍在流式传输的消息
          .map(msg => ({
            role: msg.role,
            content: msg.content
          })),
        {
          role: "user",
          content: message
        }
      ];
      
      const payload = {
        model: "deepseek-v4-pro",//模型名称  deepseek-v4-pro 思考版   DeepSeek-V4-Flash-0731 不带思索版
        thinking: {
          type: "disabled"//如果设为 enabled，则使用思考模式。如果设为 disabled，则使用非思考模式
        },
        messages: messages,
        stream: true,// 是否为流式消息
      };

      // 添加AI助手的初始消息
      this.currentStreamingMessageIndex = this.chatHistory.length;
      this.addStreamingMessage('assistant', '');
      
      try {
        const response = await fetch(apiUrl, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${this.apiKey}`
          },
          body: JSON.stringify(payload),
          signal: this.abortController.signal // 添加信号用于取消请求
        });
        console.log('打印请求结果response', response);
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        const reader = response.body.getReader();
        const decoder = new TextDecoder('utf-8');
        let accumulatedContent = '';
        
        while (true) {
            // 检查是否已取消请求
            if (this.abortController.signal.aborted) {
                break;
            }
          const { done, value } = await reader.read();
          if (done) break;
          
          const chunk = decoder.decode(value, { stream: true });
          const lines = chunk.split('\n');
          
          for (const line of lines) {
            if (this.abortController.signal.aborted) {
                break;
            }
            if (line.startsWith('data: ')) {
              const data = line.slice(6);
              if (data === '[DONE]') {
                // 流式传输完成
                this.finishStreamingMessage();
                return;
              }
              
              try {
                const parsed = JSON.parse(data);
                const content = parsed.choices[0]?.delta?.content || '';
                if (content) {
                  accumulatedContent += content;
                  this.updateStreamingMessage(accumulatedContent);
                }
              } catch (e) {
                // 忽略解析错误
                console.warn('Failed to parse stream data:', e);
              }
            }
          }
        }
        
        this.finishStreamingMessage();
      } catch (error) {
        // 检查是否是因为取消请求导致的错误
        if (error.name === 'AbortError') {
            console.log('请求已被用户取消');
            this.finishStreamingMessage();
            return; // 不抛出错误，因为这是用户主动取消的
        }
        console.error('Stream error:', error);
        this.finishStreamingMessage();
        throw error;
      }
    },


    // 添加流式消息
    addStreamingMessage(role, content) {
      const now = new Date();
      const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
      
      this.chatHistory.push({
        role: role,
        content: content,
        time: timeString,
        isStreaming: true
      });
      
      this.scrollToBottom();
    },

    // 更新流式消息内容
    updateStreamingMessage(content) {
      if (this.currentStreamingMessageIndex >= 0 && 
          this.currentStreamingMessageIndex < this.chatHistory.length) {
        this.$set(this.chatHistory[this.currentStreamingMessageIndex], 'content', content);
        this.scrollToBottom();
      }
    },

    // 完成流式消息
    finishStreamingMessage() {
      if (this.currentStreamingMessageIndex >= 0 && 
          this.currentStreamingMessageIndex < this.chatHistory.length) {
        this.$set(this.chatHistory[this.currentStreamingMessageIndex], 'isStreaming', false);
        this.currentStreamingMessageIndex = -1;
      }
      // 完成后重置用户滚动状态
      this.isUserScrolling = false;
      this.scrollToBottom();
    },

    // 添加消息到历史记录
    addMessage(role, content) {
      const now = new Date();
      const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
      
      this.chatHistory.push({
        role: role,
        content: content,
        time: timeString
      });
      
      // 滚动到底部
      this.$nextTick(() => {
        const contentElement = document.querySelector('.main_ai_content');
        if (contentElement) {
          contentElement.scrollTop = contentElement.scrollHeight;
        }
      });
    },

    // 滚动到底部
    scrollToBottom() {
      this.$nextTick(() => {
        const contentElement = document.querySelector('.main_ai_content');
        if (contentElement) {
          // 只有在用户未手动滚动或已接近底部时才自动滚动
          const { scrollTop, scrollHeight, clientHeight } = contentElement;
          const isNearBottom = scrollHeight - scrollTop - clientHeight < 50; // 距离底部50px以内
          
          // 如果用户未手动滚动或者已经接近底部，则自动滚动
          if (!this.isUserScrolling || isNearBottom) {
            contentElement.scrollTop = scrollHeight; // 修正：使用scrollHeight而不是contentHeight
            this.isUserScrolling = false; // 重置滚动状态
          }
        }
      });
    },

    // 监听用户滚动事件
    handleUserScroll() {
      const contentElement = document.querySelector('.main_ai_content');
      if (contentElement) {
        const { scrollTop, scrollHeight, clientHeight } = contentElement;
        const isNearBottom = scrollHeight - scrollTop - clientHeight < 50;
        
        // 如果用户滚动到顶部附近，标记为用户正在滚动
        if (!isNearBottom) {
          this.isUserScrolling = true;
        } else {
          // 如果滚动到底部附近，取消用户滚动标记
          this.isUserScrolling = false;
        }
      }
    },

    // 格式化消息内容
    FormatContent(content, user) 
    {
       console.log("打印用户的消息",user);
        if (user === 'user') {
            // 用户消息只显示前100个字，超出部分用省略号替代
            console.log("打印用户的消息",content.length);
            if(content.length>100) 
            {
              return this.escapeHtml(content.substring(0, 100) + '...');
            }
            else
            {
              return this.escapeHtml(content);
            }
            
        }
         const md = new MarkdownIt({
            html: true,// 允许解析HTML标签，可以直接渲染HTML代码
            linkify: true,// 自动识别URL并将其转换为可点击的链接
            typographer: true,//启用语言替换和引号美化功能，如将引号转换为更美观的样式
        });
        return md.render(content);
    },




    // 转义HTML特殊字符
    escapeHtml(text) {
      const map = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#039;'
      };
      
      return text.replace(/[&<>"']/g, function(m) { return map[m]; });
    },


    // 处理回车键发送（任何情况下的回车都发送消息）
    handleEnter(event) {
        // 如果按住 Shift 键，则允许换行（不阻止默认行为）
        if (event.shiftKey) {
            return; // 允许默认的换行行为
        }
        
        // 如果没有按住 Shift 键，则发送消息
        event.preventDefault();
        this.SendMessage();
    }
  },
};
</script>
<style lang="scss" scoped>

</style>
