/** * ChatGPT工具 * @author zhaoxianlie */ import AI from './fh.ai.js'; new Vue({ el: '#pageContainer', data: { prompt: '', demos: [ 'FeHelper是什么?怎么安装?', '用Js写一个冒泡排序的Demo', 'Js里的Fetch API是怎么用的' ], initMessage: { id:'id-test123', sendTime:'2022/12/20 12:12:12', message: '你好,可以告诉我你是谁吗?我该怎么和你沟通?', respTime: '2022/12/20 12:12:13', respContent: '你好,我是FeHelper智能助理,由OpenAI提供技术支持;你可以在下面的输入框向我提问,我会尽可能回答你~~~' }, respResult:{ id: '', sendTime:'', message:'', respTime:'', respContent:'' }, history:[], tempId:'', hideDemo: false, undergoing: false }, mounted: function () { this.$refs.prompt.focus(); this.hideDemo = !!(new URL(location.href)).searchParams.get('hideDemo'); }, methods: { // 这个代码,主要用来判断大模型返回的内容是不是包含完整的代码块 validateCodeBlocks(content) { let backticksCount = 0; let inCodeBlock = false; let codeBlockStartIndex = -1; for (let i = 0; i < content.length; i++) { // 检查当前位置是否是三个连续的反引号 if (content.startsWith('```', i)) { backticksCount++; i += 2; // 跳过接下来的两个字符,因为它们也是反引号的一部分 // 如果我们遇到了奇数个反引号序列,那么我们进入了代码块 if (backticksCount % 2 !== 0) { inCodeBlock = true; codeBlockStartIndex = i - 2; } else { // 否则,我们离开了代码块 inCodeBlock = false; if (codeBlockStartIndex === -1 || codeBlockStartIndex > i) { return false; // 这意味着有不匹配的反引号 } codeBlockStartIndex = -1; } } } // 如果最终 backticksCount 是偶数,则所有代码块都正确关闭 return backticksCount % 2 === 0 && !inCodeBlock; }, sendMessage(prompt){ if(this.undergoing) return; if(this.respResult.id){ this.history.push(this.respResult); this.respResult.id = ''; } this.undergoing = true; let sendTime = (new Date()).format('yyyy/MM/dd HH:mm:ss'); this.$nextTick(() => { this.scrollToBottom(); }); this.tempId = ''; let respContent = ''; AI.askYiLarge(prompt,(respJson,done) => { if(done){ this.undergoing = false; return; } let id = respJson.id; respContent = respJson.content || ''; if(!this.validateCodeBlocks(respContent)) { respContent += '\n```'; } respContent = marked(respContent); if(this.tempId !== id) { this.tempId = id; let dateTime = new Date(respJson.created * 1000); let respTime = dateTime.format('yyyy/MM/dd HH:mm:ss'); this.respResult = { id,sendTime,message:prompt,respTime,respContent }; }else{ this.respResult.respContent = respContent; } this.$nextTick(() => { let elm = document.getElementById(id); elm.querySelectorAll('pre code').forEach((block) => { hljs.highlightBlock(block); }); this.scrollToBottom(); }); }); }, scrollToBottom(){ this.$refs.boxResult.scrollTop = this.$refs.boxResult.scrollHeight; }, goChat(){ this.sendMessage(this.prompt); this.$nextTick(() => this.prompt=''); } } });