oxy-uni-ui 1.2.0 → 2.0.0

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.
Files changed (306) hide show
  1. package/attributes.json +1 -1
  2. package/components/common/abstracts/variable.scss +396 -321
  3. package/components/common/path.ts +9 -0
  4. package/components/common/util.ts +200 -5
  5. package/components/composables/index.ts +1 -0
  6. package/components/composables/useGlobalLoading.ts +42 -0
  7. package/components/composables/useGlobalMessage.ts +48 -0
  8. package/components/composables/useGlobalToast.ts +84 -0
  9. package/components/composables/usePopover.ts +24 -20
  10. package/components/composables/useVirtualScroll.ts +13 -11
  11. package/components/composables/useWindowResize.ts +35 -0
  12. package/components/oxy-action-sheet/index.scss +24 -11
  13. package/components/oxy-action-sheet/oxy-action-sheet.vue +27 -19
  14. package/components/oxy-action-sheet/types.ts +7 -0
  15. package/components/oxy-backtop/index.scss +3 -3
  16. package/components/oxy-backtop/oxy-backtop.vue +9 -6
  17. package/components/oxy-backtop/types.ts +7 -7
  18. package/components/oxy-badge/index.scss +4 -4
  19. package/components/oxy-badge/oxy-badge.vue +3 -3
  20. package/components/oxy-badge/types.ts +2 -2
  21. package/components/oxy-button/index.scss +5 -5
  22. package/components/oxy-button/oxy-button.vue +5 -1
  23. package/components/oxy-calendar/index.scss +11 -11
  24. package/components/oxy-calendar/oxy-calendar.vue +1 -0
  25. package/components/oxy-calendar/types.ts +5 -0
  26. package/components/oxy-calendar-view/month/index.scss +4 -4
  27. package/components/oxy-calendar-view/month/types.ts +36 -0
  28. package/components/oxy-calendar-view/monthPanel/index.scss +7 -7
  29. package/components/oxy-calendar-view/monthPanel/month-panel.vue +14 -8
  30. package/components/oxy-calendar-view/year/index.scss +4 -4
  31. package/components/oxy-calendar-view/yearPanel/index.scss +4 -4
  32. package/components/oxy-calendar-view/yearPanel/year-panel.vue +21 -5
  33. package/components/oxy-card/index.scss +2 -2
  34. package/components/oxy-cell/index.scss +8 -8
  35. package/components/oxy-cell/oxy-cell.vue +15 -2
  36. package/components/oxy-cell/types.ts +4 -0
  37. package/components/oxy-checkbox/index.scss +8 -8
  38. package/components/oxy-checkbox/oxy-checkbox.vue +2 -2
  39. package/components/oxy-checkbox-group/index.scss +2 -2
  40. package/components/oxy-circle/oxy-circle.vue +10 -7
  41. package/components/oxy-circle/types.ts +5 -5
  42. package/components/oxy-col/oxy-col.vue +2 -2
  43. package/components/oxy-col-picker/index.scss +4 -4
  44. package/components/oxy-col-picker/oxy-col-picker.vue +9 -5
  45. package/components/oxy-col-picker/types.ts +12 -3
  46. package/components/oxy-collapse/index.scss +2 -2
  47. package/components/oxy-collapse-item/oxy-collapse-item.vue +3 -3
  48. package/components/oxy-corner/index.scss +32 -32
  49. package/components/oxy-corner/oxy-corner.vue +15 -3
  50. package/components/oxy-corner/types.ts +15 -1
  51. package/components/oxy-count-to/oxy-count-to.vue +3 -3
  52. package/components/oxy-curtain/index.scss +15 -15
  53. package/components/oxy-curtain/oxy-curtain.vue +4 -2
  54. package/components/oxy-curtain/types.ts +6 -1
  55. package/components/oxy-date-strip/index.scss +10 -0
  56. package/components/oxy-date-strip/oxy-date-strip.vue +198 -0
  57. package/components/oxy-date-strip/types.ts +98 -0
  58. package/components/oxy-date-strip/utils.ts +67 -0
  59. package/components/oxy-date-strip-item/index.scss +94 -0
  60. package/components/oxy-date-strip-item/oxy-date-strip-item.vue +102 -0
  61. package/components/oxy-date-strip-item/types.ts +53 -0
  62. package/components/oxy-datetime-picker/index.scss +11 -11
  63. package/components/oxy-datetime-picker/oxy-datetime-picker.vue +4 -1
  64. package/components/oxy-datetime-picker/types.ts +10 -1
  65. package/components/oxy-drop-menu/index.scss +3 -3
  66. package/components/oxy-drop-menu/oxy-drop-menu.vue +3 -3
  67. package/components/oxy-drop-menu-item/index.scss +1 -1
  68. package/components/oxy-drop-menu-item/oxy-drop-menu-item.vue +4 -3
  69. package/components/oxy-drop-menu-item/types.ts +5 -0
  70. package/components/oxy-echarts/index.scss +17 -0
  71. package/components/oxy-echarts/index.ts +1 -0
  72. package/components/oxy-echarts/oxy-echarts.vue +32 -0
  73. package/components/oxy-echarts/types.ts +18 -0
  74. package/components/oxy-fab/index.scss +8 -8
  75. package/components/oxy-fab/oxy-fab.vue +22 -3
  76. package/components/oxy-file-list/index.scss +42 -15
  77. package/components/oxy-file-list/oxy-file-list.vue +208 -34
  78. package/components/oxy-file-list/types.ts +58 -2
  79. package/components/oxy-floating-panel/oxy-floating-panel.vue +13 -9
  80. package/components/oxy-floating-panel/{type.ts → types.ts} +8 -8
  81. package/components/oxy-footer/index.scss +19 -0
  82. package/components/oxy-footer/oxy-footer.vue +78 -0
  83. package/components/oxy-footer/types.ts +17 -0
  84. package/components/oxy-form-item/types.ts +22 -1
  85. package/components/oxy-gap/oxy-gap.vue +2 -2
  86. package/components/oxy-gap/types.ts +2 -2
  87. package/components/oxy-global-loading/oxy-global-loading.vue +53 -0
  88. package/components/oxy-global-message/oxy-global-message.vue +64 -0
  89. package/components/oxy-global-toast/oxy-global-toast.vue +53 -0
  90. package/components/oxy-grid/oxy-grid.vue +1 -1
  91. package/components/oxy-grid/types.ts +1 -1
  92. package/components/oxy-grid-item/index.scss +1 -1
  93. package/components/oxy-grid-item/oxy-grid-item.vue +7 -5
  94. package/components/oxy-grid-item/types.ts +1 -1
  95. package/components/oxy-guidance/index.scss +75 -0
  96. package/components/oxy-guidance/oxy-guidance.vue +201 -0
  97. package/components/oxy-guidance/types.ts +33 -0
  98. package/components/oxy-icon/oxy-icon.vue +2 -2
  99. package/components/oxy-icon/types.ts +1 -1
  100. package/components/oxy-img/oxy-img.vue +4 -4
  101. package/components/oxy-img/types.ts +3 -3
  102. package/components/oxy-img-cropper/index.scss +12 -12
  103. package/components/oxy-img-cropper/oxy-img-cropper.vue +97 -52
  104. package/components/oxy-img-cropper/types.ts +2 -2
  105. package/components/oxy-img-lazy/index.scss +17 -0
  106. package/components/oxy-img-lazy/oxy-img-lazy.vue +332 -0
  107. package/components/oxy-img-lazy/types.ts +69 -0
  108. package/components/oxy-index-anchor/index.scss +2 -2
  109. package/components/oxy-index-anchor/oxy-index-anchor.vue +2 -2
  110. package/components/oxy-index-anchor/{type.ts → types.ts} +3 -0
  111. package/components/oxy-index-bar/index.scss +3 -3
  112. package/components/oxy-index-bar/oxy-index-bar.vue +3 -3
  113. package/components/oxy-index-bar/{type.ts → types.ts} +2 -2
  114. package/components/oxy-input/index.scss +1 -1
  115. package/components/oxy-input-number/index.scss +5 -5
  116. package/components/oxy-input-number/oxy-input-number.vue +2 -2
  117. package/components/oxy-input-number/types.ts +3 -2
  118. package/components/oxy-keyboard/index.scss +5 -5
  119. package/components/oxy-keyboard/key/index.scss +3 -3
  120. package/components/oxy-keyboard/key/index.vue +2 -2
  121. package/components/oxy-keyboard/key/types.ts +15 -0
  122. package/components/oxy-keyboard/oxy-keyboard.vue +1 -0
  123. package/components/oxy-keyboard/types.ts +5 -0
  124. package/components/oxy-link/index.scss +57 -0
  125. package/components/oxy-link/oxy-link.vue +130 -0
  126. package/components/oxy-link/types.ts +81 -0
  127. package/components/oxy-list/index.scss +7 -1
  128. package/components/oxy-list/oxy-list.vue +4 -3
  129. package/components/oxy-list/types.ts +1 -1
  130. package/components/oxy-loading/oxy-loading.vue +8 -4
  131. package/components/oxy-loading/types.ts +1 -1
  132. package/components/oxy-loadmore/index.scss +3 -3
  133. package/components/oxy-long-press-menu/index.scss +93 -0
  134. package/components/oxy-long-press-menu/oxy-long-press-menu.vue +338 -0
  135. package/components/oxy-long-press-menu/types.ts +34 -0
  136. package/components/oxy-message-box/index.scss +12 -11
  137. package/components/oxy-message-box/oxy-message-box.vue +11 -3
  138. package/components/oxy-message-box/types.ts +14 -0
  139. package/components/oxy-navbar/index.scss +2 -2
  140. package/components/oxy-navbar/oxy-navbar.vue +58 -13
  141. package/components/oxy-navbar/types.ts +8 -1
  142. package/components/oxy-navbar-capsule/types.ts +3 -0
  143. package/components/oxy-notice-bar/index.scss +3 -3
  144. package/components/oxy-notice-bar/oxy-notice-bar.vue +9 -5
  145. package/components/oxy-notice-bar/types.ts +3 -3
  146. package/components/oxy-notify/index.ts +1 -0
  147. package/components/oxy-notify/oxy-notify.vue +3 -2
  148. package/components/oxy-notify/types.ts +7 -0
  149. package/components/oxy-pagination/index.scss +1 -1
  150. package/components/oxy-password-input/oxy-password-input.vue +2 -2
  151. package/components/oxy-password-input/types.ts +1 -1
  152. package/components/oxy-picker/index.scss +45 -2
  153. package/components/oxy-picker/oxy-picker.vue +103 -14
  154. package/components/oxy-picker/types.ts +33 -1
  155. package/components/oxy-picker-view/index.scss +3 -3
  156. package/components/oxy-picker-view/oxy-picker-view.vue +4 -4
  157. package/components/oxy-popover/index.scss +9 -9
  158. package/components/oxy-popup/index.scss +2 -2
  159. package/components/oxy-popup/oxy-popup.vue +35 -2
  160. package/components/oxy-popup/types.ts +8 -1
  161. package/components/oxy-progress/index.scss +3 -3
  162. package/components/oxy-qrcode/draw.ts +398 -0
  163. package/components/oxy-qrcode/index.scss +2 -0
  164. package/components/oxy-qrcode/oxy-qrcode.vue +124 -0
  165. package/components/oxy-qrcode/qrcode.ts +936 -0
  166. package/components/oxy-qrcode/types.ts +42 -0
  167. package/components/oxy-radio/index.scss +13 -13
  168. package/components/oxy-radio/oxy-radio.vue +1 -1
  169. package/components/oxy-radio-group/index.scss +2 -2
  170. package/components/oxy-rate/types.ts +4 -4
  171. package/components/oxy-resize/index.scss +2 -2
  172. package/components/oxy-resize/oxy-resize.vue +4 -4
  173. package/components/oxy-resize/types.ts +3 -0
  174. package/components/oxy-rich-text/icon/emjio.svg +1 -0
  175. package/components/oxy-rich-text/icon/quote.svg +1 -0
  176. package/components/oxy-rich-text/icon/text.svg +1 -0
  177. package/components/oxy-rich-text/icon/title.svg +1 -0
  178. package/components/oxy-rich-text/index.scss +160 -0
  179. package/components/oxy-rich-text/mp-html/card/card.vue +122 -0
  180. package/components/oxy-rich-text/mp-html/card/index.js +7 -0
  181. package/components/oxy-rich-text/mp-html/editable/config.js +15 -0
  182. package/components/oxy-rich-text/mp-html/editable/index.js +553 -0
  183. package/components/oxy-rich-text/mp-html/emoji/index.js +203 -0
  184. package/components/oxy-rich-text/mp-html/highlight/config.js +5 -0
  185. package/components/oxy-rich-text/mp-html/highlight/index.js +96 -0
  186. package/components/oxy-rich-text/mp-html/highlight/prism.css +1 -0
  187. package/components/oxy-rich-text/mp-html/highlight/prism.min.js +7 -0
  188. package/components/oxy-rich-text/mp-html/img-cache/index.js +138 -0
  189. package/components/oxy-rich-text/mp-html/latex/index.js +80 -0
  190. package/components/oxy-rich-text/mp-html/latex/katex.css +1 -0
  191. package/components/oxy-rich-text/mp-html/latex/katex.min.js +1 -0
  192. package/components/oxy-rich-text/mp-html/markdown/index.js +50 -0
  193. package/components/oxy-rich-text/mp-html/markdown/marked.min.js +71 -0
  194. package/components/oxy-rich-text/mp-html/mp-html.d.ts +184 -0
  195. package/components/oxy-rich-text/mp-html/mp-html.vue +684 -0
  196. package/components/oxy-rich-text/mp-html/node/node.vue +1172 -0
  197. package/components/oxy-rich-text/mp-html/parser.js +1428 -0
  198. package/components/oxy-rich-text/mp-html/search/index.js +132 -0
  199. package/components/oxy-rich-text/mp-html/style/index.js +129 -0
  200. package/components/oxy-rich-text/mp-html/style/parser.js +175 -0
  201. package/components/oxy-rich-text/mp-html/template/index.js +67 -0
  202. package/components/oxy-rich-text/mp-html/txv-video/index.js +46 -0
  203. package/components/oxy-rich-text/oxy-rich-text.vue +642 -0
  204. package/components/oxy-rich-text/types.ts +76 -0
  205. package/components/oxy-row/oxy-row.vue +3 -3
  206. package/components/oxy-row/types.ts +1 -1
  207. package/components/oxy-search/index.scss +3 -3
  208. package/components/oxy-segmented/index.scss +16 -16
  209. package/components/oxy-segmented/oxy-segmented.vue +23 -3
  210. package/components/oxy-select/index.scss +331 -0
  211. package/components/oxy-select/oxy-select.vue +456 -0
  212. package/components/oxy-select/types.ts +83 -0
  213. package/components/oxy-select-picker/index.scss +7 -7
  214. package/components/oxy-select-picker/oxy-select-picker.vue +4 -0
  215. package/components/oxy-select-picker/types.ts +7 -1
  216. package/components/oxy-sidebar-item/index.scss +1 -1
  217. package/components/oxy-signature/oxy-signature.vue +18 -10
  218. package/components/oxy-signature/types.ts +106 -13
  219. package/components/oxy-skeleton/oxy-skeleton.vue +6 -6
  220. package/components/oxy-skeleton/types.ts +1 -1
  221. package/components/oxy-slider/index.scss +3 -3
  222. package/components/oxy-sort-button/index.scss +8 -8
  223. package/components/oxy-status-tip/index.scss +4 -4
  224. package/components/oxy-status-tip/oxy-status-tip.vue +5 -5
  225. package/components/oxy-status-tip/types.ts +3 -3
  226. package/components/oxy-step/index.scss +14 -14
  227. package/components/oxy-sticky/oxy-sticky.vue +6 -6
  228. package/components/oxy-stream-render/index.scss +6 -0
  229. package/components/oxy-stream-render/oxy-stream-render.vue +204 -0
  230. package/components/oxy-stream-render/types.ts +8 -0
  231. package/components/oxy-swipe-action/oxy-swipe-action.vue +27 -2
  232. package/components/oxy-swiper/oxy-swiper.vue +6 -6
  233. package/components/oxy-swiper/types.ts +5 -5
  234. package/components/oxy-switch/index.scss +8 -8
  235. package/components/oxy-switch/oxy-switch.vue +2 -2
  236. package/components/oxy-switch/types.ts +1 -1
  237. package/components/oxy-tab/index.scss +11 -1
  238. package/components/oxy-tabbar/index.scss +1 -1
  239. package/components/oxy-tabbar/oxy-tabbar.vue +39 -10
  240. package/components/oxy-table/index.scss +5 -5
  241. package/components/oxy-table/oxy-table.vue +8 -6
  242. package/components/oxy-table/types.ts +2 -2
  243. package/components/oxy-table-col/oxy-table-col.vue +3 -3
  244. package/components/oxy-table-col/types.ts +2 -2
  245. package/components/oxy-tabs/index.scss +43 -15
  246. package/components/oxy-tabs/oxy-tabs.vue +53 -19
  247. package/components/oxy-tabs/types.ts +15 -3
  248. package/components/oxy-tag/index.scss +15 -15
  249. package/components/oxy-text/index.scss +5 -1
  250. package/components/oxy-text/oxy-text.vue +76 -7
  251. package/components/oxy-text/types.ts +12 -0
  252. package/components/oxy-textarea/index.scss +6 -6
  253. package/components/oxy-toast/oxy-toast.vue +24 -8
  254. package/components/oxy-tooltip/index.scss +9 -9
  255. package/components/oxy-tree/index.scss +61 -9
  256. package/components/oxy-tree/oxy-tree.vue +102 -17
  257. package/components/oxy-tree/types.ts +23 -10
  258. package/components/oxy-upload/index.scss +21 -21
  259. package/components/oxy-upload/types.ts +2 -2
  260. package/components/oxy-verification-code/index.scss +6 -0
  261. package/components/oxy-verification-code/oxy-verification-code.vue +187 -0
  262. package/components/oxy-verification-code/types.ts +82 -0
  263. package/components/oxy-video-preview/index.scss +4 -4
  264. package/components/oxy-virtual-scroll/index.scss +4 -4
  265. package/components/oxy-virtual-scroll/oxy-virtual-scroll.vue +11 -7
  266. package/components/oxy-virtual-scroll/types.ts +14 -14
  267. package/components/oxy-voice-player/index.scss +908 -0
  268. package/components/oxy-voice-player/oxy-voice-player.vue +821 -0
  269. package/components/oxy-voice-player/types.ts +567 -0
  270. package/components/oxy-waterfall/index.scss +18 -0
  271. package/components/oxy-waterfall/oxy-waterfall.vue +218 -0
  272. package/components/oxy-waterfall/types.ts +90 -0
  273. package/components/oxy-waterfall-item/index.scss +8 -0
  274. package/components/oxy-waterfall-item/oxy-waterfall-item.vue +89 -0
  275. package/components/oxy-waterfall-item/types.ts +16 -0
  276. package/components/oxy-watermark/oxy-watermark.vue +35 -13
  277. package/components/oxy-watermark/types.ts +14 -14
  278. package/global.d.ts +9 -0
  279. package/index.ts +3 -0
  280. package/locale/lang/ar-SA.ts +3 -0
  281. package/locale/lang/en-US.ts +29 -0
  282. package/locale/lang/zh-CN.ts +29 -0
  283. package/package.json +97 -1
  284. package/tags.json +1 -1
  285. package/uni-echarts/changelog.md +2 -0
  286. package/uni-echarts/components/index.js +1 -0
  287. package/uni-echarts/components/uni-echarts/events.js +95 -0
  288. package/uni-echarts/components/uni-echarts/types.d.ts +183 -0
  289. package/uni-echarts/components/uni-echarts/types.js +1 -0
  290. package/uni-echarts/components/uni-echarts/uni-echarts.vue +530 -0
  291. package/uni-echarts/components/uni-echarts/uni-echarts.vue.d.ts +19 -0
  292. package/uni-echarts/global.d.ts +7 -0
  293. package/uni-echarts/index.d.ts +440 -0
  294. package/uni-echarts/index.js +2 -0
  295. package/uni-echarts/package.json +105 -0
  296. package/uni-echarts/shared-core.d.ts +269 -0
  297. package/uni-echarts/shared-core.js +900 -0
  298. package/web-types.json +1 -1
  299. package/components/oxy-number-keyboard/index.scss +0 -78
  300. package/components/oxy-number-keyboard/key/index.scss +0 -81
  301. package/components/oxy-number-keyboard/key/index.vue +0 -78
  302. package/components/oxy-number-keyboard/key/types.ts +0 -11
  303. package/components/oxy-number-keyboard/oxy-number-keyboard.vue +0 -151
  304. package/components/oxy-number-keyboard/types.ts +0 -83
  305. package/components/oxy-tree/components/tree-node-content.vue +0 -72
  306. package/components/oxy-tree/index.ts +0 -51
@@ -0,0 +1,1172 @@
1
+ <template>
2
+ <view @tap="nodeTap" :id="attrs.id" :class="'_block _'+name+' '+attrs.class" :style="(ctrl.root&&opts[5]!=='simple'?'border:1px solid black;padding:10rpx;display:block;':'')+attrs.style">
3
+ <block v-for="(n, i) in nodes" 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['e'+i]&&opts[5]!=='simple'?'border:1px dashed black;padding:6rpx;':'')+(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="[{attrs:{style:n.attrs.style||'',src:n.attrs.src},name:'img'}]" :data-i="i" @tap.stop="imgTap" />
14
+ <!-- #endif -->
15
+ <!-- #ifdef APP-HARMONY -->
16
+ <image v-else-if="n.name==='img'" :id="n.attrs.id||('n'+i)" :class="'_img '+n.attrs.class" :style="(ctrl['e'+i]&&opts[5]!=='simple'?'border:1px dashed black;padding:6rpx;':'')+(ctrl[i]===-1?'display:none;':'')+'width:'+ctrl[i]+'px;'+n.attrs.style" :src="n.attrs.src||(ctrl.load?n.attrs['data-src']:'')" :mode="!n.h?'widthFix':(!n.w?'heightFix':(n.m||'scaleToFill'))" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
17
+ <!-- #endif -->
18
+ <!-- #ifndef H5 || APP-PLUS || MP-KUAISHOU -->
19
+ <image v-else-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl['e'+i]&&opts[5]!=='simple'?'border:1px dashed black;padding:6rpx;':'')+(ctrl[i]===-1?'display:none;':'')+'width:'+(ctrl[i]||1)+'px;height:'+(ctrl['h'+i]||1)+'px;'+n.attrs.style" :src="n.attrs.src" :mode="!n.h?'widthFix':(!n.w?'heightFix':(n.m||'scaleToFill'))" :lazy-load="opts[0]" :webp="n.webp" :show-menu-by-longpress="!opts[5]&&opts[3]&&!n.attrs.ignore" :image-menu-prevent="opts[5]||!opts[3]||n.attrs.ignore" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
20
+ <!-- #endif -->
21
+ <!-- #ifdef MP-KUAISHOU -->
22
+ <image v-else-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl['e'+i]&&opts[5]!=='simple'?'border:1px dashed black;padding:6rpx;':'')+(ctrl[i]===-1?'display:none;':'')+n.attrs.style" :src="n.attrs.src" :lazy-load="opts[0]" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap"></image>
23
+ <!-- #endif -->
24
+ <!-- #ifdef APP-PLUS && VUE3 -->
25
+ <image v-else-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl['e'+i]&&opts[5]!=='simple'?'border:1px dashed black;padding:6rpx;':'')+(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':(n.m||''))" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
26
+ <!-- #endif -->
27
+ <!-- 文本 -->
28
+ <text v-else-if="n.type==='text'&&!ctrl['e'+i]" :data-i="i" :user-select="opts[4]" :decode="!opts[5]" @tap="editStart">{{n.text}}
29
+ <text v-if="!n.text" style="color:gray">{{opts[6]||'请输入'}}</text>
30
+ </text>
31
+ <text v-else-if="n.type==='text'&&ctrl['e'+i]===1" :data-i="i" style="border:1px dashed black;min-width:100rpx;width:auto;padding:10rpx;display:block" @tap.stop="editStart">{{n.text}}
32
+ <text v-if="!n.text" style="color:gray">{{opts[6]||'请输入'}}</text>
33
+ </text>
34
+ <textarea v-else-if="n.type==='text'" :style="opts[5]==='simple'?'':'border:1px dashed black;'+'min-width:100rpx;width:auto;padding:10rpx'" auto-height maxlength="-1" :focus="ctrl['e'+i]===3" :value="n.text" :data-i="i" @input="editInput" @blur="editEnd" />
35
+ <text v-else-if="n.name==='br'">\n</text>
36
+ <!-- 链接 -->
37
+ <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">
38
+ <node name="span" :childs="n.children" :opts="[opts[0],opts[1],opts[2],opts[3],opts[4],opts[5],opts[6],opts[7]+'.'+i+'.children']" style="display:inherit" />
39
+ </view>
40
+ <!-- 视频 -->
41
+ <!-- #ifdef APP-PLUS -->
42
+ <view v-else-if="n.html" :data-i="i" @tap="mediaTap" :id="n.attrs.id" :class="'_video '+n.attrs.class" :style="n.attrs.style" v-html="n.html" @vplay.stop="play" />
43
+ <!-- #endif -->
44
+ <!-- #ifndef APP-PLUS -->
45
+ <video :show-center-play-btn="!opts[5]" @tap="mediaTap" 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" @pause="mediaEvent" @fullscreenchange="mediaEvent" @error="mediaError" />
46
+ <!-- #endif -->
47
+ <!-- #ifdef H5 || APP-PLUS -->
48
+ <iframe v-else-if="n.name==='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen" :frameborder="n.attrs.frameborder" :src="n.attrs.src" />
49
+ <embed v-else-if="n.name==='embed'" :style="n.attrs.style" :src="n.attrs.src" />
50
+ <!-- #endif -->
51
+ <!-- #ifndef MP-TOUTIAO || ((H5 || APP-PLUS) && VUE3) -->
52
+ <!-- 音频 -->
53
+ <audio @tap="mediaTap" 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" @pause="mediaEvent" @error="mediaError" />
54
+ <!-- #endif -->
55
+ <view v-else-if="(n.name==='table'&&(n.c||opts[5]))||n.name==='li'" :id="n.attrs.id" :class="'_'+n.name+' '+n.attrs.class" :style="n.attrs.style">
56
+ <node v-if="n.name==='li'" :childs="n.children" :opts="[opts[0],opts[1],opts[2],opts[3],opts[4],opts[5],opts[6],opts[7]+'.'+i+'.children']" />
57
+ <view v-else v-for="(tbody, x) in n.children" v-bind:key="x" :class="'_'+tbody.name+' '+tbody.attrs.class" :style="tbody.attrs.style">
58
+ <node v-if="tbody.name==='td'||tbody.name==='th'" :childs="tbody.children" :opts="[opts[0],opts[1],opts[2],opts[3],opts[4],opts[5],opts[6],opts[7]+'.'+i+'.children.'+x+'.children']" />
59
+ <block v-else v-for="(tr, y) in tbody.children" v-bind:key="y">
60
+ <view v-if="tr.name==='td'||tr.name==='th'" :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
61
+ <node :childs="tr.children" :opts="[opts[0],opts[1],opts[2],opts[3],opts[4],opts[5],opts[6],opts[7]+'.'+i+'.children.'+x+'.children.'+y+'.children']" />
62
+ </view>
63
+ <view v-else :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
64
+ <view v-for="(td, z) in tr.children" v-bind:key="z" :class="'_'+td.name+' '+td.attrs.class" :style="td.attrs.style">
65
+ <node :childs="td.children" :opts="[opts[0],opts[1],opts[2],opts[3],opts[4],opts[5],opts[6],opts[7]+'.'+i+'.children.'+x+'.children.'+y+'.children.'+z+'.children']" />
66
+ </view>
67
+ </view>
68
+ </block>
69
+ </view>
70
+ </view>
71
+
72
+ <!-- 富文本 -->
73
+ <!-- #ifdef H5 || ((MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE2) -->
74
+ <rich-text v-else-if="!opts[5]&&!n.c&&(n.l||!handler.isInline(n.name, n.attrs.style))" :id="n.attrs.id" :style="n.f" :user-select="opts[4]" :nodes="[n]" />
75
+ <!-- #endif -->
76
+ <!-- #ifndef H5 || ((MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE2) -->
77
+ <rich-text v-else-if="!opts[5]&&!n.c" :id="n.attrs.id" :style="'display:inline;'+n.f" :preview="false" :selectable="opts[4]" :user-select="opts[4]" :nodes="[n]" />
78
+ <!-- #endif -->
79
+ <!-- 继续递归 -->
80
+ <view v-else-if="n.c===2" :id="n.attrs.id" :class="'_block _'+n.name+' '+n.attrs.class" :style="n.f+';'+n.attrs.style">
81
+ <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[0],opts[1],opts[2],opts[3],opts[4],opts[5],opts[6],opts[7]+'.'+i+'.children.'+j+'.children']" />
82
+ </view>
83
+ <node v-else :style="n.f" :name="n.name" :attrs="n.attrs" :childs="n.children" :opts="[opts[0],opts[1],opts[2],opts[3],opts[4],opts[5],opts[6],opts[7]+'.'+i+'.children']" />
84
+ </block>
85
+ </view>
86
+ </template>
87
+ <script module="handler" lang="wxs">
88
+ // 行内标签列表
89
+ var inlineTags = {
90
+ abbr: true,
91
+ b: true,
92
+ big: true,
93
+ code: true,
94
+ del: true,
95
+ em: true,
96
+ i: true,
97
+ ins: true,
98
+ label: true,
99
+ q: true,
100
+ small: true,
101
+ span: true,
102
+ strong: true,
103
+ sub: true,
104
+ sup: true
105
+ }
106
+ /**
107
+ * @description 判断是否为行内标签
108
+ */
109
+ module.exports = {
110
+ isInline: function (tagName, style) {
111
+ return inlineTags[tagName] || (style || '').indexOf('display:inline') !== -1
112
+ }
113
+ }
114
+ </script>
115
+ <script>
116
+ import Parser from '../parser'
117
+ import { unitConvert } from '../../../common/util'
118
+ function getTop(e) {
119
+ let top
120
+ top = e.currentTarget.offsetTop
121
+ if (top < 30) {
122
+ top += 70
123
+ }
124
+ return top - 30
125
+ }
126
+
127
+ import node from './node'
128
+ export default {
129
+ name: 'node',
130
+ options: {
131
+ // #ifdef MP-WEIXIN
132
+ virtualHost: true,
133
+ // #endif
134
+ // #ifdef MP-TOUTIAO
135
+ addGlobalClass: false
136
+ // #endif
137
+ },
138
+ data () {
139
+ return {
140
+ ctrl: {},
141
+ nodes: [],
142
+ // #ifdef MP-WEIXIN
143
+ isiOS: (uni.canIUse('getDeviceInfo') ? uni.getDeviceInfo() : uni.getSystemInfoSync()).system.includes('iOS')
144
+ // #endif
145
+ }
146
+ },
147
+ props: {
148
+ name: String,
149
+ attrs: {
150
+ type: Object,
151
+ default () {
152
+ return {}
153
+ }
154
+ },
155
+ childs: Array,
156
+ opts: Array
157
+ },
158
+ watch: {
159
+ childs: {
160
+ handler (nodes) {
161
+ // 列表缩短会刷新整个列表,因此进行空填充
162
+ if(!nodes) return
163
+ while (this.nodes.length > nodes.length) {
164
+ nodes.push({})
165
+ }
166
+ this.nodes = nodes
167
+ },
168
+ immediate: true
169
+ }
170
+ },
171
+ components: {
172
+
173
+ // #ifndef ((H5 || APP-PLUS) && VUE3) || APP-HARMONY
174
+ node
175
+ // #endif
176
+ },
177
+ mounted () {
178
+ this.$nextTick(() => {
179
+ for (this.root = this.$parent; this.root.$options.name !== 'mp-html'; this.root = this.root.$parent);
180
+ })
181
+ // #ifdef H5 || APP-PLUS
182
+ if (this.opts[0]) {
183
+ let i
184
+ for (i = this.childs.length; i--;) {
185
+ if (this.childs[i].name === 'img') break
186
+ }
187
+ if (i !== -1) {
188
+ this.observer = uni.createIntersectionObserver(this).relativeToViewport({
189
+ top: 500,
190
+ bottom: 500
191
+ })
192
+ this.observer.observe('._img', res => {
193
+ if (res.intersectionRatio) {
194
+ this.$set(this.ctrl, 'load', 1)
195
+ this.observer.disconnect()
196
+ }
197
+ })
198
+ }
199
+ }
200
+ // #endif
201
+ },
202
+ beforeDestroy () {
203
+ if (this.root && this.root._edit === this) {
204
+ this.root._edit = undefined
205
+ }
206
+ // #ifdef H5 || APP-PLUS
207
+ if (this.observer) {
208
+ this.observer.disconnect()
209
+ }
210
+ // #endif
211
+ },
212
+ methods:{editStart (e) {
213
+ if (this.opts[5]) {
214
+ const i = e.currentTarget.dataset.i
215
+ if (!this.ctrl['e' + i] && this.opts[5] !== 'simple') {
216
+ // 显示虚线框
217
+ this.$set(this.ctrl, 'e' + i, 1)
218
+ setTimeout(() => {
219
+ this.root._mask.push(() => this.$set(this.ctrl, 'e' + i, 0))
220
+ }, 50)
221
+ this.root._edit = this
222
+ this.i = i
223
+ this.cursor = this.childs[i].text.length
224
+ } else {
225
+ if (this.opts[5] === 'simple') {
226
+ this.root._edit = this
227
+ this.i = i
228
+ this.cursor = this.childs[i].text.length
229
+ }
230
+ this.root._mask.pop()
231
+ this.root._maskTap()
232
+ // 将 text 转为 textarea
233
+ this.$set(this.ctrl, 'e' + i, 2)
234
+ // 延时对焦,避免高度错误
235
+ setTimeout(() => {
236
+ this.$set(this.ctrl, 'e' + i, 3)
237
+ }, 50)
238
+ }
239
+ }
240
+ },editInput (e) {
241
+ const i = e.target.dataset.i
242
+ // 替换连续空格
243
+ const value = e.detail.value.replace(/ {2,}/, $ => {
244
+ let res = '\xa0'
245
+ for (let i = 1; i < $.length; i++) {
246
+ res += '\xa0'
247
+ }
248
+ return res
249
+ })
250
+ this.root._editVal(`${this.opts[7]}.${i}.text`, this.childs[i].text, value) // 记录编辑历史
251
+ this.cursor = e.detail.cursor
252
+ },editEnd (e) {
253
+ const i = e.target.dataset.i
254
+ this.$set(this.ctrl, 'e' + i, 0)
255
+ // 更新到视图
256
+ this.root._setData(`${this.opts[7]}.${i}.text`, e.detail.value.replace(/ {2}/g, '\xa0 '))
257
+ if (e.detail.cursor !== undefined) {
258
+ this.cursor = e.detail.cursor
259
+ }
260
+ },insert (node) {
261
+ setTimeout(() => {
262
+ const childs = this.childs.slice(0)
263
+ if (!childs[this.i]) {
264
+ childs.push(node)
265
+ } else if (childs[this.i].text) {
266
+ // 在文本中插入
267
+ const text = childs[this.i].text
268
+ if (node.type === 'text') {
269
+ if (this.cursor) {
270
+ childs[this.i].text = text.substring(0, this.cursor) + node.text + text.substring(this.cursor)
271
+ } else {
272
+ childs[this.i].text += node.text
273
+ }
274
+ } else {
275
+ const list = []
276
+ if (this.cursor) {
277
+ list.push({
278
+ type: 'text',
279
+ text: text.substring(0, this.cursor)
280
+ })
281
+ }
282
+ list.push(node)
283
+ if (this.cursor < text.length) {
284
+ list.push({
285
+ type: 'text',
286
+ text: text.substring(this.cursor)
287
+ })
288
+ }
289
+ childs.splice(this.i, 1, ...list)
290
+ }
291
+ } else {
292
+ childs.splice(parseInt(this.i) + 1, 0, node)
293
+ }
294
+ this.root._editVal(this.opts[7], this.childs, childs, true)
295
+ this.i = parseInt(this.i) + 1
296
+ }, 200)
297
+ },remove (i) {
298
+ const arr = this.childs.slice(0)
299
+ const delEle = arr.splice(i, 1)[0]
300
+ if (delEle.name === 'img' || delEle.name === 'video' || delEle.name === 'audio') {
301
+ let src = delEle.attrs.src
302
+ if (delEle.src) {
303
+ src = delEle.src.length === 1 ? delEle.src[0] : delEle.src
304
+ }
305
+ this.root.$emit('remove', {
306
+ type: delEle.name,
307
+ src
308
+ })
309
+ }
310
+ this.root._edit = undefined
311
+ this.root._maskTap()
312
+ this.root._editVal(this.opts[7], this.childs, arr, true)
313
+ },nodeTap (e) {
314
+ if (this.opts[5]) {
315
+ if (this.root._lock) return
316
+ this.root._lock = true
317
+ setTimeout(() => {
318
+ this.root._lock = false
319
+ }, 50)
320
+ if (this.ctrl['e' + this.i] === 3) return
321
+ this.root._maskTap()
322
+ this.root._edit = this
323
+ if (this.opts[5] === 'simple') return
324
+ let start = this.opts[7].lastIndexOf('children.')
325
+ if (start !== -1) {
326
+ start += 9
327
+ } else {
328
+ start = 6
329
+ }
330
+ const i = parseInt(this.opts[7].substring(start, this.opts[7].lastIndexOf('.children')))
331
+ let parent = this.$parent
332
+ while (parent && parent.$options.name !== 'node') {
333
+ parent = parent.$parent
334
+ }
335
+ let remove = () => {
336
+ parent.remove(i)
337
+ }
338
+ if (parent && (this.opts[7].length - parent.opts[7].length > 15)) {
339
+ const parts = this.opts[7].split('.')
340
+ let childs = parent.childs
341
+ const i = parseInt(parts[parent.opts[7].split('.').length])
342
+ const oldParent = parent
343
+ // 删除整个表格
344
+ remove = () => {
345
+ oldParent.remove(i)
346
+ }
347
+ for (let i = parent.opts[7].split('.').length; i < parts.length - 2; i++) {
348
+ childs = childs[parts[i]]
349
+ }
350
+ const that = this
351
+ parent = {
352
+ childs,
353
+ opts: [undefined, undefined, undefined, undefined, undefined, undefined, undefined, parts.slice(0, parts.length - 2).join('.')],
354
+ changeStyle (name, i, value, oldVal) {
355
+ let style = this.childs[i].attrs.style || ''
356
+ if (style.includes(';' + name + ':' + oldVal)) {
357
+ style = style.replace(';' + name + ':' + oldVal, ';' + name + ':' + value)
358
+ } else {
359
+ style += ';' + name + ':' + value
360
+ }
361
+ that.root._setData(`${this.opts[7]}.${i}.attrs.style`, style)
362
+ }
363
+ }
364
+ }
365
+ if (!parent) return
366
+ // 显示实线框
367
+ this.$set(this.ctrl, 'root', 1)
368
+ this.root._mask.push(() => this.$set(this.ctrl, 'root', 0))
369
+ if (this.childs.length === 1 && this.childs[0].type === 'text' && !this.ctrl.e0) {
370
+ this.$set(this.ctrl, 'e0', 1)
371
+ this.root._mask.push(() => this.$set(this.ctrl, 'e0', 0))
372
+ this.i = 0
373
+ this.cursor = this.childs[0].text.length
374
+ }
375
+ const items = this.root._getItem(parent.childs[i], i !== 0, i !== parent.childs.length - 1)
376
+ this.root._tooltip({
377
+ top: getTop(e),
378
+ items,
379
+ success: tapIndex => {
380
+ if (items[tapIndex] === '大小') {
381
+ // 改变字体大小
382
+ const style = parent.childs[i].attrs.style || ''
383
+ let value = style.match(/;font-size:([0-9]+)px/)
384
+ if (value) {
385
+ value = parseInt(value[1])
386
+ } else {
387
+ value = 16
388
+ }
389
+ this.root._slider({
390
+ min: 10,
391
+ max: 30,
392
+ value,
393
+ top: getTop(e),
394
+ changing: val => {
395
+ if (Math.abs(val - value) > 2) {
396
+ // 字号变换超过 2 时更新到视图
397
+ parent.changeStyle(
398
+ 'font-size',
399
+ i,
400
+ unitConvert(val, 0, { output: 'px' }),
401
+ unitConvert(value, 0, { output: 'px' })
402
+ )
403
+ value = e.detail.value
404
+ }
405
+ },
406
+ change: val => {
407
+ if (val !== value) {
408
+ parent.changeStyle(
409
+ 'font-size',
410
+ i,
411
+ unitConvert(val, 0, { output: 'px' }),
412
+ unitConvert(value, 0, { output: 'px' })
413
+ )
414
+ }
415
+ this.root._editVal(`${parent.opts[7]}.${i}.attrs.style`, style, parent.childs[i].attrs.style)
416
+ }
417
+ })
418
+ } else if (items[tapIndex] === '颜色') {
419
+ // 改变文字颜色
420
+ const items = this.root._getItem('color')
421
+ this.root._color({
422
+ top: getTop(e),
423
+ items,
424
+ success: tapIndex => {
425
+ const style = parent.childs[i].attrs.style || ''
426
+ const value = style.match(/;color:([^;]+)/)
427
+ parent.changeStyle('color', i, items[tapIndex], value ? value[1] : undefined)
428
+ this.root._editVal(`${parent.opts[7]}.${i}.attrs.style`, style, parent.childs[i].attrs.style)
429
+ }
430
+ })
431
+ } else if (items[tapIndex] === '上移' || items[tapIndex] === '下移') {
432
+ const arr = parent.childs.slice(0)
433
+ const item = arr[i]
434
+ if (items[tapIndex] === '上移') {
435
+ arr[i] = arr[i - 1]
436
+ arr[i - 1] = item
437
+ } else {
438
+ arr[i] = arr[i + 1]
439
+ arr[i + 1] = item
440
+ }
441
+ this.root._editVal(parent.opts[7], parent.childs, arr, true)
442
+ } else if (items[tapIndex] === '删除') {
443
+ remove()
444
+ } else {
445
+ const style = parent.childs[i].attrs.style || ''
446
+ let newStyle = ''
447
+ const item = items[tapIndex]
448
+ let name
449
+ let value
450
+ if (item === '斜体') {
451
+ name = 'font-style'
452
+ value = 'italic'
453
+ } else if (item === '粗体') {
454
+ name = 'font-weight'
455
+ value = 'bold'
456
+ } else if (item === '下划线') {
457
+ name = 'text-decoration'
458
+ value = 'underline'
459
+ } else if (item === '居中') {
460
+ name = 'text-align'
461
+ value = 'center'
462
+ } else if (item === '缩进') {
463
+ name = 'text-indent'
464
+ value = '2em'
465
+ }
466
+ if (style.includes(name + ':')) {
467
+ // 已有则取消
468
+ newStyle = style.replace(new RegExp(name + ':[^;]+'), '')
469
+ } else {
470
+ // 没有则添加
471
+ newStyle = style + ';' + name + ':' + value
472
+ }
473
+ this.root._editVal(`${parent.opts[7]}.${i}.attrs.style`, style, newStyle, true)
474
+ }
475
+ }
476
+ })
477
+ }
478
+ },mediaTap (e, index) {
479
+ if (this.opts[5]) {
480
+ const i = e.target.dataset.i || index
481
+ const node = this.childs[i]
482
+ const items = this.root._getItem(node)
483
+ this.root._maskTap()
484
+ this.root._edit = this
485
+ this.i = i
486
+ this.root._tooltip({
487
+ top: e.currentTarget.offsetTop - 30,
488
+ items,
489
+ success: tapIndex => {
490
+ switch (items[tapIndex]) {
491
+ case '封面':
492
+ // 设置封面
493
+ this.root.getSrc('img', node.attrs.poster || '').then(url => {
494
+ this.root._editVal(`${this.opts[7]}.${i}.attrs.poster`, node.attrs.poster, url instanceof Array ? url[0] : url, true)
495
+ }).catch(() => { })
496
+ break
497
+ case '删除':
498
+ this.remove(i)
499
+ break
500
+ case '循环':
501
+ case '不循环':
502
+ // 切换循环播放
503
+ this.root._setData(`${this.opts[7]}.${i}.attrs.loop`, !node.attrs.loop)
504
+ uni.showToast({
505
+ title: '成功'
506
+ })
507
+ break
508
+ case '自动播放':
509
+ case '不自动播放':
510
+ // 切换自动播放播放
511
+ this.root._setData(`${this.opts[7]}.${i}.attrs.autoplay`, !node.attrs.autoplay)
512
+ uni.showToast({
513
+ title: '成功'
514
+ })
515
+ break
516
+ }
517
+ }
518
+ })
519
+ // 避免上层出现点击态
520
+ this.root._lock = true
521
+ setTimeout(() => {
522
+ this.root._lock = false
523
+ }, 50)
524
+ }
525
+ },changeStyle (name, i, value, oldVal) {
526
+ let style = this.childs[i].attrs.style || ''
527
+ if (style.includes(';' + name + ':' + oldVal)) {
528
+ // style 中已经有
529
+ style = style.replace(';' + name + ':' + oldVal, ';' + name + ':' + value)
530
+ } else {
531
+ // 没有则新增
532
+ style += ';' + name + ':' + value
533
+ }
534
+ this.root._setData(`${this.opts[7]}.${i}.attrs.style`, style)
535
+ },
536
+ // #ifdef MP-WEIXIN
537
+ toJSON () { return this },
538
+ // #endif
539
+ /**
540
+ * @description 播放视频事件
541
+ * @param {Event} e
542
+ */
543
+ play (e) {
544
+ const i = e.currentTarget.dataset.i
545
+ const node = this.childs[i]
546
+ this.root.$emit('play', {
547
+ source: node.name,
548
+ attrs: {
549
+ ...node.attrs,
550
+ src: node.src[this.ctrl[i] || 0]
551
+ }
552
+ })
553
+ // #ifndef APP-PLUS
554
+ if (this.root.pauseVideo) {
555
+ let flag = false
556
+ const id = e.target.id
557
+ for (let i = this.root._videos.length; i--;) {
558
+ if (this.root._videos[i].id === id) {
559
+ flag = true
560
+ } else {
561
+ this.root._videos[i].pause() // 自动暂停其他视频
562
+ }
563
+ }
564
+ // 将自己加入列表
565
+ if (!flag) {
566
+ const ctx = uni.createVideoContext(id
567
+ // #ifndef MP-BAIDU
568
+ , this
569
+ // #endif
570
+ )
571
+ ctx.id = id
572
+ if (this.root.playbackRate) {
573
+ ctx.playbackRate(this.root.playbackRate)
574
+ }
575
+ this.root._videos.push(ctx)
576
+ }
577
+ }
578
+ // #endif
579
+ },
580
+ /**
581
+ * @description 音视频其他事件
582
+ * @param {Event} e
583
+ */
584
+ mediaEvent (e) {
585
+ const i = e.currentTarget.dataset.i
586
+ const node = this.childs[i]
587
+ this.root.$emit(e.type, {
588
+ ...e.detail,
589
+ source: node.name,
590
+ attrs: {
591
+ ...node.attrs,
592
+ src: node.src[this.ctrl[i] || 0]
593
+ }
594
+ })
595
+ },
596
+
597
+ /**
598
+ * @description 图片点击事件
599
+ * @param {Event} e
600
+ */
601
+ imgTap (e) {
602
+ if (!this.opts[5]) {
603
+ const node = this.childs[e.currentTarget.dataset.i]
604
+ if (node.a) {
605
+ this.linkTap(node.a)
606
+ return
607
+ }
608
+ if (node.attrs.ignore) return
609
+ // #ifdef H5 || APP-PLUS
610
+ node.attrs.src = node.attrs.src || node.attrs['data-src']
611
+ // #endif
612
+ // #ifndef APP-HARMONY
613
+ this.root.$emit('imgtap', node.attrs)
614
+ // #endif
615
+ // #ifdef APP-HARMONY
616
+ this.root.$emit('imgtap', {
617
+ ...node.attrs
618
+ })
619
+ // #endif
620
+ // 自动预览图片
621
+ if (this.root.previewImg) {
622
+ uni.previewImage({
623
+ // #ifdef MP-WEIXIN
624
+ showmenu: this.root.showImgMenu,
625
+ // #endif
626
+ // #ifdef MP-ALIPAY
627
+ enablesavephoto: this.root.showImgMenu,
628
+ enableShowPhotoDownload: this.root.showImgMenu,
629
+ // #endif
630
+ current: parseInt(node.attrs.i),
631
+ urls: this.root.imgList
632
+ })
633
+ }
634
+ } else {
635
+ const i = e.currentTarget.dataset.i
636
+ const node = this.childs[i]
637
+ const items = this.root._getItem(node)
638
+ const parser = new Parser(this.root)
639
+ this.root._edit = this
640
+ this.i = i
641
+ this.root._maskTap()
642
+ this.$set(this.ctrl, 'e' + i, 1)
643
+ this.root._mask.push(() => this.$set(this.ctrl, 'e' + i, 0))
644
+ this.root._tooltip({
645
+ top: getTop(e),
646
+ items,
647
+ success: tapIndex => {
648
+ if (items[tapIndex] === '换图') {
649
+ // 换图
650
+ this.root.getSrc('img', node.attrs.src || '').then(url => {
651
+ this.root._editVal(this.opts[7] + '.' + i + '.attrs.src', node.attrs.src, parser.getUrl(url instanceof Array ? url[0] : url), true)
652
+ }).catch(() => { })
653
+ } else if (items[tapIndex] === '宽度') {
654
+ // 更改宽度
655
+ const style = node.attrs.style || ''
656
+ let value = style.match(/max-width:([0-9]+)%/)
657
+ if (value) {
658
+ value = parseInt(value[1])
659
+ } else {
660
+ value = 100
661
+ }
662
+ this.root._slider({
663
+ min: 0,
664
+ max: 100,
665
+ value,
666
+ top: getTop(e),
667
+ changing: val => {
668
+ // 变化超过 5% 更新时视图
669
+ if (Math.abs(val - value) > 5) {
670
+ this.changeStyle('max-width', i, val + '%', value + '%')
671
+ value = val
672
+ }
673
+ },
674
+ change: val => {
675
+ if (val !== value) {
676
+ this.changeStyle('max-width', i, val + '%', value + '%')
677
+ value = val
678
+ }
679
+ this.root._editVal(this.opts[7] + '.' + i + '.attrs.style', style, this.childs[i].attrs.style)
680
+ }
681
+ })
682
+ } else if (items[tapIndex] === '超链接') {
683
+ // 将图片设置为链接
684
+ this.root.getSrc('link', node.a ? node.a.href : '').then(url => {
685
+ // 如果有 a 标签则替换 href
686
+ if (node.a) {
687
+ this.root._editVal(this.opts[7] + '.' + i + '.a.href', node.a.href, parser.getUrl(url), true)
688
+ } else {
689
+ const link = {
690
+ name: 'a',
691
+ attrs: {
692
+ href: parser.getUrl(url)
693
+ },
694
+ children: [node]
695
+ }
696
+ node.a = link.attrs
697
+ this.root._editVal(this.opts[7] + '.' + i, node, link, true)
698
+ }
699
+ wx.showToast({
700
+ title: '成功'
701
+ })
702
+ }).catch(() => { })
703
+ } else if (items[tapIndex] === '预览图') {
704
+ // 设置预览图链接
705
+ this.root.getSrc('img', node.attrs['original-src'] || '').then(url => {
706
+ this.root._editVal(this.opts[7] + '.' + i + '.attrs.original-src', node.attrs['original-src'], parser.getUrl(url instanceof Array ? url[0] : url), true)
707
+ uni.showToast({
708
+ title: '成功'
709
+ })
710
+ }).catch(() => { })
711
+ } else if (items[tapIndex] === '删除') {
712
+ this.remove(i)
713
+ } else {
714
+ // 禁用 / 启用预览
715
+ this.root._setData(this.opts[7] + '.' + i + '.attrs.ignore', !node.attrs.ignore)
716
+ uni.showToast({
717
+ title: '成功'
718
+ })
719
+ }
720
+ }
721
+ })
722
+ this.root._lock = true
723
+ setTimeout(() => {
724
+ this.root._lock = false
725
+ }, 50)
726
+ }
727
+ },
728
+ /**
729
+ * @description 图片长按
730
+ */
731
+ imgLongTap (e) {
732
+ // #ifdef APP-PLUS
733
+ const attrs = this.childs[e.currentTarget.dataset.i].attrs
734
+ if (this.opts[3] && !attrs.ignore) {
735
+ uni.showActionSheet({
736
+ itemList: ['保存图片'],
737
+ success: () => {
738
+ const save = path => {
739
+ uni.saveImageToPhotosAlbum({
740
+ filePath: path,
741
+ success () {
742
+ uni.showToast({
743
+ title: '保存成功'
744
+ })
745
+ }
746
+ })
747
+ }
748
+ if (this.root.imgList[attrs.i].startsWith('http')) {
749
+ uni.downloadFile({
750
+ url: this.root.imgList[attrs.i],
751
+ success: res => save(res.tempFilePath)
752
+ })
753
+ } else {
754
+ save(this.root.imgList[attrs.i])
755
+ }
756
+ }
757
+ })
758
+ }
759
+ // #endif
760
+ },
761
+
762
+ /**
763
+ * @description 图片加载完成事件
764
+ * @param {Event} e
765
+ */
766
+ imgLoad(e) {
767
+ const i = e.currentTarget.dataset.i
768
+ if (i === undefined || !this.childs || !this.childs[i]) return
769
+ // #ifdef MP-WEIXIN || MP-QQ
770
+ if (this.opts[5])
771
+ this.$nextTick(() => {
772
+ const id = this.childs[i].attrs.id || ('n' + i)
773
+ uni.createSelectorQuery().in(this).select('#' + id).boundingClientRect().exec(res => {
774
+ this.$set(this.ctrl, 'h'+i, res[0]?.height)
775
+ })
776
+ })
777
+ // #endif
778
+ /* #ifndef H5 || (APP-PLUS && VUE2) */
779
+ if (!this.childs[i].w) {
780
+ this.$set(this.ctrl, i, e.detail.width)
781
+ if (this.opts[5]) {
782
+ const path = this.opts[7] + '.' + i + '.attrs.'
783
+ if (e.detail.width < 150)
784
+ this.root._setData(path + 'ignore', 'T')
785
+ this.root._setData(path + 'width', e.detail.width.toString())
786
+ }
787
+ } else /* #endif */ if ((this.opts[1] && !this.ctrl[i]) || this.ctrl[i] === -1) {
788
+ // 加载完毕,取消加载中占位图
789
+ this.$set(this.ctrl, i, 1)
790
+ }
791
+ this.checkReady()
792
+ },
793
+
794
+ /**
795
+ * @description 检查是否所有图片加载完毕
796
+ */
797
+ checkReady () {
798
+ if (this.root && !this.root.lazyLoad) {
799
+ this.root._unloadimgs -= 1
800
+ if (!this.root._unloadimgs) {
801
+ setTimeout(() => {
802
+ this.root.getRect().then(rect => {
803
+ this.root.$emit('ready', rect)
804
+ }).catch(() => {
805
+ this.root.$emit('ready', {})
806
+ })
807
+ }, 350)
808
+ }
809
+ }
810
+ },
811
+
812
+ /**
813
+ * @description 链接点击事件
814
+ * @param {Event} e
815
+ */
816
+ linkTap (e) {
817
+ if (!this.opts[5]) {
818
+ const node = e.currentTarget ? this.childs[e.currentTarget.dataset.i] : {}
819
+ const attrs = node.attrs || e
820
+ const href = attrs.href
821
+ this.root.$emit('linktap', Object.assign({
822
+ innerText: this.root.getText(node.children || []) // 链接内的文本内容
823
+ }, attrs))
824
+ if (href) {
825
+ if (href[0] === '#') {
826
+ // 跳转锚点
827
+ this.root.navigateTo(href.substring(1)).catch(() => { })
828
+ } else if (href.split('?')[0].includes('://')) {
829
+ // 复制外部链接
830
+ if (this.root.copyLink) {
831
+ // #ifdef H5
832
+ window.open(href)
833
+ // #endif
834
+ // #ifdef MP
835
+ uni.setClipboardData({
836
+ data: href,
837
+ success: () =>
838
+ uni.showToast({
839
+ title: '链接已复制'
840
+ })
841
+ })
842
+ // #endif
843
+ // #ifdef APP-PLUS
844
+ plus.runtime.openWeb(href)
845
+ // #endif
846
+ }
847
+ } else {
848
+ // 跳转页面
849
+ uni.navigateTo({
850
+ url: href,
851
+ fail () {
852
+ uni.switchTab({
853
+ url: href,
854
+ fail () { }
855
+ })
856
+ }
857
+ })
858
+ }
859
+ }
860
+ } else {
861
+ const i = e.currentTarget.dataset.i
862
+ const node = this.childs[i]
863
+ const items = this.root._getItem(node)
864
+ this.root._tooltip({
865
+ top: getTop(e),
866
+ items,
867
+ success: tapIndex => {
868
+ if (items[tapIndex] === '更换链接') {
869
+ this.root.getSrc('link', node.attrs.href).then(url => {
870
+ this.root._editVal(this.opts[7] + '.' + i + '.attrs.href', node.attrs.href, url, true)
871
+ uni.showToast({
872
+ title: '成功'
873
+ })
874
+ }).catch(() => { })
875
+ } else {
876
+ this.remove(i)
877
+ }
878
+ }
879
+ })
880
+ }
881
+ },
882
+ /**
883
+ * @description 错误事件
884
+ * @param {Event} e
885
+ */
886
+ mediaError (e) {
887
+ const i = e.currentTarget.dataset.i
888
+ const node = this.childs[i]
889
+ // 加载其他源
890
+ if (node.name === 'video' || node.name === 'audio') {
891
+ let index = (this.ctrl[i] || 0) + 1
892
+ if (index > node.src.length) {
893
+ index = 0
894
+ }
895
+ if (index < node.src.length) {
896
+ this.$set(this.ctrl, i, index)
897
+ return
898
+ }
899
+ } else if (node.name === 'img') {
900
+ // #ifdef H5 && VUE3
901
+ if (this.opts[0] && !this.ctrl.load) return
902
+ // #endif
903
+ // 显示错误占位图
904
+ if (this.opts[2]) {
905
+ this.$set(this.ctrl, i, -1)
906
+ }
907
+ this.checkReady()
908
+ }
909
+ if (this.root) {
910
+ this.root.$emit('error', {
911
+ source: node.name,
912
+ attrs: node.attrs,
913
+ // #ifndef H5 && VUE3
914
+ errMsg: e.detail.errMsg
915
+ // #endif
916
+ })
917
+ }
918
+ }
919
+ }
920
+ }
921
+ </script>
922
+ <style>/deep/ .md-p {
923
+ margin-block-start: 1em;
924
+ margin-block-end: 1em;
925
+ }
926
+
927
+ /deep/ .md-table,
928
+ /deep/ .md-blockquote {
929
+ margin-bottom: 32rpx;
930
+ }
931
+
932
+ /deep/ .md-table {
933
+ box-sizing: border-box;
934
+ width: 100%;
935
+ overflow: auto;
936
+ border-spacing: 0;
937
+ border-collapse: collapse;
938
+ }
939
+
940
+ /deep/ .md-tr {
941
+ background-color: #fff;
942
+ border-top: 1px solid #c6cbd1;
943
+ }
944
+
945
+ .md-table .md-tr:nth-child(2n) {
946
+ background-color: #f6f8fa;
947
+ }
948
+
949
+ /deep/ .md-th,
950
+ /deep/ .md-td {
951
+ padding: 12rpx 26rpx !important;
952
+ border: 1px solid #dfe2e5;
953
+ }
954
+
955
+ /deep/ .md-th {
956
+ font-weight: 600;
957
+ }
958
+
959
+ /deep/ .md-blockquote {
960
+ padding: 0 1em;
961
+ color: #6a737d;
962
+ border-left: 0.25em solid #dfe2e5;
963
+ }
964
+
965
+ /deep/ .md-code {
966
+ padding: 0.2em 0.4em;
967
+ font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
968
+ font-size: 85%;
969
+ background-color: rgba(27, 31, 35, 0.05);
970
+ border-radius: 6rpx;
971
+ }
972
+
973
+ /deep/ .md-pre .md-code {
974
+ padding: 0;
975
+ font-size: 100%;
976
+ background: transparent;
977
+ border: 0;
978
+ }/* #ifndef H5 || MP-ALIPAY || APP-PLUS */
979
+ /deep/ ._address,
980
+ /deep/ ._article,
981
+ /deep/ ._aside,
982
+ /deep/ ._body,
983
+ /deep/ ._caption,
984
+ /deep/ ._center,
985
+ /deep/ ._cite,
986
+ /deep/ ._footer,
987
+ /deep/ ._header,
988
+ /deep/ ._html,
989
+ /deep/ ._nav,
990
+ /deep/ ._pre,
991
+ /deep/ ._section {
992
+ display: block;
993
+ }
994
+
995
+ /* #endif */
996
+ /deep/ ._video {
997
+ width: 600rpx;
998
+ height: 450rpx;
999
+ display: inline-block;
1000
+ background-color: black;
1001
+ }
1002
+ /* a 标签默认效果 */
1003
+ ._a {
1004
+ padding: 3rpx 0 3rpx 0;
1005
+ color: #366092;
1006
+ word-break: break-all;
1007
+ }
1008
+
1009
+ /* a 标签点击态效果 */
1010
+ ._hover {
1011
+ text-decoration: underline;
1012
+ opacity: 0.7;
1013
+ }
1014
+
1015
+ /* 图片默认效果 */
1016
+ ._img {
1017
+ max-width: 100%;
1018
+ -webkit-touch-callout: none;
1019
+ }
1020
+
1021
+ /* 内部样式 */
1022
+
1023
+ ._block {
1024
+ display: block;
1025
+ }
1026
+
1027
+ ._b,
1028
+ ._strong {
1029
+ font-weight: bold;
1030
+ }
1031
+
1032
+ ._code {
1033
+ font-family: monospace;
1034
+ }
1035
+
1036
+ ._del {
1037
+ text-decoration: line-through;
1038
+ }
1039
+
1040
+ ._em,
1041
+ ._i {
1042
+ font-style: italic;
1043
+ }
1044
+
1045
+ ._h1 {
1046
+ font-size: 2em;
1047
+ }
1048
+
1049
+ ._h2 {
1050
+ font-size: 1.5em;
1051
+ }
1052
+
1053
+ ._h3 {
1054
+ font-size: 1.17em;
1055
+ }
1056
+
1057
+ ._h5 {
1058
+ font-size: 0.83em;
1059
+ }
1060
+
1061
+ ._h6 {
1062
+ font-size: 0.67em;
1063
+ }
1064
+
1065
+ ._h1,
1066
+ ._h2,
1067
+ ._h3,
1068
+ ._h4,
1069
+ ._h5,
1070
+ ._h6 {
1071
+ display: block;
1072
+ font-weight: bold;
1073
+ }
1074
+
1075
+ ._image {
1076
+ height: 1px;
1077
+ }
1078
+
1079
+ ._ins {
1080
+ text-decoration: underline;
1081
+ }
1082
+
1083
+ ._li {
1084
+ display: list-item;
1085
+ }
1086
+
1087
+ ._ol {
1088
+ list-style-type: decimal;
1089
+ }
1090
+
1091
+ ._ol,
1092
+ ._ul {
1093
+ display: block;
1094
+ padding-left: 80rpx;
1095
+ margin: 1em 0;
1096
+ }
1097
+
1098
+ ._q::before {
1099
+ content: '"';
1100
+ }
1101
+
1102
+ ._q::after {
1103
+ content: '"';
1104
+ }
1105
+
1106
+ ._sub {
1107
+ font-size: smaller;
1108
+ vertical-align: sub;
1109
+ }
1110
+
1111
+ ._sup {
1112
+ font-size: smaller;
1113
+ vertical-align: super;
1114
+ }
1115
+
1116
+ ._thead,
1117
+ ._tbody,
1118
+ ._tfoot {
1119
+ display: table-row-group;
1120
+ }
1121
+
1122
+ ._tr {
1123
+ display: table-row;
1124
+ }
1125
+
1126
+ ._td,
1127
+ ._th {
1128
+ display: table-cell;
1129
+ vertical-align: middle;
1130
+ }
1131
+
1132
+ ._th {
1133
+ font-weight: bold;
1134
+ text-align: center;
1135
+ }
1136
+
1137
+ ._ul {
1138
+ list-style-type: disc;
1139
+ }
1140
+
1141
+ ._ul ._ul {
1142
+ margin: 0;
1143
+ list-style-type: circle;
1144
+ }
1145
+
1146
+ ._ul ._ul ._ul {
1147
+ list-style-type: square;
1148
+ }
1149
+
1150
+ ._abbr,
1151
+ ._b,
1152
+ ._code,
1153
+ ._del,
1154
+ ._em,
1155
+ ._i,
1156
+ ._ins,
1157
+ ._label,
1158
+ ._q,
1159
+ ._span,
1160
+ ._strong,
1161
+ ._sub,
1162
+ ._sup {
1163
+ display: inline;
1164
+ }
1165
+
1166
+ /* #ifdef APP-PLUS */
1167
+ ._video {
1168
+ width: 600rpx;
1169
+ height: 450rpx;
1170
+ }
1171
+ /* #endif */
1172
+ </style>