更新记录

1.0.0(2025-04-01) 下载此版本

首次发布,支持uniapp(vue2,vue3)


平台兼容性

Vue2 Vue3
App 快应用 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
app-vue × × × × ×
钉钉小程序 快手小程序 飞书小程序 京东小程序 鸿蒙元服务
× × × × ×
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari
× × × × ×

基于lime-painter的富文本解析器(typescript)

支持Uniapp Vue3,如果想用Vue2也是可行的(需要改变语法格式) ,可能还有些缺陷 您也可以修改源码进行改动

请将下载的压缩包文件解压以后 放入您自己的文件夹 注意导入路径

基于原作者:陌上华年 lime-painter,开发的扩展插件;使用前请先下载 lime-painter

<template>
    <view style="padding: 8px;">
        <l-painter :board="poster" ref="painter" />
    </view>
</template>

<script lang="ts" setup>
    import { ref, nextTick, onMounted } from 'vue';
    import LPainter from '@/uni_modules/lime-painter/components/l-painter/l-painter';

    import HtmlParser from "@/libs/htmlPrase";
    // import { objectToString } from "@/fun/style";

    const painter = ref<InstanceType<typeof LPainter> | null>(null);

    // const style = {
    //  shareImg: objectToString({
    //      objectFit: 'cover',
    //      objectPosition: '50% 50%',
    //      width: '750rpx',
    //      height: '1200rpx',
    //      borderRadius: '12rpx',
    //  }),
    //  logo: objectToString({
    //      width: '200rpx',
    //      height: '200rpx',
    //      zIndex: 10,
    //      position: 'absolute',
    //  }),
    //  user: objectToString({
    //      display: 'flex',
    //      alignItems: 'center',
    //      justifyContent: 'space-between',
    //      backgroundColor: '#F9FCFF',
    //      padding: '20rpx 32rpx',
    //      borderRadius: '40rpx 40rpx 0 0',
    //      position: 'fixed',
    //      bottom: '0',
    //  }),
    // };

    const htmlContent = `
      <img src="https://ljx-1301875625.cos.ap-shanghai.myqcloud.com/gxfangchan/static/index/logo.png" style="width:200rpx;height:200rpx;z-index:10;position:absolute" />
      <img src="https://ljx-1301875625.cos.ap-shanghai.myqcloud.com/gxfangchan/202503/29_174321117967e74aab66586.png" style="object-fit:cover;object-position:50% 50%;width:750rpx;height:1200rpx;border-radius:12rpx" />
       <div style="display:flex;align-items:center;justify-content:space-between;background-color:#F9FCFF;padding:20rpx 32rpx;border-radius:40rpx 40rpx 0 0;position:fixed;bottom:0">
         <div style="display:flex;align-items:center;">
            <img src="https://ljx-1301875625.cos.ap-shanghai.myqcloud.com/gxfangchan/202503/13_174186170967d2b34dbca24.png" style="width:160rpx;height:160rpx;border-radius:50%" />
            <div style="margin-left:20rpx;">
              <div style="font-size:32rpx;font-weight:bold">昵称</div>
              <div style="font-size:24rpx;color:#FF5310;margin-top:10rpx">邀请用户成为我的客户</div>
            </div>
         </div>
         <img src="https://ljx-1301875625.cos.ap-shanghai.myqcloud.com/gxfangchan/202503/29_174321640667e75f166de46.png" style="width:120rpx;height:120rpx;border-radius:50%" />
       </div>
    `;

    // 海报数据
    const poster = ref({
        css: {
            backgroundColor: "#ffffff",
        },
        views: []
    });

    // 解析html
    const jsonResult = new HtmlParser().parseHtmlToJson(htmlContent);

    poster.value.views = jsonResult;

    // 生成图片
    const handleTask = () => {
        painter.value.canvasToTempFilePathSync({
            fileType: "jpg",
            // 如果返回的是base64是无法使用 saveImageToPhotosAlbum,需要设置 pathType为url
            pathType: 'url',
            quality: 1,
            success: (res) => {
                console.log(res.tempFilePath);
                // 非H5 保存到相册
                uni.saveImageToPhotosAlbum({
                    filePath: res.tempFilePath,
                    success: function () {
                        console.log('save success');
                    }
                });
            },
        });
    };
</script>

<style></style>

关于objectToString函数,这是将对象转为字符串的函数

/**
 * 获取一个值的类型字符串。
 * @param value 要检测的值。
 * @returns 返回值的类型。
 */
export const getType = (value : any) : string => {
    const temp = Object.prototype.toString.call(value);
    const type = temp.replace(/\[/g, "").replace(/\]/g, "");
    const index = type.lastIndexOf(" ");
    const str = type.substring(index + 1, type.length);
    return str;
};

/**
 * 驼峰转小写-连接
 * @param {string} str 需要转换的字符串
 * @param {string} mark 转换符号,默认为 "-"
 * @return {string} 转换后的字符串
 * @example toLine('borderRadius')  // 返回 border-radius
 */
export const toLine = (str: string = "", mark: string = "-"): string => {
  return str.replace(/([A-Z])/g, `${mark}$1`).toLowerCase();
};

/**
 * 去掉字符串的空格
 * @param {string} str 需要处理的字符串
 * @param {string} pos 去除空格的位置:both: 左右两边空格,left: 左边空格,right: 右边空格,all: 所有空格
 * @return {string} 返回去除空格后的字符串
 */
export const trim = (str: string, pos: string = "both"): string => {
  str = String(isEffective(str) ? str : "");
  switch (pos) {
    case "both":
      return str.trim();
    case "left":
      return str.replace(/^\s*/, "");
    case "right":
      return str.replace(/(\s*$)/g, "");
    case "all":
      return str.replace(/\s+/g, "");
    default:
      return str;
  }
};

/**
 * object 转 css 字符串
 * @param styleList 样式对象或字符串数组
 * @return {string} 返回字符串 style,兼容其它端
 * @example objectToString('width:10rpx', { height: '20rpx', zIndex: 2 }, 'border:2rpx')
 * @returns 'width:10rpx;height:20rpx;z-index:2;border:2rpx'
 */
export const objectToString = (...styleList : (string | Record<string, string | number>)[]) : string => {
    const styleObj : Record<string, string> = {};

    const addStyle = (name : string, value : string | number) => {
        name = trim(name);
        if (['String', 'Number'].includes(getType(value))) {
            value = trim(String(value));
            if (name && value) {
                styleObj[toLine(name)] = value;
            }
        }
    };

    styleList.forEach((style) => {
        const type = getType(style);
        if (type === 'String' && style) {
            const trimmedStyle = trim(style as string);
            if (trimmedStyle) {
                trimmedStyle
                    .replace(/^;+|;+$/, '')
                    .split(/;+/)
                    .map((str) => str.split(/:+/))
                    .forEach(([k, value]) => addStyle(k, value));
            }
        } else if (type === 'Object') {
            Object.entries(style as Record<string, string | number>).forEach(([k, v]) => addStyle(k, v));
        }
    });

    return Object.entries(styleObj)
        .map(([k, v]) => `${k}:${v}`)
        .join(';');
};

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问