From d1448cb0ef10f358bb7bddb4e1ec268515e0b787 Mon Sep 17 00:00:00 2001 From: gaoluyang <2820782392@qq.com> Date: 星期二, 15 七月 2025 11:46:57 +0800 Subject: [PATCH] 项目初始化 --- uni_modules/uview-ui/components/u-parse/u-parse.vue | 366 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 366 insertions(+), 0 deletions(-) diff --git a/uni_modules/uview-ui/components/u-parse/u-parse.vue b/uni_modules/uview-ui/components/u-parse/u-parse.vue new file mode 100644 index 0000000..7bc8b3d --- /dev/null +++ b/uni_modules/uview-ui/components/u-parse/u-parse.vue @@ -0,0 +1,366 @@ +<template> + <view id="_root" :class="(selectable?'_select ':'')+'_root'"> + <slot v-if="!nodes[0]" /> + <!-- #ifndef APP-PLUS-NVUE --> + <node v-else :childs="nodes" :opts="[lazyLoad,loadingImg,errorImg,showImgMenu]" /> + <!-- #endif --> + <!-- #ifdef APP-PLUS-NVUE --> + <web-view ref="web" src="/static/app-plus/mp-html/local.html" :style="'margin-top:-2px;height:' + height + 'px'" @onPostMessage="_onMessage" /> + <!-- #endif --> + </view> +</template> + +<script> + import props from './props.js'; +/** + * mp-html v2.0.4 + * @description 瀵屾枃鏈粍浠� + * @tutorial https://github.com/jin-yufeng/mp-html + * @property {String} bgColor 鑳屾櫙棰滆壊锛屽彧閫傜敤涓嶢PP-PLUS-NVUE + * @property {String} content 鐢ㄤ簬娓叉煋鐨勫瘜鏂囨湰瀛楃涓诧紙榛樿 true 锛� + * @property {Boolean} copyLink 鏄惁鍏佽澶栭儴閾炬帴琚偣鍑绘椂鑷姩澶嶅埗 + * @property {String} domain 涓诲煙鍚嶏紝鐢ㄤ簬鎷兼帴閾炬帴 + * @property {String} errorImg 鍥剧墖鍑洪敊鏃剁殑鍗犱綅鍥鹃摼鎺� + * @property {Boolean} lazyLoad 鏄惁寮�鍚浘鐗囨噿鍔犺浇锛堥粯璁� true 锛� + * @property {string} loadingImg 鍥剧墖鍔犺浇杩囩▼涓殑鍗犱綅鍥鹃摼鎺� + * @property {Boolean} pauseVideo 鏄惁鍦ㄦ挱鏀句竴涓棰戞椂鑷姩鏆傚仠鍏跺畠瑙嗛锛堥粯璁� true 锛� + * @property {Boolean} previewImg 鏄惁鍏佽鍥剧墖琚偣鍑绘椂鑷姩棰勮锛堥粯璁� true 锛� + * @property {Boolean} scrollTable 鏄惁缁欐瘡涓〃鏍兼坊鍔犱竴涓粴鍔ㄥ眰浣垮叾鑳藉崟鐙í鍚戞粴鍔� + * @property {Boolean} selectable 鏄惁寮�鍚暱鎸夊鍒� + * @property {Boolean} setTitle 鏄惁灏� title 鏍囩鐨勫唴瀹硅缃埌椤甸潰鏍囬锛堥粯璁� true 锛� + * @property {Boolean} showImgMenu 鏄惁鍏佽鍥剧墖琚暱鎸夋椂鏄剧ず鑿滃崟锛堥粯璁� true 锛� + * @property {Object} tagStyle 鏍囩鐨勯粯璁ゆ牱寮� + * @property {Boolean | Number} useAnchor 鏄惁浣跨敤閿氱偣閾炬帴 + * + * @event {Function} load dom 缁撴瀯鍔犺浇瀹屾瘯鏃惰Е鍙� + * @event {Function} ready 鎵�鏈夊浘鐗囧姞杞藉畬姣曟椂瑙﹀彂 + * @event {Function} imgTap 鍥剧墖琚偣鍑绘椂瑙﹀彂 + * @event {Function} linkTap 閾炬帴琚偣鍑绘椂瑙﹀彂 + * @event {Function} error 濯掍綋鍔犺浇鍑洪敊鏃惰Е鍙� + */ +const plugins=[] +const parser = require('./parser') +// #ifndef APP-PLUS-NVUE +import node from './node/node' +// #endif +// #ifdef APP-PLUS-NVUE +const dom = weex.requireModule('dom') +// #endif +export default { + name: 'mp-html', + data() { + return { + nodes: [], + // #ifdef APP-PLUS-NVUE + height: 0 + // #endif + } + }, + mixins:[props], + // #ifndef APP-PLUS-NVUE + components: { + node + }, + // #endif + watch: { + content(content) { + this.setContent(content) + } + }, + created() { + this.plugins = [] + for (let i = plugins.length; i--;) + this.plugins.push(new plugins[i](this)) + }, + mounted() { + if (this.content && !this.nodes.length) + this.setContent(this.content) + }, + beforeDestroy() { + this._hook('onDetached') + clearInterval(this._timer) + }, + methods: { + /** + * @description 灏嗛敋鐐硅烦杞殑鑼冨洿闄愬畾鍦ㄤ竴涓� scroll-view 鍐� + * @param {Object} page scroll-view 鎵�鍦ㄩ〉闈㈢殑绀轰緥 + * @param {String} selector scroll-view 鐨勯�夋嫨鍣� + * @param {String} scrollTop scroll-view scroll-top 灞炴�х粦瀹氱殑鍙橀噺鍚� + */ + in(page, selector, scrollTop) { + // #ifndef APP-PLUS-NVUE + if (page && selector && scrollTop) + this._in = { + page, + selector, + scrollTop + } + // #endif + }, + + /** + * @description 閿氱偣璺宠浆 + * @param {String} id 瑕佽烦杞殑閿氱偣 id + * @param {Number} offset 璺宠浆浣嶇疆鐨勫亸绉婚噺 + * @returns {Promise} + */ + navigateTo(id, offset) { + return new Promise((resolve, reject) => { + if (!this.useAnchor) + return reject('Anchor is disabled') + offset = offset || parseInt(this.useAnchor) || 0 + // #ifdef APP-PLUS-NVUE + if (!id) { + dom.scrollToElement(this.$refs.web, { + offset + }) + resolve() + } else { + this._navigateTo = { + resolve, + reject, + offset + } + this.$refs.web.evalJs('uni.postMessage({data:{action:"getOffset",offset:(document.getElementById(' + id + ')||{}).offsetTop}})') + } + // #endif + // #ifndef APP-PLUS-NVUE + let deep = ' ' + // #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO + deep = '>>>' + // #endif + const selector = uni.createSelectorQuery() + // #ifndef MP-ALIPAY + .in(this._in ? this._in.page : this) + // #endif + .select((this._in ? this._in.selector : '._root') + (id ? `${deep}#${id}` : '')).boundingClientRect() + if (this._in) + selector.select(this._in.selector).scrollOffset() + .select(this._in.selector).boundingClientRect() // 鑾峰彇 scroll-view 鐨勪綅缃拰婊氬姩璺濈 + else + selector.selectViewport().scrollOffset() // 鑾峰彇绐楀彛鐨勬粴鍔ㄨ窛绂� + selector.exec(res => { + if (!res[0]) + return reject('Label not found') + const scrollTop = res[1].scrollTop + res[0].top - (res[2] ? res[2].top : 0) + offset + if (this._in) + // scroll-view 璺宠浆 + this._in.page[this._in.scrollTop] = scrollTop + else + // 椤甸潰璺宠浆 + uni.pageScrollTo({ + scrollTop, + duration: 300 + }) + resolve() + }) + // #endif + }) + }, + + /** + * @description 鑾峰彇鏂囨湰鍐呭 + * @return {String} + */ + getText() { + let text = ''; + (function traversal(nodes) { + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i] + if (node.type == 'text') + text += node.text.replace(/&/g, '&') + else if (node.name == 'br') + text += '\n' + else { + // 鍧楃骇鏍囩鍓嶅悗鍔犳崲琛� + const isBlock = node.name == 'p' || node.name == 'div' || node.name == 'tr' || node.name == 'li' || (node.name[0] == 'h' && node.name[1] > '0' && node.name[1] < '7') + if (isBlock && text && text[text.length - 1] != '\n') + text += '\n' + // 閫掑綊鑾峰彇瀛愯妭鐐圭殑鏂囨湰 + if (node.children) + traversal(node.children) + if (isBlock && text[text.length - 1] != '\n') + text += '\n' + else if (node.name == 'td' || node.name == 'th') + text += '\t' + } + } + })(this.nodes) + return text + }, + + /** + * @description 鑾峰彇鍐呭澶у皬鍜屼綅缃� + * @return {Promise} + */ + getRect() { + return new Promise((resolve, reject) => { + uni.createSelectorQuery() + // #ifndef MP-ALIPAY + .in(this) + // #endif + .select('#_root').boundingClientRect().exec(res => res[0] ? resolve(res[0]) : reject('Root label not found')) + }) + }, + + /** + * @description 璁剧疆鍐呭 + * @param {String} content html 鍐呭 + * @param {Boolean} append 鏄惁鍦ㄥ熬閮ㄨ拷鍔� + */ + setContent(content, append) { + if (!append || !this.imgList) + this.imgList = [] + const nodes = new parser(this).parse(content) + // #ifdef APP-PLUS-NVUE + if (this._ready) + this._set(nodes, append) + // #endif + this.$set(this, 'nodes', append ? (this.nodes || []).concat(nodes) : nodes) + + // #ifndef APP-PLUS-NVUE + this._videos = [] + this.$nextTick(() => { + this._hook('onLoad') + this.$emit('load') + }) + + // 绛夊緟鍥剧墖鍔犺浇瀹屾瘯 + let height + clearInterval(this._timer) + this._timer = setInterval(() => { + this.getRect().then(rect => { + // 350ms 鎬婚珮搴︽棤鍙樺寲灏辫Е鍙� ready 浜嬩欢 + if (rect.height == height) { + this.$emit('ready', rect) + clearInterval(this._timer) + } + height = rect.height + }).catch(() => { }) + }, 350) + // #endif + }, + + /** + * @description 璋冪敤鎻掍欢閽╁瓙鍑芥暟 + */ + _hook(name) { + for (let i = plugins.length; i--;) + if (this.plugins[i][name]) + this.plugins[i][name]() + }, + + // #ifdef APP-PLUS-NVUE + /** + * @description 璁剧疆鍐呭 + */ + _set(nodes, append) { + this.$refs.web.evalJs('setContent(' + JSON.stringify(nodes) + ',' + JSON.stringify([this.bgColor, this.errorImg, this.loadingImg, this.pauseVideo, this.scrollTable, this.selectable]) + ',' + append + ')') + }, + + /** + * @description 鎺ユ敹鍒� web-view 娑堟伅 + */ + _onMessage(e) { + const message = e.detail.data[0] + switch (message.action) { + // web-view 鍒濆鍖栧畬姣� + case 'onJSBridgeReady': + this._ready = true + if (this.nodes) + this._set(this.nodes) + break + // 鍐呭 dom 鍔犺浇瀹屾瘯 + case 'onLoad': + this.height = message.height + this._hook('onLoad') + this.$emit('load') + break + // 鎵�鏈夊浘鐗囧姞杞藉畬姣� + case 'onReady': + this.getRect().then(res => { + this.$emit('ready', res) + }).catch(() => { }) + break + // 鎬婚珮搴﹀彂鐢熷彉鍖� + case 'onHeightChange': + this.height = message.height + break + // 鍥剧墖鐐瑰嚮 + case 'onImgTap': + this.$emit('imgTap', message.attrs) + if (this.previewImg) + uni.previewImage({ + current: parseInt(message.attrs.i), + urls: this.imgList + }) + break + // 閾炬帴鐐瑰嚮 + case 'onLinkTap': + const href = message.attrs.href + this.$emit('linkTap', message.attrs) + if (href) { + // 閿氱偣璺宠浆 + if (href[0] == '#') { + if (this.useAnchor) + dom.scrollToElement(this.$refs.web, { + offset: message.offset + }) + } + // 鎵撳紑澶栭摼 + else if (href.includes('://')) { + if (this.copyLink) + plus.runtime.openWeb(href) + } + else + uni.navigateTo({ + url: href, + fail() { + wx.switchTab({ + url: href + }) + } + }) + } + break + // 鑾峰彇鍒伴敋鐐圭殑鍋忕Щ閲� + case 'getOffset': + if (typeof message.offset == 'number') { + dom.scrollToElement(this.$refs.web, { + offset: message.offset + this._navigateTo.offset + }) + this._navigateTo.resolve() + } else + this._navigateTo.reject('Label not found') + break + // 鐐瑰嚮 + case 'onClick': + this.$emit('tap') + break + // 鍑洪敊 + case 'onError': + this.$emit('error', { + source: message.source, + attrs: message.attrs + }) + } + } + // #endif + } +} +</script> + +<style> +/* #ifndef APP-PLUS-NVUE */ +/* 鏍硅妭鐐规牱寮� */ +._root { + overflow: auto; + -webkit-overflow-scrolling: touch; +} + +/* 闀挎寜澶嶅埗 */ +._select { + user-select: text; +} +/* #endif */ +</style> -- Gitblit v1.9.3