手把手教你!0 基础搭建 H5 AI 对话页面:渲染信息全攻略-基础版

在上一篇文章里,咱们热热闹闹地聊了 AI 产品的交互实现。今天,就继续带大家探索 Markdown 内容解析,以及超酷炫的可视化展示,这可都是开发 AI 对话页面的 "秘密武器"!

Markdown内容解析

在解析 Markdown 信息之前,得先唠唠 AI 交互时的思考过程。这部分内容得按原有格式展示,直接用<pre>标签就行。而处理 Markdown 信息,就得请出 MarkdownIt 这个 "得力助手" 啦!话不多说,上代码:

php 复制代码
import MarkdownIt from "markdown-it";
// import emoji from "markdown-it-emoji";
import deflist from "markdown-it-deflist";
import abbr from "markdown-it-abbr";
import footnote from "markdown-it-footnote";
import ins from "markdown-it-ins";
import mark from "markdown-it-mark";
import taskLists from "markdown-it-task-lists";
import container from "markdown-it-container";
import toc from "markdown-it-toc-done-right";
// import mermaid from "@DatatracCorporation/markdown-it-mermaid";
import MarkdownItAnchor from "markdown-it-anchor";

export const useMarkDown = () => {
    var config = {
        html: true,
        xhtmlOut: true,
        breaks: true,
        langPrefix: "lang-",
        linkify: false,
        typographer: true,
        quotes: """''",
    };
    let markdownIt = new MarkdownIt(config);
    markdownIt.renderer.rules.hr = function () {
        return '';
    };

    // 自定义表格开始标签的渲染规则
    markdownIt.renderer.rules.table_open = function (tokens, idx, options, env, self) {
        // 在表格开始标签前添加带有指定 class 的 div 开始标签
        let result = '<div class="custom-table-wrapper">';
        result += '<table';
        if (tokens[idx].attrPush) {
            tokens[idx].attrPush(['class', 'custom-table']);
        }
        result += self.renderAttrs(tokens[idx]);
        result += '>';
        return result;
    };

    // 自定义表格结束标签的渲染规则
    markdownIt.renderer.rules.table_close = function (tokens, idx, options, env, self) {
        let result = '</table>';
        // 在表格结束标签后添加 div 结束标签
        result += '</div>';
        return result;
    };

    // 自定义 th 开始标签的渲染规则
    markdownIt.renderer.rules.th_open = function (tokens, idx, options, env, self) {
        return '<th><div class="custom-cell-wrapper">';
    };

    // 自定义 th 结束标签的渲染规则
    markdownIt.renderer.rules.th_close = function (tokens, idx, options, env, self) {
        return '</div></th>';
    };

    // 自定义 td 开始标签的渲染规则
    markdownIt.renderer.rules.td_open = function (tokens, idx, options, env, self) {
        return '<td><div class="custom-cell-wrapper">';
    };

    // 自定义 td 结束标签的渲染规则
    markdownIt.renderer.rules.td_close = function (tokens, idx, options, env, self) {
        return '</div></td>';
    };
    markdownIt
        // .use(emoji)
        .use(deflist)
        .use(abbr)
        .use(MarkdownItAnchor)
        .use(footnote)
        .use(ins)
        .use(mark)
        .use(taskLists)
        .use(container)
        .use(container, "hljs-left")
        .use(container, "hljs-center")
        .use(container, "hljs-right")
        .use(toc)
    // .use(mermaid);

    return {
        markdownIt
    }
}

MarkdownIt 的时候,你完全可以根据自己的想法,通过markdownIt.renderer.rules对某些标签进行 "改造",让它更贴合你的需求!

可视化内容解析

和 Markdown 内容相比,可视化内容的处理就简单多啦!直接有请 echarts 这个 "可视化小能手" 闪亮登场!代码如下

javascript 复制代码
/*
 * @Author: Robin LEI
 * @Date: 2025-03-24 09:06:17
 * @LastEditTime: 2025-04-03 11:38:59
 * @FilePath: \uniapp\插件模板\前端页面模板\uniapp-ai-mobile\src\utils\echart.ts
 */
import * as echarts from 'echarts/core';
import {
    BarChart,
    LineChart,
    PieChart
} from 'echarts/charts';
import {
    TitleComponent,
    TooltipComponent,
    GridComponent,
    // 数据集组件
    DatasetComponent,
    // 内置数据转换器组件 (filter, sort)
    TransformComponent,
    ToolboxComponent,
    DataZoomComponent
     
} from 'echarts/components';
import { LabelLayout, UniversalTransition } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers';

// 注册必须的组件
echarts.use([
    TitleComponent,
    TooltipComponent,
    GridComponent,
    DatasetComponent,
    TransformComponent,
    BarChart,
    LineChart,
    PieChart,
    LabelLayout,
    UniversalTransition,
    CanvasRenderer,
    ToolboxComponent,
    DataZoomComponent
]);
export default echarts;
yaml 复制代码
const initChartFunc = (content: any, domName: string, chatType: string = "bar") => {
    let chartDom: any = document.querySelector(`#${domName}`);
    if (chartDom) {
        const chart = echarts.init(chartDom);
        arrDom.push(chart);
        const xAxisKey = content?.visualization?.data?.xAxis[0];
        const yAxisKey = content?.visualization?.data?.yAxis[0];
        let option = {};
        if (chatType === "line" || chatType === "bar") {
            let xAxisData: any = [];
            let yAxisData: any = [];
            content?.sqlData.data.forEach((item) => {
                xAxisData.push(item[xAxisKey]);
                yAxisData.push(initNumFunc(item[yAxisKey]));
            });
            option = {
                title: {
                    text: "",
                },
                tooltip: {
                    trigger: "axis",
                    formatter: "{b0}: {c0}",
                },
                toolbox: {
                    show: false,
                },
                grid: {
                    left: "12%",
                },
                xAxis: {
                    nameTextStyle: {
                        fontSize: 14,
                        color: "#999",
                    },
                    type: "category",
                    data: xAxisData,
                    show: true,
                    name: xAxisKey,
                    nameLocation: "middle",
                    nameGap: 30,
                    axisLabel: {
                        fontSize: 14,
                        color: "#999",
                    },
                },
                yAxis: {
                    show: true,
                    nameTextStyle: {
                        fontSize: 14,
                        color: "#999",
                    },
                    type: "value",
                    name: yAxisKey,
                    axisTick: {
                        inside: true,
                    },
                    scale: true,
                    axisLabel: {
                        fontSize: 14,
                        color: "#999",
                        formatter: function (value, index) {
                            if (value >= 10000 && value < 10000000) {
                                value = value / 10000 + "万";
                            } else if (value >= 10000000) {
                                value = value / 10000000 + "千万";
                            }
                            return value;
                        },
                    },
                },
                series: [
                    {
                        data: yAxisData,
                        type: chatType,
                        itemStyle: {
                            color: {
                                type: "linear",
                                x: 0,
                                y: 0,
                                x2: 0,
                                y2: 1,
                                colorStops: [
                                    {
                                        offset: 0,
                                        color: "rgb(158,144,255)", // 0% 处的颜色
                                    },
                                    {
                                        offset: 1,
                                        color: "rgb(136,85,255)", // 100% 处的颜色
                                    },
                                ],
                                global: false, // 缺省为 false
                            },
                        },
                    },
                ],
                dataZoom: {
                    start: 0,
                    end: 100, // 初始显示范围的结束百分比
                    type: "inside",
                    zoomLock: false,
                },
            };
        } else {
            const seriesData = content?.sqlData.data.map((item) => {
                return {
                    name: item[xAxisKey],
                    value: initNumFunc(item[yAxisKey]),
                };
            });
            option = {
                title: {
                    text: "",
                },
                tooltip: {
                    trigger: "item",
                },
                toolbox: {
                    show: true,
                },
                xAxis: {
                    show: false,
                },
                yAxis: {
                    show: false,
                },
                label: {
                    formatter: "{b}\n{c}",
                    lineHeight: 15,
                    fontSize: 14,
                    color: "#999",
                },
                series: [
                    {
                        type: "pie",
                        radius: "50%",
                        data: seriesData,
                    },
                ],
            };
        }
        chart.setOption(option);
    }
};

到这儿,一个超基础的 AI 对话交互内容渲染就大功告成啦!要是你觉得这些代码超有趣,想实际跑一跑,直接从 GitHub 上下载代码就行:github.com/xknk/uniapp... 。要是觉得这个项目还挺不错,别忘了给个 Star,这对我来说可是超级大的鼓励!希望这篇文章能成为你开发 AI 对话页面的 "神助攻",也欢迎各位技术大佬在评论区畅所欲言,一起交流讨论!

相关推荐
天天向上102412 分钟前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js
芬兰y28 分钟前
VUE 带有搜索功能的穿梭框(简单demo)
前端·javascript·vue.js
好果不榨汁34 分钟前
qiankun 路由选择不同模式如何书写不同的配置
前端·vue.js
小蜜蜂dry34 分钟前
Fetch 笔记
前端·javascript
拾光拾趣录36 分钟前
列表分页中的快速翻页竞态问题
前端·javascript
小old弟36 分钟前
vue3,你看setup设计详解,也是个人才
前端
Lefan41 分钟前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson1 小时前
青苔漫染待客迟
前端·设计模式·架构
写不出来就跑路1 小时前
基于 Vue 3 的智能聊天界面实现:从 UI 到流式响应全解析
前端·vue.js·ui
OpenTiny社区1 小时前
盘点字体性能优化方案
前端·javascript