后台/业务/微信链接转成app站内链接

137 阅读2分钟

背景

运营人员通常会在公众号发布一些文章,同样的文章内容也需要发布到app站内,但是如果直接使用微信链接会出现几个问题。

  1. 图片链接问题,图片用的是微信的,有可能会把图片给删除。
  2. 微信链接会携带微信app专属内容,比如二维码、关注等。

目标

研发人员在运营后台的的页面上开发一个功能,通过抓取微信链接的主要内容,将图片链接变成app站内的,删除微信app专属内容。

调研

通过调研发现,微信公众号的文章链接的主要内容全部写在一个id为js_contentdiv里面,微信app的专属内容则是写在其他div元素,而且它的css样式也是内联的形式存在。

也就是说:研发同学只需要拿到id为js_content的div所有元素内容,以及将里面的图片资源转换成app站内资源即可!

如何获取制定id的div元素内容与图片?

通过服务端的接口,我们可以获取到微信链接的html字符串内容。那么方便获取我们想要的元素。 使用DOMParser

它支持将htmlStr转换成dom元素。

通过wangEditor实现链接内容的二次更改

当我们转换完毕之后,除了需要显示链接内容,还要支持二次修改。更关键的是,研发同学可以通过wangEditor在浏览器开发者模式下直接修改代码。

页面展示优化

为了h5能够快速展示文章内容,将图片的src以data-src存储,待contenload事件后再下载图片。

实现方案

graph TD
a[ 输入url ]-.通过接口获取htmlStr.->c[ ]
c[ htmlStr ] -.使用DomParser将htmlStr转换成HTMLDom元素.-> d[ ]
d[ HTMLDom ] -.调用其方法getElementById获取id为js_conten的DivEle.-> e[ ]
e[ DivEle ] -.调用其方法querySelectorAll获取所有的图片元素imgEles.-> f[ ]
f[ 遍历imgEles ] -.1 获取data-src并上传图片.-> g[  ]
f[ 遍历imgEles ] -.2 将回传的url赋值到data-src上.-> g[  ]
f[ 遍历imgEles ] -.3 将src赋值成默认值base64方便优化.-> g[  ]
g[ imgEles ] -.将HTMLDom转换成html上传.-> h[  ]
h[ 创建outHtmlStr ] -.编写outHtmlStr,编写函数方法来懒加载图片.-> i[  ]
i[ 组合h5_content ] -.将DivEle转成str注入到outHtmlStr形成h5_content.-> j[ 上传 ]

遇到的问题

图片上传问题

图片url转blob

转化后元素不显示

查看源码后发现微信网页给js_conntent元素设置了style='visibility: hidden';

字符串scrpit问题

在组合htmlStr中,vue编译层不支持写<scrpts></scripts>,需要通过添加子节点的形式导入。

let Dom = new DOMParser().parseFromString(outHtmlStr, "text/html");
let htmlEle = Dom.getElementsByTagName("html")[0];
let scriptEle = Dom.createElement("script");
scriptEle.innerHtml = 'console.log(1)'
htmlEle.appendChild(scriptEle);
console.log(htmlEle.outerHTML);

图片回显异常问题

如果只是单单转化图片的src,在实际浏览过程中会发现图片的尺寸有的过大问题。这是因为微信h5有js代码处理了图片的显示问题,而我们并没有js代码处理。

处理方法:给组合的html添加一个函数方法,遍历所有的图片,将当前屏幕的可视宽度innerWidth与图片绑定的data-w的值进行比较,

如果innerWidth > data-w,则将图片的style设置为width:data-w,

如果innerWidth <= data-w,则将图片的style设置为width:100%,

(function () {
var imgs = document.getElementsByTagName('img')
function lazyLoad(imgs) {
    var h = window.innerHeight;
    var w = window.innerWidth;
    var s = document.documentElement.scrollTop || document.body.scrollTop;
    for (let i = 0; i < imgs.length; i++) {
        // 如果图片距离顶部的距离 小于 滚动区域与可视区域之和时,加载图片
        if ((h + s) > imgs[i].offsetTop) {
            // 替换真实图片
            if (!imgs[i].src) {
                let imgW = imgs[i].getAttribute('data-w')
                const style = imgW > w ? 'width:100%' : 'width:'+imgW+'px'
                imgs[i].setAttribute('style',style);
                imgs[i].src = imgs[i].getAttribute('data-src')
            }
        }
    }
}
lazyLoad(imgs);
// 监听页面滚动
window.onscroll = function () {
    lazyLoad(imgs)
}
})()