作者 卢胜

bug

<script>
var wx = require('jweixin-module')
import {
authorization,
getOpenid
... ... @@ -12,9 +11,9 @@
if (!openId && !e.query.code) {
console.log('获取code');
getApp().authorization()
// getApp().authorization()
} else if (e.query.code) {
getApp().getOpenid(e.query.code)
// getApp().getOpenid(e.query.code)
}
// else {
// uni.showModal({
... ... @@ -26,11 +25,14 @@
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
console.log('App')
},
onHide: function() {
console.log('App Hide')
},
watch:{
},
methods: {
// 拿code
async authorization() {
... ...
... ... @@ -54,3 +54,6 @@ export const sort_all = (keyword) => request({url: 'product/sort_all',method: '
//搜索弹窗分类
export const sort_search = (keyword) => request({url: 'product/sort_search',method: 'post',data: {keyword}})
//获取jssdk数据
export const get_jssdk = (url) => request({url: 'common/get_jssdk',method: 'post',data: {url}})
\ No newline at end of file
... ...
import App from './App'
// #ifndef VUE3
import App from './App'
import {Shares} from '@/utils/share.js'
// #ifndef VUE3
import Vue from 'vue'
import uView from "uview-ui";
Vue.use(uView);
import uView from "uview-ui";
Vue.use(uView);
Vue.config.productionTip = false
Vue.prototype.$wxH5Share = Shares
App.mpType = 'app'
const app = new Vue({
...App
...App
})
app.$mount()
// #endif
// #ifdef VUE3
import { createSSRApp } from 'vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
app.$mount()
// #endif
// router.beforeEach((to, from, next) => {
// var u = navigator.userAgent;
// var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
// if (isiOS && to.path !== location.pathname) {
// location.assign(to.fullPath)
// } else {
// next();
// }
// })
// #ifdef VUE3
import {
createSSRApp
} from 'vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
}
// #endif
\ No newline at end of file
// #endif
... ...
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/jweixin-js-sdk.iml" filepath="$PROJECT_DIR$/.idea/jweixin-js-sdk.iml" />
</modules>
</component>
</project>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
... ...
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
... ...
!(function (e, n) {
module.exports = n(e)
}(window, function (o, e) {
if (!o.jWeixin) {
var n;
var c = {
config: 'preVerifyJSAPI',
onMenuShareTimeline: 'menu:share:timeline',
onMenuShareAppMessage: 'menu:share:appmessage',
onMenuShareQQ: 'menu:share:qq',
onMenuShareWeibo: 'menu:share:weiboApp',
onMenuShareQZone: 'menu:share:QZone',
previewImage: 'imagePreview',
getLocation: 'geoLocation',
openProductSpecificView: 'openProductViewWithPid',
addCard: 'batchAddCard',
openCard: 'batchViewCard',
chooseWXPay: 'getBrandWCPayRequest',
openEnterpriseRedPacket: 'getRecevieBizHongBaoRequest',
startSearchBeacons: 'startMonitoringBeacons',
stopSearchBeacons: 'stopMonitoringBeacons',
onSearchBeacons: 'onBeaconsInRange',
consumeAndShareCard: 'consumedShareCard',
openAddress: 'editAddress'
};
var a = (function () {
var e = {};
for (var n in c) e[c[n]] = n;
return e
}());
var i = o.document;
var t = i.title;
var r = navigator.userAgent.toLowerCase();
var s = navigator.platform.toLowerCase();
var d = !(!s.match('mac') && !s.match('win'));
var u = r.indexOf('wxdebugger') != -1;
var l = r.indexOf('micromessenger') != -1;
var p = r.indexOf('android') != -1;
var f = r.indexOf('iphone') != -1 || r.indexOf('ipad') != -1;
var m = (n = r.match(/micromessenger\/(\d+\.\d+\.\d+)/) || r.match(/micromessenger\/(\d+\.\d+)/)) ? n[1] : '';
var g = {initStartTime: L(), initEndTime: 0, preVerifyStartTime: 0, preVerifyEndTime: 0};
var h = {
version: 1,
appId: '',
initTime: 0,
preVerifyTime: 0,
networkType: '',
isPreVerifyOk: 1,
systemType: f ? 1 : p ? 2 : -1,
clientVersion: m,
url: encodeURIComponent(location.href)
};
var v = {};
var S = {_completes: []};
var y = {state: 0, data: {}};
O(function () {
g.initEndTime = L()
});
var I = !1;
var _ = [];
var w = {
config: function (e) {
B('config', v = e);
var t = !1 !== v.check;
O(function () {
if (t) M(c.config, {
verifyJsApiList: C(v.jsApiList),
verifyOpenTagList: C(v.openTagList)
}, (function () {
S._complete = function (e) {
g.preVerifyEndTime = L(), y.state = 1, y.data = e
}, S.success = function (e) {
h.isPreVerifyOk = 0
}, S.fail = function (e) {
S._fail ? S._fail(e) : y.state = -1
};
var t = S._completes;
return t.push(function () {
!(function () {
if (!(d || u || v.debug || m < '6.0.2' || h.systemType < 0)) {
var i = new Image();
h.appId = v.appId, h.initTime = g.initEndTime - g.initStartTime, h.preVerifyTime = g.preVerifyEndTime - g.preVerifyStartTime, w.getNetworkType({
isInnerInvoke: !0,
success: function (e) {
h.networkType = e.networkType;
var n = 'https://open.weixin.qq.com/sdk/report?v=' + h.version + '&o=' + h.isPreVerifyOk + '&s=' + h.systemType + '&c=' + h.clientVersion + '&a=' + h.appId + '&n=' + h.networkType + '&i=' + h.initTime + '&p=' + h.preVerifyTime + '&u=' + h.url;
i.src = n
}
})
}
}())
}), S.complete = function (e) {
for (var n = 0, i = t.length; n < i; ++n) t[n]();
S._completes = []
}, S
}())), g.preVerifyStartTime = L(); else {
y.state = 1;
for (var e = S._completes, n = 0, i = e.length; n < i; ++n) e[n]();
S._completes = []
}
}), w.invoke || (w.invoke = function (e, n, i) {
o.WeixinJSBridge && WeixinJSBridge.invoke(e, x(n), i)
}, w.on = function (e, n) {
o.WeixinJSBridge && WeixinJSBridge.on(e, n)
})
},
signurl: function() {
return h.url
},
ready: function (e) {
y.state != 0 ? e() : (S._completes.push(e), !l && v.debug && e())
}, error: function (e) {
m < '6.0.2' || (y.state == -1 ? e(y.data) : S._fail = e)
}, checkJsApi: function (e) {
M('checkJsApi', {jsApiList: C(e.jsApiList)}, (e._complete = function (e) {
if (p) {
var n = e.checkResult;
n && (e.checkResult = JSON.parse(n))
}
e = (function (e) {
var n = e.checkResult;
for (var i in n) {
var t = a[i];
t && (n[t] = n[i], delete n[i])
}
return e
}(e))
}, e))
}, onMenuShareTimeline: function (e) {
P(c.onMenuShareTimeline, {
complete: function () {
M('shareTimeline', {
title: e.title || t,
desc: e.title || t,
img_url: e.imgUrl || '',
link: e.link || location.href,
type: e.type || 'link',
data_url: e.dataUrl || ''
}, e)
}
}, e)
}, onMenuShareAppMessage: function (n) {
P(c.onMenuShareAppMessage, {
complete: function (e) {
e.scene === 'favorite' ? M('sendAppMessage', {
title: n.title || t,
desc: n.desc || '',
link: n.link || location.href,
img_url: n.imgUrl || '',
type: n.type || 'link',
data_url: n.dataUrl || ''
}) : M('sendAppMessage', {
title: n.title || t,
desc: n.desc || '',
link: n.link || location.href,
img_url: n.imgUrl || '',
type: n.type || 'link',
data_url: n.dataUrl || ''
}, n)
}
}, n)
}, onMenuShareQQ: function (e) {
P(c.onMenuShareQQ, {
complete: function () {
M('shareQQ', {
title: e.title || t,
desc: e.desc || '',
img_url: e.imgUrl || '',
link: e.link || location.href
}, e)
}
}, e)
}, onMenuShareWeibo: function (e) {
P(c.onMenuShareWeibo, {
complete: function () {
M('shareWeiboApp', {
title: e.title || t,
desc: e.desc || '',
img_url: e.imgUrl || '',
link: e.link || location.href
}, e)
}
}, e)
}, onMenuShareQZone: function (e) {
P(c.onMenuShareQZone, {
complete: function () {
M('shareQZone', {
title: e.title || t,
desc: e.desc || '',
img_url: e.imgUrl || '',
link: e.link || location.href
}, e)
}
}, e)
}, updateTimelineShareData: function (e) {
M('updateTimelineShareData', {title: e.title, link: e.link, imgUrl: e.imgUrl}, e)
}, updateAppMessageShareData: function (e) {
M('updateAppMessageShareData', {title: e.title, desc: e.desc, link: e.link, imgUrl: e.imgUrl}, e)
}, startRecord: function (e) {
M('startRecord', {}, e)
}, stopRecord: function (e) {
M('stopRecord', {}, e)
}, onVoiceRecordEnd: function (e) {
P('onVoiceRecordEnd', e)
}, playVoice: function (e) {
M('playVoice', {localId: e.localId}, e)
}, pauseVoice: function (e) {
M('pauseVoice', {localId: e.localId}, e)
}, stopVoice: function (e) {
M('stopVoice', {localId: e.localId}, e)
}, onVoicePlayEnd: function (e) {
P('onVoicePlayEnd', e)
}, uploadVoice: function (e) {
M('uploadVoice', {localId: e.localId, isShowProgressTips: e.isShowProgressTips == 0 ? 0 : 1}, e)
}, downloadVoice: function (e) {
M('downloadVoice', {serverId: e.serverId, isShowProgressTips: e.isShowProgressTips == 0 ? 0 : 1}, e)
}, translateVoice: function (e) {
M('translateVoice', {localId: e.localId, isShowProgressTips: e.isShowProgressTips == 0 ? 0 : 1}, e)
}, chooseImage: function (e) {
M('chooseImage', {
scene: '1|2',
count: e.count || 9,
sizeType: e.sizeType || ['original', 'compressed'],
sourceType: e.sourceType || ['album', 'camera']
}, (e._complete = function (e) {
if (p) {
var n = e.localIds;
try {
n && (e.localIds = JSON.parse(n))
} catch (e) {
}
}
}, e))
}, getLocation: function (e) {
}, previewImage: function (e) {
M(c.previewImage, {current: e.current, urls: e.urls}, e)
}, uploadImage: function (e) {
M('uploadImage', {localId: e.localId, isShowProgressTips: e.isShowProgressTips == 0 ? 0 : 1}, e)
}, downloadImage: function (e) {
M('downloadImage', {serverId: e.serverId, isShowProgressTips: e.isShowProgressTips == 0 ? 0 : 1}, e)
}, getLocalImgData: function (e) {
!1 === I ? (I = !0, M('getLocalImgData', {localId: e.localId}, (e._complete = function (e) {
if (I = !1, _.length > 0) {
var n = _.shift();
wx.getLocalImgData(n)
}
}, e))) : _.push(e)
}, getNetworkType: function (e) {
M('getNetworkType', {}, (e._complete = function (e) {
e = (function (e) {
var n = e.errMsg;
e.errMsg = 'getNetworkType:ok';
var i = e.subtype;
if (delete e.subtype, i) e.networkType = i; else {
var t = n.indexOf(':');
var o = n.substring(t + 1);
switch (o) {
case 'wifi':
case 'edge':
case 'wwan':
e.networkType = o;
break;
default:
e.errMsg = 'getNetworkType:fail'
}
}
return e
}(e))
}, e))
}, openLocation: function (e) {
M('openLocation', {
latitude: e.latitude,
longitude: e.longitude,
name: e.name || '',
address: e.address || '',
scale: e.scale || 28,
infoUrl: e.infoUrl || ''
}, e)
}, getLocation: function (e) {
M(c.getLocation, {type: (e = e || {}).type || 'wgs84'}, (e._complete = function (e) {
delete e.type
}, e))
}, hideOptionMenu: function (e) {
M('hideOptionMenu', {}, e)
}, showOptionMenu: function (e) {
M('showOptionMenu', {}, e)
}, closeWindow: function (e) {
M('closeWindow', {}, e = e || {})
}, hideMenuItems: function (e) {
M('hideMenuItems', {menuList: e.menuList}, e)
}, showMenuItems: function (e) {
M('showMenuItems', {menuList: e.menuList}, e)
}, hideAllNonBaseMenuItem: function (e) {
M('hideAllNonBaseMenuItem', {}, e)
}, showAllNonBaseMenuItem: function (e) {
M('showAllNonBaseMenuItem', {}, e)
}, scanQRCode: function (e) {
M('scanQRCode', {
needResult: (e = e || {}).needResult || 0,
scanType: e.scanType || ['qrCode', 'barCode']
}, (e._complete = function (e) {
if (f) {
var n = e.resultStr;
if (n) {
var i = JSON.parse(n);
e.resultStr = i && i.scan_code && i.scan_code.scan_result
}
}
}, e))
}, openAddress: function (e) {
M(c.openAddress, {}, (e._complete = function (e) {
e = (function (e) {
return e.postalCode = e.addressPostalCode, delete e.addressPostalCode, e.provinceName = e.proviceFirstStageName, delete e.proviceFirstStageName, e.cityName = e.addressCitySecondStageName, delete e.addressCitySecondStageName, e.countryName = e.addressCountiesThirdStageName, delete e.addressCountiesThirdStageName, e.detailInfo = e.addressDetailInfo, delete e.addressDetailInfo, e
}(e))
}, e))
}, openProductSpecificView: function (e) {
M(c.openProductSpecificView, {pid: e.productId, view_type: e.viewType || 0, ext_info: e.extInfo}, e)
}, addCard: function (e) {
for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
var r = n[t];
var a = {card_id: r.cardId, card_ext: r.cardExt};
i.push(a)
}
M(c.addCard, {card_list: i}, (e._complete = function (e) {
var n = e.card_list;
if (n) {
for (var i = 0, t = (n = JSON.parse(n)).length; i < t; ++i) {
var o = n[i];
o.cardId = o.card_id, o.cardExt = o.card_ext, o.isSuccess = !!o.is_succ, delete o.card_id, delete o.card_ext, delete o.is_succ
}
e.cardList = n, delete e.card_list
}
}, e))
}, chooseCard: function (e) {
M('chooseCard', {
app_id: v.appId,
location_id: e.shopId || '',
sign_type: e.signType || 'SHA1',
card_id: e.cardId || '',
card_type: e.cardType || '',
card_sign: e.cardSign,
time_stamp: e.timestamp + '',
nonce_str: e.nonceStr
}, (e._complete = function (e) {
e.cardList = e.choose_card_info, delete e.choose_card_info
}, e))
}, openCard: function (e) {
for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
var r = n[t];
var a = {card_id: r.cardId, code: r.code};
i.push(a)
}
M(c.openCard, {card_list: i}, e)
}, consumeAndShareCard: function (e) {
M(c.consumeAndShareCard, {consumedCardId: e.cardId, consumedCode: e.code}, e)
}, chooseWXPay: function (e) {
M(c.chooseWXPay, V(e), e)
}, openEnterpriseRedPacket: function (e) {
M(c.openEnterpriseRedPacket, V(e), e)
}, startSearchBeacons: function (e) {
M(c.startSearchBeacons, {ticket: e.ticket}, e)
}, stopSearchBeacons: function (e) {
M(c.stopSearchBeacons, {}, e)
}, onSearchBeacons: function (e) {
P(c.onSearchBeacons, e)
}, openEnterpriseChat: function (e) {
M('openEnterpriseChat', {useridlist: e.userIds, chatname: e.groupName}, e)
}, launchMiniProgram: function (e) {
M('launchMiniProgram', {
targetAppId: e.targetAppId, path: (function (e) {
if (typeof e === 'string' && e.length > 0) {
var n = e.split('?')[0];
var i = e.split('?')[1];
return n += '.html', void 0 !== i ? n + '?' + i : n
}
}(e.path)), envVersion: e.envVersion
}, e)
}, openBusinessView: function (e) {
M('openBusinessView', {
businessType: e.businessType,
queryString: e.queryString || '',
envVersion: e.envVersion
}, (e._complete = function (n) {
if (p) {
var e = n.extraData;
if (e) try {
n.extraData = JSON.parse(e)
} catch (e) {
n.extraData = {}
}
}
}, e))
}, miniProgram: {
navigateBack: function (e) {
e = e || {}, O(function () {
M('invokeMiniProgramAPI', {name: 'navigateBack', arg: {delta: e.delta || 1}}, e)
})
}, navigateTo: function (e) {
O(function () {
M('invokeMiniProgramAPI', {name: 'navigateTo', arg: {url: e.url}}, e)
})
}, redirectTo: function (e) {
O(function () {
M('invokeMiniProgramAPI', {name: 'redirectTo', arg: {url: e.url}}, e)
})
}, switchTab: function (e) {
O(function () {
M('invokeMiniProgramAPI', {name: 'switchTab', arg: {url: e.url}}, e)
})
}, reLaunch: function (e) {
O(function () {
M('invokeMiniProgramAPI', {name: 'reLaunch', arg: {url: e.url}}, e)
})
}, postMessage: function (e) {
O(function () {
M('invokeMiniProgramAPI', {name: 'postMessage', arg: e.data || {}}, e)
})
}, getEnv: function (e) {
O(function () {
e({miniprogram: o.__wxjs_environment === 'miniprogram'})
})
}
}
};
var T = 1;
var k = {};
return i.addEventListener('error', function (e) {
if (!p) {
var n = e.target;
var i = n.tagName;
var t = n.src;
if (i == 'IMG' || i == 'VIDEO' || i == 'AUDIO' || i == 'SOURCE') if (t.indexOf('wxlocalresource://') != -1) {
e.preventDefault(), e.stopPropagation();
var o = n['wx-id'];
if (o || (o = T++, n['wx-id'] = o), k[o]) return;
k[o] = !0, wx.ready(function () {
wx.getLocalImgData({
localId: t, success: function (e) {
n.src = e.localData
}
})
})
}
}
}, !0), i.addEventListener('load', function (e) {
if (!p) {
var n = e.target;
var i = n.tagName;
n.src;
if (i == 'IMG' || i == 'VIDEO' || i == 'AUDIO' || i == 'SOURCE') {
var t = n['wx-id'];
t && (k[t] = !1)
}
}
}, !0), e && (o.wx = o.jWeixin = w), w
}
function M(n, e, i) {
o.WeixinJSBridge ? WeixinJSBridge.invoke(n, x(e), function (e) {
A(n, e, i)
}) : B(n, i)
}
function P(n, i, t) {
o.WeixinJSBridge ? WeixinJSBridge.on(n, function (e) {
t && t.trigger && t.trigger(e), A(n, e, i)
}) : B(n, t || i)
}
function x(e) {
return (e = e || {}).appId = v.appId, e.verifyAppId = v.appId, e.verifySignType = 'sha1', e.verifyTimestamp = v.timestamp + '', e.verifyNonceStr = v.nonceStr, e.verifySignature = v.signature, e
}
function V(e) {
return {
timeStamp: e.timestamp + '',
nonceStr: e.nonceStr,
package: e.package,
paySign: e.paySign,
signType: e.signType || 'SHA1'
}
}
function A(e, n, i) {
e != 'openEnterpriseChat' && e !== 'openBusinessView' || (n.errCode = n.err_code), delete n.err_code, delete n.err_desc, delete n.err_detail;
var t = n.errMsg;
t || (t = n.err_msg, delete n.err_msg, t = (function (e, n) {
var i = e;
var t = a[i];
t && (i = t);
var o = 'ok';
if (n) {
var r = n.indexOf(':');
(o = n.substring(r + 1)) == 'confirm' && (o = 'ok'), o == 'failed' && (o = 'fail'), o.indexOf('failed_') != -1 && (o = o.substring(7)), o.indexOf('fail_') != -1 && (o = o.substring(5)), (o = (o = o.replace(/_/g, ' ')).toLowerCase()) != 'access denied' && o != 'no permission to execute' || (o = 'permission denied'), i == 'config' && o == 'function not exist' && (o = 'ok'), o == '' && (o = 'fail')
}
return n = i + ':' + o
}(e, t)), n.errMsg = t), (i = i || {})._complete && (i._complete(n), delete i._complete), t = n.errMsg || '', v.debug && !i.isInnerInvoke && alert(JSON.stringify(n));
var o = t.indexOf(':');
switch (t.substring(o + 1)) {
case 'ok':
i.success && i.success(n);
break;
case 'cancel':
i.cancel && i.cancel(n);
break;
default:
i.fail && i.fail(n)
}
i.complete && i.complete(n)
}
function C(e) {
if (e) {
for (var n = 0, i = e.length; n < i; ++n) {
var t = e[n];
var o = c[t];
o && (e[n] = o)
}
return e
}
}
function B(e, n) {
if (!(!v.debug || n && n.isInnerInvoke)) {
var i = a[e];
i && (e = i), n && n._complete && delete n._complete, console.log('"' + e + '",', n || '')
}
}
function L() {
return (new Date()).getTime()
}
function O(e) {
l && (o.WeixinJSBridge ? e() : i.addEventListener && i.addEventListener('WeixinJSBridgeReady', e, !1))
}
}))
... ...
!(function(e, n) { typeof define === 'function' && (define.amd || define.cmd) ? define(function() { return n(e) }) : n(e, !0) }(window, function(o, e) { if (!o.jWeixin) { var n; var c = { config: 'preVerifyJSAPI', onMenuShareTimeline: 'menu:share:timeline', onMenuShareAppMessage: 'menu:share:appmessage', onMenuShareQQ: 'menu:share:qq', onMenuShareWeibo: 'menu:share:weiboApp', onMenuShareQZone: 'menu:share:QZone', previewImage: 'imagePreview', getLocation: 'geoLocation', openProductSpecificView: 'openProductViewWithPid', addCard: 'batchAddCard', openCard: 'batchViewCard', chooseWXPay: 'getBrandWCPayRequest', openEnterpriseRedPacket: 'getRecevieBizHongBaoRequest', startSearchBeacons: 'startMonitoringBeacons', stopSearchBeacons: 'stopMonitoringBeacons', onSearchBeacons: 'onBeaconsInRange', consumeAndShareCard: 'consumedShareCard', openAddress: 'editAddress' }; var a = (function() { var e = {}; for (var n in c)e[c[n]] = n; return e }()); var i = e.document; var t = i.title; var r = navigator.userAgent.toLowerCase(); var s = navigator.platform.toLowerCase(); var d = !(!s.match('mac') && !s.match('win')); var u = r.indexOf('wxdebugger') != -1; var l = r.indexOf('micromessenger') != -1; var p = r.indexOf('android') != -1; var f = r.indexOf('iphone') != -1 || r.indexOf('ipad') != -1; var m = (n = r.match(/micromessenger\/(\d+\.\d+\.\d+)/) || r.match(/micromessenger\/(\d+\.\d+)/)) ? n[1] : ''; var g = { initStartTime: L(), initEndTime: 0, preVerifyStartTime: 0, preVerifyEndTime: 0 }; var h = { version: 1, appId: '', initTime: 0, preVerifyTime: 0, networkType: '', isPreVerifyOk: 1, systemType: f ? 1 : p ? 2 : -1, clientVersion: m, url: encodeURIComponent(location.href) }; var v = {}; var S = { _completes: [] }; var y = { state: 0, data: {} }; O(function() { g.initEndTime = L() }); var I = !1; var _ = []; var w = { config: function(e) { B('config', v = e); var t = !1 !== v.check; O(function() { if (t)M(c.config, { verifyJsApiList: C(v.jsApiList), verifyOpenTagList: C(v.openTagList) }, (function() { S._complete = function(e) { g.preVerifyEndTime = L(), y.state = 1, y.data = e }, S.success = function(e) { h.isPreVerifyOk = 0 }, S.fail = function(e) { S._fail ? S._fail(e) : y.state = -1 }; var t = S._completes; return t.push(function() { !(function() { if (!(d || u || v.debug || m < '6.0.2' || h.systemType < 0)) { var i = new Image(); h.appId = v.appId, h.initTime = g.initEndTime - g.initStartTime, h.preVerifyTime = g.preVerifyEndTime - g.preVerifyStartTime, w.getNetworkType({ isInnerInvoke: !0, success: function(e) { h.networkType = e.networkType; var n = 'https://open.weixin.qq.com/sdk/report?v=' + h.version + '&o=' + h.isPreVerifyOk + '&s=' + h.systemType + '&c=' + h.clientVersion + '&a=' + h.appId + '&n=' + h.networkType + '&i=' + h.initTime + '&p=' + h.preVerifyTime + '&u=' + h.url; i.src = n } }) } }()) }), S.complete = function(e) { for (var n = 0, i = t.length; n < i; ++n)t[n](); S._completes = [] }, S }())), g.preVerifyStartTime = L(); else { y.state = 1; for (var e = S._completes, n = 0, i = e.length; n < i; ++n)e[n](); S._completes = [] } }), w.invoke || (w.invoke = function(e, n, i) { o.WeixinJSBridge && WeixinJSBridge.invoke(e, x(n), i) }, w.on = function(e, n) { o.WeixinJSBridge && WeixinJSBridge.on(e, n) }) }, ready: function(e) { y.state != 0 ? e() : (S._completes.push(e), !l && v.debug && e()) }, error: function(e) { m < '6.0.2' || (y.state == -1 ? e(y.data) : S._fail = e) }, checkJsApi: function(e) { M('checkJsApi', { jsApiList: C(e.jsApiList) }, (e._complete = function(e) { if (p) { var n = e.checkResult; n && (e.checkResult = JSON.parse(n)) }e = (function(e) { var n = e.checkResult; for (var i in n) { var t = a[i]; t && (n[t] = n[i], delete n[i]) } return e }(e)) }, e)) }, onMenuShareTimeline: function(e) { P(c.onMenuShareTimeline, { complete: function() { M('shareTimeline', { title: e.title || t, desc: e.title || t, img_url: e.imgUrl || '', link: e.link || location.href, type: e.type || 'link', data_url: e.dataUrl || '' }, e) } }, e) }, onMenuShareAppMessage: function(n) { P(c.onMenuShareAppMessage, { complete: function(e) { e.scene === 'favorite' ? M('sendAppMessage', { title: n.title || t, desc: n.desc || '', link: n.link || location.href, img_url: n.imgUrl || '', type: n.type || 'link', data_url: n.dataUrl || '' }) : M('sendAppMessage', { title: n.title || t, desc: n.desc || '', link: n.link || location.href, img_url: n.imgUrl || '', type: n.type || 'link', data_url: n.dataUrl || '' }, n) } }, n) }, onMenuShareQQ: function(e) { P(c.onMenuShareQQ, { complete: function() { M('shareQQ', { title: e.title || t, desc: e.desc || '', img_url: e.imgUrl || '', link: e.link || location.href }, e) } }, e) }, onMenuShareWeibo: function(e) { P(c.onMenuShareWeibo, { complete: function() { M('shareWeiboApp', { title: e.title || t, desc: e.desc || '', img_url: e.imgUrl || '', link: e.link || location.href }, e) } }, e) }, onMenuShareQZone: function(e) { P(c.onMenuShareQZone, { complete: function() { M('shareQZone', { title: e.title || t, desc: e.desc || '', img_url: e.imgUrl || '', link: e.link || location.href }, e) } }, e) }, updateTimelineShareData: function(e) { M('updateTimelineShareData', { title: e.title, link: e.link, imgUrl: e.imgUrl }, e) }, updateAppMessageShareData: function(e) { M('updateAppMessageShareData', { title: e.title, desc: e.desc, link: e.link, imgUrl: e.imgUrl }, e) }, startRecord: function(e) { M('startRecord', {}, e) }, stopRecord: function(e) { M('stopRecord', {}, e) }, onVoiceRecordEnd: function(e) { P('onVoiceRecordEnd', e) }, playVoice: function(e) { M('playVoice', { localId: e.localId }, e) }, pauseVoice: function(e) { M('pauseVoice', { localId: e.localId }, e) }, stopVoice: function(e) { M('stopVoice', { localId: e.localId }, e) }, onVoicePlayEnd: function(e) { P('onVoicePlayEnd', e) }, uploadVoice: function(e) { M('uploadVoice', { localId: e.localId, isShowProgressTips: e.isShowProgressTips == 0 ? 0 : 1 }, e) }, downloadVoice: function(e) { M('downloadVoice', { serverId: e.serverId, isShowProgressTips: e.isShowProgressTips == 0 ? 0 : 1 }, e) }, translateVoice: function(e) { M('translateVoice', { localId: e.localId, isShowProgressTips: e.isShowProgressTips == 0 ? 0 : 1 }, e) }, chooseImage: function(e) { M('chooseImage', { scene: '1|2', count: e.count || 9, sizeType: e.sizeType || ['original', 'compressed'], sourceType: e.sourceType || ['album', 'camera'] }, (e._complete = function(e) { if (p) { var n = e.localIds; try { n && (e.localIds = JSON.parse(n)) } catch (e) {} } }, e)) }, getLocation: function(e) {}, previewImage: function(e) { M(c.previewImage, { current: e.current, urls: e.urls }, e) }, uploadImage: function(e) { M('uploadImage', { localId: e.localId, isShowProgressTips: e.isShowProgressTips == 0 ? 0 : 1 }, e) }, downloadImage: function(e) { M('downloadImage', { serverId: e.serverId, isShowProgressTips: e.isShowProgressTips == 0 ? 0 : 1 }, e) }, getLocalImgData: function(e) { !1 === I ? (I = !0, M('getLocalImgData', { localId: e.localId }, (e._complete = function(e) { if (I = !1, _.length > 0) { var n = _.shift(); wx.getLocalImgData(n) } }, e))) : _.push(e) }, getNetworkType: function(e) { M('getNetworkType', {}, (e._complete = function(e) { e = (function(e) { var n = e.errMsg; e.errMsg = 'getNetworkType:ok'; var i = e.subtype; if (delete e.subtype, i)e.networkType = i; else { var t = n.indexOf(':'); var o = n.substring(t + 1); switch (o) { case 'wifi':case 'edge':case 'wwan':e.networkType = o; break; default:e.errMsg = 'getNetworkType:fail' } } return e }(e)) }, e)) }, openLocation: function(e) { M('openLocation', { latitude: e.latitude, longitude: e.longitude, name: e.name || '', address: e.address || '', scale: e.scale || 28, infoUrl: e.infoUrl || '' }, e) }, getLocation: function(e) { M(c.getLocation, { type: (e = e || {}).type || 'wgs84' }, (e._complete = function(e) { delete e.type }, e)) }, hideOptionMenu: function(e) { M('hideOptionMenu', {}, e) }, showOptionMenu: function(e) { M('showOptionMenu', {}, e) }, closeWindow: function(e) { M('closeWindow', {}, e = e || {}) }, hideMenuItems: function(e) { M('hideMenuItems', { menuList: e.menuList }, e) }, showMenuItems: function(e) { M('showMenuItems', { menuList: e.menuList }, e) }, hideAllNonBaseMenuItem: function(e) { M('hideAllNonBaseMenuItem', {}, e) }, showAllNonBaseMenuItem: function(e) { M('showAllNonBaseMenuItem', {}, e) }, scanQRCode: function(e) { M('scanQRCode', { needResult: (e = e || {}).needResult || 0, scanType: e.scanType || ['qrCode', 'barCode'] }, (e._complete = function(e) { if (f) { var n = e.resultStr; if (n) { var i = JSON.parse(n); e.resultStr = i && i.scan_code && i.scan_code.scan_result } } }, e)) }, openAddress: function(e) { M(c.openAddress, {}, (e._complete = function(e) { e = (function(e) { return e.postalCode = e.addressPostalCode, delete e.addressPostalCode, e.provinceName = e.proviceFirstStageName, delete e.proviceFirstStageName, e.cityName = e.addressCitySecondStageName, delete e.addressCitySecondStageName, e.countryName = e.addressCountiesThirdStageName, delete e.addressCountiesThirdStageName, e.detailInfo = e.addressDetailInfo, delete e.addressDetailInfo, e }(e)) }, e)) }, openProductSpecificView: function(e) { M(c.openProductSpecificView, { pid: e.productId, view_type: e.viewType || 0, ext_info: e.extInfo }, e) }, addCard: function(e) { for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) { var r = n[t]; var a = { card_id: r.cardId, card_ext: r.cardExt }; i.push(a) }M(c.addCard, { card_list: i }, (e._complete = function(e) { var n = e.card_list; if (n) { for (var i = 0, t = (n = JSON.parse(n)).length; i < t; ++i) { var o = n[i]; o.cardId = o.card_id, o.cardExt = o.card_ext, o.isSuccess = !!o.is_succ, delete o.card_id, delete o.card_ext, delete o.is_succ }e.cardList = n, delete e.card_list } }, e)) }, chooseCard: function(e) { M('chooseCard', { app_id: v.appId, location_id: e.shopId || '', sign_type: e.signType || 'SHA1', card_id: e.cardId || '', card_type: e.cardType || '', card_sign: e.cardSign, time_stamp: e.timestamp + '', nonce_str: e.nonceStr }, (e._complete = function(e) { e.cardList = e.choose_card_info, delete e.choose_card_info }, e)) }, openCard: function(e) { for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) { var r = n[t]; var a = { card_id: r.cardId, code: r.code }; i.push(a) }M(c.openCard, { card_list: i }, e) }, consumeAndShareCard: function(e) { M(c.consumeAndShareCard, { consumedCardId: e.cardId, consumedCode: e.code }, e) }, chooseWXPay: function(e) { M(c.chooseWXPay, V(e), e) }, openEnterpriseRedPacket: function(e) { M(c.openEnterpriseRedPacket, V(e), e) }, startSearchBeacons: function(e) { M(c.startSearchBeacons, { ticket: e.ticket }, e) }, stopSearchBeacons: function(e) { M(c.stopSearchBeacons, {}, e) }, onSearchBeacons: function(e) { P(c.onSearchBeacons, e) }, openEnterpriseChat: function(e) { M('openEnterpriseChat', { useridlist: e.userIds, chatname: e.groupName }, e) }, launchMiniProgram: function(e) { M('launchMiniProgram', { targetAppId: e.targetAppId, path: (function(e) { if (typeof e === 'string' && e.length > 0) { var n = e.split('?')[0]; var i = e.split('?')[1]; return n += '.html', void 0 !== i ? n + '?' + i : n } }(e.path)), envVersion: e.envVersion }, e) }, openBusinessView: function(e) { M('openBusinessView', { businessType: e.businessType, queryString: e.queryString || '', envVersion: e.envVersion }, (e._complete = function(n) { if (p) { var e = n.extraData; if (e) try { n.extraData = JSON.parse(e) } catch (e) { n.extraData = {} } } }, e)) }, miniProgram: { navigateBack: function(e) { e = e || {}, O(function() { M('invokeMiniProgramAPI', { name: 'navigateBack', arg: { delta: e.delta || 1 } }, e) }) }, navigateTo: function(e) { O(function() { M('invokeMiniProgramAPI', { name: 'navigateTo', arg: { url: e.url } }, e) }) }, redirectTo: function(e) { O(function() { M('invokeMiniProgramAPI', { name: 'redirectTo', arg: { url: e.url } }, e) }) }, switchTab: function(e) { O(function() { M('invokeMiniProgramAPI', { name: 'switchTab', arg: { url: e.url } }, e) }) }, reLaunch: function(e) { O(function() { M('invokeMiniProgramAPI', { name: 'reLaunch', arg: { url: e.url } }, e) }) }, postMessage: function(e) { O(function() { M('invokeMiniProgramAPI', { name: 'postMessage', arg: e.data || {} }, e) }) }, getEnv: function(e) { O(function() { e({ miniprogram: o.__wxjs_environment === 'miniprogram' }) }) } } }; var T = 1; var k = {}; return i.addEventListener('error', function(e) { if (!p) { var n = e.target; var i = n.tagName; var t = n.src; if (i == 'IMG' || i == 'VIDEO' || i == 'AUDIO' || i == 'SOURCE') if (t.indexOf('wxlocalresource://') != -1) { e.preventDefault(), e.stopPropagation(); var o = n['wx-id']; if (o || (o = T++, n['wx-id'] = o), k[o]) return; k[o] = !0, wx.ready(function() { wx.getLocalImgData({ localId: t, success: function(e) { n.src = e.localData } }) }) } } }, !0), i.addEventListener('load', function(e) { if (!p) { var n = e.target; var i = n.tagName; n.src; if (i == 'IMG' || i == 'VIDEO' || i == 'AUDIO' || i == 'SOURCE') { var t = n['wx-id']; t && (k[t] = !1) } } }, !0), e && (o.wx = o.jWeixin = w), w } function M(n, e, i) { o.WeixinJSBridge ? WeixinJSBridge.invoke(n, x(e), function(e) { A(n, e, i) }) : B(n, i) } function P(n, i, t) { o.WeixinJSBridge ? WeixinJSBridge.on(n, function(e) { t && t.trigger && t.trigger(e), A(n, e, i) }) : B(n, t || i) } function x(e) { return (e = e || {}).appId = v.appId, e.verifyAppId = v.appId, e.verifySignType = 'sha1', e.verifyTimestamp = v.timestamp + '', e.verifyNonceStr = v.nonceStr, e.verifySignature = v.signature, e } function V(e) { return { timeStamp: e.timestamp + '', nonceStr: e.nonceStr, package: e.package, paySign: e.paySign, signType: e.signType || 'SHA1' } } function A(e, n, i) { e != 'openEnterpriseChat' && e !== 'openBusinessView' || (n.errCode = n.err_code), delete n.err_code, delete n.err_desc, delete n.err_detail; var t = n.errMsg; t || (t = n.err_msg, delete n.err_msg, t = (function(e, n) { var i = e; var t = a[i]; t && (i = t); var o = 'ok'; if (n) { var r = n.indexOf(':'); (o = n.substring(r + 1)) == 'confirm' && (o = 'ok'), o == 'failed' && (o = 'fail'), o.indexOf('failed_') != -1 && (o = o.substring(7)), o.indexOf('fail_') != -1 && (o = o.substring(5)), (o = (o = o.replace(/_/g, ' ')).toLowerCase()) != 'access denied' && o != 'no permission to execute' || (o = 'permission denied'), i == 'config' && o == 'function not exist' && (o = 'ok'), o == '' && (o = 'fail') } return n = i + ':' + o }(e, t)), n.errMsg = t), (i = i || {})._complete && (i._complete(n), delete i._complete), t = n.errMsg || '', v.debug && !i.isInnerInvoke && alert(JSON.stringify(n)); var o = t.indexOf(':'); switch (t.substring(o + 1)) { case 'ok':i.success && i.success(n); break; case 'cancel':i.cancel && i.cancel(n); break; default:i.fail && i.fail(n) }i.complete && i.complete(n) } function C(e) { if (e) { for (var n = 0, i = e.length; n < i; ++n) { var t = e[n]; var o = c[t]; o && (e[n] = o) } return e } } function B(e, n) { if (!(!v.debug || n && n.isInnerInvoke)) { var i = a[e]; i && (e = i), n && n._complete && delete n._complete, console.log('"' + e + '",', n || '') } } function L() { return (new Date()).getTime() } function O(e) { l && (o.WeixinJSBridge ? e() : i.addEventListener && i.addEventListener('WeixinJSBridgeReady', e, !1)) } }))
... ...
{
"_from": "jweixin-1.6.0",
"_id": "jweixin-1.6.0@1.0.0",
"_inBundle": false,
"_integrity": "sha512-QH69Y/j4h8p9dy6wqIplXmhjLy67AGJswvrjwWUD84HUdB22QyHaX1PmV7oJFbsYL+Vn9Qe1uIx/2NFKkD51Bg==",
"_location": "/jweixin-1.6.0",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "jweixin-1.6.0",
"name": "jweixin-1.6.0",
"escapedName": "jweixin-1.6.0",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/jweixin-1.6.0/-/jweixin-1.6.0-1.0.0.tgz",
"_shasum": "d65ec53e738a95b5c54cd5f42a3f34f0e82e29d5",
"_spec": "jweixin-1.6.0",
"_where": "F:\\minigroup\\Bitcoin",
"author": {
"name": "luquan基于微信官方jdk"
},
"bugs": {
"url": "https://github.com/luquan22/jweixin-js-sdk/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "基于官方1.6.0制作",
"homepage": "https://github.com/luquan22/jweixin-js-sdk#readme",
"keywords": [
"jweixin"
],
"license": "ISC",
"main": "index.js",
"name": "jweixin-1.6.0",
"repository": {
"type": "git",
"url": "git+https://github.com/luquan22/jweixin-js-sdk.git"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"version": "1.0.0"
}
... ...
... ... @@ -2,6 +2,11 @@
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"jweixin-1.6.0": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/jweixin-1.6.0/-/jweixin-1.6.0-1.0.0.tgz",
"integrity": "sha512-QH69Y/j4h8p9dy6wqIplXmhjLy67AGJswvrjwWUD84HUdB22QyHaX1PmV7oJFbsYL+Vn9Qe1uIx/2NFKkD51Bg=="
},
"jweixin-module": {
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/jweixin-module/-/jweixin-module-1.6.0.tgz",
... ...
... ... @@ -48,6 +48,8 @@
},
onLoad() {
this.sort_all()
let URL=window.location.href
this.$wxH5Share.get_jssdk("分类",URL)
},
methods: {
//返回
... ...
... ... @@ -8,7 +8,8 @@
</view>
<image src="../../static/ic_fenxiang.png" mode="" @click="shareModel=true"></image>
</view>
<rich-text :nodes="detail.content"></rich-text>
<mp-html :content="detail.content" />
<!-- <rich-text :nodes="detail.content"></rich-text> -->
</view>
<view class="share" v-if="shareModel" @click="shareModel=false">
<image src="/static/detailShare.png" mode=""></image>
... ... @@ -23,8 +24,9 @@
import {
arc_detail
} from '@/api/index.js'
var jweixin = require('jweixin-module');
console.log(jweixin, "000")
// import wx from 'jweixin-1.6.0'
// var jweixin = require('jweixin-module');
// console.log(jweixin, "000")
export default {
data() {
return {
... ... @@ -36,16 +38,26 @@
},
shareModel: false,
Images: "http://yuanjie.n.broing.cn/assets/img/share_logo.jpg",
jssdk:{},
jssdk: {},
}
},
onLoad(options) {
this.id = options.id
let title = uni.getStorageSync("deltitle")
uni.setNavigationBarTitle({
title: title //这是修改后的导航栏文字
})
let URL=window.location.href
this.$wxH5Share.get_jssdk(title,URL)
this.arc_detail()
// console.log(!(uni.getSystemInfoSync().platform == 'android'))
// if (!(uni.getSystemInfoSync().platform == 'android')) {
// if (location.href.indexOf("#reloaded") == -1) {
// location.href = location.href + "#reloaded";
// location.reload();
// }
// }
},
onUnload() {
uni.removeStorageSync("deltitle")
... ... @@ -55,9 +67,10 @@
async arc_detail() {
try {
const res = await arc_detail(this.id, window.location.href)
this.detail = res.detail
this.jssdk = res.jssdk
this.share()
// this.share()
console.log('arc_detail', res)
// 保存数据
} catch (err) {
... ... @@ -68,83 +81,6 @@
console.log('arc_detail', err)
}
},
share() {
let that = this;
jweixin.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: that.jssdk.appId, // 必填,公众号的唯一标识
timestamp: that.jssdk.timestamp, // 必填,生成签名的时间戳
nonceStr: that.jssdk.nonceStr, // 必填,生成签名的随机串
signature: that.jssdk.signature, // 必填,签名
jsApiList: that.jssdk.jsApiList // 必填,需要使用的JS接口列表
})
jweixin.error(function(res) {
console.log(res, '错误')
});
console.log('分享了', that.jssdk.signature);
jweixin.ready(function() {
//分享给朋友
jweixin.onMenuShareAppMessage({
title: that.detail.title, // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc: "【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: that.Images, // 分享图标
success: function() {
// 用户点击了分享后执行的回调函数
uni.showToast({
title: '分享成功',
duration: 2000
});
},
cancel: function(res) {
console.log('取消分享')
}
});
jweixin.updateAppMessageShareData({
title: that.detail.title, // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc: "【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: that.Images, // 分享图标
success: function() {
console.log('设置分享给朋友成功')
},
cancel: function(res) {
console.log('取消分享')
}
});
//分享到朋友圈
jweixin.onMenuShareTimeline({
title: that.detail.title, // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc: "【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: that.Images, // 分享图标
success: function() {
// 用户点击了分享后执行的回调函数
uni.showToast({
title: '分享成功',
duration: 2000
});
},
cancel: function(res) {
console.log('取消分享')
}
});
jweixin.updateTimelineShareData({
title: that.detail.title, // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc: "【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: that.Images, // 分享图标
success: function() {
console.log('设置分享到朋友圈成功')
},
cancel: function(res) {
console.log('取消分享')
}
});
});
},
}
}
</script>
... ...
<template>
<view class="Detail">
<view class="topbg">
<view class="bgimage">
<u-swiper :list="list1" @change="change" @click="onclick" :height="375"></u-swiper>
</view>
<view class="topmain">
<view class="toptitle">
<view class="money">
<text>¥</text>{{detail.price}}
</view>
<view class="topgroup">
<image src="../../static/heart.png" mode="" v-if="detail.is_fav==0" @click="product_favorite">
</image>
<image src="../../static/1.png" mode="" v-else @click="product_favorite"></image>
<image src="../../static/share.png" @click="shareModel=true" mode=""></image>
<image src="../../static/result.png" mode="" @click="show = true"></image>
</view>
</view>
<view class="topcommit">
{{detail.name}}
</view>
<view class="toptype">
<view class="type">
所属分类:{{detail.sort.name}}
</view>
<view class="time">
发布于:{{detail.publishtime}}
</view>
</view>
</view>
</view>
<view class="mainmiss">
<view class="misstop">
<view class="tip">
</view>
<text>卖家信息</text>
</view>
<view class="missbar flexA">
<view class="name">
姓名
</view>
<view class="namelast">
{{detail.seller_name}}
</view>
</view>
<view class="missbar flexA">
<view class="name">
联系电话:
</view>
<view class="namelast">
{{detail.seller_mobile}}
<template>
<view class="Detail">
<view class="topbg">
<view class="bgimage">
<u-swiper :list="list1" @change="change" @click="onclick" :height="375"></u-swiper>
</view>
<view class="topmain">
<view class="toptitle">
<view class="money">
<text>¥</text>{{detail.price}}
</view>
<view class="topgroup">
<image src="../../static/heart.png" mode="" v-if="detail.is_fav==0" @click="product_favorite">
</image>
<image src="../../static/1.png" mode="" v-else @click="product_favorite"></image>
<image src="../../static/share.png" @click="shareModel=true" mode=""></image>
<image src="../../static/result.png" mode="" @click="show = true"></image>
</view>
</view>
<view class="topcommit">
{{detail.name}}
</view>
<view class="toptype">
<view class="type">
所属分类:{{detail.sort.name}}
</view>
<view class="time">
发布于:{{detail.publishtime}}
</view>
</view>
</view>
</view>
<view class="mainmiss">
<view class="misstop">
<view class="tip">
</view>
<text>卖家信息</text>
</view>
<view class="missbar flexA">
<view class="name">
姓名
</view>
<view class="namelast">
{{detail.seller_name}}
</view>
</view>
<view class="missbar flexA">
<view class="name">
联系电话:
</view>
<view class="namelast">
{{detail.seller_mobile}}
</view>
<view style=" margin-left:8rpx; font-size: 26rpx; color: deepskyblue;" v-if="detail.seller_mobile">
<a :href="'tel:' + detail.seller_mobile" >拨号</a>
</view>
</view>
<view class="missbar flexA" >
<view class="name">
钱包地址:
</view>
<view class="namelast">
{{detail.package_add}}
<a :href="'tel:' + detail.seller_mobile">拨号</a>
</view>
<view @click="copy(detail.package_add)" style=" margin-left:8rpx; font-size: 26rpx; color: deepskyblue;">
</view>
<view class="missbar flexA">
<view class="name">
钱包地址:
</view>
<view class="namelast">
{{detail.package_add}}
</view>
<view @click="copy(detail.package_add)"
style=" margin-left:8rpx; font-size: 26rpx; color: deepskyblue;">
复制
</view>
</view>
<view class="missbar flexA">
<view class="name">
微信号:
</view>
<view class="namelast">
{{detail.wechat_num}}
</view>
</view>
<view class="missbar flexA">
<view class="name">
微信号:
</view>
<view class="namelast">
{{detail.wechat_num}}
</view>
<view @click="copy(detail.wechat_num)" style=" margin-left:8rpx; font-size: 26rpx; color: deepskyblue;">
复制
</view>
</view>
</view>
<view class="contail">
<view class="misstop">
<view class="tip">
</view>
<text>商品详情</text>
</view>
<view class="showcontant">
{{detail.description}}
</view>
</view>
<view class="btn">
<view class="paybtn" :class="detail.status==2?'sold':''" @click="product_buy">
{{detail.status==2?'已售出':'立即购买'}}
</view>
</view>
<!-- <u-picker :show="resurtshow" :columns="columns"></u-picker> -->
<u-popup :show="show" @close="close" @open="open" mode="center" :round="12">
<view class="popshow">
<view class="title">
举报
</view>
<view class="showbar">
<view class="name">
举报原因
</view>
<view class="select" @click.stop="showbox">
<text>{{isshowname}}</text>
<image src="../../static/ic-arrow2.png" mode=""></image>
</view>
</view>
<view class="showarear">
<view class="showtltle">
详细描述
</view>
<view class="showcont">
<textarea name="" v-model="content" id="" cols="30" rows="10" placeholder="请输入"></textarea>
</view>
</view>
<view class="btngroup">
<view class="concle" @click="close">
取消
</view>
<view class="requt" @click="product_report">
提交
</view>
</view>
<view class="boxsel" v-if="isshow">
<scroll-view scroll-y="true" style="200rpx">
<view class="selbar" v-for="(item,index) in range" :key="index"
@click="choosritem(item.name,item.id)">{{item.name}} </view>
</scroll-view>
</view>
</view>
</view>
</view>
</view>
<view class="contail">
<view class="misstop">
<view class="tip">
</view>
<text>商品详情</text>
</view>
<view class="showcontant">
{{detail.description}}
</view>
</view>
<view class="btn">
<view class="paybtn" :class="detail.status==2?'sold':''" @click="product_buy">
{{detail.status==2?'已售出':'立即购买'}}
</view>
</view>
<!-- <u-picker :show="resurtshow" :columns="columns"></u-picker> -->
<u-popup :show="show" @close="close" @open="open" mode="center" :round="12">
<view class="popshow">
<view class="title">
举报
</view>
<view class="showbar">
<view class="name">
举报原因
</view>
<view class="select" @click.stop="showbox">
<text>{{isshowname}}</text>
<image src="../../static/ic-arrow2.png" mode=""></image>
</view>
</view>
<view class="showarear">
<view class="showtltle">
详细描述
</view>
<view class="showcont">
<textarea name="" v-model="content" id="" cols="30" rows="10" placeholder="请输入"></textarea>
</view>
</view>
<view class="btngroup">
<view class="concle" @click="close">
取消
</view>
<view class="requt" @click="product_report">
提交
</view>
</view>
<view class="boxsel" v-if="isshow">
<scroll-view scroll-y="true" style="200rpx">
<view class="selbar" v-for="(item,index) in range" :key="index"
@click="choosritem(item.name,item.id)">{{item.name}} </view>
</scroll-view>
</view>
</view>
</u-popup>
<image class="goTop" @click="goTop" src="/static/top.png" mode=""></image>
<image class="home" @click="goHome" src="/static/home.png" mode=""></image>
... ... @@ -142,73 +143,80 @@
<view class="">
点击这里进行分享
</view>
</view>
</view>
</template>
</view>
</view>
</template>
<script>
var jweixin = require('jweixin-module');
import {
product_detail,
product_favorite,
report_list,
product_report
} from '@/api/index.js'
import {
toa
} from '@/utils/toast.js'
export default {
data() {
return {
id: "",
String: "",
show: false,
value: 0,
detail: {
sort: {
name: ""
}
var jweixin = require('jweixin-module');
import {
product_detail,
product_favorite,
report_list,
product_report
} from '@/api/index.js'
import {
toa
} from '@/utils/toast.js'
export default {
data() {
return {
id: "",
String: "",
show: false,
value: 0,
detail: {
sort: {
name: ""
}
},
jssdk:{},
list1: [], //轮播图
range: [{
value: 0,
text: "篮球"
},
{
value: 1,
text: "足球"
},
{
value: 2,
text: "游泳"
},
],
//举报弹窗
isshow: false,
isshowname: "请选择",
isid: "",
jssdk: {},
list1: [], //轮播图
range: [{
value: 0,
text: "篮球"
},
{
value: 1,
text: "足球"
},
{
value: 2,
text: "游泳"
},
],
//举报弹窗
isshow: false,
isshowname: "请选择",
isid: "",
content: "",
shareModel:false
}
shareModel: false
}
},
onShow() {
},
onLoad(options) {
this.id = options.id
this.product_detail()
onLoad(options) {
this.id = options.id
this.product_detail()
this.report_list()
},
// console.log(!(uni.getSystemInfoSync().platform == 'android'))
// if (!(uni.getSystemInfoSync().platform == 'android')) {
// if (location.href.indexOf("#reloaded") == -1) {
// location.href = location.href + "#reloaded";
// location.reload();
// }
// }
},
methods: {
onclick(index){
onclick(index) {
uni.previewImage({
current: index,
urls: this.list1,
});
},
goTop(){
goTop() {
uni.pageScrollTo({
scrollTop: 0
});
... ... @@ -225,502 +233,506 @@
}
});
},
goHome(){
goHome() {
uni.reLaunch({
url:'/pages/index/index'
url: '/pages/index/index'
})
},
share(){
share() {
let that = this;
jweixin.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: that.jssdk.appId, // 必填,公众号的唯一标识
timestamp: that.jssdk.timestamp, // 必填,生成签名的时间戳
nonceStr: that.jssdk.nonceStr, // 必填,生成签名的随机串
signature: that.jssdk.signature, // 必填,签名
jsApiList: that.jssdk.jsApiList // 必填,需要使用的JS接口列表
})
jweixin.error(function(res) {
console.log(res, '错误')
});
console.log('分享了',that.jssdk.signature);
jweixin.ready(function() {
//分享给朋友
jweixin.onMenuShareAppMessage({
title: that.detail.name, // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc:"【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: that.detail.images_preview[0], // 分享图标
success: function() {
// 用户点击了分享后执行的回调函数
uni.showToast({
title: '分享成功',
duration: 2000
});
},
cancel: function(res) {
console.log('取消分享')
}
});
jweixin.updateAppMessageShareData({
title: that.detail.name, // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc:"【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: that.detail.images_preview[0], // 分享图标
success: function() {
console.log('设置分享给朋友成功')
},
cancel: function(res) {
console.log('取消分享')
}
});
//分享到朋友圈
jweixin.onMenuShareTimeline({
title: that.detail.name, // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc:"【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: that.detail.images_preview[0], // 分享图标
success: function() {
// 用户点击了分享后执行的回调函数
uni.showToast({
title: '分享成功',
duration: 2000
});
},
cancel: function(res) {
console.log('取消分享')
}
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: that.jssdk.appId, // 必填,公众号的唯一标识
timestamp: that.jssdk.timestamp, // 必填,生成签名的时间戳
nonceStr: that.jssdk.nonceStr, // 必填,生成签名的随机串
signature: that.jssdk.signature, // 必填,签名
jsApiList: that.jssdk.jsApiList // 必填,需要使用的JS接口列表
})
jweixin.error(function(res) {
console.log(res, '错误')
});
console.log('分享了', that.jssdk.signature);
jweixin.ready(function() {
//分享给朋友
jweixin.onMenuShareAppMessage({
title: that.detail.name, // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc: "【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: that.detail.images_preview[0], // 分享图标
success: function() {
// 用户点击了分享后执行的回调函数
uni.showToast({
title: '分享成功',
duration: 2000
});
jweixin.updateTimelineShareData({
title: that.detail.name, // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc:"【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: that.detail.images_preview[0], // 分享图标
success: function() {
console.log('设置分享到朋友圈成功')
},
cancel: function(res) {
console.log('取消分享')
}
},
cancel: function(res) {
console.log('取消分享')
}
});
jweixin.updateAppMessageShareData({
title: that.detail.name, // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc: "【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: that.detail.images_preview[0], // 分享图标
success: function() {
console.log('设置分享给朋友成功')
},
cancel: function(res) {
console.log('取消分享')
}
});
//分享到朋友圈
jweixin.onMenuShareTimeline({
title: that.detail.name, // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc: "【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: that.detail.images_preview[0], // 分享图标
success: function() {
// 用户点击了分享后执行的回调函数
uni.showToast({
title: '分享成功',
duration: 2000
});
},
cancel: function(res) {
console.log('取消分享')
}
});
jweixin.updateTimelineShareData({
title: that.detail.name, // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc: "【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: that.detail.images_preview[0], // 分享图标
success: function() {
console.log('设置分享到朋友圈成功')
},
cancel: function(res) {
console.log('取消分享')
}
});
});
},
showbox() {
this.isshow = !this.isshow
},
open() {},
close() {
this.show = false
},
change(e) {
// console.log("e:", e);
},
//选中效果
choosritem(name, id) {
this.isshowname = name
this.isid = id
this.isshow = false
},
// 举报原因
async report_list() {
try {
const res = await report_list()
console.log('report_list', res)
this.range = res.list
// 保存数据
} catch (err) {
uni.showToast({
title: err,
icon: 'none'
})
console.log('report_list', err)
}
},
// 举报
async product_report() {
if (!this.isid) return toa.toast('请选择举报原因')
if (!this.content) return toa.toast('请填写举报信息')
let obj = {
product_id: this.id,
report_id: this.isid,
content: this.content,
}
try {
const res = await product_report(obj)
console.log('product_report', res)
toa.toast('举报成功')
this.show = false
// 保存数据
} catch (err) {
uni.showToast({
title: err,
icon: 'none'
})
console.log('product_report', err)
}
},
//收藏、取消收藏
async product_favorite() {
try {
const res = await product_favorite(this.id)
console.log('product_favorite', res)
this.product_detail()
// 保存数据
} catch (err) {
uni.showToast({
title: err,
icon: 'none'
})
console.log('product_favorite', err)
}
},
//详情
},
showbox() {
this.isshow = !this.isshow
},
open() {},
close() {
this.show = false
},
change(e) {
// console.log("e:", e);
},
//选中效果
choosritem(name, id) {
this.isshowname = name
this.isid = id
this.isshow = false
},
// 举报原因
async report_list() {
try {
const res = await report_list()
console.log('report_list', res)
this.range = res.list
// 保存数据
} catch (err) {
uni.showToast({
title: err,
icon: 'none'
})
console.log('report_list', err)
}
},
// 举报
async product_report() {
if (!this.isid) return toa.toast('请选择举报原因')
if (!this.content) return toa.toast('请填写举报信息')
let obj = {
product_id: this.id,
report_id: this.isid,
content: this.content,
}
try {
const res = await product_report(obj)
console.log('product_report', res)
toa.toast('举报成功')
this.show = false
// 保存数据
} catch (err) {
uni.showToast({
title: err,
icon: 'none'
})
console.log('product_report', err)
}
},
//收藏、取消收藏
async product_favorite() {
try {
const res = await product_favorite(this.id)
console.log('product_favorite', res)
this.product_detail()
// 保存数据
} catch (err) {
uni.showToast({
title: err,
icon: 'none'
})
console.log('product_favorite', err)
}
},
//详情
async product_detail() {
try {
const res = await product_detail(this.id,window.location.href)
console.log('product_detail', res)
try {
const res = await product_detail(this.id, window.location.href)
console.log('product_detail', res)
this.detail = res.detail
this.jssdk = res.jssdk
this.jssdk = res.jssdk
this.list1 = res.detail.images_preview
this.share()
// 保存数据
} catch (err) {
uni.showToast({
title: err,
icon: 'none'
})
console.log('product_detail', err)
}
},
//下单跳转
this.share()
// 保存数据
} catch (err) {
uni.showToast({
title: err,
icon: 'none'
})
console.log('product_detail', err)
}
},
//下单跳转
async product_buy() {
if(this.detail.status==2) return
uni.navigateTo({
url: "/pages/index/buy?id=" + this.id
})
if (this.detail.status == 2) return
uni.navigateTo({
url: "/pages/index/buy?id=" + this.id
})
},
},
}
</script>
<style lang="scss">
page {
background-color: #f0f0f0;
}
.Detail {
padding-bottom: 160rpx;
.topbg {
.bgimage {
width: 750rpx;
height: 750rpx;
}
.topmain {
padding: 32rpx;
background-color: #ffffff;
.toptitle {
display: flex;
align-items: center;
justify-content: space-between;
.money {
font-size: 52rpx;
font-weight: 500;
font-family: "PingFang SC";
color: rgba(248, 83, 23, 1);
text {
color: rgba(248, 83, 23, 1);
font-size: 32rpx;
font-weight: 500;
font-family: "PingFang SC";
}
}
.topgroup {
display: flex;
align-items: center;
image {
margin-right: 32rpx;
width: 40rpx;
height: 40rpx;
}
}
}
.topcommit {
margin-top: 16rpx;
color: rgba(0, 0, 0, 1);
font-size: 36rpx;
font-weight: 600;
font-family: "PingFang SC";
text-align: left;
}
.toptype {
margin-top: 24rpx;
display: flex;
align-items: center;
color: rgba(0, 0, 0, 0.4);
font-size: 26rpx;
font-weight: 400;
font-family: "PingFang SC";
justify-content: space-between;
}
}
}
.mainmiss {
margin-top: 24rpx;
background-color: #ffffff;
border-radius: 24rpx;
padding: 32rpx;
box-sizing: border-box;
.misstop {
display: flex;
align-items: center;
color: rgba(0, 0, 0, 0.9);
font-size: 32rpx;
font-weight: 600;
font-family: "PingFang SC";
.tip {
margin-right: 8rpx;
width: 4rpx;
height: 24rpx;
border-radius: 18rpx;
opacity: 1;
background: rgba(254, 208, 0, 1);
}
}
.showcontant {
margin-top: 24rpx;
color: rgba(0, 0, 0, 0.4);
font-size: 24rpx;
font-weight: 400;
},
}
</script>
<style lang="scss">
page {
background-color: #f0f0f0;
}
.Detail {
padding-bottom: 160rpx;
.topbg {
.bgimage {
width: 750rpx;
height: 750rpx;
}
.topmain {
padding: 32rpx;
background-color: #ffffff;
.toptitle {
display: flex;
align-items: center;
justify-content: space-between;
.money {
font-size: 52rpx;
font-weight: 500;
font-family: "PingFang SC";
color: rgba(248, 83, 23, 1);
text {
color: rgba(248, 83, 23, 1);
font-size: 32rpx;
font-weight: 500;
font-family: "PingFang SC";
}
}
.topgroup {
display: flex;
align-items: center;
image {
margin-right: 32rpx;
width: 40rpx;
height: 40rpx;
}
}
}
.topcommit {
margin-top: 16rpx;
color: rgba(0, 0, 0, 1);
font-size: 36rpx;
font-weight: 600;
font-family: "PingFang SC";
text-align: left;
}
.toptype {
margin-top: 24rpx;
display: flex;
align-items: center;
color: rgba(0, 0, 0, 0.4);
font-size: 26rpx;
font-weight: 400;
font-family: "PingFang SC";
justify-content: space-between;
}
}
}
.mainmiss {
margin-top: 24rpx;
background-color: #ffffff;
border-radius: 24rpx;
padding: 32rpx;
box-sizing: border-box;
.misstop {
display: flex;
align-items: center;
color: rgba(0, 0, 0, 0.9);
font-size: 32rpx;
font-weight: 600;
font-family: "PingFang SC";
}
.missbar {
margin-top: 24rpx;
.name {
color: rgba(0, 0, 0, 0.6);
font-size: 28rpx;
font-weight: 400;
font-family: "PingFang SC";
width: 168rpx;
}
.tip {
margin-right: 8rpx;
width: 4rpx;
height: 24rpx;
border-radius: 18rpx;
opacity: 1;
background: rgba(254, 208, 0, 1);
}
}
.showcontant {
margin-top: 24rpx;
color: rgba(0, 0, 0, 0.4);
font-size: 24rpx;
font-weight: 400;
font-family: "PingFang SC";
}
.missbar {
margin-top: 24rpx;
.name {
color: rgba(0, 0, 0, 0.6);
font-size: 28rpx;
font-weight: 400;
font-family: "PingFang SC";
width: 168rpx;
}
.namelast {
width: 420rpx;
word-break: break-all;
color: rgba(0, 0, 0, 1);
font-size: 28rpx;
font-weight: 400;
font-family: "PingFang SC";
word-break: break-all;
color: rgba(0, 0, 0, 1);
font-size: 28rpx;
font-weight: 400;
font-family: "PingFang SC";
}
a{
a {
text-decoration: none;
color: deepskyblue;
}
}
}
.contail {
margin-top: 24rpx;
background-color: #ffffff;
border-radius: 24rpx;
padding: 32rpx;
box-sizing: border-box;
white-space: pre-wrap;
.misstop {
display: flex;
align-items: center;
color: rgba(0, 0, 0, 0.9);
font-size: 32rpx;
font-weight: 600;
font-family: "PingFang SC";
.tip {
margin-right: 8rpx;
width: 4rpx;
height: 24rpx;
border-radius: 18rpx;
opacity: 1;
background: rgba(254, 208, 0, 1);
}
}
}
.btn {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 128rpx;
padding: 16rpx 32rpx;
box-sizing: border-box;
opacity: 1;
background: rgba(255, 255, 255, 1);
.paybtn {
width: 100%;
height: 96rpx;
line-height: 96rpx;
text-align: center;
border-radius: 28rpx;
opacity: 1;
color: rgba(0, 0, 0, 0.9);
font-size: 32rpx;
font-weight: 600;
font-family: "PingFang SC";
background: linear-gradient(134.8deg, rgba(255, 232, 100, 1) 0%, rgba(255, 216, 0, 1) 100%);
}
}
.popshow {
border-radius: 32rpx;
width: 622rpx;
padding: 48rpx;
box-sizing: border-box;
.title {
color: rgba(0, 0, 0, 1);
font-size: 28rpx;
font-weight: 600;
font-family: "PingFang SC";
text-align: center;
}
.showbar {
padding: 24rpx 0;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
border-bottom: 1px solid #f0f0f0;
color: rgba(0, 0, 0, 0.9);
font-size: 28rpx;
font-weight: 400;
.name {
font-family: "PingFang SC";
}
.select {
display: flex;
align-items: center;
image {
width: 24rpx;
height: 16rpx;
}
}
}
.showarear {
text-align: left;
.showtltle {
margin-top: 32rpx;
color: rgba(0, 0, 0, 1);
font-size: 28rpx;
font-weight: 400;
font-family: "PingFang SC";
}
.showcont {
color: rgba(0, 0, 0, 0.4);
font-size: 24rpx;
font-weight: 400;
font-family: "PingFang SC";
text-align: left;
}
textarea {
margin-top: 12rpx;
box-sizing: border-box;
padding: 24rpx;
width: 526rpx;
height: 252rpx;
border: 2rpx solid rgba(0.9407999515533447, 0.9475764036178589, 0.9599999785423279, .1);
}
}
.btngroup {
margin-top: 80rpx;
display: flex;
align-items: center;
justify-content: space-between;
.concle {
width: 240rpx;
height: 76rpx;
border-radius: 16rpx;
opacity: 1;
line-height: 76rpx;
color: rgba(0, 0, 0, 0.9);
font-size: 28rpx;
font-weight: 500;
font-family: "PingFang SC";
text-align: center;
background: rgba(246, 246, 246, 1);
}
.requt {
width: 240rpx;
height: 76rpx;
color: rgba(0, 0, 0, 0.9);
font-size: 28rpx;
font-weight: 500;
font-family: "PingFang SC";
text-align: center;
line-height: 76rpx;
border-radius: 16rpx;
opacity: 1;
background: rgba(254, 208, 0, 1);
}
}
.boxsel {
position: absolute;
top: 75px;
right: 26px;
border: 1px solid #f0f0f0;
padding: 6px;
color: rgba(0, 0, 0, 1);
font-size: 24rpx;
font-weight: 400;
background-color: #ffffff;
.selbar {
padding: 6px;
}
}
}
}
}
}
.contail {
margin-top: 24rpx;
background-color: #ffffff;
border-radius: 24rpx;
padding: 32rpx;
box-sizing: border-box;
white-space: pre-wrap;
.misstop {
display: flex;
align-items: center;
color: rgba(0, 0, 0, 0.9);
font-size: 32rpx;
font-weight: 600;
font-family: "PingFang SC";
.tip {
margin-right: 8rpx;
width: 4rpx;
height: 24rpx;
border-radius: 18rpx;
opacity: 1;
background: rgba(254, 208, 0, 1);
}
}
}
.btn {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 128rpx;
padding: 16rpx 32rpx;
box-sizing: border-box;
opacity: 1;
background: rgba(255, 255, 255, 1);
.paybtn {
width: 100%;
height: 96rpx;
line-height: 96rpx;
text-align: center;
border-radius: 28rpx;
opacity: 1;
color: rgba(0, 0, 0, 0.9);
font-size: 32rpx;
font-weight: 600;
font-family: "PingFang SC";
background: linear-gradient(134.8deg, rgba(255, 232, 100, 1) 0%, rgba(255, 216, 0, 1) 100%);
}
}
.popshow {
border-radius: 32rpx;
width: 622rpx;
padding: 48rpx;
box-sizing: border-box;
.title {
color: rgba(0, 0, 0, 1);
font-size: 28rpx;
font-weight: 600;
font-family: "PingFang SC";
text-align: center;
}
.showbar {
padding: 24rpx 0;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
border-bottom: 1px solid #f0f0f0;
color: rgba(0, 0, 0, 0.9);
font-size: 28rpx;
font-weight: 400;
.name {
font-family: "PingFang SC";
}
.select {
display: flex;
align-items: center;
image {
width: 24rpx;
height: 16rpx;
}
}
}
.showarear {
text-align: left;
.showtltle {
margin-top: 32rpx;
color: rgba(0, 0, 0, 1);
font-size: 28rpx;
font-weight: 400;
font-family: "PingFang SC";
}
.showcont {
color: rgba(0, 0, 0, 0.4);
font-size: 24rpx;
font-weight: 400;
font-family: "PingFang SC";
text-align: left;
}
textarea {
margin-top: 12rpx;
box-sizing: border-box;
padding: 24rpx;
width: 526rpx;
height: 252rpx;
border: 2rpx solid rgba(0.9407999515533447, 0.9475764036178589, 0.9599999785423279, .1);
}
}
.btngroup {
margin-top: 80rpx;
display: flex;
align-items: center;
justify-content: space-between;
.concle {
width: 240rpx;
height: 76rpx;
border-radius: 16rpx;
opacity: 1;
line-height: 76rpx;
color: rgba(0, 0, 0, 0.9);
font-size: 28rpx;
font-weight: 500;
font-family: "PingFang SC";
text-align: center;
background: rgba(246, 246, 246, 1);
}
.requt {
width: 240rpx;
height: 76rpx;
color: rgba(0, 0, 0, 0.9);
font-size: 28rpx;
font-weight: 500;
font-family: "PingFang SC";
text-align: center;
line-height: 76rpx;
border-radius: 16rpx;
opacity: 1;
background: rgba(254, 208, 0, 1);
}
}
.boxsel {
position: absolute;
top: 75px;
right: 26px;
border: 1px solid #f0f0f0;
padding: 6px;
color: rgba(0, 0, 0, 1);
font-size: 24rpx;
font-weight: 400;
background-color: #ffffff;
.selbar {
padding: 6px;
}
}
}
}
.share {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,.6);
background: rgba(0, 0, 0, .6);
image {
position: fixed;
right: 80rpx;
... ... @@ -728,15 +740,17 @@
width: 188rpx;
height: 262rpx;
}
view {
position: fixed;
right: 80rpx;
top: 300rpx;
color: rgba(255,255,255,1);
font-size: 36rpx;
font-weight: 700;
color: rgba(255, 255, 255, 1);
font-size: 36rpx;
font-weight: 700;
}
}
.home {
width: 96rpx;
height: 96rpx;
... ... @@ -744,6 +758,7 @@
right: 28rpx;
bottom: 320rpx;
}
.goTop {
width: 96rpx;
height: 96rpx;
... ... @@ -751,7 +766,8 @@
right: 28rpx;
bottom: 186rpx;
}
.sold {
background: rgba(0,0,0,.2) !important;
}
background: rgba(0, 0, 0, .2) !important;
}
</style>
... ...
... ... @@ -116,6 +116,7 @@
} from '@/api/index'
import helangWaterfall from "@/uni_modules/custom-waterfalls-flow/components/custom-waterfalls-flow/custom-waterfalls-flow.vue"
import Botton from "@/components/Botton.vue"
export default {
components: {
"custom-waterfalls-flow": helangWaterfall,
... ... @@ -142,6 +143,8 @@
},
onLoad(e) {
this.product_list(true)
let URL=window.location.href
this.$wxH5Share.get_jssdk("首页",URL)
},
onReachBottom() {
this.currentpage++
... ...
... ... @@ -57,6 +57,8 @@
uni.setNavigationBarTitle({
title: "产品" //这是修改后的导航栏文字
})
let URL=window.location.href
this.$wxH5Share.get_jssdk("产品",URL)
}
if (options.sort_id) {
this.sort_id = options.sort_id
... ... @@ -65,6 +67,8 @@
uni.setNavigationBarTitle({
title: that.sort_name //这是修改后的导航栏文字
})
let URL=window.location.href
this.$wxH5Share.get_jssdk(that.sort_name,URL)
}
this.product_list(true)
},
... ...
... ... @@ -21,7 +21,7 @@
<view class="bot flexA">
<view class="left flexA">
<image :src="item.image_preview" mode=""></image>
<view class="">
<view class="lefte">
<view class="title">{{item.title}}</view>
<view class="time">发布时间:{{item.publishtime}}</view>
</view>
... ... @@ -56,6 +56,8 @@
uni.setNavigationBarTitle({
title: title //这是修改后的导航栏文字
})
let URL=window.location.href
this.$wxH5Share.get_jssdk(title,URL)
this.sort_list(true)
},
... ... @@ -230,17 +232,21 @@
}
.left {
.title {
font-size: 28rpx;
font-weight: 700;
.lefte{
flex: 1;
.title {
font-size: 28rpx;
font-weight: 700;
}
.time {
margin-top: 32rpx;
color: rgba(0, 0, 0, 0.6);
font-size: 26rpx;
}
}
.time {
margin-top: 32rpx;
color: rgba(0, 0, 0, 0.6);
font-size: 26rpx;
}
}
}
... ...
... ... @@ -29,7 +29,9 @@
ktext: "",
};
},
onLoad() {
onLoad() {
let URL=window.location.href
this.$wxH5Share.get_jssdk("搜索",URL)
},
onShow() {
this.search_list()
... ...
... ... @@ -35,6 +35,8 @@
},
onLoad() {
this.problemSort()
let URL=window.location.href
this.$wxH5Share.get_jssdk("意见反馈",URL)
},
methods: {
toItem(id) {
... ...
... ... @@ -110,6 +110,10 @@
showLogin:false
}
},
onLoad() {
let URL=window.location.href
this.$wxH5Share.get_jssdk("我的",URL)
},
onShow() {
this.token = uni.getStorageSync('token') || ''
this.userInfo = uni.getStorageSync('userInfo') || ''
... ...
... ... @@ -47,6 +47,10 @@
lastPage:1
}
},
onLoad() {
let URL=window.location.href
this.$wxH5Share.get_jssdk("收藏",URL)
},
onShow() {
this.page = 1
this.list= [ ]
... ...
... ... @@ -82,6 +82,8 @@
onLoad() {
that = this
this.myProduct()
let URL=window.location.href
this.$wxH5Share.get_jssdk("发布",URL)
},
methods: {
async myProduct(f){
... ...
<template>
<view class="">
<rich-text :nodes="detail"></rich-text>
<view class="" style="padding: 24rpx;">
<mp-html :content="detail" />
</view>
</template>
... ...
## news
1. 欢迎加入 `QQ` 交流群:`699734691`
![group](https://6874-html-foe72-1259071903.tcb.qcloud.la/assets/group.jpg?sign=558401bccbd56b01debe1bfac6a3b55e&t=1648801090)
2. 示例微信小程序 `富文本插件` 添加 `获取组件包` 功能 [详细](https://jin-yufeng.gitee.io/mp-html/#/overview/quickstart?id=mp)
![富文本插件](https://6874-html-foe72-1259071903.tcb.qcloud.la/assets/case/%E5%AF%8C%E6%96%87%E6%9C%AC%E6%8F%92%E4%BB%B6.jpg?sign=200e28d06f36049c18d42cdd46270c35&t=1648801110)
## 功能介绍
- 全端支持(含 `v3、NVUE`
- 支持丰富的标签(包括 `table`、`video`、`svg` 等)
- 支持丰富的事件效果(自动预览图片、链接处理等)
- 支持设置占位图(加载中、出错时、预览时)
- 支持锚点跳转、长按复制等丰富功能
- 支持大部分 *html* 实体
- 丰富的插件(关键词搜索、内容 **编辑** 等)
- 效率高、容错性强且轻量化
查看 [功能介绍](https://jin-yufeng.gitee.io/mp-html/#/overview/feature) 了解更多
## 使用方法
- `uni_modules` 方式
1. 点击右上角的 `使用 HBuilder X 导入插件` 按钮直接导入项目或点击 `下载插件 ZIP` 按钮下载插件包并解压到项目的 `uni_modules/mp-html` 目录下
2. 在需要使用页面的 `(n)vue` 文件中添加
```html
<!-- 不需要引入,可直接使用 -->
<mp-html :content="html" />
```
```javascript
export default {
data() {
return {
html: '<div>Hello World!</div>'
}
}
}
```
3. 需要更新版本时在 `HBuilder X` 中右键 `uni_modules/mp-html` 目录选择 `从插件市场更新` 即可
- 源码方式
1.[github](https://github.com/jin-yufeng/mp-html/tree/master/dist/uni-app)[gitee](https://gitee.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 下载源码
插件市场的 **非 uni_modules 版本** 无法更新,不建议从插件市场获取
2. 在需要使用页面的 `(n)vue` 文件中添加
```html
<mp-html :content="html" />
```
```javascript
import mpHtml from '@/components/mp-html/mp-html'
export default {
// HBuilderX 2.5.5+ 可以通过 easycom 自动引入
components: {
mpHtml
},
data() {
return {
html: '<div>Hello World!</div>'
}
}
}
```
- npm 方式
1. 在项目根目录下执行
```bash
npm install mp-html
```
2. 在需要使用页面的 `(n)vue` 文件中添加
```html
<mp-html :content="html" />
```
```javascript
import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html'
export default {
// 不可省略
components: {
mpHtml
},
data() {
return {
html: '<div>Hello World!</div>'
}
}
}
```
3. 需要更新版本时执行以下命令即可
```bash
npm update mp-html
```
使用 *cli* 方式运行的项目,通过 *npm* 方式引入时,需要在 *vue.config.js* 中配置 *transpileDependencies*,详情可见 [#330](https://github.com/jin-yufeng/mp-html/issues/330#issuecomment-913617687)
如果在 **nvue** 中使用还要将 `dist/uni-app/static` 目录下的内容拷贝到项目的 `static` 目录下,否则无法运行
查看 [快速开始](https://jin-yufeng.gitee.io/mp-html/#/overview/quickstart) 了解更多
## 组件属性
| 属性 | 类型 | 默认值 | 说明 |
|:---:|:---:|:---:|---|
| container-style | String | | 容器的样式([2.1.0+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v210)) |
| content | String | | 用于渲染的 html 字符串 |
| copy-link | Boolean | true | 是否允许外部链接被点击时自动复制 |
| domain | String | | 主域名(用于链接拼接) |
| error-img | String | | 图片出错时的占位图链接 |
| lazy-load | Boolean | false | 是否开启图片懒加载 |
| loading-img | String | | 图片加载过程中的占位图链接 |
| pause-video | Boolean | true | 是否在播放一个视频时自动暂停其他视频 |
| preview-img | Boolean | true | 是否允许图片被点击时自动预览 |
| scroll-table | Boolean | false | 是否给每个表格添加一个滚动层使其能单独横向滚动 |
| selectable | Boolean | false | 是否开启文本长按复制 |
| set-title | Boolean | true | 是否将 title 标签的内容设置到页面标题 |
| show-img-menu | Boolean | true | 是否允许图片被长按时显示菜单 |
| tag-style | Object | | 设置标签的默认样式 |
| use-anchor | Boolean | false | 是否使用锚点链接 |
查看 [属性](https://jin-yufeng.gitee.io/mp-html/#/basic/prop) 了解更多
## 组件事件
| 名称 | 触发时机 |
|:---:|---|
| load | dom 树加载完毕时 |
| ready | 图片加载完毕时 |
| error | 发生渲染错误时 |
| imgtap | 图片被点击时 |
| linktap | 链接被点击时 |
查看 [事件](https://jin-yufeng.gitee.io/mp-html/#/basic/event) 了解更多
## api
组件实例上提供了一些 `api` 方法可供调用
| 名称 | 作用 |
|:---:|---|
| in | 将锚点跳转的范围限定在一个 scroll-view 内 |
| navigateTo | 锚点跳转 |
| getText | 获取文本内容 |
| getRect | 获取富文本内容的位置和大小 |
| setContent | 设置富文本内容 |
| imgList | 获取所有图片的数组 |
查看 [api](https://jin-yufeng.gitee.io/mp-html/#/advanced/api) 了解更多
## 插件扩展
除基本功能外,本组件还提供了丰富的扩展,可按照需要选用
| 名称 | 作用 |
|:---:|---|
| audio | 音乐播放器 |
| editable | 富文本 **编辑**[示例项目](https://6874-html-foe72-1259071903.tcb.qcloud.la/editable.zip?sign=cc0017be203fb3dbca62d33a0c15792e&t=1608447445)) |
| emoji | 解析 emoji |
| highlight | 代码块高亮显示 |
| markdown | 渲染 markdown |
| search | 关键词搜索 |
| style | 匹配 style 标签中的样式 |
| txv-video | 使用腾讯视频 |
| img-cache | 图片缓存 by [@PentaTea](https://github.com/PentaTea) |
从插件市场导入的包中 **不含有** 扩展插件,需要使用插件参考以下方法:
1. 获取完整组件包
```bash
npm install mp-html
```
2. 编辑 `tools/config.js` 中的 `plugins` 项,选择需要的插件
3. 生成新的组件包
`node_modules/mp-html` 目录下执行
```bash
npm install
npm run build:uni-app
```
4. 拷贝 `dist/uni-app` 中的内容到项目根目录
查看 [插件](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin) 了解更多
## 关于 nvue
`nvue` 使用原生渲染,不支持部分 `css` 样式,为实现和 `html` 相同的效果,组件内部通过 `web-view` 进行渲染,性能上差于原生,根据 `weex` 官方建议,`web` 标签仅应用在非常规的降级场景。因此,如果通过原生的方式(如 `richtext`)能够满足需要,则不建议使用本组件,如果有较多的富文本内容,则可以直接使用 `vue` 页面
由于渲染方式与其他端不同,有以下限制:
1. 不支持 `lazy-load` 属性
2. 视频不支持全屏播放
`nvue` 模式下,[此问题](https://ask.dcloud.net.cn/question/119678) 修复前,不支持通过 `uni_modules` 引入,需要本地引入(将 [dist/uni-app](https://github.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 中的内容拷贝到项目根目录下)
## 问题反馈
遇到问题时,请先查阅 [常见问题](https://jin-yufeng.gitee.io/mp-html/#/question/faq)[issue](https://github.com/jin-yufeng/mp-html/issues) 中是否已有相同的问题
可通过 [issue](https://github.com/jin-yufeng/mp-html/issues/new/choose) 、插件问答或发送邮件到 [mp_html@126.com](mailto:mp_html@126.com) 提问,不建议在评论区提问(不方便回复)
提问请严格按照 [issue 模板](https://github.com/jin-yufeng/mp-html/issues/new/choose) ,描述清楚使用环境、`html` 内容或可复现的 `demo` 项目以及复现方式,对于 **描述不清****无法复现** 或重复的问题将不予回复
查看 [问题反馈](https://jin-yufeng.gitee.io/mp-html/#/question/feedback) 了解更多
\ No newline at end of file
... ...
## v2.3.1(2022-05-20)
1. `U` `app` 端支持使用本地图片
2. `U` 优化了微信小程序 `selectable` 属性在 `ios` 端的处理 [详细](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#selectable)
3. `F` 修复了 `editable` 插件不在顶部时 `tooltip` 位置可能错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/430)
4. `F` 修复了 `vue3` 运行到微信小程序可能报错丢失内容的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/414)
5. `F` 修复了 `vue3` 部分标签可能被错误换行的问题
6. `F` 修复了 `editable` 插件 `app` 端插入视频无法预览的问题
## v2.3.0(2022-04-01)
1. `A` 增加了 `play` 事件,音视频播放时触发,可用于与页面其他音视频进行互斥播放 [详细](basic/event#play)
2. `U` `show-img-menu` 属性支持控制预览时是否长按弹出菜单
3. `U` 优化 `wxs` 处理,提高渲染性能 [详细](https://developers.weixin.qq.com/community/develop/article/doc/0006cc2b204740f601bd43fa25a413)
4. `U` `video` 标签支持 `object-fit` 属性
5. `U` 增加支持一些常用实体编码 [详细](https://github.com/jin-yufeng/mp-html/issues/418)
6. `F` 修复了图片仅设置高度可能不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/410)
7. `F` 修复了 `video` 标签高度设置为 `auto` 不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/411)
8. `F` 修复了使用 `grid` 布局时可能样式错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/413)
9. `F` 修复了含有合并单元格的表格部分情况下显示异常的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/417)
10. `F` 修复了 `editable` 插件连续插入内容时顺序不正确的问题
11. `F` 修复了 `uni-app` 包 `vue3` 使用 `audio` 插件报错的问题
12. `F` 修复了 `uni-app` 包 `highlight` 插件使用自定义的 `prism.min.js` 报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/416)
## v2.2.2(2022-02-26)
1. `A` 增加了 [pauseMedia](https://jin-yufeng.gitee.io/mp-html/#/advanced/api#pauseMedia) 的 `api`,可用于暂停播放音视频 [详细](https://github.com/jin-yufeng/mp-html/issues/317)
2. `U` 优化了长内容的加载速度
3. `U` 适配 `vue3` [#389](https://github.com/jin-yufeng/mp-html/issues/389)[#398](https://github.com/jin-yufeng/mp-html/pull/398) by [@zhouhuafei](https://github.com/zhouhuafei)[#400](https://github.com/jin-yufeng/mp-html/issues/400)
4. `F` 修复了小程序端图片高度设置为百分比时可能不显示的问题
5. `F` 修复了 `highlight` 插件部分情况下可能显示不完整的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/403)
## v2.2.1(2021-12-24)
1. `A` `editable` 插件增加上下移动标签功能
2. `U` `editable` 插件支持在文本中间光标处插入内容
3. `F` 修复了 `nvue` 端设置 `margin` 后可能导致高度不正确的问题
4. `F` 修复了 `highlight` 插件使用压缩版的 `prism.css` 可能导致背景失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/367)
5. `F` 修复了编辑状态下使用 `emoji` 插件内容为空时可能报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/371)
6. `F` 修复了使用 `editable` 插件后将 `selectable` 属性设置为 `force` 不生效的问题
## v2.2.0(2021-10-12)
1. `A` 增加 `customElements` 配置项,便于添加自定义功能性标签 [详细](https://github.com/jin-yufeng/mp-html/issues/350)
2. `A` `editable` 插件增加切换音视频自动播放状态的功能 [详细](https://github.com/jin-yufeng/mp-html/pull/341) by [@leeseett](https://github.com/leeseett)
3. `A` `editable` 插件删除媒体标签时触发 `remove` 事件,便于删除已上传的文件
4. `U` `editable` 插件 `insertImg` 方法支持同时插入多张图片 [详细](https://github.com/jin-yufeng/mp-html/issues/342)
5. `U` `editable` 插入图片和音视频时支持拼接 `domian` 主域名
6. `F` 修复了内部链接参数中包含 `://` 时被认为是外部链接的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/356)
7. `F` 修复了部分 `svg` 标签名或属性名大小写不正确时不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/351)
8. `F` 修复了 `nvue` 页面运行到非 `app` 平台时可能样式错误的问题
## v2.1.5(2021-08-13)
1. `A` 增加支持标签的 `dir` 属性
2. `F` 修复了 `ruby` 标签文字与拼音没有居中对齐的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/325)
3. `F` 修复了音视频标签内有 `a` 标签时可能无法播放的问题
4. `F` 修复了 `externStyle` 中的 `class` 名包含下划线或数字时可能失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/326)
5. `F` 修复了 `h5` 端引入 `externStyle` 可能不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/326)
## v2.1.4(2021-07-14)
1. `F` 修复了 `rt` 标签无法设置样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/318)
2. `F` 修复了表格中有单元格同时合并行和列时可能显示不正确的问题
3. `F` 修复了 `app` 端无法关闭图片长按菜单的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/322)
4. `F` 修复了 `editable` 插件只能添加图片链接不能修改的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/312) by [@leeseett](https://github.com/leeseett)
## v2.1.3(2021-06-12)
1. `A` `editable` 插件增加 `insertTable` 方法
2. `U` `editable` 插件支持编辑表格中的空白单元格 [详细](https://github.com/jin-yufeng/mp-html/issues/310)
3. `F` 修复了 `externStyle` 中使用伪类可能失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/298)
4. `F` 修复了多个组件同时使用时 `tag-style` 属性时可能互相影响的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/305) by [@woodguoyu](https://github.com/woodguoyu)
5. `F` 修复了包含 `linearGradient` 的 `svg` 可能无法显示的问题
6. `F` 修复了编译到头条小程序时可能报错的问题
7. `F` 修复了 `nvue` 端不触发 `click` 事件的问题
8. `F` 修复了 `editable` 插件尾部插入时无法撤销的问题
9. `F` 修复了 `editable` 插件的 `insertHtml` 方法只能在末尾插入的问题
10. `F` 修复了 `editable` 插件插入音频不显示的问题
## v2.1.2(2021-04-24)
1. `A` 增加了 [img-cache](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#img-cache) 插件,可以在 `app` 端缓存图片 [详细](https://github.com/jin-yufeng/mp-html/issues/292) by [@PentaTea](https://github.com/PentaTea)
2. `U` 支持通过 `container-style` 属性设置 `white-space` 来保留连续空格和换行符 [详细](https://jin-yufeng.gitee.io/mp-html/#/question/faq#space)
3. `U` 代码风格符合 [standard](https://standardjs.com) 标准
4. `U` `editable` 插件编辑状态下支持预览视频 [详细](https://github.com/jin-yufeng/mp-html/issues/286)
5. `F` 修复了 `svg` 标签内嵌 `svg` 时无法显示的问题
6. `F` 修复了编译到支付宝和头条小程序时部分区域不可复制的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/291)
## v2.1.1(2021-04-09)
1. 修复了对 `p` 标签设置 `tag-style` 可能不生效的问题
2. 修复了 `svg` 标签中的文本无法显示的问题
3. 修复了使用 `editable` 插件编辑表格时可能报错的问题
4. 修复了使用 `highlight` 插件运行到头条小程序时可能没有样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/280)
5. 修复了使用 `editable` 插件 `editable` 属性为 `false` 时会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/284)
6. 修复了 `style` 插件连续子选择器失效的问题
7. 修复了 `editable` 插件无法修改图片和字体大小的问题
## v2.1.0.2(2021-03-21)
修复了 `nvue` 端使用可能报错的问题
## v2.1.0(2021-03-20)
1. `A` 增加了 [container-style](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#container-style) 属性 [详细](https://gitee.com/jin-yufeng/mp-html/pulls/1)
2. `A` 增加支持 `strike` 标签
3. `A` `editable` 插件增加 `placeholder` 属性 [详细](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#editable)
4. `A` `editable` 插件增加 `insertHtml` 方法 [详细](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#editable)
5. `U` 外部样式支持标签名选择器 [详细](https://jin-yufeng.gitee.io/mp-html/#/overview/quickstart#setting)
6. `F` 修复了 `nvue` 端部分情况下可能不显示的问题
## v2.0.5(2021-03-12)
1. `U` [linktap](https://jin-yufeng.gitee.io/mp-html/#/basic/event#linktap) 事件增加返回内部文本内容 `innerText` [详细](https://github.com/jin-yufeng/mp-html/issues/271)
2. `U` [selectable](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#selectable) 属性设置为 `force` 时能够在微信 `iOS` 端生效(文本块会变成 `inline-block`[详细](https://github.com/jin-yufeng/mp-html/issues/267)
3. `F` 修复了部分情况下竖向无法滚动的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/182)
4. `F` 修复了多次修改富文本数据时部分内容可能不显示的问题
5. `F` 修复了 [腾讯视频](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#txv-video) 插件可能无法播放的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/265)
6. `F` 修复了 [highlight](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#highlight) 插件没有设置高亮语言时没有应用默认样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/276) by [@fuzui](https://github.com/fuzui)
... ...
<template>
<view id="_root" :class="(selectable?'_select ':'')+'_root'" :style="containerStyle">
<slot v-if="!nodes[0]" />
<!-- #ifndef APP-PLUS-NVUE -->
<node v-else :childs="nodes" :opts="[lazyLoad,loadingImg,errorImg,showImgMenu,selectable]" name="span" />
<!-- #endif -->
<!-- #ifdef APP-PLUS-NVUE -->
<web-view ref="web" src="/uni_modules/mp-html/static/app-plus/mp-html/local.html" :style="'margin-top:-2px;height:' + height + 'px'" @onPostMessage="_onMessage" />
<!-- #endif -->
</view>
</template>
<script>
/**
* mp-html v2.3.1
* @description 富文本组件
* @tutorial https://github.com/jin-yufeng/mp-html
* @property {String} container-style 容器的样式
* @property {String} content 用于渲染的 html 字符串
* @property {Boolean} copy-link 是否允许外部链接被点击时自动复制
* @property {String} domain 主域名,用于拼接链接
* @property {String} error-img 图片出错时的占位图链接
* @property {Boolean} lazy-load 是否开启图片懒加载
* @property {string} loading-img 图片加载过程中的占位图链接
* @property {Boolean} pause-video 是否在播放一个视频时自动暂停其他视频
* @property {Boolean} preview-img 是否允许图片被点击时自动预览
* @property {Boolean} scroll-table 是否给每个表格添加一个滚动层使其能单独横向滚动
* @property {Boolean | String} selectable 是否开启长按复制
* @property {Boolean} set-title 是否将 title 标签的内容设置到页面标题
* @property {Boolean} show-img-menu 是否允许图片被长按时显示菜单
* @property {Object} tag-style 标签的默认样式
* @property {Boolean | Number} use-anchor 是否使用锚点链接
* @event {Function} load dom 结构加载完毕时触发
* @event {Function} ready 所有图片加载完毕时触发
* @event {Function} imgtap 图片被点击时触发
* @event {Function} linktap 链接被点击时触发
* @event {Function} play 音视频播放时触发
* @event {Function} error 媒体加载出错时触发
*/
// #ifndef APP-PLUS-NVUE
import node from './node/node'
// #endif
import Parser from './parser'
const plugins=[]
// #ifdef APP-PLUS-NVUE
const dom = weex.requireModule('dom')
// #endif
export default {
name: 'mp-html',
data () {
return {
nodes: [],
// #ifdef APP-PLUS-NVUE
height: 3
// #endif
}
},
props: {
containerStyle: {
type: String,
default: ''
},
content: {
type: String,
default: ''
},
copyLink: {
type: [Boolean, String],
default: true
},
domain: String,
errorImg: {
type: String,
default: ''
},
lazyLoad: {
type: [Boolean, String],
default: false
},
loadingImg: {
type: String,
default: ''
},
pauseVideo: {
type: [Boolean, String],
default: true
},
previewImg: {
type: [Boolean, String],
default: true
},
scrollTable: [Boolean, String],
selectable: [Boolean, String],
setTitle: {
type: [Boolean, String],
default: true
},
showImgMenu: {
type: [Boolean, String],
default: true
},
tagStyle: Object,
useAnchor: [Boolean, Number]
},
// #ifdef VUE3
emits: ['load', 'ready', 'imgtap', 'linktap', 'play', 'error'],
// #endif
// #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) {
reject(Error('Anchor is disabled'))
return
}
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()
} else {
// 获取 scroll-view 的位置和滚动距离
selector.selectViewport().scrollOffset() // 获取窗口的滚动距离
}
selector.exec(res => {
if (!res[0]) {
reject(Error('Label not found'))
return
}
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 (nodes) {
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(/&amp;/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'
}
}
}
})(nodes || 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(Error('Root label not found')))
})
},
/**
* @description 暂停播放媒体
*/
pauseMedia () {
for (let i = (this._videos || []).length; i--;) {
this._videos[i].pause()
}
// #ifdef APP-PLUS
const command = 'for(var e=document.getElementsByTagName("video"),i=e.length;i--;)e[i].pause()'
// #ifndef APP-PLUS-NVUE
let page = this.$parent
while (!page.$scope) page = page.$parent
page.$scope.$getAppWebview().evalJS(command)
// #endif
// #ifdef APP-PLUS-NVUE
this.$refs.web.evalJs(command)
// #endif
// #endif
},
/**
* @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.containerStyle.replace(/(?:margin|padding)[^;]+/g, ''), 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 () {
uni.switchTab({
url: href
})
}
})
}
}
break
}
case 'onPlay':
this.$emit('play')
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(Error('Label not found'))
}
break
// 点击
case 'onClick':
this.$emit('tap')
this.$emit('click')
break
// 出错
case 'onError':
this.$emit('error', {
source: message.source,
attrs: message.attrs
})
}
}
// #endif
}
}
</script>
<style>
/* #ifndef APP-PLUS-NVUE */
/* 根节点样式 */
._root {
padding: 1px 0;
overflow-x: auto;
overflow-y: hidden;
--webkit-overflow-scrolling: touch;
}
/* 长按复制 */
._select {
user-select: text;
}
/* #endif */
</style>
... ...
<template>
<view :id="attrs.id" :class="'_block _'+name+' '+attrs.class" :style="attrs.style">
<block v-for="(n, i) in childs" v-bind:key="i">
<!-- 图片 -->
<!-- 占位图 -->
<image v-if="n.name==='img'&&((opts[1]&&!ctrl[i])||ctrl[i]<0)" class="_img" :style="n.attrs.style" :src="ctrl[i]<0?opts[2]:opts[1]" mode="widthFix" />
<!-- 显示图片 -->
<!-- #ifdef H5 || (APP-PLUS && VUE2) -->
<img v-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]===-1?'display:none;':'')+n.attrs.style" :src="n.attrs.src||(ctrl.load?n.attrs['data-src']:'')" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
<!-- #endif -->
<!-- #ifndef H5 || APP-PLUS -->
<image v-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]===-1?'display:none;':'')+'width:'+(ctrl[i]||1)+'px;height:1px;'+n.attrs.style" :src="n.attrs.src" :mode="!n.h?'widthFix':(!n.w?'heightFix':'')" :lazy-load="opts[0]" :webp="n.webp" :show-menu-by-longpress="opts[3]&&!n.attrs.ignore" :image-menu-prevent="!opts[3]||n.attrs.ignore" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
<!-- #endif -->
<!-- #ifdef APP-PLUS && VUE3 -->
<image v-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]===-1?'display:none;':'')+'width:'+(ctrl[i]||1)+'px;'+n.attrs.style" :src="n.attrs.src||(ctrl.load?n.attrs['data-src']:'')" :mode="!n.h?'widthFix':(!n.w?'heightFix':'')" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
<!-- #endif -->
<!-- 文本 -->
<!-- #ifndef MP-BAIDU || MP-ALIPAY || MP-TOUTIAO -->
<text v-else-if="n.text" :user-select="opts[4]" decode>{{n.text}}</text>
<!-- #endif -->
<text v-else-if="n.name==='br'">\n</text>
<!-- 链接 -->
<view v-else-if="n.name==='a'" :id="n.attrs.id" :class="(n.attrs.href?'_a ':'')+n.attrs.class" hover-class="_hover" :style="'display:inline;'+n.attrs.style" :data-i="i" @tap.stop="linkTap">
<node name="span" :childs="n.children" :opts="opts" style="display:inherit" />
</view>
<!-- 视频 -->
<!-- #ifdef APP-PLUS -->
<view v-else-if="n.html" :id="n.attrs.id" :class="'_video '+n.attrs.class" :style="n.attrs.style" v-html="n.html" @vplay.stop="play" />
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<video v-else-if="n.name==='video'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :autoplay="n.attrs.autoplay" :controls="n.attrs.controls" :loop="n.attrs.loop" :muted="n.attrs.muted" :object-fit="n.attrs['object-fit']" :poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" @play="play" @error="mediaError" />
<!-- #endif -->
<!-- #ifdef H5 || APP-PLUS -->
<iframe v-else-if="n.name==='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen" :frameborder="n.attrs.frameborder" :src="n.attrs.src" />
<embed v-else-if="n.name==='embed'" :style="n.attrs.style" :src="n.attrs.src" />
<!-- #endif -->
<!-- #ifndef MP-TOUTIAO || ((H5 || APP-PLUS) && VUE3) -->
<!-- 音频 -->
<audio v-else-if="n.name==='audio'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :author="n.attrs.author" :controls="n.attrs.controls" :loop="n.attrs.loop" :name="n.attrs.name" :poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" @play="play" @error="mediaError" />
<!-- #endif -->
<view v-else-if="(n.name==='table'&&n.c)||n.name==='li'" :id="n.attrs.id" :class="'_'+n.name+' '+n.attrs.class" :style="n.attrs.style">
<node v-if="n.name==='li'" :childs="n.children" :opts="opts" />
<view v-else v-for="(tbody, x) in n.children" v-bind:key="x" :class="'_'+tbody.name+' '+tbody.attrs.class" :style="tbody.attrs.style">
<node v-if="tbody.name==='td'||tbody.name==='th'" :childs="tbody.children" :opts="opts" />
<block v-else v-for="(tr, y) in tbody.children" v-bind:key="y">
<view v-if="tr.name==='td'||tr.name==='th'" :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
<node :childs="tr.children" :opts="opts" />
</view>
<view v-else :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
<view v-for="(td, z) in tr.children" v-bind:key="z" :class="'_'+td.name+' '+td.attrs.class" :style="td.attrs.style">
<node :childs="td.children" :opts="opts" />
</view>
</view>
</block>
</view>
</view>
<!-- 富文本 -->
<!-- #ifdef H5 || ((MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE2) -->
<rich-text v-else-if="!n.c&&!handler.isInline(n.name, n.attrs.style)" :id="n.attrs.id" :style="n.f" :user-select="opts[4]" :nodes="[n]" />
<!-- #endif -->
<!-- #ifndef H5 || ((MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE2) -->
<rich-text v-else-if="!n.c" :id="n.attrs.id" :style="n.f+';display:inline'" :preview="false" :selectable="opts[4]" :user-select="opts[4]" :nodes="[n]" />
<!-- #endif -->
<!-- 继续递归 -->
<view v-else-if="n.c===2" :id="n.attrs.id" :class="'_block _'+n.name+' '+n.attrs.class" :style="n.f+';'+n.attrs.style">
<node v-for="(n2, j) in n.children" v-bind:key="j" :style="n2.f" :name="n2.name" :attrs="n2.attrs" :childs="n2.children" :opts="opts" />
</view>
<node v-else :style="n.f" :name="n.name" :attrs="n.attrs" :childs="n.children" :opts="opts" />
</block>
</view>
</template>
<script module="handler" lang="wxs">
// 行内标签列表
var inlineTags = {
abbr: true,
b: true,
big: true,
code: true,
del: true,
em: true,
i: true,
ins: true,
label: true,
q: true,
small: true,
span: true,
strong: true,
sub: true,
sup: true
}
/**
* @description 判断是否为行内标签
*/
module.exports = {
isInline: function (tagName, style) {
return inlineTags[tagName] || (style || '').indexOf('display:inline') !== -1
}
}
</script>
<script>
import node from './node'
export default {
name: 'node',
options: {
// #ifdef MP-WEIXIN
virtualHost: true,
// #endif
// #ifdef MP-TOUTIAO
addGlobalClass: false
// #endif
},
data () {
return {
ctrl: {}
}
},
props: {
name: String,
attrs: {
type: Object,
default () {
return {}
}
},
childs: Array,
opts: Array
},
components: {
// #ifndef H5 && VUE3
node
// #endif
},
mounted () {
this.$nextTick(() => {
for (this.root = this.$parent; this.root.$options.name !== 'mp-html'; this.root = this.root.$parent);
})
// #ifdef H5 || APP-PLUS
if (this.opts[0]) {
let i
for (i = this.childs.length; i--;) {
if (this.childs[i].name === 'img') break
}
if (i !== -1) {
this.observer = uni.createIntersectionObserver(this).relativeToViewport({
top: 500,
bottom: 500
})
this.observer.observe('._img', res => {
if (res.intersectionRatio) {
this.$set(this.ctrl, 'load', 1)
this.observer.disconnect()
}
})
}
}
// #endif
},
beforeDestroy () {
// #ifdef H5 || APP-PLUS
if (this.observer) {
this.observer.disconnect()
}
// #endif
},
methods:{
// #ifdef MP-WEIXIN
toJSON () { },
// #endif
/**
* @description 播放视频事件
* @param {Event} e
*/
play (e) {
this.root.$emit('play')
// #ifndef APP-PLUS
if (this.root.pauseVideo) {
let flag = false
const id = e.target.id
for (let i = this.root._videos.length; i--;) {
if (this.root._videos[i].id === id) {
flag = true
} else {
this.root._videos[i].pause() // 自动暂停其他视频
}
}
// 将自己加入列表
if (!flag) {
const ctx = uni.createVideoContext(id
// #ifndef MP-BAIDU
, this
// #endif
)
ctx.id = id
this.root._videos.push(ctx)
}
}
// #endif
},
/**
* @description 图片点击事件
* @param {Event} e
*/
imgTap (e) {
const node = this.childs[e.currentTarget.dataset.i]
if (node.a) {
this.linkTap(node.a)
return
}
if (node.attrs.ignore) return
// #ifdef H5 || APP-PLUS
node.attrs.src = node.attrs.src || node.attrs['data-src']
// #endif
this.root.$emit('imgtap', node.attrs)
// 自动预览图片
if (this.root.previewImg) {
uni.previewImage({
// #ifdef MP-WEIXIN
showmenu: this.root.showImgMenu,
// #endif
// #ifdef MP-ALIPAY
enablesavephoto: this.root.showImgMenu,
enableShowPhotoDownload: this.root.showImgMenu,
// #endif
current: parseInt(node.attrs.i),
urls: this.root.imgList
})
}
},
/**
* @description 图片长按
*/
imgLongTap (e) {
// #ifdef APP-PLUS
const attrs = this.childs[e.currentTarget.dataset.i].attrs
if (this.opts[3] && !attrs.ignore) {
uni.showActionSheet({
itemList: ['保存图片'],
success: () => {
const save = path => {
uni.saveImageToPhotosAlbum({
filePath: path,
success () {
uni.showToast({
title: '保存成功'
})
}
})
}
if (this.root.imgList[attrs.i].startsWith('http')) {
uni.downloadFile({
url: this.root.imgList[attrs.i],
success: res => save(res.tempFilePath)
})
} else {
save(this.root.imgList[attrs.i])
}
}
})
}
// #endif
},
/**
* @description 图片加载完成事件
* @param {Event} e
*/
imgLoad (e) {
const i = e.currentTarget.dataset.i
/* #ifndef H5 || (APP-PLUS && VUE2) */
if (!this.childs[i].w) {
// 设置原宽度
this.$set(this.ctrl, i, e.detail.width)
} else /* #endif */ if ((this.opts[1] && !this.ctrl[i]) || this.ctrl[i] === -1) {
// 加载完毕,取消加载中占位图
this.$set(this.ctrl, i, 1)
}
},
/**
* @description 链接点击事件
* @param {Event} e
*/
linkTap (e) {
const node = e.currentTarget ? this.childs[e.currentTarget.dataset.i] : {}
const attrs = node.attrs || e
const href = attrs.href
this.root.$emit('linktap', Object.assign({
innerText: this.root.getText(node.children || []) // 链接内的文本内容
}, attrs))
if (href) {
if (href[0] === '#') {
// 跳转锚点
this.root.navigateTo(href.substring(1)).catch(() => { })
} else if (href.split('?')[0].includes('://')) {
// 复制外部链接
if (this.root.copyLink) {
// #ifdef H5
window.open(href)
// #endif
// #ifdef MP
uni.setClipboardData({
data: href,
success: () =>
uni.showToast({
title: '链接已复制'
})
})
// #endif
// #ifdef APP-PLUS
plus.runtime.openWeb(href)
// #endif
}
} else {
// 跳转页面
uni.navigateTo({
url: href,
fail () {
uni.switchTab({
url: href,
fail () { }
})
}
})
}
}
},
/**
* @description 错误事件
* @param {Event} e
*/
mediaError (e) {
const i = e.currentTarget.dataset.i
const node = this.childs[i]
// 加载其他源
if (node.name === 'video' || node.name === 'audio') {
let index = (this.ctrl[i] || 0) + 1
if (index > node.src.length) {
index = 0
}
if (index < node.src.length) {
this.$set(this.ctrl, i, index)
return
}
} else if (node.name === 'img') {
// #ifdef H5 && VUE3
if (this.opts[0] && !this.ctrl.load) return
// #endif
// 显示错误占位图
if (this.opts[2]) {
this.$set(this.ctrl, i, -1)
}
}
if (this.root) {
this.root.$emit('error', {
source: node.name,
attrs: node.attrs,
// #ifndef H5 && VUE3
errMsg: e.detail.errMsg
// #endif
})
}
}
}
}
</script>
<style>
/* a 标签默认效果 */
._a {
padding: 1.5px 0 1.5px 0;
color: #366092;
word-break: break-all;
}
/* a 标签点击态效果 */
._hover {
text-decoration: underline;
opacity: 0.7;
}
/* 图片默认效果 */
._img {
max-width: 100%;
-webkit-touch-callout: none;
}
/* 内部样式 */
._block {
display: block;
}
._b,
._strong {
font-weight: bold;
}
._code {
font-family: monospace;
}
._del {
text-decoration: line-through;
}
._em,
._i {
font-style: italic;
}
._h1 {
font-size: 2em;
}
._h2 {
font-size: 1.5em;
}
._h3 {
font-size: 1.17em;
}
._h5 {
font-size: 0.83em;
}
._h6 {
font-size: 0.67em;
}
._h1,
._h2,
._h3,
._h4,
._h5,
._h6 {
display: block;
font-weight: bold;
}
._image {
height: 1px;
}
._ins {
text-decoration: underline;
}
._li {
display: list-item;
}
._ol {
list-style-type: decimal;
}
._ol,
._ul {
display: block;
padding-left: 40px;
margin: 1em 0;
}
._q::before {
content: '"';
}
._q::after {
content: '"';
}
._sub {
font-size: smaller;
vertical-align: sub;
}
._sup {
font-size: smaller;
vertical-align: super;
}
._thead,
._tbody,
._tfoot {
display: table-row-group;
}
._tr {
display: table-row;
}
._td,
._th {
display: table-cell;
vertical-align: middle;
}
._th {
font-weight: bold;
text-align: center;
}
._ul {
list-style-type: disc;
}
._ul ._ul {
margin: 0;
list-style-type: circle;
}
._ul ._ul ._ul {
list-style-type: square;
}
._abbr,
._b,
._code,
._del,
._em,
._i,
._ins,
._label,
._q,
._span,
._strong,
._sub,
._sup {
display: inline;
}
/* #ifdef APP-PLUS */
._video {
width: 300px;
height: 225px;
}
/* #endif */
</style>
\ No newline at end of file
... ...
/**
* @fileoverview html 解析器
*/
// 配置
const config = {
// 信任的标签(保持标签名不变)
trustTags: makeMap('a,abbr,ad,audio,b,blockquote,br,code,col,colgroup,dd,del,dl,dt,div,em,fieldset,h1,h2,h3,h4,h5,h6,hr,i,img,ins,label,legend,li,ol,p,q,ruby,rt,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video'),
// 块级标签(转为 div,其他的非信任标签转为 span)
blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,pre,section'),
// #ifdef (MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE3
// 行内标签
inlineTags: makeMap('abbr,b,big,code,del,em,i,ins,label,q,small,span,strong,sub,sup'),
// #endif
// 要移除的标签
ignoreTags: makeMap('area,base,canvas,embed,frame,head,iframe,input,link,map,meta,param,rp,script,source,style,textarea,title,track,wbr'),
// 自闭合的标签
voidTags: makeMap('area,base,br,col,circle,ellipse,embed,frame,hr,img,input,line,link,meta,param,path,polygon,rect,source,track,use,wbr'),
// html 实体
entities: {
lt: '<',
gt: '>',
quot: '"',
apos: "'",
ensp: '\u2002',
emsp: '\u2003',
nbsp: '\xA0',
semi: ';',
ndash: '–',
mdash: '—',
middot: '·',
lsquo: '‘',
rsquo: '’',
ldquo: '“',
rdquo: '”',
bull: '•',
hellip: '…',
larr: '←',
uarr: '↑',
rarr: '→',
darr: '↓'
},
// 默认的标签样式
tagStyle: {
// #ifndef APP-PLUS-NVUE
address: 'font-style:italic',
big: 'display:inline;font-size:1.2em',
caption: 'display:table-caption;text-align:center',
center: 'text-align:center',
cite: 'font-style:italic',
dd: 'margin-left:40px',
mark: 'background-color:yellow',
pre: 'font-family:monospace;white-space:pre',
s: 'text-decoration:line-through',
small: 'display:inline;font-size:0.8em',
strike: 'text-decoration:line-through',
u: 'text-decoration:underline'
// #endif
},
// svg 大小写对照表
svgDict: {
animatetransform: 'animateTransform',
lineargradient: 'linearGradient',
viewbox: 'viewBox',
attributename: 'attributeName',
repeatcount: 'repeatCount',
repeatdur: 'repeatDur'
}
}
const tagSelector={}
const {
windowWidth,
// #ifdef MP-WEIXIN
system
// #endif
} = uni.getSystemInfoSync()
const blankChar = makeMap(' ,\r,\n,\t,\f')
let idIndex = 0
// #ifdef H5 || APP-PLUS
config.ignoreTags.iframe = undefined
config.trustTags.iframe = true
config.ignoreTags.embed = undefined
config.trustTags.embed = true
// #endif
// #ifdef APP-PLUS-NVUE
config.ignoreTags.source = undefined
config.ignoreTags.style = undefined
// #endif
/**
* @description 创建 map
* @param {String} str 逗号分隔
*/
function makeMap (str) {
const map = Object.create(null)
const list = str.split(',')
for (let i = list.length; i--;) {
map[list[i]] = true
}
return map
}
/**
* @description 解码 html 实体
* @param {String} str 要解码的字符串
* @param {Boolean} amp 要不要解码 &amp;
* @returns {String} 解码后的字符串
*/
function decodeEntity (str, amp) {
let i = str.indexOf('&')
while (i !== -1) {
const j = str.indexOf(';', i + 3)
let code
if (j === -1) break
if (str[i + 1] === '#') {
// &#123; 形式的实体
code = parseInt((str[i + 2] === 'x' ? '0' : '') + str.substring(i + 2, j))
if (!isNaN(code)) {
str = str.substr(0, i) + String.fromCharCode(code) + str.substr(j + 1)
}
} else {
// &nbsp; 形式的实体
code = str.substring(i + 1, j)
if (config.entities[code] || (code === 'amp' && amp)) {
str = str.substr(0, i) + (config.entities[code] || '&') + str.substr(j + 1)
}
}
i = str.indexOf('&', i + 1)
}
return str
}
/**
* @description html 解析器
* @param {Object} vm 组件实例
*/
function Parser (vm) {
this.options = vm || {}
this.tagStyle = Object.assign({}, config.tagStyle, this.options.tagStyle)
this.imgList = vm.imgList || []
this.plugins = vm.plugins || []
this.attrs = Object.create(null)
this.stack = []
this.nodes = []
this.pre = (this.options.containerStyle || '').includes('white-space') && this.options.containerStyle.includes('pre') ? 2 : 0
}
/**
* @description 执行解析
* @param {String} content 要解析的文本
*/
Parser.prototype.parse = function (content) {
// 插件处理
for (let i = this.plugins.length; i--;) {
if (this.plugins[i].onUpdate) {
content = this.plugins[i].onUpdate(content, config) || content
}
}
new Lexer(this).parse(content)
// 出栈未闭合的标签
while (this.stack.length) {
this.popNode()
}
return this.nodes
}
/**
* @description 将标签暴露出来(不被 rich-text 包含)
*/
Parser.prototype.expose = function () {
// #ifndef APP-PLUS-NVUE
for (let i = this.stack.length; i--;) {
const item = this.stack[i]
if (item.c || item.name === 'a' || item.name === 'video' || item.name === 'audio') return
item.c = 1
}
// #endif
}
/**
* @description 处理插件
* @param {Object} node 要处理的标签
* @returns {Boolean} 是否要移除此标签
*/
Parser.prototype.hook = function (node) {
for (let i = this.plugins.length; i--;) {
if (this.plugins[i].onParse && this.plugins[i].onParse(node, this) === false) {
return false
}
}
return true
}
/**
* @description 将链接拼接上主域名
* @param {String} url 需要拼接的链接
* @returns {String} 拼接后的链接
*/
Parser.prototype.getUrl = function (url) {
const domain = this.options.domain
if (url[0] === '/') {
if (url[1] === '/') {
// // 开头的补充协议名
url = (domain ? domain.split('://')[0] : 'http') + ':' + url
} else if (domain) {
// 否则补充整个域名
url = domain + url
} /* #ifdef APP-PLUS */ else {
url = plus.io.convertLocalFileSystemURL(url)
} /* #endif */
} else if (!url.includes('data:') && !url.includes('://')) {
if (domain) {
url = domain + '/' + url
} /* #ifdef APP-PLUS */ else {
url = plus.io.convertLocalFileSystemURL(url)
} /* #endif */
}
return url
}
/**
* @description 解析样式表
* @param {Object} node 标签
* @returns {Object}
*/
Parser.prototype.parseStyle = function (node) {
const attrs = node.attrs
const list = (this.tagStyle[node.name] || '').split(';').concat((attrs.style || '').split(';'))
const styleObj = {}
let tmp = ''
if (attrs.id && !this.xml) {
// 暴露锚点
if (this.options.useAnchor) {
this.expose()
} else if (node.name !== 'img' && node.name !== 'a' && node.name !== 'video' && node.name !== 'audio') {
attrs.id = undefined
}
}
// 转换 width 和 height 属性
if (attrs.width) {
styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px')
attrs.width = undefined
}
if (attrs.height) {
styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px')
attrs.height = undefined
}
for (let i = 0, len = list.length; i < len; i++) {
const info = list[i].split(':')
if (info.length < 2) continue
const key = info.shift().trim().toLowerCase()
let value = info.join(':').trim()
if ((value[0] === '-' && value.lastIndexOf('-') > 0) || value.includes('safe')) {
// 兼容性的 css 不压缩
tmp += `;${key}:${value}`
} else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import')) {
// 重复的样式进行覆盖
if (value.includes('url')) {
// 填充链接
let j = value.indexOf('(') + 1
if (j) {
while (value[j] === '"' || value[j] === "'" || blankChar[value[j]]) {
j++
}
value = value.substr(0, j) + this.getUrl(value.substr(j))
}
} else if (value.includes('rpx')) {
// 转换 rpx(rich-text 内部不支持 rpx)
value = value.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * windowWidth / 750 + 'px')
}
styleObj[key] = value
}
}
node.attrs.style = tmp
return styleObj
}
/**
* @description 解析到标签名
* @param {String} name 标签名
* @private
*/
Parser.prototype.onTagName = function (name) {
this.tagName = this.xml ? name : name.toLowerCase()
if (this.tagName === 'svg') {
this.xml = (this.xml || 0) + 1 // svg 标签内大小写敏感
}
}
/**
* @description 解析到属性名
* @param {String} name 属性名
* @private
*/
Parser.prototype.onAttrName = function (name) {
name = this.xml ? name : name.toLowerCase()
if (name.substr(0, 5) === 'data-') {
if (name === 'data-src' && !this.attrs.src) {
// data-src 自动转为 src
this.attrName = 'src'
} else if (this.tagName === 'img' || this.tagName === 'a') {
// a 和 img 标签保留 data- 的属性,可以在 imgtap 和 linktap 事件中使用
this.attrName = name
} else {
// 剩余的移除以减小大小
this.attrName = undefined
}
} else {
this.attrName = name
this.attrs[name] = 'T' // boolean 型属性缺省设置
}
}
/**
* @description 解析到属性值
* @param {String} val 属性值
* @private
*/
Parser.prototype.onAttrVal = function (val) {
const name = this.attrName || ''
if (name === 'style' || name === 'href') {
// 部分属性进行实体解码
this.attrs[name] = decodeEntity(val, true)
} else if (name.includes('src')) {
// 拼接主域名
this.attrs[name] = this.getUrl(decodeEntity(val, true))
} else if (name) {
this.attrs[name] = val
}
}
/**
* @description 解析到标签开始
* @param {Boolean} selfClose 是否有自闭合标识 />
* @private
*/
Parser.prototype.onOpenTag = function (selfClose) {
// 拼装 node
const node = Object.create(null)
node.name = this.tagName
node.attrs = this.attrs
// 避免因为自动 diff 使得 type 被设置为 null 导致部分内容不显示
if (this.options.nodes.length) {
node.type = 'node'
}
this.attrs = Object.create(null)
const attrs = node.attrs
const parent = this.stack[this.stack.length - 1]
const siblings = parent ? parent.children : this.nodes
const close = this.xml ? selfClose : config.voidTags[node.name]
// 替换标签名选择器
if (tagSelector[node.name]) {
attrs.class = tagSelector[node.name] + (attrs.class ? ' ' + attrs.class : '')
}
// 转换 embed 标签
if (node.name === 'embed') {
// #ifndef H5 || APP-PLUS
const src = attrs.src || ''
// 按照后缀名和 type 将 embed 转为 video 或 audio
if (src.includes('.mp4') || src.includes('.3gp') || src.includes('.m3u8') || (attrs.type || '').includes('video')) {
node.name = 'video'
} else if (src.includes('.mp3') || src.includes('.wav') || src.includes('.aac') || src.includes('.m4a') || (attrs.type || '').includes('audio')) {
node.name = 'audio'
}
if (attrs.autostart) {
attrs.autoplay = 'T'
}
attrs.controls = 'T'
// #endif
// #ifdef H5 || APP-PLUS
this.expose()
// #endif
}
// #ifndef APP-PLUS-NVUE
// 处理音视频
if (node.name === 'video' || node.name === 'audio') {
// 设置 id 以便获取 context
if (node.name === 'video' && !attrs.id) {
attrs.id = 'v' + idIndex++
}
// 没有设置 controls 也没有设置 autoplay 的自动设置 controls
if (!attrs.controls && !attrs.autoplay) {
attrs.controls = 'T'
}
// 用数组存储所有可用的 source
node.src = []
if (attrs.src) {
node.src.push(attrs.src)
attrs.src = undefined
}
this.expose()
}
// #endif
// 处理自闭合标签
if (close) {
if (!this.hook(node) || config.ignoreTags[node.name]) {
// 通过 base 标签设置主域名
if (node.name === 'base' && !this.options.domain) {
this.options.domain = attrs.href
} /* #ifndef APP-PLUS-NVUE */ else if (node.name === 'source' && parent && (parent.name === 'video' || parent.name === 'audio') && attrs.src) {
// 设置 source 标签(仅父节点为 video 或 audio 时有效)
parent.src.push(attrs.src)
} /* #endif */
return
}
// 解析 style
const styleObj = this.parseStyle(node)
// 处理图片
if (node.name === 'img') {
if (attrs.src) {
// 标记 webp
if (attrs.src.includes('webp')) {
node.webp = 'T'
}
// data url 图片如果没有设置 original-src 默认为不可预览的小图片
if (attrs.src.includes('data:') && !attrs['original-src']) {
attrs.ignore = 'T'
}
if (!attrs.ignore || node.webp || attrs.src.includes('cloud://')) {
for (let i = this.stack.length; i--;) {
const item = this.stack[i]
if (item.name === 'a') {
node.a = item.attrs
break
}
// #ifndef H5 || APP-PLUS
const style = item.attrs.style || ''
if (style.includes('flex:') && !style.includes('flex:0') && !style.includes('flex: 0') && (!styleObj.width || !styleObj.width.includes('%'))) {
styleObj.width = '100% !important'
styleObj.height = ''
for (let j = i + 1; j < this.stack.length; j++) {
this.stack[j].attrs.style = (this.stack[j].attrs.style || '').replace('inline-', '')
}
} else if (style.includes('flex') && styleObj.width === '100%') {
for (let j = i + 1; j < this.stack.length; j++) {
const style = this.stack[j].attrs.style || ''
if (!style.includes(';width') && !style.includes(' width') && style.indexOf('width') !== 0) {
styleObj.width = ''
break
}
}
} else if (style.includes('inline-block')) {
if (styleObj.width && styleObj.width[styleObj.width.length - 1] === '%') {
item.attrs.style += ';max-width:' + styleObj.width
styleObj.width = ''
} else {
item.attrs.style += ';max-width:100%'
}
}
// #endif
item.c = 1
}
attrs.i = this.imgList.length.toString()
let src = attrs['original-src'] || attrs.src
// #ifndef H5 || MP-ALIPAY || APP-PLUS || MP-360
if (this.imgList.includes(src)) {
// 如果有重复的链接则对域名进行随机大小写变换避免预览时错位
let i = src.indexOf('://')
if (i !== -1) {
i += 3
let newSrc = src.substr(0, i)
for (; i < src.length; i++) {
if (src[i] === '/') break
newSrc += Math.random() > 0.5 ? src[i].toUpperCase() : src[i]
}
newSrc += src.substr(i)
src = newSrc
}
}
// #endif
this.imgList.push(src)
// #ifdef H5 || APP-PLUS
if (this.options.lazyLoad) {
attrs['data-src'] = attrs.src
attrs.src = undefined
}
// #endif
}
}
if (styleObj.display === 'inline') {
styleObj.display = ''
}
// #ifndef APP-PLUS-NVUE
if (attrs.ignore) {
styleObj['max-width'] = styleObj['max-width'] || '100%'
attrs.style += ';-webkit-touch-callout:none'
}
// #endif
// 设置的宽度超出屏幕,为避免变形,高度转为自动
if (parseInt(styleObj.width) > windowWidth) {
styleObj.height = undefined
}
// 记录是否设置了宽高
if (!isNaN(parseInt(styleObj.width))) {
node.w = 'T'
}
if (!isNaN(parseInt(styleObj.height)) && (!styleObj.height.includes('%') || (parent && (parent.attrs.style || '').includes('height')))) {
node.h = 'T'
}
} else if (node.name === 'svg') {
siblings.push(node)
this.stack.push(node)
this.popNode()
return
}
for (const key in styleObj) {
if (styleObj[key]) {
attrs.style += `;${key}:${styleObj[key].replace(' !important', '')}`
}
}
attrs.style = attrs.style.substr(1) || undefined
// #ifdef (MP-WEIXIN || MP-QQ) && VUE3
if (!attrs.style) {
delete attrs.style
}
// #endif
} else {
if ((node.name === 'pre' || ((attrs.style || '').includes('white-space') && attrs.style.includes('pre'))) && this.pre !== 2) {
this.pre = node.pre = 1
}
node.children = []
this.stack.push(node)
}
// 加入节点树
siblings.push(node)
}
/**
* @description 解析到标签结束
* @param {String} name 标签名
* @private
*/
Parser.prototype.onCloseTag = function (name) {
// 依次出栈到匹配为止
name = this.xml ? name : name.toLowerCase()
let i
for (i = this.stack.length; i--;) {
if (this.stack[i].name === name) break
}
if (i !== -1) {
while (this.stack.length > i) {
this.popNode()
}
} else if (name === 'p' || name === 'br') {
const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes
siblings.push({
name,
attrs: {
class: tagSelector[name] || '',
style: this.tagStyle[name] || ''
}
})
}
}
/**
* @description 处理标签出栈
* @private
*/
Parser.prototype.popNode = function () {
const node = this.stack.pop()
let attrs = node.attrs
const children = node.children
const parent = this.stack[this.stack.length - 1]
const siblings = parent ? parent.children : this.nodes
if (!this.hook(node) || config.ignoreTags[node.name]) {
// 获取标题
if (node.name === 'title' && children.length && children[0].type === 'text' && this.options.setTitle) {
uni.setNavigationBarTitle({
title: children[0].text
})
}
siblings.pop()
return
}
if (node.pre && this.pre !== 2) {
// 是否合并空白符标识
this.pre = node.pre = undefined
for (let i = this.stack.length; i--;) {
if (this.stack[i].pre) {
this.pre = 1
}
}
}
const styleObj = {}
// 转换 svg
if (node.name === 'svg') {
if (this.xml > 1) {
// 多层 svg 嵌套
this.xml--
return
}
// #ifdef APP-PLUS-NVUE
(function traversal (node) {
if (node.name) {
// 调整 svg 的大小写
node.name = config.svgDict[node.name] || node.name
for (const item in node.attrs) {
if (config.svgDict[item]) {
node.attrs[config.svgDict[item]] = node.attrs[item]
node.attrs[item] = undefined
}
}
for (let i = 0; i < (node.children || []).length; i++) {
traversal(node.children[i])
}
}
})(node)
// #endif
// #ifndef APP-PLUS-NVUE
let src = ''
const style = attrs.style
attrs.style = ''
attrs.xmlns = 'http://www.w3.org/2000/svg';
(function traversal (node) {
if (node.type === 'text') {
src += node.text
return
}
const name = config.svgDict[node.name] || node.name
src += '<' + name
for (const item in node.attrs) {
const val = node.attrs[item]
if (val) {
src += ` ${config.svgDict[item] || item}="${val}"`
}
}
if (!node.children) {
src += '/>'
} else {
src += '>'
for (let i = 0; i < node.children.length; i++) {
traversal(node.children[i])
}
src += '</' + name + '>'
}
})(node)
node.name = 'img'
node.attrs = {
src: 'data:image/svg+xml;utf8,' + src.replace(/#/g, '%23'),
style,
ignore: 'T'
}
node.children = undefined
// #endif
this.xml = false
return
}
// #ifndef APP-PLUS-NVUE
// 转换 align 属性
if (attrs.align) {
if (node.name === 'table') {
if (attrs.align === 'center') {
styleObj['margin-inline-start'] = styleObj['margin-inline-end'] = 'auto'
} else {
styleObj.float = attrs.align
}
} else {
styleObj['text-align'] = attrs.align
}
attrs.align = undefined
}
// 转换 dir 属性
if (attrs.dir) {
styleObj.direction = attrs.dir
attrs.dir = undefined
}
// 转换 font 标签的属性
if (node.name === 'font') {
if (attrs.color) {
styleObj.color = attrs.color
attrs.color = undefined
}
if (attrs.face) {
styleObj['font-family'] = attrs.face
attrs.face = undefined
}
if (attrs.size) {
let size = parseInt(attrs.size)
if (!isNaN(size)) {
if (size < 1) {
size = 1
} else if (size > 7) {
size = 7
}
styleObj['font-size'] = ['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', 'xxx-large'][size - 1]
}
attrs.size = undefined
}
}
// #endif
// 一些编辑器的自带 class
if ((attrs.class || '').includes('align-center')) {
styleObj['text-align'] = 'center'
}
Object.assign(styleObj, this.parseStyle(node))
if (node.name !== 'table' && parseInt(styleObj.width) > windowWidth) {
styleObj['max-width'] = '100%'
styleObj['box-sizing'] = 'border-box'
}
// #ifndef APP-PLUS-NVUE
if (config.blockTags[node.name]) {
node.name = 'div'
} else if (!config.trustTags[node.name] && !this.xml) {
// 未知标签转为 span,避免无法显示
node.name = 'span'
}
if (node.name === 'a' || node.name === 'ad'
// #ifdef H5 || APP-PLUS
|| node.name === 'iframe' // eslint-disable-line
// #endif
) {
this.expose()
} else if (node.name === 'video') {
if ((styleObj.height || '').includes('auto')) {
styleObj.height = undefined
}
/* #ifdef APP-PLUS */
let str = '<video style="width:100%;height:100%"'
for (const item in attrs) {
if (attrs[item]) {
str += ' ' + item + '="' + attrs[item] + '"'
}
}
if (this.options.pauseVideo) {
str += ' onplay="this.dispatchEvent(new CustomEvent(\'vplay\',{bubbles:!0}));for(var e=document.getElementsByTagName(\'video\'),t=0;t<e.length;t++)e[t]!=this&&e[t].pause()"'
}
str += '>'
for (let i = 0; i < node.src.length; i++) {
str += '<source src="' + node.src[i] + '">'
}
str += '</video>'
node.html = str
/* #endif */
} else if ((node.name === 'ul' || node.name === 'ol') && node.c) {
// 列表处理
const types = {
a: 'lower-alpha',
A: 'upper-alpha',
i: 'lower-roman',
I: 'upper-roman'
}
if (types[attrs.type]) {
attrs.style += ';list-style-type:' + types[attrs.type]
attrs.type = undefined
}
for (let i = children.length; i--;) {
if (children[i].name === 'li') {
children[i].c = 1
}
}
} else if (node.name === 'table') {
// 表格处理
// cellpadding、cellspacing、border 这几个常用表格属性需要通过转换实现
let padding = parseFloat(attrs.cellpadding)
let spacing = parseFloat(attrs.cellspacing)
const border = parseFloat(attrs.border)
if (node.c) {
// padding 和 spacing 默认 2
if (isNaN(padding)) {
padding = 2
}
if (isNaN(spacing)) {
spacing = 2
}
}
if (border) {
attrs.style += ';border:' + border + 'px solid gray'
}
if (node.flag && node.c) {
// 有 colspan 或 rowspan 且含有链接的表格通过 grid 布局实现
styleObj.display = 'grid'
if (spacing) {
styleObj['grid-gap'] = spacing + 'px'
styleObj.padding = spacing + 'px'
} else if (border) {
// 无间隔的情况下避免边框重叠
attrs.style += ';border-left:0;border-top:0'
}
const width = [] // 表格的列宽
const trList = [] // tr 列表
const cells = [] // 保存新的单元格
const map = {}; // 被合并单元格占用的格子
(function traversal (nodes) {
for (let i = 0; i < nodes.length; i++) {
if (nodes[i].name === 'tr') {
trList.push(nodes[i])
} else {
traversal(nodes[i].children || [])
}
}
})(children)
for (let row = 1; row <= trList.length; row++) {
let col = 1
for (let j = 0; j < trList[row - 1].children.length; j++) {
const td = trList[row - 1].children[j]
if (td.name === 'td' || td.name === 'th') {
// 这个格子被上面的单元格占用,则列号++
while (map[row + '.' + col]) {
col++
}
let style = td.attrs.style || ''
const start = style.indexOf('width') ? style.indexOf(';width') : 0
// 提取出 td 的宽度
if (start !== -1) {
let end = style.indexOf(';', start + 6)
if (end === -1) {
end = style.length
}
if (!td.attrs.colspan) {
width[col] = style.substring(start ? start + 7 : 6, end)
}
style = style.substr(0, start) + style.substr(end)
}
style += (border ? `;border:${border}px solid gray` + (spacing ? '' : ';border-right:0;border-bottom:0') : '') + (padding ? `;padding:${padding}px` : '')
// 处理列合并
if (td.attrs.colspan) {
style += `;grid-column-start:${col};grid-column-end:${col + parseInt(td.attrs.colspan)}`
if (!td.attrs.rowspan) {
style += `;grid-row-start:${row};grid-row-end:${row + 1}`
}
col += parseInt(td.attrs.colspan) - 1
}
// 处理行合并
if (td.attrs.rowspan) {
style += `;grid-row-start:${row};grid-row-end:${row + parseInt(td.attrs.rowspan)}`
if (!td.attrs.colspan) {
style += `;grid-column-start:${col};grid-column-end:${col + 1}`
}
// 记录下方单元格被占用
for (let rowspan = 1; rowspan < td.attrs.rowspan; rowspan++) {
for (let colspan = 0; colspan < (td.attrs.colspan || 1); colspan++) {
map[(row + rowspan) + '.' + (col - colspan)] = 1
}
}
}
if (style) {
td.attrs.style = style
}
cells.push(td)
col++
}
}
if (row === 1) {
let temp = ''
for (let i = 1; i < col; i++) {
temp += (width[i] ? width[i] : 'auto') + ' '
}
styleObj['grid-template-columns'] = temp
}
}
node.children = cells
} else {
// 没有使用合并单元格的表格通过 table 布局实现
if (node.c) {
styleObj.display = 'table'
}
if (!isNaN(spacing)) {
styleObj['border-spacing'] = spacing + 'px'
}
if (border || padding) {
// 遍历
(function traversal (nodes) {
for (let i = 0; i < nodes.length; i++) {
const td = nodes[i]
if (td.name === 'th' || td.name === 'td') {
if (border) {
td.attrs.style = `border:${border}px solid gray;${td.attrs.style || ''}`
}
if (padding) {
td.attrs.style = `padding:${padding}px;${td.attrs.style || ''}`
}
} else if (td.children) {
traversal(td.children)
}
}
})(children)
}
}
// 给表格添加一个单独的横向滚动层
if (this.options.scrollTable && !(attrs.style || '').includes('inline')) {
const table = Object.assign({}, node)
node.name = 'div'
node.attrs = {
style: 'overflow:auto'
}
node.children = [table]
attrs = table.attrs
}
} else if ((node.name === 'td' || node.name === 'th') && (attrs.colspan || attrs.rowspan)) {
for (let i = this.stack.length; i--;) {
if (this.stack[i].name === 'table') {
this.stack[i].flag = 1 // 指示含有合并单元格
break
}
}
} else if (node.name === 'ruby') {
// 转换 ruby
node.name = 'span'
for (let i = 0; i < children.length - 1; i++) {
if (children[i].type === 'text' && children[i + 1].name === 'rt') {
children[i] = {
name: 'div',
attrs: {
style: 'display:inline-block;text-align:center'
},
children: [{
name: 'div',
attrs: {
style: 'font-size:50%;' + (children[i + 1].attrs.style || '')
},
children: children[i + 1].children
}, children[i]]
}
children.splice(i + 1, 1)
}
}
} else if (node.c) {
(function traversal (node) {
node.c = 2
for (let i = node.children.length; i--;) {
const child = node.children[i]
// #ifdef (MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE3
if (child.name && (config.inlineTags[child.name] || (child.attrs.style || '').includes('inline')) && !child.c) {
traversal(child)
}
// #endif
if (!child.c || child.name === 'table') {
node.c = 1
}
}
})(node)
}
if ((styleObj.display || '').includes('flex') && !node.c) {
for (let i = children.length; i--;) {
const item = children[i]
if (item.f) {
item.attrs.style = (item.attrs.style || '') + item.f
item.f = undefined
}
}
}
// flex 布局时部分样式需要提取到 rich-text 外层
const flex = parent && ((parent.attrs.style || '').includes('flex') || (parent.attrs.style || '').includes('grid'))
// #ifdef MP-WEIXIN
// 检查基础库版本 virtualHost 是否可用
&& !(node.c && wx.getNFCAdapter) // eslint-disable-line
// #endif
// #ifndef MP-WEIXIN || MP-QQ || MP-BAIDU || MP-TOUTIAO
&& !node.c // eslint-disable-line
// #endif
if (flex) {
node.f = ';max-width:100%'
}
// 优化长内容加载速度
if (children.length >= 50 && node.c && !(styleObj.display || '').includes('flex')) {
let i = children.length - 1
for (let j = i; j >= -1; j--) {
// 合并多个块级标签
if (j === -1 || children[j].c || !children[j].name || (children[j].name !== 'div' && children[j].name !== 'p' && children[j].name[0] !== 'h') || (children[j].attrs.style || '').includes('inline')) {
if (i - j >= 5) {
children.splice(j + 1, i - j, {
name: 'div',
attrs: {},
children: node.children.slice(j + 1, i + 1)
})
}
i = j - 1
}
}
}
// #endif
for (const key in styleObj) {
if (styleObj[key]) {
const val = `;${key}:${styleObj[key].replace(' !important', '')}`
/* #ifndef APP-PLUS-NVUE */
if (flex && ((key.includes('flex') && key !== 'flex-direction') || key === 'align-self' || key.includes('grid') || styleObj[key][0] === '-' || (key.includes('width') && val.includes('%')))) {
node.f += val
if (key === 'width') {
attrs.style += ';width:100%'
}
} else /* #endif */ {
attrs.style += val
}
}
}
attrs.style = attrs.style.substr(1) || undefined
// #ifdef (MP-WEIXIN || MP-QQ) && VUE3
for (const key in attrs) {
if (!attrs[key]) {
delete attrs[key]
}
}
// #endif
}
/**
* @description 解析到文本
* @param {String} text 文本内容
*/
Parser.prototype.onText = function (text) {
if (!this.pre) {
// 合并空白符
let trim = ''
let flag
for (let i = 0, len = text.length; i < len; i++) {
if (!blankChar[text[i]]) {
trim += text[i]
} else {
if (trim[trim.length - 1] !== ' ') {
trim += ' '
}
if (text[i] === '\n' && !flag) {
flag = true
}
}
}
// 去除含有换行符的空串
if (trim === ' ' && flag) return
text = trim
}
const node = Object.create(null)
node.type = 'text'
// #ifdef (MP-BAIDU || MP-ALIPAY || MP-TOUTIAO) && VUE3
node.attrs = {}
// #endif
node.text = decodeEntity(text)
if (this.hook(node)) {
// #ifdef MP-WEIXIN
if (this.options.selectable === 'force' && system.includes('iOS') && !uni.canIUse('rich-text.user-select')) {
this.expose()
}
// #endif
const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes
siblings.push(node)
}
}
/**
* @description html 词法分析器
* @param {Object} handler 高层处理器
*/
function Lexer (handler) {
this.handler = handler
}
/**
* @description 执行解析
* @param {String} content 要解析的文本
*/
Lexer.prototype.parse = function (content) {
this.content = content || ''
this.i = 0 // 标记解析位置
this.start = 0 // 标记一个单词的开始位置
this.state = this.text // 当前状态
for (let len = this.content.length; this.i !== -1 && this.i < len;) {
this.state()
}
}
/**
* @description 检查标签是否闭合
* @param {String} method 如果闭合要进行的操作
* @returns {Boolean} 是否闭合
* @private
*/
Lexer.prototype.checkClose = function (method) {
const selfClose = this.content[this.i] === '/'
if (this.content[this.i] === '>' || (selfClose && this.content[this.i + 1] === '>')) {
if (method) {
this.handler[method](this.content.substring(this.start, this.i))
}
this.i += selfClose ? 2 : 1
this.start = this.i
this.handler.onOpenTag(selfClose)
if (this.handler.tagName === 'script') {
this.i = this.content.indexOf('</', this.i)
if (this.i !== -1) {
this.i += 2
this.start = this.i
}
this.state = this.endTag
} else {
this.state = this.text
}
return true
}
return false
}
/**
* @description 文本状态
* @private
*/
Lexer.prototype.text = function () {
this.i = this.content.indexOf('<', this.i) // 查找最近的标签
if (this.i === -1) {
// 没有标签了
if (this.start < this.content.length) {
this.handler.onText(this.content.substring(this.start, this.content.length))
}
return
}
const c = this.content[this.i + 1]
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
// 标签开头
if (this.start !== this.i) {
this.handler.onText(this.content.substring(this.start, this.i))
}
this.start = ++this.i
this.state = this.tagName
} else if (c === '/' || c === '!' || c === '?') {
if (this.start !== this.i) {
this.handler.onText(this.content.substring(this.start, this.i))
}
const next = this.content[this.i + 2]
if (c === '/' && ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
// 标签结尾
this.i += 2
this.start = this.i
this.state = this.endTag
return
}
// 处理注释
let end = '-->'
if (c !== '!' || this.content[this.i + 2] !== '-' || this.content[this.i + 3] !== '-') {
end = '>'
}
this.i = this.content.indexOf(end, this.i)
if (this.i !== -1) {
this.i += end.length
this.start = this.i
}
} else {
this.i++
}
}
/**
* @description 标签名状态
* @private
*/
Lexer.prototype.tagName = function () {
if (blankChar[this.content[this.i]]) {
// 解析到标签名
this.handler.onTagName(this.content.substring(this.start, this.i))
while (blankChar[this.content[++this.i]]);
if (this.i < this.content.length && !this.checkClose()) {
this.start = this.i
this.state = this.attrName
}
} else if (!this.checkClose('onTagName')) {
this.i++
}
}
/**
* @description 属性名状态
* @private
*/
Lexer.prototype.attrName = function () {
let c = this.content[this.i]
if (blankChar[c] || c === '=') {
// 解析到属性名
this.handler.onAttrName(this.content.substring(this.start, this.i))
let needVal = c === '='
const len = this.content.length
while (++this.i < len) {
c = this.content[this.i]
if (!blankChar[c]) {
if (this.checkClose()) return
if (needVal) {
// 等号后遇到第一个非空字符
this.start = this.i
this.state = this.attrVal
return
}
if (this.content[this.i] === '=') {
needVal = true
} else {
this.start = this.i
this.state = this.attrName
return
}
}
}
} else if (!this.checkClose('onAttrName')) {
this.i++
}
}
/**
* @description 属性值状态
* @private
*/
Lexer.prototype.attrVal = function () {
const c = this.content[this.i]
const len = this.content.length
if (c === '"' || c === "'") {
// 有冒号的属性
this.start = ++this.i
this.i = this.content.indexOf(c, this.i)
if (this.i === -1) return
this.handler.onAttrVal(this.content.substring(this.start, this.i))
} else {
// 没有冒号的属性
for (; this.i < len; this.i++) {
if (blankChar[this.content[this.i]]) {
this.handler.onAttrVal(this.content.substring(this.start, this.i))
break
} else if (this.checkClose('onAttrVal')) return
}
}
while (blankChar[this.content[++this.i]]);
if (this.i < len && !this.checkClose()) {
this.start = this.i
this.state = this.attrName
}
}
/**
* @description 结束标签状态
* @returns {String} 结束的标签名
* @private
*/
Lexer.prototype.endTag = function () {
const c = this.content[this.i]
if (blankChar[c] || c === '>' || c === '/') {
this.handler.onCloseTag(this.content.substring(this.start, this.i))
if (c !== '>') {
this.i = this.content.indexOf('>', this.i)
if (this.i === -1) return
}
this.start = ++this.i
this.state = this.text
} else {
this.i++
}
}
export default Parser
... ...
{
"id": "mp-html",
"displayName": "mp-html 富文本组件【全端支持,可编辑】",
"version": "v2.3.1",
"description": "一个强大的富文本组件,高效轻量,功能丰富",
"keywords": [
"富文本",
"编辑器",
"html",
"rich-text",
"editor"
],
"repository": "https://github.com/jin-yufeng/mp-html",
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/mp-html"
},
"uni_modules": {
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "u",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "y",
"联盟": "y"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}
\ No newline at end of file
... ...
"use strict";function t(t){for(var e=Object.create(null),n=t.attributes.length;n--;)e[t.attributes[n].name]=t.attributes[n].value;return e}function e(){o[1]&&(this.src=o[1],this.onerror=null),this.onclick=null,this.ontouchstart=null,uni.postMessage({data:{action:"onError",source:"img",attrs:t(this)}})}function n(r,i,s){for(var c=0;c<r.length;c++)!function(c){var u=r[c],l=void 0;if(u.type&&"node"!==u.type)l=document.createTextNode(u.text.replace(/&amp;/g,"&"));else{var d=u.name;"svg"===d&&(s="http://www.w3.org/2000/svg"),"html"!==d&&"body"!==d||(d="div"),l=s?document.createElementNS(s,d):document.createElement(d);for(var g in u.attrs)l.setAttribute(g,u.attrs[g]);if(u.children&&n(u.children,l,s),"img"===d){if(!l.src&&l.getAttribute("data-src")&&(l.src=l.getAttribute("data-src")),u.attrs.ignore||(l.onclick=function(e){e.stopPropagation(),uni.postMessage({data:{action:"onImgTap",attrs:t(this)}})}),o[2]){var p=new Image;p.src=l.src,l.src=o[2],p.onload=function(){l.src=this.src},p.onerror=function(){l.onerror()}}l.onerror=e}else if("a"===d)l.addEventListener("click",function(e){e.stopPropagation(),e.preventDefault();var n,o=this.getAttribute("href");o&&"#"===o[0]&&(n=(document.getElementById(o.substr(1))||{}).offsetTop),uni.postMessage({data:{action:"onLinkTap",attrs:t(this),offset:n}})},!0);else if("video"===d||"audio"===d)a.push(l),u.attrs.autoplay||u.attrs.controls||l.setAttribute("controls","true"),l.onplay=function(){if(uni.postMessage({data:{action:"onPlay"}}),o[3])for(var t=0;t<a.length;t++)a[t]!==this&&a[t].pause()},l.onerror=function(){uni.postMessage({data:{action:"onError",source:d,attrs:t(this)}})};else if("table"===d&&o[4]&&!l.style.cssText.includes("inline")){var f=document.createElement("div");f.style.overflow="auto",f.appendChild(l),l=f}else"svg"===d&&(s=void 0)}i.appendChild(l)}(c)}document.addEventListener("UniAppJSBridgeReady",function(){document.body.onclick=function(){return uni.postMessage({data:{action:"onClick"}})},uni.postMessage({data:{action:"onJSBridgeReady"}})});var o,a=[];window.setContent=function(t,e,r){var i=document.getElementById("content");e[0]&&(document.body.style.cssText=e[0]),e[5]||(i.style.userSelect="none"),r||(i.innerHTML="",a=[]),o=e;var s=document.createDocumentFragment();n(t,s),i.appendChild(s);var c=i.scrollHeight;uni.postMessage({data:{action:"onLoad",height:c}}),clearInterval(window.timer);var u=!1;window.timer=setInterval(function(){i.scrollHeight!==c?(c=i.scrollHeight,uni.postMessage({data:{action:"onHeightChange",height:c}})):u||(u=!0,uni.postMessage({data:{action:"onReady"}}))},350)},window.onunload=function(){clearInterval(window.timer)};
\ No newline at end of file
... ...
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){"use strict";try{var e={};Object.defineProperty(e,"passive",{get:function(){!0}}),window.addEventListener("test-passive",null,e)}catch(e){}var n=Object.prototype.hasOwnProperty;function t(e,t){return n.call(e,t)}var i=[],a=function(e,n){var t={options:{timestamp:+new Date},name:e,arg:n};if(window.__dcloud_weex_postMessage||window.__dcloud_weex_){if("postMessage"===e){var a={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(a):window.__dcloud_weex_.postMessage(JSON.stringify(a))}var o={type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(o):window.__dcloud_weex_.postMessageToService(JSON.stringify(o))}if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data:t,pageId:""},"*");if(0===i.length){var r=plus.webview.currentWebview();if(!r)throw new Error("plus.webview.currentWebview() is undefined");var d=r.parent(),s="";s=d?d.id:r.id,i.push(s)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}},"__uniapp__service");else{var w=JSON.stringify(t);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(w,",").concat(JSON.stringify(i),");"))}},o={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;a("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("redirectTo",{url:encodeURI(n)})},getEnv:function(e){window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};a("postMessage",e.data||{})}},r=/uni-app/i.test(navigator.userAgent),d=/Html5Plus/i.test(navigator.userAgent),s=/complete|loaded|interactive/;var w=window.my&&navigator.userAgent.indexOf("AlipayClient")>-1;var u=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var g=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var v=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.qa&&/quickapp/i.test(navigator.userAgent);for(var l,_=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},f=[function(e){if(r||d)return window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&s.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),o},function(e){if(v)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(w){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(u)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(g)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(p){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){return document.addEventListener("DOMContentLoaded",e),o}],m=0;m<f.length&&!(l=f[m](_));m++);l||(l={});var E="undefined"!=typeof uni?uni:{};if(!E.navigateTo)for(var b in l)t(l,b)&&(E[b]=l[b]);return E.webView=l,E}));
\ No newline at end of file
... ...
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><style>body,html{width:100%;height:100%;overflow-x:scroll;overflow-y:hidden}body{margin:0}video{width:300px;height:225px}img{max-width:100%;-webkit-touch-callout:none}</style></head><body><div id="content" style="overflow:hidden"></div><script type="text/javascript" src="./js/uni.webview.min.js"></script><script type="text/javascript" src="./js/handler.js"></script></body>
\ No newline at end of file
... ...
<!DOCTYPE html><html lang=zh-CN><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><title>琉璃藏宝阁</title><script>var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')</script><link rel=stylesheet href=/static/index.2772579d.css></head><body><noscript><strong>Please enable JavaScript to continue.</strong></noscript><div id=app></div><script src=/static/js/chunk-vendors.25d822ea.js></script><script src=/static/js/index.f0cd1748.js></script></body></html>
\ No newline at end of file
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')</script><link rel=stylesheet href=/static/index.2772579d.css></head><body><noscript><strong>Please enable JavaScript to continue.</strong></noscript><div id=app></div><script src=/static/js/chunk-vendors.25d822ea.js></script><script src=/static/js/index.c92d288b.js></script></body></html>
\ No newline at end of file
... ...
export const baseURL = 'http://yuanjie.n.broing.cn/api/'
// export const baseURL = 'http://yuanjie.n.broing.cn/api/'
export const baseURL = 'https://admin.llcbg.com/api/'
export const request = (options) => {
return new Promise((resolve, reject) => {
uni.request({
... ...
var jweixin = require('jweixin-module');
import {
get_jssdk
} from '@/api/index.js' // 分享接口后台提供,用于获取appid,timestamp,nonceStr,signature
var Shares = {
async get_jssdk(title, href) {
console.log(title,href, 'YE面数据')
let that = this;
try {
const res = await get_jssdk(href)
console.log('get_jssdk', res)
jweixin.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: res.jssdk.appId, // 必填,公众号的唯一标识
timestamp: res.jssdk.timestamp, // 必填,生成签名的时间戳
nonceStr: res.jssdk.nonceStr, // 必填,生成签名的随机串
signature: res.jssdk.signature, // 必填,签名
jsApiList: res.jssdk.jsApiList // 必填,需要使用的JS接口列表
})
jweixin.error(function(res) {
console.log(res, '错误')
});
console.log('分享了', res.jssdk.signature);
jweixin.ready(function() {
//分享给朋友
jweixin.onMenuShareAppMessage({
title: title, // 分享标题
link: href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc: "【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: "http://yuanjie.n.broing.cn/assets/img/share_logo.jpg", // 分享图标
success: function() {
// 用户点击了分享后执行的回调函数
uni.showToast({
title: '分享成功',
duration: 2000
});
},
cancel: function(res) {
console.log('取消分享')
}
});
jweixin.updateAppMessageShareData({
title: title, // 分享标题
link: href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc: "【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: "http://yuanjie.n.broing.cn/assets/img/share_logo.jpg", // 分享图标
success: function() {
console.log('设置分享给朋友成功')
},
cancel: function(res) {
console.log('取消分享')
}
});
//分享到朋友圈
jweixin.onMenuShareTimeline({
title: title, // 分享标题
link: href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc: "【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: "http://yuanjie.n.broing.cn/assets/img/share_logo.jpg", // 分享图标
success: function() {
// 用户点击了分享后执行的回调函数
uni.showToast({
title: '分享成功',
duration: 2000
});
},
cancel: function(res) {
console.log('取消分享')
}
});
jweixin.updateTimelineShareData({
title: title, // 分享标题
link: href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
desc: "【琉璃藏宝阁】数字藏品流转平台,顺利“琉”转,藏品“璃”手",
imgUrl: "http://yuanjie.n.broing.cn/assets/img/share_logo.jpg", // 分享图标
success: function() {
console.log('设置分享到朋友圈成功')
},
cancel: function(res) {
console.log('取消分享')
}
});
});
// 保存数据
} catch (err) {
uni.showToast({
title: err,
icon: 'none'
})
console.log('get_jssdk', err)
}
}
}
export {
Shares
}
... ...