手把手教你!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 对话页面的 "神助攻",也欢迎各位技术大佬在评论区畅所欲言,一起交流讨论!

相关推荐
snow@li几秒前
前端:开源软件镜像站 / 清华大学开源软件镜像站 / 阿里云 / 网易 / 搜狐
前端·开源软件镜像站
小小小小宇28 分钟前
配置 Gemini Code Assist 插件
前端
one 大白(●—●)40 分钟前
前端用用jsonp的方式解决跨域问题
前端·jsonp跨域
刺客-Andy43 分钟前
前端加密方式 AES对称加密 RSA非对称加密 以及 MD5哈希算法详解
前端·javascript·算法·哈希算法
前端开发张小七1 小时前
13.Python Socket服务端开发指南
前端·python
前端开发张小七1 小时前
14.Python Socket客户端开发指南
前端·python
ElasticPDF-新国产PDF编辑器1 小时前
Vue 项目 PDF 批注插件库在线版 API 示例教程
前端·vue.js·pdf
拉不动的猪1 小时前
react基础2
前端·javascript·面试
kovlistudio2 小时前
红宝书第二十九讲:详解编辑器和IDE:VS Code与WebStorm
开发语言·前端·javascript·ide·学习·编辑器·webstorm
拉不动的猪2 小时前
react基础1
前端·javascript·面试