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

相关推荐
树叶会结冰4 分钟前
HTML语义化:当网页会说话
前端·html
冰万森10 分钟前
解决 React 项目初始化(npx create-react-app)速度慢的 7 个实用方案
前端·react.js·前端框架
牧羊人_myr23 分钟前
Ajax 技术详解
前端
浩男孩32 分钟前
🍀封装个 Button 组件,使用 vitest 来测试一下
前端
蓝银草同学36 分钟前
阿里 Iconfont 项目丢失?手把手教你将已引用的 SVG 图标下载到本地
前端·icon
布列瑟农的星空1 小时前
重学React —— React事件机制 vs 浏览器事件机制
前端
程序定小飞1 小时前
基于springboot的在线商城系统设计与开发
java·数据库·vue.js·spring boot·后端
一小池勺1 小时前
CommonJS
前端·面试
孙牛牛1 小时前
实战分享:一招解决嵌套依赖版本失控问题,以 undici 为例
前端