hy-app 0.5.11 → 0.5.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,473 +1,670 @@
1
1
  <template>
2
- <view :id="attrs.id" :class="'_block _'+name+' '+attrs.class" :style="attrs.style">
3
- <block v-for="(n, i) in childs" v-bind:key="i">
4
- <!-- 图片 -->
5
- <!-- 占位图 -->
6
- <image v-if="n.name==='img'&&!n.t&&((opts[1]&&!ctrl[i])||ctrl[i]<0)" class="_img" :style="n.attrs.style" :src="ctrl[i]<0?opts[2]:opts[1]" mode="widthFix" />
7
- <!-- 显示图片 -->
8
- <!-- #ifdef H5 || (APP-PLUS && VUE2) -->
9
- <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" />
10
- <!-- #endif -->
11
- <!-- #ifndef H5 || (APP-PLUS && VUE2) -->
12
- <!-- 表格中的图片,使用 rich-text 防止大小不正确 -->
13
- <rich-text v-if="n.name==='img'&&n.t" :style="'display:'+n.t" :nodes="'<img class=\'_img\' style=\''+n.attrs.style+'\' src=\''+n.attrs.src+'\'>'" :data-i="i" @tap.stop="imgTap" />
14
- <!-- #endif -->
15
- <!-- #ifndef H5 || APP-PLUS -->
16
- <image v-else-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" />
17
- <!-- #endif -->
18
- <!-- #ifdef APP-PLUS && VUE3 -->
19
- <image v-else-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" />
20
- <!-- #endif -->
21
- <!-- 文本 -->
22
- <!-- #ifdef MP-WEIXIN -->
23
- <text v-else-if="n.text" :user-select="opts[4]=='force'&&isiOS" decode>{{n.text}}</text>
24
- <!-- #endif -->
25
- <!-- #ifndef MP-WEIXIN || MP-BAIDU || MP-ALIPAY || MP-TOUTIAO -->
26
- <text v-else-if="n.text" decode>{{n.text}}</text>
27
- <!-- #endif -->
28
- <text v-else-if="n.name==='br'">\n</text>
29
- <!-- 链接 -->
30
- <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">
31
- <node name="span" :childs="n.children" :opts="opts" style="display:inherit" />
32
- </view>
33
- <!-- 视频 -->
34
- <!-- #ifdef APP-PLUS -->
35
- <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" />
36
- <!-- #endif -->
37
- <!-- #ifndef APP-PLUS -->
38
- <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" />
39
- <!-- #endif -->
40
- <!-- #ifdef H5 || APP-PLUS -->
41
- <iframe v-else-if="n.name==='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen" :frameborder="n.attrs.frameborder" :src="n.attrs.src" />
42
- <embed v-else-if="n.name==='embed'" :style="n.attrs.style" :src="n.attrs.src" />
43
- <!-- #endif -->
44
- <!-- #ifndef MP-TOUTIAO || ((H5 || APP-PLUS) && VUE3) -->
45
- <!-- 音频 -->
46
- <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" />
47
- <!-- #endif -->
48
- <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">
49
- <node v-if="n.name==='li'" :childs="n.children" :opts="opts" />
50
- <view v-else v-for="(tbody, x) in n.children" v-bind:key="x" :class="'_'+tbody.name+' '+tbody.attrs.class" :style="tbody.attrs.style">
51
- <node v-if="tbody.name==='td'||tbody.name==='th'" :childs="tbody.children" :opts="opts" />
52
- <block v-else v-for="(tr, y) in tbody.children" v-bind:key="y">
53
- <view v-if="tr.name==='td'||tr.name==='th'" :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
54
- <node :childs="tr.children" :opts="opts" />
2
+ <view :id="attrs.id" :class="'_block _' + name + ' ' + attrs.class" :style="attrs.style">
3
+ <block v-for="(n, i) in childs" v-bind:key="i">
4
+ <!-- 图片 -->
5
+ <!-- 占位图 -->
6
+ <image
7
+ v-if="n.name === 'img' && !n.t && ((opts[1] && !ctrl[i]) || ctrl[i] < 0)"
8
+ class="_img"
9
+ :style="n.attrs.style"
10
+ :src="ctrl[i] < 0 ? opts[2] : opts[1]"
11
+ mode="widthFix"
12
+ />
13
+ <!-- 显示图片 -->
14
+ <!-- #ifdef H5 || (APP-PLUS && VUE2) -->
15
+ <img
16
+ v-if="n.name === 'img'"
17
+ :id="n.attrs.id"
18
+ :class="'_img ' + n.attrs.class"
19
+ :style="(ctrl[i] === -1 ? 'display:none;' : '') + n.attrs.style"
20
+ :src="n.attrs.src || (ctrl.load ? n.attrs['data-src'] : '')"
21
+ :data-i="i"
22
+ @load="imgLoad"
23
+ @error="mediaError"
24
+ @tap.stop="imgTap"
25
+ @longpress="imgLongTap"
26
+ />
27
+ <!-- #endif -->
28
+ <!-- #ifndef H5 || (APP-PLUS && VUE2) -->
29
+ <!-- 表格中的图片,使用 rich-test 防止大小不正确 -->
30
+ <rich-text
31
+ v-if="n.name === 'img' && n.t"
32
+ :style="'display:' + n.t"
33
+ :nodes="
34
+ '<img class=\'_img\' style=\'' +
35
+ n.attrs.style +
36
+ '\' src=\'' +
37
+ n.attrs.src +
38
+ '\'>'
39
+ "
40
+ :data-i="i"
41
+ @tap.stop="imgTap"
42
+ />
43
+ <!-- #endif -->
44
+ <!-- #ifndef H5 || APP-PLUS -->
45
+ <image
46
+ v-else-if="n.name === 'img'"
47
+ :id="n.attrs.id"
48
+ :class="'_img ' + n.attrs.class"
49
+ :style="
50
+ (ctrl[i] === -1 ? 'display:none;' : '') +
51
+ 'width:' +
52
+ (ctrl[i] || 1) +
53
+ 'px;height:1px;' +
54
+ n.attrs.style
55
+ "
56
+ :src="n.attrs.src"
57
+ :mode="!n.h ? 'widthFix' : !n.w ? 'heightFix' : ''"
58
+ :lazy-load="opts[0]"
59
+ :webp="n.webp"
60
+ :show-menu-by-longpress="opts[3] && !n.attrs.ignore"
61
+ :image-menu-prevent="!opts[3] || n.attrs.ignore"
62
+ :data-i="i"
63
+ @load="imgLoad"
64
+ @error="mediaError"
65
+ @tap.stop="imgTap"
66
+ @longpress="imgLongTap"
67
+ />
68
+ <!-- #endif -->
69
+ <!-- #ifdef APP-PLUS && VUE3 -->
70
+ <image
71
+ v-else-if="n.name === 'img'"
72
+ :id="n.attrs.id"
73
+ :class="'_img ' + n.attrs.class"
74
+ :style="
75
+ (ctrl[i] === -1 ? 'display:none;' : '') +
76
+ 'width:' +
77
+ (ctrl[i] || 1) +
78
+ 'px;' +
79
+ n.attrs.style
80
+ "
81
+ :src="n.attrs.src || (ctrl.load ? n.attrs['data-src'] : '')"
82
+ :mode="!n.h ? 'widthFix' : !n.w ? 'heightFix' : ''"
83
+ :data-i="i"
84
+ @load="imgLoad"
85
+ @error="mediaError"
86
+ @tap.stop="imgTap"
87
+ @longpress="imgLongTap"
88
+ />
89
+ <!-- #endif -->
90
+ <!-- 文本 -->
91
+ <!-- #ifdef MP-WEIXIN -->
92
+ <text v-else-if="n.text" :user-select="opts[4] == 'force' && isiOS" decode>{{
93
+ n.text
94
+ }}</text>
95
+ <!-- #endif -->
96
+ <!-- #ifndef MP-WEIXIN || MP-BAIDU || MP-ALIPAY || MP-TOUTIAO -->
97
+ <text v-else-if="n.text" decode>{{ n.text }}</text>
98
+ <!-- #endif -->
99
+ <text v-else-if="n.name === 'br'">\n</text>
100
+ <!-- 链接 -->
101
+ <view
102
+ v-else-if="n.name === 'a'"
103
+ :id="n.attrs.id"
104
+ :class="(n.attrs.href ? '_a ' : '') + n.attrs.class"
105
+ hover-class="_hover"
106
+ :style="'display:inline;' + n.attrs.style"
107
+ :data-i="i"
108
+ @tap.stop="linkTap"
109
+ >
110
+ <node name="span" :childs="n.children" :opts="opts" style="display: inherit" />
55
111
  </view>
56
- <view v-else :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
57
- <view v-for="(td, z) in tr.children" v-bind:key="z" :class="'_'+td.name+' '+td.attrs.class" :style="td.attrs.style">
58
- <node :childs="td.children" :opts="opts" />
59
- </view>
112
+ <!-- 视频 -->
113
+ <!-- #ifdef APP-PLUS -->
114
+ <view
115
+ v-else-if="n.html"
116
+ :id="n.attrs.id"
117
+ :class="'_video ' + n.attrs.class"
118
+ :style="n.attrs.style"
119
+ v-html="n.html"
120
+ @vplay.stop="play"
121
+ />
122
+ <!-- #endif -->
123
+ <!-- #ifndef APP-PLUS -->
124
+ <video
125
+ v-else-if="n.name === 'video'"
126
+ :id="n.attrs.id"
127
+ :class="n.attrs.class"
128
+ :style="n.attrs.style"
129
+ :autoplay="n.attrs.autoplay"
130
+ :controls="n.attrs.controls"
131
+ :loop="n.attrs.loop"
132
+ :muted="n.attrs.muted"
133
+ :object-fit="n.attrs['object-fit']"
134
+ :poster="n.attrs.poster"
135
+ :src="n.src[ctrl[i] || 0]"
136
+ :data-i="i"
137
+ @play="play"
138
+ @error="mediaError"
139
+ />
140
+ <!-- #endif -->
141
+ <!-- #ifdef H5 || APP-PLUS -->
142
+ <iframe
143
+ v-else-if="n.name === 'iframe'"
144
+ :style="n.attrs.style"
145
+ :allowfullscreen="n.attrs.allowfullscreen"
146
+ :frameborder="n.attrs.frameborder"
147
+ :src="n.attrs.src"
148
+ />
149
+ <embed v-else-if="n.name === 'embed'" :style="n.attrs.style" :src="n.attrs.src" />
150
+ <!-- #endif -->
151
+ <!-- #ifndef MP-TOUTIAO || ((H5 || APP-PLUS) && VUE3) -->
152
+ <!-- 音频 -->
153
+ <audio
154
+ v-else-if="n.name === 'audio'"
155
+ :id="n.attrs.id"
156
+ :class="n.attrs.class"
157
+ :style="n.attrs.style"
158
+ :author="n.attrs.author"
159
+ :controls="n.attrs.controls"
160
+ :loop="n.attrs.loop"
161
+ :name="n.attrs.name"
162
+ :poster="n.attrs.poster"
163
+ :src="n.src[ctrl[i] || 0]"
164
+ :data-i="i"
165
+ @play="play"
166
+ @error="mediaError"
167
+ />
168
+ <!-- #endif -->
169
+ <view
170
+ v-else-if="(n.name === 'table' && n.c) || n.name === 'li'"
171
+ :id="n.attrs.id"
172
+ :class="'_' + n.name + ' ' + n.attrs.class"
173
+ :style="n.attrs.style"
174
+ >
175
+ <node v-if="n.name === 'li'" :childs="n.children" :opts="opts" />
176
+ <view
177
+ v-else
178
+ v-for="(tbody, x) in n.children"
179
+ v-bind:key="x"
180
+ :class="'_' + tbody.name + ' ' + tbody.attrs.class"
181
+ :style="tbody.attrs.style"
182
+ >
183
+ <node
184
+ v-if="tbody.name === 'td' || tbody.name === 'th'"
185
+ :childs="tbody.children"
186
+ :opts="opts"
187
+ />
188
+ <block v-else v-for="(tr, y) in tbody.children" v-bind:key="y">
189
+ <view
190
+ v-if="tr.name === 'td' || tr.name === 'th'"
191
+ :class="'_' + tr.name + ' ' + tr.attrs.class"
192
+ :style="tr.attrs.style"
193
+ >
194
+ <node :childs="tr.children" :opts="opts" />
195
+ </view>
196
+ <view
197
+ v-else
198
+ :class="'_' + tr.name + ' ' + tr.attrs.class"
199
+ :style="tr.attrs.style"
200
+ >
201
+ <view
202
+ v-for="(td, z) in tr.children"
203
+ v-bind:key="z"
204
+ :class="'_' + td.name + ' ' + td.attrs.class"
205
+ :style="td.attrs.style"
206
+ >
207
+ <node :childs="td.children" :opts="opts" />
208
+ </view>
209
+ </view>
210
+ </block>
211
+ </view>
60
212
  </view>
61
- </block>
62
- </view>
63
- </view>
64
-
65
- <!-- 富文本 -->
66
- <!-- #ifdef H5 || ((MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE2) -->
67
- <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]" />
68
- <!-- #endif -->
69
- <!-- #ifndef H5 || ((MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE2) -->
70
- <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]" />
71
- <!-- #endif -->
72
- <!-- 继续递归 -->
73
- <view v-else-if="n.c===2" :id="n.attrs.id" :class="'_block _'+n.name+' '+n.attrs.class" :style="n.f+';'+n.attrs.style">
74
- <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" />
75
- </view>
76
- <node v-else :style="n.f" :name="n.name" :attrs="n.attrs" :childs="n.children" :opts="opts" />
77
- </block>
78
- </view>
213
+
214
+ <!-- 富文本 -->
215
+ <!-- #ifdef H5 || ((MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE2) -->
216
+ <rich-text
217
+ v-else-if="!n.c && !handler.isInline(n.name, n.attrs.style)"
218
+ :id="n.attrs.id"
219
+ :style="n.f"
220
+ :user-select="opts[4]"
221
+ :nodes="[n]"
222
+ />
223
+ <!-- #endif -->
224
+ <!-- #ifndef H5 || ((MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE2) -->
225
+ <rich-text
226
+ v-else-if="!n.c"
227
+ :id="n.attrs.id"
228
+ :style="n.f + ';display:inline'"
229
+ :preview="false"
230
+ :selectable="opts[4]"
231
+ :user-select="opts[4]"
232
+ :nodes="[n]"
233
+ />
234
+ <!-- #endif -->
235
+ <!-- 继续递归 -->
236
+ <view
237
+ v-else-if="n.c === 2"
238
+ :id="n.attrs.id"
239
+ :class="'_block _' + n.name + ' ' + n.attrs.class"
240
+ :style="n.f + ';' + n.attrs.style"
241
+ >
242
+ <node
243
+ v-for="(n2, j) in n.children"
244
+ v-bind:key="j"
245
+ :style="n2.f"
246
+ :name="n2.name"
247
+ :attrs="n2.attrs"
248
+ :childs="n2.children"
249
+ :opts="opts"
250
+ />
251
+ </view>
252
+ <node
253
+ v-else
254
+ :style="n.f"
255
+ :name="n.name"
256
+ :attrs="n.attrs"
257
+ :childs="n.children"
258
+ :opts="opts"
259
+ />
260
+ </block>
261
+ </view>
79
262
  </template>
80
263
  <script module="handler" lang="wxs">
81
264
  // 行内标签列表
82
265
  var inlineTags = {
83
- abbr: true,
84
- b: true,
85
- big: true,
86
- code: true,
87
- del: true,
88
- em: true,
89
- i: true,
90
- ins: true,
91
- label: true,
92
- q: true,
93
- small: true,
94
- span: true,
95
- strong: true,
96
- sub: true,
97
- sup: true
266
+ abbr: true,
267
+ b: true,
268
+ big: true,
269
+ code: true,
270
+ del: true,
271
+ em: true,
272
+ i: true,
273
+ ins: true,
274
+ label: true,
275
+ q: true,
276
+ small: true,
277
+ span: true,
278
+ strong: true,
279
+ sub: true,
280
+ sup: true
98
281
  }
99
282
  /**
100
283
  * @description 判断是否为行内标签
101
284
  */
102
285
  module.exports = {
103
- isInline: function (tagName, style) {
104
- return inlineTags[tagName] || (style || '').indexOf('display:inline') !== -1
105
- }
286
+ isInline: function (tagName, style) {
287
+ return inlineTags[tagName] || (style || '').indexOf('display:inline') !== -1
288
+ }
106
289
  }
107
290
  </script>
108
291
  <script>
109
-
110
292
  import node from './node'
111
293
  export default {
112
- name: 'node',
113
- options: {
114
- // #ifdef MP-WEIXIN
115
- virtualHost: true,
116
- // #endif
117
- // #ifdef MP-TOUTIAO
118
- addGlobalClass: false
119
- // #endif
120
- },
121
- data () {
122
- return {
123
- ctrl: {},
124
- // #ifdef MP-WEIXIN
125
- isiOS: uni.getDeviceInfo().system.includes('iOS')
126
- // #endif
127
- }
128
- },
129
- props: {
130
- name: String,
131
- attrs: {
132
- type: Object,
133
- default () {
134
- return {}
135
- }
294
+ name: 'node',
295
+ options: {
296
+ // #ifdef MP-WEIXIN
297
+ virtualHost: true,
298
+ // #endif
299
+ // #ifdef MP-TOUTIAO
300
+ addGlobalClass: false
301
+ // #endif
136
302
  },
137
- childs: Array,
138
- opts: Array
139
- },
140
- components: {
141
-
142
- // #ifndef (H5 || APP-PLUS) && VUE3
143
- node
144
- // #endif
145
- },
146
- mounted () {
147
- this.$nextTick(() => {
148
- for (this.root = this.$parent; this.root.$options.name !== 'hy-parse'; this.root = this.root.$parent);
149
- })
150
- // #ifdef H5 || APP-PLUS
151
- if (this.opts[0]) {
152
- let i
153
- for (i = this.childs.length; i--;) {
154
- if (this.childs[i].name === 'img') break
155
- }
156
- if (i !== -1) {
157
- this.observer = uni.createIntersectionObserver(this).relativeToViewport({
158
- top: 500,
159
- bottom: 500
160
- })
161
- this.observer.observe('._img', res => {
162
- if (res.intersectionRatio) {
163
- this.$set(this.ctrl, 'load', 1)
164
- this.observer.disconnect()
165
- }
166
- })
167
- }
168
- }
169
- // #endif
170
- },
171
- beforeUnmount () {
172
- // #ifdef H5 || APP-PLUS
173
- if (this.observer) {
174
- this.observer.disconnect()
175
- }
176
- // #endif
177
- },
178
- methods:{
179
- // #ifdef MP-WEIXIN
180
- toJSON () { return this },
181
- // #endif
182
- /**
183
- * @description 播放视频事件
184
- * @param {Event} e
185
- */
186
- play (e) {
187
- this.root.$emit('play')
188
- // #ifndef APP-PLUS
189
- if (this.root.pauseVideo) {
190
- let flag = false
191
- const id = e.target.id
192
- for (let i = this.root._videos.length; i--;) {
193
- if (this.root._videos[i].id === id) {
194
- flag = true
195
- } else {
196
- this.root._videos[i].pause() // 自动暂停其他视频
197
- }
198
- }
199
- // 将自己加入列表
200
- if (!flag) {
201
- const ctx = uni.createVideoContext(id
202
- // #ifndef MP-BAIDU
203
- , this
303
+ data() {
304
+ return {
305
+ ctrl: {},
306
+ // #ifdef MP-WEIXIN
307
+ isiOS: uni.getDeviceInfo().system.includes('iOS')
204
308
  // #endif
205
- )
206
- ctx.id = id
207
- if (this.root.playbackRate) {
208
- ctx.playbackRate(this.root.playbackRate)
209
- }
210
- this.root._videos.push(ctx)
211
309
  }
212
- }
213
- // #endif
214
310
  },
215
-
216
- /**
217
- * @description 图片点击事件
218
- * @param {Event} e
219
- */
220
- imgTap (e) {
221
- const node = this.childs[e.currentTarget.dataset.i]
222
- if (node.a) {
223
- this.linkTap(node.a)
224
- return
225
- }
226
- if (node.attrs.ignore) return
227
- // #ifdef H5 || APP-PLUS
228
- node.attrs.src = node.attrs.src || node.attrs['data-src']
229
- // #endif
230
- this.root.$emit('imgTap', node.attrs)
231
- // 自动预览图片
232
- if (this.root.previewImg) {
233
- uni.previewImage({
234
- // #ifdef MP-WEIXIN
235
- showmenu: this.root.showImgMenu,
236
- // #endif
237
- // #ifdef MP-ALIPAY
238
- enablesavephoto: this.root.showImgMenu,
239
- enableShowPhotoDownload: this.root.showImgMenu,
240
- // #endif
241
- current: parseInt(node.attrs.i),
242
- urls: this.root.imgList
243
- })
244
- }
311
+ props: {
312
+ name: String,
313
+ attrs: {
314
+ type: Object,
315
+ default() {
316
+ return {}
317
+ }
318
+ },
319
+ childs: Array,
320
+ opts: Array
245
321
  },
246
-
247
- /**
248
- * @description 图片长按
249
- */
250
- imgLongTap (e) {
251
- // #ifdef APP-PLUS
252
- const attrs = this.childs[e.currentTarget.dataset.i].attrs
253
- if (this.opts[3] && !attrs.ignore) {
254
- uni.showActionSheet({
255
- itemList: ['保存图片'],
256
- success: () => {
257
- const save = path => {
258
- uni.saveImageToPhotosAlbum({
259
- filePath: path,
260
- success () {
261
- uni.showToast({
262
- title: '保存成功'
263
- })
264
- }
265
- })
322
+ components: {
323
+ // #ifndef (H5 || APP-PLUS) && VUE3
324
+ node
325
+ // #endif
326
+ },
327
+ mounted() {
328
+ this.$nextTick(() => {
329
+ for (
330
+ this.root = this.$parent;
331
+ this.root.$options.name !== 'hy-parse';
332
+ this.root = this.root.$parent
333
+ );
334
+ })
335
+ // #ifdef H5 || APP-PLUS
336
+ if (this.opts[0]) {
337
+ let i
338
+ for (i = this.childs.length; i--; ) {
339
+ if (this.childs[i].name === 'img') break
266
340
  }
267
- if (this.root.imgList[attrs.i].startsWith('http')) {
268
- uni.downloadFile({
269
- url: this.root.imgList[attrs.i],
270
- success: res => save(res.tempFilePath)
271
- })
272
- } else {
273
- save(this.root.imgList[attrs.i])
341
+ if (i !== -1) {
342
+ this.observer = uni.createIntersectionObserver(this).relativeToViewport({
343
+ top: 500,
344
+ bottom: 500
345
+ })
346
+ this.observer.observe('._img', (res) => {
347
+ if (res.intersectionRatio) {
348
+ this.$set(this.ctrl, 'load', 1)
349
+ this.observer.disconnect()
350
+ }
351
+ })
274
352
  }
275
- }
276
- })
277
- }
278
- // #endif
279
- },
280
-
281
- /**
282
- * @description 图片加载完成事件
283
- * @param {Event} e
284
- */
285
- imgLoad (e) {
286
- const i = e.currentTarget.dataset.i
287
- /* #ifndef H5 || (APP-PLUS && VUE2) */
288
- if (!this.childs[i].w) {
289
- // 设置原宽度
290
- this.$set(this.ctrl, i, e.detail.width)
291
- } else /* #endif */ if ((this.opts[1] && !this.ctrl[i]) || this.ctrl[i] === -1) {
292
- // 加载完毕,取消加载中占位图
293
- this.$set(this.ctrl, i, 1)
294
- }
295
- this.checkReady()
353
+ }
354
+ // #endif
296
355
  },
297
-
298
- /**
299
- * @description 检查是否所有图片加载完毕
300
- */
301
- checkReady () {
302
- if (!this.root.lazyLoad) {
303
- this.root._unloadimgs -= 1
304
- if (!this.root._unloadimgs) {
305
- setTimeout(() => {
306
- this.root.getRect().then(rect => {
307
- this.root.$emit('ready', rect)
308
- }).catch(() => {
309
- this.root.$emit('ready', {})
310
- })
311
- }, 350)
356
+ beforeUnmount() {
357
+ // #ifdef H5 || APP-PLUS
358
+ if (this.observer) {
359
+ this.observer.disconnect()
312
360
  }
313
- }
361
+ // #endif
314
362
  },
315
-
316
- /**
317
- * @description 链接点击事件
318
- * @param {Event} e
319
- */
320
- linkTap (e) {
321
- const node = e.currentTarget ? this.childs[e.currentTarget.dataset.i] : {}
322
- const attrs = node.attrs || e
323
- const href = attrs.href
324
- this.root.$emit('linkTap', Object.assign({
325
- innerText: this.root.getText(node.children || []) // 链接内的文本内容
326
- }, attrs))
327
- if (href) {
328
- if (href[0] === '#') {
329
- // 跳转锚点
330
- this.root.navigateTo(href.substring(1)).catch(() => { })
331
- } else if (href.split('?')[0].includes('://')) {
332
- // 复制外部链接
333
- if (this.root.copyLink) {
334
- // #ifdef H5
335
- window.open(href)
363
+ methods: {
364
+ // #ifdef MP-WEIXIN
365
+ toJSON() {
366
+ return this
367
+ },
368
+ // #endif
369
+ /**
370
+ * @description 播放视频事件
371
+ * @param {Event} e
372
+ */
373
+ play(e) {
374
+ this.root.$emit('play')
375
+ // #ifndef APP-PLUS
376
+ if (this.root.pauseVideo) {
377
+ let flag = false
378
+ const id = e.target.id
379
+ for (let i = this.root._videos.length; i--; ) {
380
+ if (this.root._videos[i].id === id) {
381
+ flag = true
382
+ } else {
383
+ this.root._videos[i].pause() // 自动暂停其他视频
384
+ }
385
+ }
386
+ // 将自己加入列表
387
+ if (!flag) {
388
+ const ctx = uni.createVideoContext(
389
+ id,
390
+ // #ifndef MP-BAIDU
391
+ this
392
+ // #endif
393
+ )
394
+ ctx.id = id
395
+ if (this.root.playbackRate) {
396
+ ctx.playbackRate(this.root.playbackRate)
397
+ }
398
+ this.root._videos.push(ctx)
399
+ }
400
+ }
336
401
  // #endif
337
- // #ifdef MP
338
- uni.setClipboardData({
339
- data: href,
340
- success: () =>
341
- uni.showToast({
342
- title: '链接已复制'
343
- })
344
- })
402
+ },
403
+
404
+ /**
405
+ * @description 图片点击事件
406
+ * @param {Event} e
407
+ */
408
+ imgTap(e) {
409
+ const node = this.childs[e.currentTarget.dataset.i]
410
+ if (node.a) {
411
+ this.linkTap(node.a)
412
+ return
413
+ }
414
+ if (node.attrs.ignore) return
415
+ // #ifdef H5 || APP-PLUS
416
+ node.attrs.src = node.attrs.src || node.attrs['data-src']
345
417
  // #endif
418
+ this.root.$emit('imgTap', node.attrs)
419
+ // 自动预览图片
420
+ if (this.root.previewImg) {
421
+ uni.previewImage({
422
+ // #ifdef MP-WEIXIN
423
+ showmenu: this.root.showImgMenu,
424
+ // #endif
425
+ // #ifdef MP-ALIPAY
426
+ enablesavephoto: this.root.showImgMenu,
427
+ enableShowPhotoDownload: this.root.showImgMenu,
428
+ // #endif
429
+ current: parseInt(node.attrs.i),
430
+ urls: this.root.imgList
431
+ })
432
+ }
433
+ },
434
+
435
+ /**
436
+ * @description 图片长按
437
+ */
438
+ imgLongTap(e) {
346
439
  // #ifdef APP-PLUS
347
- plus.runtime.openWeb(href)
440
+ const attrs = this.childs[e.currentTarget.dataset.i].attrs
441
+ if (this.opts[3] && !attrs.ignore) {
442
+ uni.showActionSheet({
443
+ itemList: ['保存图片'],
444
+ success: () => {
445
+ const save = (path) => {
446
+ uni.saveImageToPhotosAlbum({
447
+ filePath: path,
448
+ success() {
449
+ uni.showToast({
450
+ title: '保存成功'
451
+ })
452
+ }
453
+ })
454
+ }
455
+ if (this.root.imgList[attrs.i].startsWith('http')) {
456
+ uni.downloadFile({
457
+ url: this.root.imgList[attrs.i],
458
+ success: (res) => save(res.tempFilePath)
459
+ })
460
+ } else {
461
+ save(this.root.imgList[attrs.i])
462
+ }
463
+ }
464
+ })
465
+ }
348
466
  // #endif
349
- }
350
- } else {
351
- // 跳转页面
352
- uni.navigateTo({
353
- url: href,
354
- fail () {
355
- uni.switchTab({
356
- url: href,
357
- fail () { }
358
- })
467
+ },
468
+
469
+ /**
470
+ * @description 图片加载完成事件
471
+ * @param {Event} e
472
+ */
473
+ imgLoad(e) {
474
+ const i = e.currentTarget.dataset.i
475
+ /* #ifndef H5 || (APP-PLUS && VUE2) */
476
+ if (!this.childs[i].w) {
477
+ // 设置原宽度
478
+ this.$set(this.ctrl, i, e.detail.width)
479
+ } else if ((this.opts[1] && !this.ctrl[i]) || this.ctrl[i] === -1) {
480
+ /* #endif */ // 加载完毕,取消加载中占位图
481
+ this.$set(this.ctrl, i, 1)
482
+ }
483
+ this.checkReady()
484
+ },
485
+
486
+ /**
487
+ * @description 检查是否所有图片加载完毕
488
+ */
489
+ checkReady() {
490
+ if (!this.root.lazyLoad) {
491
+ this.root._unloadimgs -= 1
492
+ if (!this.root._unloadimgs) {
493
+ setTimeout(() => {
494
+ this.root
495
+ .getRect()
496
+ .then((rect) => {
497
+ this.root.$emit('ready', rect)
498
+ })
499
+ .catch(() => {
500
+ this.root.$emit('ready', {})
501
+ })
502
+ }, 350)
503
+ }
504
+ }
505
+ },
506
+
507
+ /**
508
+ * @description 链接点击事件
509
+ * @param {Event} e
510
+ */
511
+ linkTap(e) {
512
+ const node = e.currentTarget ? this.childs[e.currentTarget.dataset.i] : {}
513
+ const attrs = node.attrs || e
514
+ const href = attrs.href
515
+ this.root.$emit(
516
+ 'linkTap',
517
+ Object.assign(
518
+ {
519
+ innerText: this.root.getText(node.children || []) // 链接内的文本内容
520
+ },
521
+ attrs
522
+ )
523
+ )
524
+ if (href) {
525
+ if (href[0] === '#') {
526
+ // 跳转锚点
527
+ this.root.navigateTo(href.substring(1)).catch(() => {})
528
+ } else if (href.split('?')[0].includes('://')) {
529
+ // 复制外部链接
530
+ if (this.root.copyLink) {
531
+ // #ifdef H5
532
+ window.open(href)
533
+ // #endif
534
+ // #ifdef MP
535
+ uni.setClipboardData({
536
+ data: href,
537
+ success: () =>
538
+ uni.showToast({
539
+ title: '链接已复制'
540
+ })
541
+ })
542
+ // #endif
543
+ // #ifdef APP-PLUS
544
+ plus.runtime.openWeb(href)
545
+ // #endif
546
+ }
547
+ } else {
548
+ // 跳转页面
549
+ uni.navigateTo({
550
+ url: href,
551
+ fail() {
552
+ uni.switchTab({
553
+ url: href,
554
+ fail() {}
555
+ })
556
+ }
557
+ })
558
+ }
559
+ }
560
+ },
561
+
562
+ /**
563
+ * @description 错误事件
564
+ * @param {Event} e
565
+ */
566
+ mediaError(e) {
567
+ const i = e.currentTarget.dataset.i
568
+ const node = this.childs[i]
569
+ // 加载其他源
570
+ if (node.name === 'video' || node.name === 'audio') {
571
+ let index = (this.ctrl[i] || 0) + 1
572
+ if (index > node.src.length) {
573
+ index = 0
574
+ }
575
+ if (index < node.src.length) {
576
+ this.$set(this.ctrl, i, index)
577
+ return
578
+ }
579
+ } else if (node.name === 'img') {
580
+ // #ifdef H5 && VUE3
581
+ if (this.opts[0] && !this.ctrl.load) return
582
+ // #endif
583
+ // 显示错误占位图
584
+ if (this.opts[2]) {
585
+ this.$set(this.ctrl, i, -1)
586
+ }
587
+ this.checkReady()
588
+ }
589
+ if (this.root) {
590
+ this.root.$emit('error', {
591
+ source: node.name,
592
+ attrs: node.attrs,
593
+ // #ifndef H5 && VUE3
594
+ errMsg: e.detail.errMsg
595
+ // #endif
596
+ })
359
597
  }
360
- })
361
- }
362
- }
363
- },
364
-
365
- /**
366
- * @description 错误事件
367
- * @param {Event} e
368
- */
369
- mediaError (e) {
370
- const i = e.currentTarget.dataset.i
371
- const node = this.childs[i]
372
- // 加载其他源
373
- if (node.name === 'video' || node.name === 'audio') {
374
- let index = (this.ctrl[i] || 0) + 1
375
- if (index > node.src.length) {
376
- index = 0
377
- }
378
- if (index < node.src.length) {
379
- this.$set(this.ctrl, i, index)
380
- return
381
- }
382
- } else if (node.name === 'img') {
383
- // #ifdef H5 && VUE3
384
- if (this.opts[0] && !this.ctrl.load) return
385
- // #endif
386
- // 显示错误占位图
387
- if (this.opts[2]) {
388
- this.$set(this.ctrl, i, -1)
389
598
  }
390
- this.checkReady()
391
- }
392
- if (this.root) {
393
- this.root.$emit('error', {
394
- source: node.name,
395
- attrs: node.attrs,
396
- // #ifndef H5 && VUE3
397
- errMsg: e.detail.errMsg
398
- // #endif
399
- })
400
- }
401
599
  }
402
- }
403
600
  }
404
601
  </script>
405
602
  <style>
406
603
  /* a 标签默认效果 */
407
604
  ._a {
408
- padding: 1.5px 0 1.5px 0;
409
- color: #366092;
410
- /* #ifndef APP-NVUE */
411
- word-break: break-all;
412
- /* #endif */
605
+ padding: 1.5px 0 1.5px 0;
606
+ color: #366092;
607
+ /* #ifndef APP-NVUE */
608
+ word-break: break-all;
609
+ /* #endif */
413
610
  }
414
611
 
415
612
  /* a 标签点击态效果 */
416
613
  ._hover {
417
- text-decoration: underline;
418
- opacity: 0.7;
614
+ text-decoration: underline;
615
+ opacity: 0.7;
419
616
  }
420
617
 
421
618
  /* 图片默认效果 */
422
619
  ._img {
423
- max-width: 100%;
424
- -webkit-touch-callout: none;
620
+ max-width: 100%;
621
+ -webkit-touch-callout: none;
425
622
  }
426
623
 
427
624
  /* 内部样式 */
428
625
 
429
626
  ._block {
430
- /* #ifndef APP-NVUE */
431
- display: block;
432
- /* #endif */
627
+ /* #ifndef APP-NVUE */
628
+ display: block;
629
+ /* #endif */
433
630
  }
434
631
 
435
632
  ._b,
436
633
  ._strong {
437
- font-weight: bold;
634
+ font-weight: bold;
438
635
  }
439
636
 
440
637
  ._code {
441
- font-family: monospace;
638
+ font-family: monospace;
442
639
  }
443
640
 
444
641
  ._del {
445
- text-decoration: line-through;
642
+ text-decoration: line-through;
446
643
  }
447
644
 
448
645
  ._em,
449
646
  ._i {
450
- font-style: italic;
647
+ font-style: italic;
451
648
  }
452
649
 
453
650
  ._h1 {
454
- font-size: 2em;
651
+ font-size: 2em;
455
652
  }
456
653
 
457
654
  ._h2 {
458
- font-size: 1.5em;
655
+ font-size: 1.5em;
459
656
  }
460
657
 
461
658
  ._h3 {
462
- font-size: 1.17em;
659
+ font-size: 1.17em;
463
660
  }
464
661
 
465
662
  ._h5 {
466
- font-size: 0.83em;
663
+ font-size: 0.83em;
467
664
  }
468
665
 
469
666
  ._h6 {
470
- font-size: 0.67em;
667
+ font-size: 0.67em;
471
668
  }
472
669
 
473
670
  ._h1,
@@ -476,87 +673,87 @@ export default {
476
673
  ._h4,
477
674
  ._h5,
478
675
  ._h6 {
479
- /* #ifndef APP-NVUE */
480
- display: block;
481
- /* #endif */
482
- font-weight: bold;
676
+ /* #ifndef APP-NVUE */
677
+ display: block;
678
+ /* #endif */
679
+ font-weight: bold;
483
680
  }
484
681
 
485
682
  ._image {
486
- height: 1px;
683
+ height: 1px;
487
684
  }
488
685
 
489
686
  ._ins {
490
- text-decoration: underline;
687
+ text-decoration: underline;
491
688
  }
492
689
 
493
690
  ._li {
494
- display: list-item;
691
+ display: list-item;
495
692
  }
496
693
 
497
694
  ._ol {
498
- list-style-type: decimal;
695
+ list-style-type: decimal;
499
696
  }
500
697
 
501
698
  ._ol,
502
699
  ._ul {
503
- /* #ifndef APP-NVUE */
504
- display: block;
505
- /* #endif */
506
- padding-left: 40px;
507
- margin: 1em 0;
700
+ /* #ifndef APP-NVUE */
701
+ display: block;
702
+ /* #endif */
703
+ padding-left: 40px;
704
+ margin: 1em 0;
508
705
  }
509
706
 
510
707
  ._q::before {
511
- content: '"';
708
+ content: '"';
512
709
  }
513
710
 
514
711
  ._q::after {
515
- content: '"';
712
+ content: '"';
516
713
  }
517
714
 
518
715
  ._sub {
519
- font-size: smaller;
520
- vertical-align: sub;
716
+ font-size: smaller;
717
+ vertical-align: sub;
521
718
  }
522
719
 
523
720
  ._sup {
524
- font-size: smaller;
525
- vertical-align: super;
721
+ font-size: smaller;
722
+ vertical-align: super;
526
723
  }
527
724
 
528
725
  ._thead,
529
726
  ._tbody,
530
727
  ._tfoot {
531
- display: table-row-group;
728
+ display: table-row-group;
532
729
  }
533
730
 
534
731
  ._tr {
535
- display: table-row;
732
+ display: table-row;
536
733
  }
537
734
 
538
735
  ._td,
539
736
  ._th {
540
- display: table-cell;
541
- vertical-align: middle;
737
+ display: table-cell;
738
+ vertical-align: middle;
542
739
  }
543
740
 
544
741
  ._th {
545
- font-weight: bold;
546
- text-align: center;
742
+ font-weight: bold;
743
+ text-align: center;
547
744
  }
548
745
 
549
746
  ._ul {
550
- list-style-type: disc;
747
+ list-style-type: disc;
551
748
  }
552
749
 
553
750
  ._ul ._ul {
554
- margin: 0;
555
- list-style-type: circle;
751
+ margin: 0;
752
+ list-style-type: circle;
556
753
  }
557
754
 
558
755
  ._ul ._ul ._ul {
559
- list-style-type: square;
756
+ list-style-type: square;
560
757
  }
561
758
 
562
759
  ._abbr,
@@ -572,13 +769,13 @@ export default {
572
769
  ._strong,
573
770
  ._sub,
574
771
  ._sup {
575
- display: inline;
772
+ display: inline;
576
773
  }
577
774
 
578
775
  /* #ifdef APP-PLUS */
579
776
  ._video {
580
- width: 300px;
581
- height: 225px;
777
+ width: 300px;
778
+ height: 225px;
582
779
  }
583
780
  /* #endif */
584
- </style>
781
+ </style>