gpt问答页面简单开发记录

一、准备工作

  1. 前端页面采用tailwind.css html 进行开发
  2. 还有代码块高亮的jshighlight.js
  3. 由于后端返回的是流,文本包含有反斜线等,我们需要使用marked.js进行处理

二、实现过程

首先是后端返回的流

code 请求的核心片段如下:

 if (window.EventSource) {
        const eventsource = new EventSource(`http://192.168.80/80/openai/openai/chat/sse?id=${uuid}&key=${apikey}&prompt=${pro}`)
        //建立连接
        let test = ''
        eventsource.onopen = function (evt) {
          console.log("server connect successed");
        };
        eventsource.onmessage = function (e) {
          let aiMessage = JSON.parse(e.data)
          console.info("server connect ai", aiMessage);
        };
        //发送错误,结束
        eventsource.onerror = function (evt) {
          console.log("服务器内部错误");
         //关闭流
          eventsource.close();
        };
      } else {
        alert("浏览器不支持!请更换或者升级浏览器版本")
      }

code 模拟请求的数据结构如下:

let arr = [
        { content: "简" },
        { content: "单" },
        { content: "的" },
        { content: "for" },
        { content: "循" },
        { content: "环" },
        { content: "的" },
        { content: "示" },
        { content: "例" },
        { content: ":\n\n" },
        { content: "``" },
        { content: "`\n" },
        { content: "for" },
        { content: "(int" },
        { content: " i" },

        { content: "=" },

        { content: "0" },

        { content: ";" },

        { content: " i" },

        { content: "<" },

        { content: "10" },

        { content: ";" },

        { content: " i" },

        { content: "++)" },

        { content: " {\n" },

        { content: "  " },

        { content: " System" },

        { content: ".out" },

        { content: ".println" },

        { content: "(i" },

        { content: ");\n" },

        { content: "}\n" },

        { content: "``" },

        { content: "`\n\n" },

        { content: "这" },

        { content: "个" },

        { content: "循" },

        { content: "环" },

        { content: "会" },

        { content: "从" },

        { content: "0" },

        { content: "开始" },

        { content: "," },

        { content: "每" },

        { content: "次" },

        { content: "增" },

        { content: "加" },

        { content: "1" },

        { content: "," },

        { content: "一" },

        { content: "直" },

        { content: "循" },

        { content: "环" },

        { content: "到" },

        { content: "i" },

        { content: "的" },

        { content: "值" },

        { content: "等" },

        { content: "于" },

        { content: "10" },

        { content: "为" },

        { content: "止" },

        { content: "。" },

        { content: "在" },

        { content: "每" },

        { content: "次" },

        { content: "循" },

        { content: "环" },

        { content: "中" },{ content: "," },
{ content: "会" },{ content: "输出" },{ content: "当前" },{ content: "的" },{ content: "i" },{ content: "的" },{ content: "值" },{ content: "。\n\n" },{ content: "如果" }, { content: "需要" },{ content: "环" },{ content: "的" },{ content: "次" },{ content: "数" },{ content: "已" }, { content: "知" },{ content: "," },{ content: "那" },{ content: "么" },{ content: "可以" },{ content: "使用" },{ content: "for" },{ content: "循" },{ content: "环" },{ content: "。" }, { content: "如果" },{ content: "循" },{ content: "环" },{ content: "次" },{ content: "数" },{ content: "未" },{ content: "知" },{ content: ",则" },{ content: "应" }, { content: "该" },{ content: "使用" },{ content: "while" },{ content: "循" }, { content: "环" }, { content: "。" },

      ];

重点:

首先要明白这个hightlight.js高亮的是哪部分?hightlight.js对<pre><code></code></pre> 里面code包裹的代码进行高亮
问题一 :在实现的过程中我们需要对代码片段实现一个黑色背景,并且实现自己的样式,效果如下图2-1所示,问题就是怎么将系统marked.js
渲染的代码片段pre code中间加入自己的代码片段如下code-1,那么我们在hightlight.js里面预设将我们的这个代码片段加入进去呢?如代码code-2片段所示
我们使用自定义的函数给它识别到code的时候自动加上代码片段。

<div class="bg-black rounded-md mb-4">
<div class="flex items-center relative text-gray-200 bg-gray-800 px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span>Java</span>
<button class="flex ml-auto gap-2"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>复制代码</button></div>
<div class="p-4 overflow-y-auto">
<code class="!whitespace-pre hljs language-java">
	//这里简单的代码示例
	for (var i = 0; i < 10; i++)...
</code>
</div>
</div>
																					code-1

![[Pasted image 20230606095924.png]]
2-1

	<script>

    hljs.initHighlightingOnLoad();

    // 设置marked

    marked.marked.setOptions({

      renderer: new marked.Renderer(),

      highlight: function (code, language) {

        const validLang = !!(language && hljs.getLanguage(language))

        console.log(language);

        if (validLang) {

          const lang = language ?? ''

          return highlightBlock(hljs.highlight(code, { language: lang }).value, lang)

        }
        return highlightBlock(hljs.highlightAuto(code).value, '')

      },

      pedantic: false,

      gfm: true,

      tables: true,

      breaks: false,

      sanitize: false,

      smartLists: true,

      smartypants: false,

      xhtml: false,

    });	
																		code-2	
//下面的return 后面的代码一定不能换行或者格式化,保持在一行,不然marked.js会将这些空格识别出来,改变里面的样式
function highlightBlock(str, lang) {
	return `<div class="bg-black rounded-md mb-4"><div class="flex items-center relative text-gray-200 bg-gray-800 px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span>${lang}</span><button class="flex ml-auto gap-2"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button></div><div class="p-4 overflow-y-auto"><code class="!whitespace-pre hljs language-java">${str}</code></div></div>`

    }

																	code-3

问题梳理

— 上面的渲染完成了,接下来遇到的效果是,输入框使用的textarea,里面输入的时候自动撑开,然后使用backspace进行删除,然后不满足的行数就是自动缩小。

问题一:textarea 随着内容高度自动撑开

通过js检测文本的高度,然后动态设置文本框的高度。核心设置row=1,就会出现滚动条,然后获取scrollTop获取文本的高度,动态进行设置高度
html代码片段

              <textarea id="prompt-textarea" oninput="getInput()" tabindex="0" data-id="root" rows="1"

                onfocus="getFocus()" placeholder="Send a message..."

                class="m-0 w-full resize-none border-0 bg-transparent p-0 pr-7 focus:ring-0 focus-visible:ring-0 dark:bg-transparent pl-2 md:pl-0"

                style=" overflow-y: hidden; outline: none;"></textarea>

js代码片段

 $("#prompt-textarea").css("height", $("#prompt-textarea")[0].scrollHeight + "px");

问题二:textarea内容高度撑开了,文本高度减少了,但是textarea高度不会降低

 $("#prompt-textarea").css("height", "auto");
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值