山东大学软件学院项目实训——创新实训——角色疆界(5)

前言

在之前的工作里,已经实现了前端界面的基本功能。接下来将试着添加一些辅助功能以提升界面的视觉体验,给用户给好的体验。下面是现在界面的样子:
在这里插入图片描述

一些辅助功能的实现

深浅色模式切换

通过以下的逻辑思路,可以实现在深色模式和浅色模式之间的切换,并且确保用户的主题偏好在刷新后能够被记忆和恢复:
1.更新组件的主题数据属性:

  • this.theme = theme;:将传入的 theme 参数(可以是 “light” 或 “dark”)赋值给组件的 theme 数据属性。

2.获取 HTML 根元素:

  • var html = document.getElementsByTagName(“html”)[0];:获取 HTML 文档的根元素 。

3.移除现有的主题类:

  • html.classList.remove(“light”, “dark”);:移除 HTML 根元素上可能存在的 light 和 dark 类,确保不会有多个主题类共存。

4.添加当前主题类:

  • html.classList.add(theme);:将传入的 theme 类(“light” 或 “dark”)添加到 HTML 根元素上,应用对应的主题样式。

5. 设置 color-scheme 属性:

  • html.style[“color-scheme”] = theme;:设置 HTML 元素的 color-scheme 属性为当前的主题,以便支持系统级的颜色方案。

6.保存主题到本地存储:

  • localStorage.setItem(“theme”, theme);:将当前的主题存储到浏览器的 localStorage 中,以便在用户重新访问页面时能够记住用户的主题偏好。
<a v-if="theme == 'light'" @click="changeTheme('dark')" class="flex py-3 px-3 items-center gap-3 rounded-md hover:bg-gray-500/10 transition-colors duration-200 text-white cursor-pointer text-sm">
  <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="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
  </svg>
  深色模式
</a>

<a v-if="theme == 'dark'" @click="changeTheme('light')" class="flex py-3 px-3 items-center gap-3 rounded-md hover:bg-gray-500/10 transition-colors duration-200 text-white cursor-pointer text-sm">
  <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">
    <circle cx="12" cy="12" r="5"></circle>
    <line x1="12" y1="1" x2="12" y2="3"></line>
    <line x1="12" y1="21" x2="12" y2="23"></line>
    <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
    <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
    <line x1="1" y1="12" x2="3" y2="12"></line>
    <line x1="21" y1="12" x2="23" y2="12"></line>
    <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
    <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
  </svg>
  浅色模式
</a>

changeTheme(theme) {                //修改页面风格
  this.theme = theme; // 更新组件的 theme 数据属性
  var html = document.getElementsByTagName("html")[0]; // 获取 HTML 根元素
  html.classList.remove("light", "dark"); // 移除 light 和 dark 类
  html.classList.add(theme); // 添加当前主题的类
  html.style["color-scheme"] = theme; // 设置 HTML 元素的 color-scheme 属性
  localStorage.setItem("theme", theme); // 将主题保存到 localStorage 中
},

代码高亮

大致逻辑思路如下:
1.引入库:

  • marked 用于解析 Markdown。
  • highlight.js 用于代码高亮。
  • highlight.js 的样式文件 github.css 被引入以应用代码高亮的样式。

2.自定义渲染器:

  • 创建了一个 renderer 对象,覆盖了 marked 默认的代码块渲染行为。

3.处理代码块

  • 在 renderer 对象的 code 方法中处理代码块。
    code 方法有三个参数:code(代码内容),infostring(代码语言),escaped(是否已转义)。

4.编码 HTML 内容

  • codeHtml = encodeURIComponent(code):对于 HTML 内容进行编码。

5.代码高亮

  • hljs.highlightAuto(code).value:使用 highlight.js 自动检测代码语言并应用高亮。
  • 如果 infostring 存在(表示代码块指定了语言),则对代码内容进行高亮处理。

6.生成 HTML:

  • 返回一个 HTML 字符串,包含一个容器 div和嵌套的 code 元素。
    代码容器具有一些 CSS 类,如 bg-black,mb-4,rounded-md 等,应用样式。
  • 在代码块顶部添加了一个按钮,用于复制代码内容。

7.使用 marked 渲染:

  • marked.use({ renderer }):告知 marked 使用自定义渲染器处理 Markdown。

引入库:

import { marked } from 'marked';
import hljs from 'highlight.js';
import 'highlight.js/styles/github.css'

自定义渲染器:

const renderer = {
  code(code, infostring, escaped) {
    var codeHtml = code;
    if (infostring && infostring == "html") {
      codeHtml = encodeURIComponent(code);
    }
    if (infostring) {
      codeHtml = hljs.highlightAuto(code).value;
    }

    console.log(code, infostring, escaped, codeHtml);

    return `<div class="bg-black mb-4 rounded-md">
      <div class="code_header flex items-center relative text-gray-200 bg-gray-800 px-4 py-2 text-xs font-sans">
        <span>${infostring || ""}</span>
        <button οnclick="copy(this)" 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>
          <span>Copy code</span>
          <code style="display:none">${encodeURIComponent(code)}</code>
        </button>
      </div>
      <div class="p-4 overflow-y-auto">
        <code class="!whitespace-pre hljs language-${infostring}">${codeHtml}</code>
      </div>
    </div>`;
  },
  paragraph(text) {
    return `<p style="white-space:pre-wrap;">${text}</p>`;
  }
};
marked.use({ renderer });

渲染:

export default {
  data() {
    return {
      markdownContent: `
        \`\`\`javascript
        console.log('Hello, world!');
        \`\`\`
      `
    };
  },
  computed: {
    renderedContent() {
      return marked(this.markdownContent);
    }
  },
  template: `
    <div v-html="renderedContent"></div>
  `
};

css部分:

.code_header {
  border-top-left-radius: 5px;
  border-top-right-radius: 5px;
}

.prose-r {
  font-size: 1rem;
  line-height: 1.75;
}

.hljs {
  display: block;
  overflow-x: auto;
  padding: 0.5em;
  background: #f0f0f0;
  color: #333;
}

.hljs-comment,
.hljs-quote {
  color: #8e908c;
  font-style: italic;
}

.hljs-keyword,
.hljs-selector-tag,
.hljs-subst {
  color: #c82829;
}

.hljs-literal,
.hljs-number,
.hljs-tag .hljs-attr {
  color: #f5871f;
}

.hljs-string,
.hljs-doctag {
  color: #718c00;
}

.hljs-title,
.hljs-section,
.hljs-selector-id {
  color: #4271ae;
}

.hljs-subst {
  font-weight: normal;
}

.hljs-type,
.hljs-class .hljs-title {
  color: #4271ae;
  font-weight: bold;
}

.hljs-tag,
.hljs-name,
.hljs-attribute {
  color: #c82829;
}

.hljs-regexp,
.hljs-link {
  color: #eab700;
}

.hljs-symbol,
.hljs-bullet {
  color: #f5871f;
}

.hljs-built_in,
.hljs-builtin-name {
  color: #f5871f;
}

.hljs-meta {
  color: #c82829;
}

.hljs-deletion {
  background: #ffdddd;
}

.hljs-addition {
  background: #ddffdd;
}

清空所有会话

大致逻辑思路如下:
1.clearConversations 方法:

  • 设置 this.conversations 为一个空数组,清空所有的会话记录。
  • 调用 saveConversations 方法,将空的会话列表保存到本地存储中。

2.saveConversations 方法

  • 深度复制当前的会话列表,避免直接修改原数据。
  • 遍历会话列表,删除每个会话的 editable、selected 和 delete 属性。
  • 将会话列表转换为 JSON 字符串,并保存到 localStorage 中。

3.清空对话记录的按钮:

  • 在模板中添加一个按钮,并绑定 clearConversations 方法。当用户点击按钮时,触发 clearConversations 方法,清空所有对话记录。
methods: {

  clearConversations() {
    this.conversations = []; // 清空会话列表
    this.saveConversations(); // 保存空的会话列表到本地存储
  },

  saveConversations() {
    var conversations = JSON.parse(JSON.stringify(this.conversations)); // 深度复制会话列表,避免直接修改原数据
    for (let idx in conversations) { // 遍历会话列表
      var conv = conversations[idx]; // 获取每个会话
      delete conv.editable; // 删除会话的编辑属性
      delete conv.selected; // 删除会话的选择属性
      delete conv.delete; // 删除会话的删除属性
    }
    let convs = JSON.stringify(conversations); // 将会话列表转换为 JSON 字符串
    localStorage.setItem("conversations", convs); // 将 JSON 字符串保存到本地存储中
  }
}

<a v-if="conversations.length > 0" @click.stop.prevent="clearConversations"
   class="flex py-3 px-3 items-center gap-3 rounded-md hover:bg-gray-500/10 transition-colors duration-200 text-white cursor-pointer text-sm">
  <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">
    <polyline points="3 6 5 6 21 6"></polyline>
    <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2">
    </path>
    <line x1="10" y1="11" x2="10" y2="17"></line>
    <line x1="14" y1="11" x2="14" y2="17"></line>
  </svg>
  清空所有会话
</a>

  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值