DaMowang 2 年之前
父節點
當前提交
ea86b028a2
共有 87 個文件被更改,包括 2754 次插入7473 次删除
  1. 5 0
      src/app.scss
  2. 0 631
      src/components/jyf-parser/jyf-parser.vue
  3. 0 97
      src/components/jyf-parser/libs/CssHandler.js
  4. 0 535
      src/components/jyf-parser/libs/MpHtmlParser.js
  5. 0 80
      src/components/jyf-parser/libs/config.js
  6. 0 22
      src/components/jyf-parser/libs/handler.wxs
  7. 0 501
      src/components/jyf-parser/libs/trees.vue
  8. 0 0
      src/components/swiperBanner/index.vue
  9. 0 40
      src/components/tabbar.vue
  10. 27 27
      src/pages/agreement/index.vue
  11. 1 2
      src/pages/index/index.vue
  12. 3 3
      src/pages/notice/detail.vue
  13. 3 3
      src/pages/pay-agreement/index.vue
  14. 4 4
      src/pages/product/p_details.vue
  15. 67 45
      src/pages/protocol/index.vue
  16. 5 4
      src/pagesB/hotel/hotelDetail.vue
  17. 4 4
      src/pagesB/hotel/orderDetail.vue
  18. 24 3
      src/pagesB/scenicSpotTicket/index.vue
  19. 4 3
      src/pagesB/scenicSpotTicket/scenic.vue
  20. 4 4
      src/pagesB/scenicSpotTicket/scenicDetail.vue
  21. 193 0
      src/uni_modules/mp-html/README.md
  22. 498 0
      src/uni_modules/mp-html/components/mp-html/mp-html.vue
  23. 576 0
      src/uni_modules/mp-html/components/mp-html/node/node.vue
  24. 1335 0
      src/uni_modules/mp-html/components/mp-html/parser.js
  25. 0 0
      src/uni_modules/mp-html/static/app-plus/mp-html/js/handler.js
  26. 0 0
      src/uni_modules/mp-html/static/app-plus/mp-html/js/uni.webview.min.js
  27. 1 0
      src/uni_modules/mp-html/static/app-plus/mp-html/local.html
  28. 0 23
      src/uni_modules/uv-icon/changelog.md
  29. 0 160
      src/uni_modules/uv-icon/components/uv-icon/icons.js
  30. 0 90
      src/uni_modules/uv-icon/components/uv-icon/props.js
  31. 0 221
      src/uni_modules/uv-icon/components/uv-icon/uv-icon.vue
  32. 二進制
      src/uni_modules/uv-icon/components/uv-icon/uvicons.ttf
  33. 0 83
      src/uni_modules/uv-icon/package.json
  34. 0 15
      src/uni_modules/uv-icon/readme.md
  35. 0 7
      src/uni_modules/uv-loading-icon/changelog.md
  36. 0 60
      src/uni_modules/uv-loading-icon/components/uv-loading-icon/props.js
  37. 0 346
      src/uni_modules/uv-loading-icon/components/uv-loading-icon/uv-loading-icon.vue
  38. 0 87
      src/uni_modules/uv-loading-icon/package.json
  39. 0 11
      src/uni_modules/uv-loading-icon/readme.md
  40. 0 15
      src/uni_modules/uv-search/changelog.md
  41. 0 127
      src/uni_modules/uv-search/components/uv-search/props.js
  42. 0 295
      src/uni_modules/uv-search/components/uv-search/uv-search.vue
  43. 0 89
      src/uni_modules/uv-search/package.json
  44. 0 19
      src/uni_modules/uv-search/readme.md
  45. 0 26
      src/uni_modules/uv-ui-tools/changelog.md
  46. 0 6
      src/uni_modules/uv-ui-tools/components/uv-ui-tools/uv-ui-tools.vue
  47. 0 77
      src/uni_modules/uv-ui-tools/index.js
  48. 0 7
      src/uni_modules/uv-ui-tools/index.scss
  49. 0 34
      src/uni_modules/uv-ui-tools/libs/config/config.js
  50. 0 32
      src/uni_modules/uv-ui-tools/libs/css/color.scss
  51. 0 100
      src/uni_modules/uv-ui-tools/libs/css/common.scss
  52. 0 23
      src/uni_modules/uv-ui-tools/libs/css/components.scss
  53. 0 111
      src/uni_modules/uv-ui-tools/libs/css/variable.scss
  54. 0 40
      src/uni_modules/uv-ui-tools/libs/css/vue.scss
  55. 0 134
      src/uni_modules/uv-ui-tools/libs/function/colorGradient.js
  56. 0 29
      src/uni_modules/uv-ui-tools/libs/function/debounce.js
  57. 0 167
      src/uni_modules/uv-ui-tools/libs/function/digit.js
  58. 0 734
      src/uni_modules/uv-ui-tools/libs/function/index.js
  59. 0 75
      src/uni_modules/uv-ui-tools/libs/function/platform.js
  60. 0 287
      src/uni_modules/uv-ui-tools/libs/function/test.js
  61. 0 30
      src/uni_modules/uv-ui-tools/libs/function/throttle.js
  62. 0 97
      src/uni_modules/uv-ui-tools/libs/luch-request/adapters/index.js
  63. 0 50
      src/uni_modules/uv-ui-tools/libs/luch-request/core/InterceptorManager.js
  64. 0 198
      src/uni_modules/uv-ui-tools/libs/luch-request/core/Request.js
  65. 0 20
      src/uni_modules/uv-ui-tools/libs/luch-request/core/buildFullPath.js
  66. 0 29
      src/uni_modules/uv-ui-tools/libs/luch-request/core/defaults.js
  67. 0 3
      src/uni_modules/uv-ui-tools/libs/luch-request/core/dispatchRequest.js
  68. 0 103
      src/uni_modules/uv-ui-tools/libs/luch-request/core/mergeConfig.js
  69. 0 16
      src/uni_modules/uv-ui-tools/libs/luch-request/core/settle.js
  70. 0 69
      src/uni_modules/uv-ui-tools/libs/luch-request/helpers/buildURL.js
  71. 0 14
      src/uni_modules/uv-ui-tools/libs/luch-request/helpers/combineURLs.js
  72. 0 14
      src/uni_modules/uv-ui-tools/libs/luch-request/helpers/isAbsoluteURL.js
  73. 0 116
      src/uni_modules/uv-ui-tools/libs/luch-request/index.d.ts
  74. 0 3
      src/uni_modules/uv-ui-tools/libs/luch-request/index.js
  75. 0 131
      src/uni_modules/uv-ui-tools/libs/luch-request/utils.js
  76. 0 264
      src/uni_modules/uv-ui-tools/libs/luch-request/utils/clone.js
  77. 0 13
      src/uni_modules/uv-ui-tools/libs/mixin/button.js
  78. 0 152
      src/uni_modules/uv-ui-tools/libs/mixin/mixin.js
  79. 0 8
      src/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js
  80. 0 13
      src/uni_modules/uv-ui-tools/libs/mixin/mpShare.js
  81. 0 44
      src/uni_modules/uv-ui-tools/libs/mixin/openType.js
  82. 0 59
      src/uni_modules/uv-ui-tools/libs/mixin/touch.js
  83. 0 218
      src/uni_modules/uv-ui-tools/libs/util/dayjs.js
  84. 0 124
      src/uni_modules/uv-ui-tools/libs/util/route.js
  85. 0 81
      src/uni_modules/uv-ui-tools/package.json
  86. 0 23
      src/uni_modules/uv-ui-tools/readme.md
  87. 0 43
      src/uni_modules/uv-ui-tools/theme.scss

+ 5 - 0
src/app.scss

@@ -162,4 +162,9 @@ uni-input {
 
 .hover_a{
     color: #17bb87;
+}
+
+.inp_pl{
+    font-size: 28rpx;
+    color: #bbb;
 }

+ 0 - 631
src/components/jyf-parser/jyf-parser.vue

@@ -1,631 +0,0 @@
-<template>
-    <view>
-        <slot v-if="!nodes.length" />
-        <!--#ifdef APP-PLUS-NVUE-->
-        <web-view id="_top" ref="web" :style="'margin-top:-2px;height:'+height+'px'" @onPostMessage="_message" />
-        <!--#endif-->
-        <!--#ifndef APP-PLUS-NVUE-->
-        <view id="_top" :style="showAm+(selectable?';user-select:text;-webkit-user-select:text':'')">
-            <!--#ifdef H5 || MP-360-->
-            <div :id="'rtf'+uid"></div>
-            <!--#endif-->
-            <!--#ifndef H5 || MP-360-->
-            <trees :nodes="nodes" :lazyLoad="lazyLoad" :loading="loadingImg" />
-            <!--#endif-->
-        </view>
-        <!--#endif-->
-    </view>
-</template>
-<script>
-// #ifndef H5 || APP-PLUS-NVUE || MP-360
-import trees from './libs/trees';
-var cache = {},
-    // #ifdef MP-WEIXIN || MP-TOUTIAO
-    fs = uni.getFileSystemManager ? uni.getFileSystemManager() : null,
-    // #endif
-    Parser = require('./libs/MpHtmlParser.js');
-var dom;
-// 计算 cache 的 key
-function hash(str) {
-    for (var i = str.length, val = 5381; i--;)
-        val += (val << 5) + str.charCodeAt(i);
-    return val;
-}
-// #endif
-// #ifdef H5 || APP-PLUS-NVUE || MP-360
-var {
-    windowWidth,
-    platform
-} = uni.getSystemInfoSync(),
-    cfg = require('./libs/config.js');
-// #endif
-// #ifdef APP-PLUS-NVUE
-var weexDom = weex.requireModule('dom');
-// #endif
-/**
- * Parser 富文本组件
- * @tutorial https://github.com/jin-yufeng/Parser
- * @property {String} html 富文本数据
- * @property {Boolean} autopause 是否在播放一个视频时自动暂停其他视频
- * @property {Boolean} autoscroll 是否自动给所有表格添加一个滚动层
- * @property {Boolean} autosetTitle 是否自动将 title 标签中的内容设置到页面标题
- * @property {Number} compress 压缩等级
- * @property {String} domain 图片、视频等链接的主域名
- * @property {Boolean} lazyLoad 是否开启图片懒加载
- * @property {String} loadingImg 图片加载完成前的占位图
- * @property {Boolean} selectable 是否开启长按复制
- * @property {Object} tagStyle 标签的默认样式
- * @property {Boolean} showWithAnimation 是否使用渐显动画
- * @property {Boolean} useAnchor 是否使用锚点
- * @property {Boolean} useCache 是否缓存解析结果
- * @event {Function} parse 解析完成事件
- * @event {Function} load dom 加载完成事件
- * @event {Function} ready 所有图片加载完毕事件
- * @event {Function} error 错误事件
- * @event {Function} imgtap 图片点击事件
- * @event {Function} linkpress 链接点击事件
- * @author JinYufeng
- * @version 20200828
- * @listens MIT
- */
-export default {
-    name: 'parser',
-    data() {
-        return {
-            // #ifdef H5 || MP-360
-            uid: this._uid,
-            // #endif
-            // #ifdef APP-PLUS-NVUE
-            height: 1,
-            // #endif
-            // #ifndef APP-PLUS-NVUE
-            showAm: '',
-            // #endif
-            nodes: []
-        }
-    },
-    // #ifndef H5 || APP-PLUS-NVUE || MP-360
-    components: {
-        trees
-    },
-    // #endif
-    props: {
-        html: String,
-        autopause: {
-            type: Boolean,
-            default: true
-        },
-        autoscroll: Boolean,
-        autosetTitle: {
-            type: Boolean,
-            default: true
-        },
-        // #ifndef H5 || APP-PLUS-NVUE || MP-360
-        compress: Number,
-        loadingImg: String,
-        useCache: Boolean,
-        // #endif
-        domain: String,
-        lazyLoad: Boolean,
-        selectable: Boolean,
-        tagStyle: Object,
-        showWithAnimation: Boolean,
-        useAnchor: Boolean
-    },
-    watch: {
-        html(html) {
-            this.setContent(html);
-        }
-    },
-    created() {
-        // 图片数组
-        this.imgList = [];
-        this.imgList.each = function(f) {
-            for (var i = 0, len = this.length; i < len; i++)
-                this.setItem(i, f(this[i], i, this));
-        }
-        this.imgList.setItem = function(i, src) {
-            if (i == void 0 || !src) return;
-            // #ifndef MP-ALIPAY || APP-PLUS
-            // 去重
-            if (src.indexOf('http') == 0 && this.includes(src)) {
-                var newSrc = src.split('://')[0];
-                for (var j = newSrc.length, c; c = src[j]; j++) {
-                    if (c == '/' && src[j - 1] != '/' && src[j + 1] != '/') break;
-                    newSrc += Math.random() > 0.5 ? c.toUpperCase() : c;
-                }
-                newSrc += src.substr(j);
-                return this[i] = newSrc;
-            }
-            // #endif
-            this[i] = src;
-            // 暂存 data src
-            if (src.includes('data:image')) {
-                var filePath, info = src.match(/data:image\/(\S+?);(\S+?),(.+)/);
-                if (!info) return;
-                // #ifdef MP-WEIXIN || MP-TOUTIAO
-                filePath = `${wx.env.USER_DATA_PATH}/${Date.now()}.${info[1]}`;
-                fs && fs.writeFile({
-                    filePath,
-                    data: info[3],
-                    encoding: info[2],
-                    success: () => this[i] = filePath
-                })
-                // #endif
-                // #ifdef APP-PLUS
-                filePath = `_doc/parser_tmp/${Date.now()}.${info[1]}`;
-                var bitmap = new plus.nativeObj.Bitmap();
-                bitmap.loadBase64Data(src, () => {
-                    bitmap.save(filePath, {}, () => {
-                        bitmap.clear()
-                        this[i] = filePath;
-                    })
-                })
-                // #endif
-            }
-        }
-    },
-    mounted() {
-        // #ifdef H5 || MP-360
-        this.document = document.getElementById('rtf' + this._uid);
-        // #endif
-        // #ifndef H5 || APP-PLUS-NVUE || MP-360
-        if (dom) this.document = new dom(this);
-        // #endif
-        // #ifdef APP-PLUS-NVUE
-        this.document = this.$refs.web;
-        setTimeout(() => {
-            // #endif
-            if (this.html) this.setContent(this.html);
-            // #ifdef APP-PLUS-NVUE
-        }, 30)
-        // #endif
-    },
-    beforeDestroy() {
-        // #ifdef H5 || MP-360
-        if (this._observer) this._observer.disconnect();
-        // #endif
-        this.imgList.each(src => {
-            // #ifdef APP-PLUS
-            if (src && src.includes('_doc')) {
-                plus.io.resolveLocalFileSystemURL(src, entry => {
-                    entry.remove();
-                });
-            }
-            // #endif
-            // #ifdef MP-WEIXIN || MP-TOUTIAO
-            if (src && src.includes(uni.env.USER_DATA_PATH))
-                fs && fs.unlink({
-                    filePath: src
-                })
-            // #endif
-        })
-        clearInterval(this._timer);
-    },
-    methods: {
-        // 设置富文本内容
-        setContent(html, append) {
-            // #ifdef APP-PLUS-NVUE
-            if (!html)
-                return this.height = 1;
-            if (append)
-                this.$refs.web.evalJs("var b=document.createElement('div');b.innerHTML='" + html.replace(/'/g, "\\'") +
-                    "';document.getElementById('parser').appendChild(b)");
-            else {
-                html =
-                    '<meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><style>html,body{width:100%;height:100%;overflow:hidden}body{margin:0}</style><base href="' +
-                    this.domain + '"><div id="parser"' + (this.selectable ? '>' : ' style="user-select:none">') + this._handleHtml(html).replace(/\n/g, '\\n') +
-                    '</div><script>"use strict";function e(e){if(window.__dcloud_weex_postMessage||window.__dcloud_weex_){var t={data:[e]};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(t):window.__dcloud_weex_.postMessage(JSON.stringify(t))}}document.body.onclick=function(){e({action:"click"})},' +
-                    (this.showWithAnimation ? 'document.body.style.animation="_show .5s",' : '') +
-                    'setTimeout(function(){e({action:"load",text:document.body.innerText,height:document.getElementById("parser").scrollHeight})},50);\x3c/script>';
-                if (platform == 'android') html = html.replace(/%/g, '%25');
-                this.$refs.web.evalJs("document.write('" + html.replace(/'/g, "\\'") + "');document.close()");
-            }
-            this.$refs.web.evalJs(
-                'var t=document.getElementsByTagName("title");t.length&&e({action:"getTitle",title:t[0].innerText});for(var o,n=document.getElementsByTagName("style"),r=1;o=n[r++];)o.innerHTML=o.innerHTML.replace(/body/g,"#parser");for(var a,c=document.getElementsByTagName("img"),s=[],i=0==c.length,d=0,l=0,g=0;a=c[l];l++)parseInt(a.style.width||a.getAttribute("width"))>' +
-                windowWidth + '&&(a.style.height="auto"),a.onload=function(){++d==c.length&&(i=!0)},a.onerror=function(){++d==c.length&&(i=!0),' + (cfg.errorImg ? 'this.src="' + cfg.errorImg + '",' : '') +
-                'e({action:"error",source:"img",target:this})},a.hasAttribute("ignore")||"A"==a.parentElement.nodeName||(a.i=g++,s.push(a.getAttribute("original-src")||a.src||a.getAttribute("data-src")),a.onclick=function(){e({action:"preview",img:{i:this.i,src:this.src}})});e({action:"getImgList",imgList:s});for(var u,m=document.getElementsByTagName("a"),f=0;u=m[f];f++)u.onclick=function(){var t,o=this.getAttribute("href");if("#"==o[0]){var n=document.getElementById(o.substr(1));n&&(t=n.offsetTop)}return e({action:"linkpress",href:o,offset:t}),!1};for(var h,y=document.getElementsByTagName("video"),v=0;h=y[v];v++)h.style.maxWidth="100%",h.onerror=function(){e({action:"error",source:"video",target:this})}' +
-                (this.autopause ? ',h.onplay=function(){for(var e,t=0;e=y[t];t++)e!=this&&e.pause()}' : '') +
-                ';for(var _,p=document.getElementsByTagName("audio"),w=0;_=p[w];w++)_.onerror=function(){e({action:"error",source:"audio",target:this})};' +
-                (this.autoscroll ? 'for(var T,E=document.getElementsByTagName("table"),B=0;T=E[B];B++){var N=document.createElement("div");N.style.overflow="scroll",T.parentNode.replaceChild(N,T),N.appendChild(T)}' : '') +
-                'var x=document.getElementById("parser");clearInterval(window.timer),window.timer=setInterval(function(){i&&clearInterval(window.timer),e({action:"ready",ready:i,height:x.scrollHeight})},350)'
-            )
-            this.nodes = [1];
-            // #endif
-            // #ifdef H5 || MP-360
-            if (!html) {
-                if (this.rtf && !append) this.rtf.parentNode.removeChild(this.rtf);
-                return;
-            }
-            var div = document.createElement('div');
-            if (!append) {
-                if (this.rtf) this.rtf.parentNode.removeChild(this.rtf);
-                this.rtf = div;
-            } else {
-                if (!this.rtf) this.rtf = div;
-                else this.rtf.appendChild(div);
-            }
-            div.innerHTML = this._handleHtml(html, append);
-            for (var styles = this.rtf.getElementsByTagName('style'), i = 0, style; style = styles[i++];) {
-                style.innerHTML = style.innerHTML.replace(/body/g, '#rtf' + this._uid);
-                style.setAttribute('scoped', 'true');
-            }
-            // 懒加载
-            if (!this._observer && this.lazyLoad && IntersectionObserver) {
-                this._observer = new IntersectionObserver(changes => {
-                    for (let item, i = 0; item = changes[i++];) {
-                        if (item.isIntersecting) {
-                            item.target.src = item.target.getAttribute('data-src');
-                            item.target.removeAttribute('data-src');
-                            this._observer.unobserve(item.target);
-                        }
-                    }
-                }, {
-                    rootMargin: '500px 0px 500px 0px'
-                })
-            }
-            var _ts = this;
-            // 获取标题
-            var title = this.rtf.getElementsByTagName('title');
-            if (title.length && this.autosetTitle)
-                uni.setNavigationBarTitle({
-                    title: title[0].innerText
-                })
-            // 图片处理
-            this.imgList.length = 0;
-            var imgs = this.rtf.getElementsByTagName('img');
-            for (let i = 0, j = 0, img; img = imgs[i]; i++) {
-                if (parseInt(img.style.width || img.getAttribute('width')) > windowWidth)
-                    img.style.height = 'auto';
-                var src = img.getAttribute('src');
-                if (this.domain && src) {
-                    if (src[0] == '/') {
-                        if (src[1] == '/')
-                            img.src = (this.domain.includes('://') ? this.domain.split('://')[0] : '') + ':' + src;
-                        else img.src = this.domain + src;
-                    } else if (!src.includes('://')) img.src = this.domain + '/' + src;
-                }
-                if (!img.hasAttribute('ignore') && img.parentElement.nodeName != 'A') {
-                    img.i = j++;
-                    _ts.imgList.push(img.getAttribute('original-src') || img.src || img.getAttribute('data-src'));
-                    img.onclick = function() {
-                        var preview = true;
-                        this.ignore = () => preview = false;
-                        _ts.$emit('imgtap', this);
-                        if (preview) {
-                            uni.previewImage({
-                                current: this.i,
-                                urls: _ts.imgList
-                            });
-                        }
-                    }
-                }
-                img.onerror = function() {
-                    if (cfg.errorImg)
-                        _ts.imgList[this.i] = this.src = cfg.errorImg;
-                    _ts.$emit('error', {
-                        source: 'img',
-                        target: this
-                    });
-                }
-                if (_ts.lazyLoad && this._observer && img.src && img.i != 0) {
-                    img.setAttribute('data-src', img.src);
-                    img.removeAttribute('src');
-                    this._observer.observe(img);
-                }
-            }
-            // 链接处理
-            var links = this.rtf.getElementsByTagName('a');
-            for (var link of links) {
-                link.onclick = function() {
-                    var jump = true,
-                        href = this.getAttribute('href');
-                    _ts.$emit('linkpress', {
-                        href,
-                        ignore: () => jump = false
-                    });
-                    if (jump && href) {
-                        if (href[0] == '#') {
-                            if (_ts.useAnchor) {
-                                _ts.navigateTo({
-                                    id: href.substr(1)
-                                })
-                            }
-                        } else if (href.indexOf('http') == 0 || href.indexOf('//') == 0)
-                            return true;
-                        else
-                            uni.navigateTo({
-                                url: href
-                            })
-                    }
-                    return false;
-                }
-            }
-            // 视频处理
-            var videos = this.rtf.getElementsByTagName('video');
-            _ts.videoContexts = videos;
-            for (let video, i = 0; video = videos[i++];) {
-                video.style.maxWidth = '100%';
-                video.onerror = function() {
-                    _ts.$emit('error', {
-                        source: 'video',
-                        target: this
-                    });
-                }
-                video.onplay = function() {
-                    if (_ts.autopause)
-                        for (let item, i = 0; item = _ts.videoContexts[i++];)
-                            if (item != this) item.pause();
-                }
-            }
-            // 音频处理
-            var audios = this.rtf.getElementsByTagName('audio');
-            for (var audio of audios)
-                audio.onerror = function() {
-                    _ts.$emit('error', {
-                        source: 'audio',
-                        target: this
-                    });
-                }
-            // 表格处理
-            if (this.autoscroll) {
-                var tables = this.rtf.getElementsByTagName('table');
-                for (var table of tables) {
-                    let div = document.createElement('div');
-                    div.style.overflow = 'scroll';
-                    table.parentNode.replaceChild(div, table);
-                    div.appendChild(table);
-                }
-            }
-            if (!append) this.document.appendChild(this.rtf);
-            this.$nextTick(() => {
-                this.nodes = [1];
-                this.$emit('load');
-            });
-            setTimeout(() => this.showAm = '', 500);
-            // #endif
-            // #ifndef APP-PLUS-NVUE
-            // #ifndef H5 || MP-360
-            var nodes;
-            if (!html) return this.nodes = [];
-            var parser = new Parser(html, this);
-            // 缓存读取
-            if (this.useCache) {
-                var hashVal = hash(html);
-                if (cache[hashVal])
-                    nodes = cache[hashVal];
-                else {
-                    nodes = parser.parse();
-                    cache[hashVal] = nodes;
-                }
-            } else nodes = parser.parse();
-            this.$emit('parse', nodes);
-            if (append) this.nodes = this.nodes.concat(nodes);
-            else this.nodes = nodes;
-            if (nodes.length && nodes.title && this.autosetTitle)
-                uni.setNavigationBarTitle({
-                    title: nodes.title
-                })
-            if (this.imgList) this.imgList.length = 0;
-            this.videoContexts = [];
-            this.$nextTick(() => {
-                (function f(cs) {
-                    for (var i = cs.length; i--;) {
-                        if (cs[i].top) {
-                            cs[i].controls = [];
-                            cs[i].init();
-                            f(cs[i].$children);
-                        }
-                    }
-                })(this.$children)
-                this.$emit('load');
-            })
-            // #endif
-            var height;
-            clearInterval(this._timer);
-            this._timer = setInterval(() => {
-                // #ifdef H5 || MP-360
-                this.rect = this.rtf.getBoundingClientRect();
-                // #endif
-                // #ifndef H5 || MP-360
-                uni.createSelectorQuery().in(this)
-                    .select('#_top').boundingClientRect().exec(res => {
-                        if (!res) return;
-                        this.rect = res[0];
-                        // #endif
-                        if (this.rect.height == height) {
-                            this.$emit('ready', this.rect)
-                            clearInterval(this._timer);
-                        }
-                        height = this.rect.height;
-                        // #ifndef H5 || MP-360
-                    });
-                // #endif
-            }, 350);
-            if (this.showWithAnimation && !append) this.showAm = 'animation:_show .5s';
-            // #endif
-        },
-        // 获取文本内容
-        getText(ns = this.nodes) {
-            var txt = '';
-            // #ifdef APP-PLUS-NVUE
-            txt = this._text;
-            // #endif
-            // #ifdef H5 || MP-360
-            txt = this.rtf.innerText;
-            // #endif
-            // #ifndef H5 || APP-PLUS-NVUE || MP-360
-            for (var i = 0, n; n = ns[i++];) {
-                if (n.type == 'text') txt += n.text.replace(/&nbsp;/g, '\u00A0').replace(/&lt;/g, '<').replace(/&gt;/g, '>')
-                    .replace(/&amp;/g, '&');
-                else if (n.type == 'br') txt += '\n';
-                else {
-                    // 块级标签前后加换行
-                    var block = n.name == 'p' || n.name == 'div' || n.name == 'tr' || n.name == 'li' || (n.name[0] == 'h' && n.name[1] >
-                        '0' && n.name[1] < '7');
-                    if (block && txt && txt[txt.length - 1] != '\n') txt += '\n';
-                    if (n.children) txt += this.getText(n.children);
-                    if (block && txt[txt.length - 1] != '\n') txt += '\n';
-                    else if (n.name == 'td' || n.name == 'th') txt += '\t';
-                }
-            }
-            // #endif
-            return txt;
-        },
-        // 锚点跳转
-        in (obj) {
-            if (obj.page && obj.selector && obj.scrollTop) this._in = obj;
-        },
-        navigateTo(obj) {
-            if (!this.useAnchor) return obj.fail && obj.fail('Anchor is disabled');
-            // #ifdef APP-PLUS-NVUE
-            if (!obj.id)
-                weexDom.scrollToElement(this.$refs.web);
-            else
-                this.$refs.web.evalJs('var pos=document.getElementById("' + obj.id + '");if(pos)post({action:"linkpress",href:"#",offset:pos.offsetTop+' + (obj.offset || 0) + '})');
-            obj.success && obj.success();
-            // #endif
-            // #ifndef APP-PLUS-NVUE
-            var d = ' ';
-            // #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO
-            d = '>>>';
-            // #endif
-            var selector = uni.createSelectorQuery().in(this._in ? this._in.page : this).select((this._in ? this._in.selector :
-                '#_top') + (obj.id ? `${d}#${obj.id},${this._in?this._in.selector:'#_top'}${d}.${obj.id}` : '')).boundingClientRect();
-            if (this._in) selector.select(this._in.selector).scrollOffset().select(this._in.selector).boundingClientRect();
-            else selector.selectViewport().scrollOffset();
-            selector.exec(res => {
-                if (!res[0]) return obj.fail && obj.fail('Label not found')
-                var scrollTop = res[1].scrollTop + res[0].top - (res[2] ? res[2].top : 0) + (obj.offset || 0);
-                if (this._in) this._in.page[this._in.scrollTop] = scrollTop;
-                else uni.pageScrollTo({
-                    scrollTop,
-                    duration: 300
-                })
-                obj.success && obj.success();
-            })
-            // #endif
-        },
-        // 获取视频对象
-        getVideoContext(id) {
-            // #ifndef APP-PLUS-NVUE
-            if (!id) return this.videoContexts;
-            else
-                for (var i = this.videoContexts.length; i--;)
-                    if (this.videoContexts[i].id == id) return this.videoContexts[i];
-            // #endif
-        },
-        // #ifdef H5 || APP-PLUS-NVUE || MP-360
-        _handleHtml(html, append) {
-            if (!append) {
-                // 处理 tag-style 和 userAgentStyles
-                var style = '<style>@keyframes _show{0%{opacity:0}100%{opacity:1}}img{max-width:100%}';
-                for (var item in cfg.userAgentStyles)
-                    style += `${item}{${cfg.userAgentStyles[item]}}`;
-                for (item in this.tagStyle)
-                    style += `${item}{${this.tagStyle[item]}}`;
-                style += '</style>';
-                html = style + html;
-            }
-            // 处理 rpx
-            if (html.includes('rpx'))
-                html = html.replace(/[0-9.]+\s*rpx/g, $ => (parseFloat($) * windowWidth / 750) + 'px');
-            return html;
-        },
-        // #endif
-        // #ifdef APP-PLUS-NVUE
-        _message(e) {
-            // 接收 web-view 消息
-            var d = e.detail.data[0];
-            switch (d.action) {
-                case 'load':
-                    this.$emit('load');
-                    this.height = d.height;
-                    this._text = d.text;
-                    break;
-                case 'getTitle':
-                    if (this.autosetTitle)
-                        uni.setNavigationBarTitle({
-                            title: d.title
-                        })
-                    break;
-                case 'getImgList':
-                    this.imgList.length = 0;
-                    for (var i = d.imgList.length; i--;)
-                        this.imgList.setItem(i, d.imgList[i]);
-                    break;
-                case 'preview':
-                    var preview = true;
-                    d.img.ignore = () => preview = false;
-                    this.$emit('imgtap', d.img);
-                    if (preview)
-                        uni.previewImage({
-                            current: d.img.i,
-                            urls: this.imgList
-                        })
-                    break;
-                case 'linkpress':
-                    var jump = true,
-                        href = d.href;
-                    this.$emit('linkpress', {
-                        href,
-                        ignore: () => jump = false
-                    })
-                    if (jump && href) {
-                        if (href[0] == '#') {
-                            if (this.useAnchor)
-                                weexDom.scrollToElement(this.$refs.web, {
-                                    offset: d.offset
-                                })
-                        } else if (href.includes('://'))
-                            plus.runtime.openWeb(href);
-                        else
-                            uni.navigateTo({
-                                url: href
-                            })
-                    }
-                    break;
-                case 'error':
-                    if (d.source == 'img' && cfg.errorImg)
-                        this.imgList.setItem(d.target.i, cfg.errorImg);
-                    this.$emit('error', {
-                        source: d.source,
-                        target: d.target
-                    })
-                    break;
-                case 'ready':
-                    this.height = d.height;
-                    if (d.ready) uni.createSelectorQuery().in(this).select('#_top').boundingClientRect().exec(res => {
-                        this.rect = res[0];
-                        this.$emit('ready', res[0]);
-                    })
-                    break;
-                case 'click':
-                    this.$emit('click');
-                    this.$emit('tap');
-            }
-        },
-        // #endif
-    }
-}
-</script>
-<style>
-@keyframes _show {
-    0% {
-        opacity: 0;
-    }
-
-    100% {
-        opacity: 1;
-    }
-}
-
-/* #ifdef MP-WEIXIN */
-:host {
-    display: block;
-    overflow: scroll;
-    -webkit-overflow-scrolling: touch;
-}
-
-/* #endif */
-</style>

+ 0 - 97
src/components/jyf-parser/libs/CssHandler.js

@@ -1,97 +0,0 @@
-const cfg = require('./config.js'),
-	isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
-
-function CssHandler(tagStyle) {
-	var styles = Object.assign(Object.create(null), cfg.userAgentStyles);
-	for (var item in tagStyle)
-		styles[item] = (styles[item] ? styles[item] + ';' : '') + tagStyle[item];
-	this.styles = styles;
-}
-CssHandler.prototype.getStyle = function(data) {
-	this.styles = new parser(data, this.styles).parse();
-}
-CssHandler.prototype.match = function(name, attrs) {
-	var tmp, matched = (tmp = this.styles[name]) ? tmp + ';' : '';
-	if (attrs.class) {
-		var items = attrs.class.split(' ');
-		for (var i = 0, item; item = items[i]; i++)
-			if (tmp = this.styles['.' + item])
-				matched += tmp + ';';
-	}
-	if (tmp = this.styles['#' + attrs.id])
-		matched += tmp + ';';
-	return matched;
-}
-module.exports = CssHandler;
-
-function parser(data, init) {
-	this.data = data;
-	this.floor = 0;
-	this.i = 0;
-	this.list = [];
-	this.res = init;
-	this.state = this.Space;
-}
-parser.prototype.parse = function() {
-	for (var c; c = this.data[this.i]; this.i++)
-		this.state(c);
-	return this.res;
-}
-parser.prototype.section = function() {
-	return this.data.substring(this.start, this.i);
-}
-// 状态机
-parser.prototype.Space = function(c) {
-	if (c == '.' || c == '#' || isLetter(c)) {
-		this.start = this.i;
-		this.state = this.Name;
-	} else if (c == '/' && this.data[this.i + 1] == '*')
-		this.Comment();
-	else if (!cfg.blankChar[c] && c != ';')
-		this.state = this.Ignore;
-}
-parser.prototype.Comment = function() {
-	this.i = this.data.indexOf('*/', this.i) + 1;
-	if (!this.i) this.i = this.data.length;
-	this.state = this.Space;
-}
-parser.prototype.Ignore = function(c) {
-	if (c == '{') this.floor++;
-	else if (c == '}' && !--this.floor) this.state = this.Space;
-}
-parser.prototype.Name = function(c) {
-	if (cfg.blankChar[c]) {
-		this.list.push(this.section());
-		this.state = this.NameSpace;
-	} else if (c == '{') {
-		this.list.push(this.section());
-		this.Content();
-	} else if (c == ',') {
-		this.list.push(this.section());
-		this.Comma();
-	} else if (!isLetter(c) && (c < '0' || c > '9') && c != '-' && c != '_')
-		this.state = this.Ignore;
-}
-parser.prototype.NameSpace = function(c) {
-	if (c == '{') this.Content();
-	else if (c == ',') this.Comma();
-	else if (!cfg.blankChar[c]) this.state = this.Ignore;
-}
-parser.prototype.Comma = function() {
-	while (cfg.blankChar[this.data[++this.i]]);
-	if (this.data[this.i] == '{') this.Content();
-	else {
-		this.start = this.i--;
-		this.state = this.Name;
-	}
-}
-parser.prototype.Content = function() {
-	this.start = ++this.i;
-	if ((this.i = this.data.indexOf('}', this.i)) == -1) this.i = this.data.length;
-	var content = this.section();
-	for (var i = 0, item; item = this.list[i++];)
-		if (this.res[item]) this.res[item] += ';' + content;
-		else this.res[item] = content;
-	this.list = [];
-	this.state = this.Space;
-}

+ 0 - 535
src/components/jyf-parser/libs/MpHtmlParser.js

@@ -1,535 +0,0 @@
-/**
- * html 解析器
- * @tutorial https://github.com/jin-yufeng/Parser
- * @version 20200828
- * @author JinYufeng
- * @listens MIT
- */
-const cfg = require('./config.js'),
-	blankChar = cfg.blankChar,
-	CssHandler = require('./CssHandler.js'),
-	windowWidth = uni.getSystemInfoSync().windowWidth;
-var emoji;
-
-function MpHtmlParser(data, options = {}) {
-	this.attrs = {};
-	this.CssHandler = new CssHandler(options.tagStyle, windowWidth);
-	this.data = data;
-	this.domain = options.domain;
-	this.DOM = [];
-	this.i = this.start = this.audioNum = this.imgNum = this.videoNum = 0;
-	options.prot = (this.domain || '').includes('://') ? this.domain.split('://')[0] : 'http';
-	this.options = options;
-	this.state = this.Text;
-	this.STACK = [];
-	// 工具函数
-	this.bubble = () => {
-		for (var i = this.STACK.length, item; item = this.STACK[--i];) {
-			if (cfg.richOnlyTags[item.name]) {
-				if (item.name == 'table' && !Object.hasOwnProperty.call(item, 'c')) item.c = 1;
-				return false;
-			}
-			item.c = 1;
-		}
-		return true;
-	}
-	this.decode = (val, amp) => {
-		var i = -1,
-			j, en;
-		while (1) {
-			if ((i = val.indexOf('&', i + 1)) == -1) break;
-			if ((j = val.indexOf(';', i + 2)) == -1) break;
-			if (val[i + 1] == '#') {
-				en = parseInt((val[i + 2] == 'x' ? '0' : '') + val.substring(i + 2, j));
-				if (!isNaN(en)) val = val.substr(0, i) + String.fromCharCode(en) + val.substr(j + 1);
-			} else {
-				en = val.substring(i + 1, j);
-				if (cfg.entities[en] || en == amp)
-					val = val.substr(0, i) + (cfg.entities[en] || '&') + val.substr(j + 1);
-			}
-		}
-		return val;
-	}
-	this.getUrl = url => {
-		if (url[0] == '/') {
-			if (url[1] == '/') url = this.options.prot + ':' + url;
-			else if (this.domain) url = this.domain + url;
-		} else if (this.domain && url.indexOf('data:') != 0 && !url.includes('://'))
-			url = this.domain + '/' + url;
-		return url;
-	}
-	this.isClose = () => this.data[this.i] == '>' || (this.data[this.i] == '/' && this.data[this.i + 1] == '>');
-	this.section = () => this.data.substring(this.start, this.i);
-	this.parent = () => this.STACK[this.STACK.length - 1];
-	this.siblings = () => this.STACK.length ? this.parent().children : this.DOM;
-}
-MpHtmlParser.prototype.parse = function() {
-	if (emoji) this.data = emoji.parseEmoji(this.data);
-	for (var c; c = this.data[this.i]; this.i++)
-		this.state(c);
-	if (this.state == this.Text) this.setText();
-	while (this.STACK.length) this.popNode(this.STACK.pop());
-	return this.DOM;
-}
-// 设置属性
-MpHtmlParser.prototype.setAttr = function() {
-	var name = this.attrName.toLowerCase(),
-		val = this.attrVal;
-	if (cfg.boolAttrs[name]) this.attrs[name] = 'T';
-	else if (val) {
-		if (name == 'src' || (name == 'data-src' && !this.attrs.src)) this.attrs.src = this.getUrl(this.decode(val, 'amp'));
-		else if (name == 'href' || name == 'style') this.attrs[name] = this.decode(val, 'amp');
-		else if (name.substr(0, 5) != 'data-') this.attrs[name] = val;
-	}
-	this.attrVal = '';
-	while (blankChar[this.data[this.i]]) this.i++;
-	if (this.isClose()) this.setNode();
-	else {
-		this.start = this.i;
-		this.state = this.AttrName;
-	}
-}
-// 设置文本节点
-MpHtmlParser.prototype.setText = function() {
-	var back, text = this.section();
-	if (!text) return;
-	text = (cfg.onText && cfg.onText(text, () => back = true)) || text;
-	if (back) {
-		this.data = this.data.substr(0, this.start) + text + this.data.substr(this.i);
-		let j = this.start + text.length;
-		for (this.i = this.start; this.i < j; this.i++) this.state(this.data[this.i]);
-		return;
-	}
-	if (!this.pre) {
-		// 合并空白符
-		var flag, tmp = [];
-		for (let i = text.length, c; c = text[--i];)
-			if (!blankChar[c]) {
-				tmp.unshift(c);
-				if (!flag) flag = 1;
-			} else {
-				if (tmp[0] != ' ') tmp.unshift(' ');
-				if (c == '\n' && flag == void 0) flag = 0;
-			}
-		if (flag == 0) return;
-		text = tmp.join('');
-	}
-	this.siblings().push({
-		type: 'text',
-		text: this.decode(text)
-	});
-}
-// 设置元素节点
-MpHtmlParser.prototype.setNode = function() {
-	var node = {
-			name: this.tagName.toLowerCase(),
-			attrs: this.attrs
-		},
-		close = cfg.selfClosingTags[node.name];
-	if (this.options.nodes.length) node.type = 'node';
-	this.attrs = {};
-	if (!cfg.ignoreTags[node.name]) {
-		// 处理属性
-		var attrs = node.attrs,
-			style = this.CssHandler.match(node.name, attrs, node) + (attrs.style || ''),
-			styleObj = {};
-		if (attrs.id) {
-			if (this.options.compress & 1) attrs.id = void 0;
-			else if (this.options.useAnchor) this.bubble();
-		}
-		if ((this.options.compress & 2) && attrs.class) attrs.class = void 0;
-		switch (node.name) {
-			case 'a':
-			case 'ad': // #ifdef APP-PLUS
-			case 'iframe':
-				// #endif
-				this.bubble();
-				break;
-			case 'font':
-				if (attrs.color) {
-					styleObj['color'] = attrs.color;
-					attrs.color = void 0;
-				}
-				if (attrs.face) {
-					styleObj['font-family'] = attrs.face;
-					attrs.face = void 0;
-				}
-				if (attrs.size) {
-					var size = parseInt(attrs.size);
-					if (size < 1) size = 1;
-					else if (size > 7) size = 7;
-					var map = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'];
-					styleObj['font-size'] = map[size - 1];
-					attrs.size = void 0;
-				}
-				break;
-			case 'embed':
-				// #ifndef APP-PLUS
-				var src = node.attrs.src || '',
-					type = node.attrs.type || '';
-				if (type.includes('video') || src.includes('.mp4') || src.includes('.3gp') || src.includes('.m3u8'))
-					node.name = 'video';
-				else if (type.includes('audio') || src.includes('.m4a') || src.includes('.wav') || src.includes('.mp3') || src.includes(
-						'.aac'))
-					node.name = 'audio';
-				else break;
-				if (node.attrs.autostart)
-					node.attrs.autoplay = 'T';
-				node.attrs.controls = 'T';
-				// #endif
-				// #ifdef APP-PLUS
-				this.bubble();
-				break;
-				// #endif
-			case 'video':
-			case 'audio':
-				if (!attrs.id) attrs.id = node.name + (++this[`${node.name}Num`]);
-				else this[`${node.name}Num`]++;
-				if (node.name == 'video') {
-					if (this.videoNum > 3)
-						node.lazyLoad = 1;
-					if (attrs.width) {
-						styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px');
-						attrs.width = void 0;
-					}
-					if (attrs.height) {
-						styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px');
-						attrs.height = void 0;
-					}
-				}
-				if (!attrs.controls && !attrs.autoplay) attrs.controls = 'T';
-				attrs.source = [];
-				if (attrs.src) {
-					attrs.source.push(attrs.src);
-					attrs.src = void 0;
-				}
-				this.bubble();
-				break;
-			case 'td':
-			case 'th':
-				if (attrs.colspan || attrs.rowspan)
-					for (var k = this.STACK.length, item; item = this.STACK[--k];)
-						if (item.name == 'table') {
-							item.c = void 0;
-							break;
-						}
-		}
-		if (attrs.align) {
-			styleObj['text-align'] = attrs.align;
-			attrs.align = void 0;
-		}
-		// 压缩 style
-		var styles = style.split(';');
-		style = '';
-		for (var i = 0, len = styles.length; i < len; i++) {
-			var info = styles[i].split(':');
-			if (info.length < 2) continue;
-			let key = info[0].trim().toLowerCase(),
-				value = info.slice(1).join(':').trim();
-			if (value[0] == '-' || value.includes('safe'))
-				style += `;${key}:${value}`;
-			else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import'))
-				styleObj[key] = value;
-		}
-		if (node.name == 'img') {
-			if (attrs.src && !attrs.ignore) {
-				if (this.bubble())
-					attrs.i = (this.imgNum++).toString();
-				else attrs.ignore = 'T';
-			}
-			if (attrs.ignore) {
-				style += ';-webkit-touch-callout:none';
-				styleObj['max-width'] = '100%';
-			}
-			var width;
-			if (styleObj.width) width = styleObj.width;
-			else if (attrs.width) width = attrs.width.includes('%') ? attrs.width : parseFloat(attrs.width) + 'px';
-			if (width) {
-				styleObj.width = width;
-				attrs.width = '100%';
-				if (parseInt(width) > windowWidth) {
-					styleObj.height = '';
-					if (attrs.height) attrs.height = void 0;
-				}
-			}
-			if (styleObj.height) {
-				attrs.height = styleObj.height;
-				styleObj.height = '';
-			} else if (attrs.height && !attrs.height.includes('%'))
-				attrs.height = parseFloat(attrs.height) + 'px';
-		}
-		for (var key in styleObj) {
-			var value = styleObj[key];
-			if (!value) continue;
-			if (key.includes('flex') || key == 'order' || key == 'self-align') node.c = 1;
-			// 填充链接
-			if (value.includes('url')) {
-				var j = value.indexOf('(');
-				if (j++ != -1) {
-					while (value[j] == '"' || value[j] == "'" || blankChar[value[j]]) j++;
-					value = value.substr(0, j) + this.getUrl(value.substr(j));
-				}
-			}
-			// 转换 rpx
-			else if (value.includes('rpx'))
-				value = value.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * windowWidth / 750 + 'px');
-			else if (key == 'white-space' && value.includes('pre') && !close)
-				this.pre = node.pre = true;
-			style += `;${key}:${value}`;
-		}
-		style = style.substr(1);
-		if (style) attrs.style = style;
-		if (!close) {
-			node.children = [];
-			if (node.name == 'pre' && cfg.highlight) {
-				this.remove(node);
-				this.pre = node.pre = true;
-			}
-			this.siblings().push(node);
-			this.STACK.push(node);
-		} else if (!cfg.filter || cfg.filter(node, this) != false)
-			this.siblings().push(node);
-	} else {
-		if (!close) this.remove(node);
-		else if (node.name == 'source') {
-			var parent = this.parent();
-			if (parent && (parent.name == 'video' || parent.name == 'audio') && node.attrs.src)
-				parent.attrs.source.push(node.attrs.src);
-		} else if (node.name == 'base' && !this.domain) this.domain = node.attrs.href;
-	}
-	if (this.data[this.i] == '/') this.i++;
-	this.start = this.i + 1;
-	this.state = this.Text;
-}
-// 移除标签
-MpHtmlParser.prototype.remove = function(node) {
-	var name = node.name,
-		j = this.i;
-	// 处理 svg
-	var handleSvg = () => {
-		var src = this.data.substring(j, this.i + 1);
-		if (!node.attrs.xmlns) src = ' xmlns="http://www.w3.org/2000/svg"' + src;
-		var i = j;
-		while (this.data[j] != '<') j--;
-		src = this.data.substring(j, i).replace("viewbox", "viewBox") + src;
-		var parent = this.parent();
-		if (node.attrs.width == '100%' && parent && (parent.attrs.style || '').includes('inline'))
-			parent.attrs.style = 'width:300px;max-width:100%;' + parent.attrs.style;
-		this.siblings().push({
-			name: 'img',
-			attrs: {
-				src: 'data:image/svg+xml;utf8,' + src.replace(/#/g, '%23'),
-				style: (/vertical[^;]+/.exec(node.attrs.style) || []).shift(),
-				ignore: 'T'
-			}
-		})
-	}
-	if (node.name == 'svg' && this.data[j] == '/') return handleSvg(this.i++);
-	while (1) {
-		if ((this.i = this.data.indexOf('</', this.i + 1)) == -1) {
-			if (name == 'pre' || name == 'svg') this.i = j;
-			else this.i = this.data.length;
-			return;
-		}
-		this.start = (this.i += 2);
-		while (!blankChar[this.data[this.i]] && !this.isClose()) this.i++;
-		if (this.section().toLowerCase() == name) {
-			// 代码块高亮
-			if (name == 'pre') {
-				this.data = this.data.substr(0, j + 1) + cfg.highlight(this.data.substring(j + 1, this.i - 5), node.attrs) + this.data
-					.substr(this.i - 5);
-				return this.i = j;
-			} else if (name == 'style')
-				this.CssHandler.getStyle(this.data.substring(j + 1, this.i - 7));
-			else if (name == 'title')
-				this.DOM.title = this.data.substring(j + 1, this.i - 7);
-			if ((this.i = this.data.indexOf('>', this.i)) == -1) this.i = this.data.length;
-			if (name == 'svg') handleSvg();
-			return;
-		}
-	}
-}
-// 节点出栈处理
-MpHtmlParser.prototype.popNode = function(node) {
-	// 空白符处理
-	if (node.pre) {
-		node.pre = this.pre = void 0;
-		for (let i = this.STACK.length; i--;)
-			if (this.STACK[i].pre)
-				this.pre = true;
-	}
-	var siblings = this.siblings(),
-		len = siblings.length,
-		childs = node.children;
-	if (node.name == 'head' || (cfg.filter && cfg.filter(node, this) == false))
-		return siblings.pop();
-	var attrs = node.attrs;
-	// 替换一些标签名
-	if (cfg.blockTags[node.name]) node.name = 'div';
-	else if (!cfg.trustTags[node.name]) node.name = 'span';
-	// 处理列表
-	if (node.c && (node.name == 'ul' || node.name == 'ol')) {
-		if ((node.attrs.style || '').includes('list-style:none')) {
-			for (let i = 0, child; child = childs[i++];)
-				if (child.name == 'li')
-					child.name = 'div';
-		} else if (node.name == 'ul') {
-			var floor = 1;
-			for (let i = this.STACK.length; i--;)
-				if (this.STACK[i].name == 'ul') floor++;
-			if (floor != 1)
-				for (let i = childs.length; i--;)
-					childs[i].floor = floor;
-		} else {
-			for (let i = 0, num = 1, child; child = childs[i++];)
-				if (child.name == 'li') {
-					child.type = 'ol';
-					child.num = ((num, type) => {
-						if (type == 'a') return String.fromCharCode(97 + (num - 1) % 26);
-						if (type == 'A') return String.fromCharCode(65 + (num - 1) % 26);
-						if (type == 'i' || type == 'I') {
-							num = (num - 1) % 99 + 1;
-							var one = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'],
-								ten = ['X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'],
-								res = (ten[Math.floor(num / 10) - 1] || '') + (one[num % 10 - 1] || '');
-							if (type == 'i') return res.toLowerCase();
-							return res;
-						}
-						return num;
-					})(num++, attrs.type) + '.';
-				}
-		}
-	}
-	// 处理表格的边框
-	if (node.name == 'table') {
-		var padding = attrs.cellpadding,
-			spacing = attrs.cellspacing,
-			border = attrs.border;
-		if (node.c) {
-			this.bubble();
-			attrs.style = (attrs.style || '') + ';display:table';
-			if (!padding) padding = 2;
-			if (!spacing) spacing = 2;
-		}
-		if (border) attrs.style = `border:${border}px solid gray;${attrs.style || ''}`;
-		if (spacing) attrs.style = `border-spacing:${spacing}px;${attrs.style || ''}`;
-		if (border || padding || node.c)
-			(function f(ns) {
-				for (var i = 0, n; n = ns[i]; i++) {
-					if (n.type == 'text') continue;
-					var style = n.attrs.style || '';
-					if (node.c && n.name[0] == 't') {
-						n.c = 1;
-						style += ';display:table-' + (n.name == 'th' || n.name == 'td' ? 'cell' : (n.name == 'tr' ? 'row' : 'row-group'));
-					}
-					if (n.name == 'th' || n.name == 'td') {
-						if (border) style = `border:${border}px solid gray;${style}`;
-						if (padding) style = `padding:${padding}px;${style}`;
-					} else f(n.children || []);
-					if (style) n.attrs.style = style;
-				}
-			})(childs)
-		if (this.options.autoscroll) {
-			var table = Object.assign({}, node);
-			node.name = 'div';
-			node.attrs = {
-				style: 'overflow:scroll'
-			}
-			node.children = [table];
-		}
-	}
-	this.CssHandler.pop && this.CssHandler.pop(node);
-	// 自动压缩
-	if (node.name == 'div' && !Object.keys(attrs).length && childs.length == 1 && childs[0].name == 'div')
-		siblings[len - 1] = childs[0];
-}
-// 状态机
-MpHtmlParser.prototype.Text = function(c) {
-	if (c == '<') {
-		var next = this.data[this.i + 1],
-			isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
-		if (isLetter(next)) {
-			this.setText();
-			this.start = this.i + 1;
-			this.state = this.TagName;
-		} else if (next == '/') {
-			this.setText();
-			if (isLetter(this.data[++this.i + 1])) {
-				this.start = this.i + 1;
-				this.state = this.EndTag;
-			} else this.Comment();
-		} else if (next == '!' || next == '?') {
-			this.setText();
-			this.Comment();
-		}
-	}
-}
-MpHtmlParser.prototype.Comment = function() {
-	var key;
-	if (this.data.substring(this.i + 2, this.i + 4) == '--') key = '-->';
-	else if (this.data.substring(this.i + 2, this.i + 9) == '[CDATA[') key = ']]>';
-	else key = '>';
-	if ((this.i = this.data.indexOf(key, this.i + 2)) == -1) this.i = this.data.length;
-	else this.i += key.length - 1;
-	this.start = this.i + 1;
-	this.state = this.Text;
-}
-MpHtmlParser.prototype.TagName = function(c) {
-	if (blankChar[c]) {
-		this.tagName = this.section();
-		while (blankChar[this.data[this.i]]) this.i++;
-		if (this.isClose()) this.setNode();
-		else {
-			this.start = this.i;
-			this.state = this.AttrName;
-		}
-	} else if (this.isClose()) {
-		this.tagName = this.section();
-		this.setNode();
-	}
-}
-MpHtmlParser.prototype.AttrName = function(c) {
-	if (c == '=' || blankChar[c] || this.isClose()) {
-		this.attrName = this.section();
-		if (blankChar[c])
-			while (blankChar[this.data[++this.i]]);
-		if (this.data[this.i] == '=') {
-			while (blankChar[this.data[++this.i]]);
-			this.start = this.i--;
-			this.state = this.AttrValue;
-		} else this.setAttr();
-	}
-}
-MpHtmlParser.prototype.AttrValue = function(c) {
-	if (c == '"' || c == "'") {
-		this.start++;
-		if ((this.i = this.data.indexOf(c, this.i + 1)) == -1) return this.i = this.data.length;
-		this.attrVal = this.section();
-		this.i++;
-	} else {
-		for (; !blankChar[this.data[this.i]] && !this.isClose(); this.i++);
-		this.attrVal = this.section();
-	}
-	this.setAttr();
-}
-MpHtmlParser.prototype.EndTag = function(c) {
-	if (blankChar[c] || c == '>' || c == '/') {
-		var name = this.section().toLowerCase();
-		for (var i = this.STACK.length; i--;)
-			if (this.STACK[i].name == name) break;
-		if (i != -1) {
-			var node;
-			while ((node = this.STACK.pop()).name != name) this.popNode(node);
-			this.popNode(node);
-		} else if (name == 'p' || name == 'br')
-			this.siblings().push({
-				name,
-				attrs: {}
-			});
-		this.i = this.data.indexOf('>', this.i);
-		this.start = this.i + 1;
-		if (this.i == -1) this.i = this.data.length;
-		else this.state = this.Text;
-	}
-}
-module.exports = MpHtmlParser;

+ 0 - 80
src/components/jyf-parser/libs/config.js

@@ -1,80 +0,0 @@
-/* 配置文件 */
-var cfg = {
-	// 出错占位图
-	errorImg: null,
-	// 过滤器函数
-	filter: null,
-	// 代码高亮函数
-	highlight: null,
-	// 文本处理函数
-	onText: null,
-	// 实体编码列表
-	entities: {
-		quot: '"',
-		apos: "'",
-		semi: ';',
-		nbsp: '\xA0',
-		ensp: '\u2002',
-		emsp: '\u2003',
-		ndash: '–',
-		mdash: '—',
-		middot: '·',
-		lsquo: '‘',
-		rsquo: '’',
-		ldquo: '“',
-		rdquo: '”',
-		bull: '•',
-		hellip: '…'
-	},
-	blankChar: makeMap(' ,\xA0,\t,\r,\n,\f'),
-	boolAttrs: makeMap('allowfullscreen,autoplay,autostart,controls,ignore,loop,muted'),
-	// 块级标签,将被转为 div
-	blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,pre,section'),
-	// 将被移除的标签
-	ignoreTags: makeMap('area,base,canvas,frame,iframe,input,link,map,meta,param,script,source,style,svg,textarea,title,track,wbr'),
-	// 只能被 rich-text 显示的标签
-	richOnlyTags: makeMap('a,colgroup,fieldset,legend,table'),
-	// 自闭合的标签
-	selfClosingTags: makeMap('area,base,br,col,circle,ellipse,embed,frame,hr,img,input,line,link,meta,param,path,polygon,rect,source,track,use,wbr'),
-	// 信任的标签
-	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,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video'),
-	// 默认的标签样式
-	userAgentStyles: {
-		address: 'font-style:italic',
-		big: 'display:inline;font-size:1.2em',
-		blockquote: 'background-color:#f6f6f6;border-left:3px solid #dbdbdb;color:#6c6c6c;padding:5px 0 5px 10px',
-		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;overflow:scroll',
-		s: 'text-decoration:line-through',
-		small: 'display:inline;font-size:0.8em',
-		u: 'text-decoration:underline'
-	}
-}
-
-function makeMap(str) {
-	var map = Object.create(null),
-		list = str.split(',');
-	for (var i = list.length; i--;)
-		map[list[i]] = true;
-	return map;
-}
-
-// #ifdef MP-WEIXIN
-if (wx.canIUse('editor')) {
-	cfg.blockTags.pre = void 0;
-	cfg.ignoreTags.rp = true;
-	Object.assign(cfg.richOnlyTags, makeMap('bdi,bdo,caption,rt,ruby'));
-	Object.assign(cfg.trustTags, makeMap('bdi,bdo,caption,pre,rt,ruby'));
-}
-// #endif
-
-// #ifdef APP-PLUS
-cfg.ignoreTags.iframe = void 0;
-Object.assign(cfg.trustTags, makeMap('embed,iframe'));
-// #endif
-
-module.exports = cfg;

+ 0 - 22
src/components/jyf-parser/libs/handler.wxs

@@ -1,22 +0,0 @@
-var inline = {
-	abbr: 1,
-	b: 1,
-	big: 1,
-	code: 1,
-	del: 1,
-	em: 1,
-	i: 1,
-	ins: 1,
-	label: 1,
-	q: 1,
-	small: 1,
-	span: 1,
-	strong: 1,
-	sub: 1,
-	sup: 1
-}
-module.exports = {
-	use: function(item) {
-		return !item.c && !inline[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1
-	}
-}

+ 0 - 501
src/components/jyf-parser/libs/trees.vue

@@ -1,501 +0,0 @@
-<template>
-	<view :class="'interlayer '+(c||'')" :style="s">
-		<block v-for="(n, i) in nodes" v-bind:key="i">
-			<!--图片-->
-			<view v-if="n.name=='img'" :class="'_img '+n.attrs.class" :style="n.attrs.style" :data-attrs="n.attrs" @tap="imgtap">
-				<rich-text v-if="ctrl[i]!=0" :nodes="[{attrs:{src:loading&&(ctrl[i]||0)<2?loading:(lazyLoad&&!ctrl[i]?placeholder:(ctrl[i]==3?errorImg:n.attrs.src||'')),alt:n.attrs.alt||'',width:n.attrs.width||'',style:'-webkit-touch-callout:none;max-width:100%;display:block'+(n.attrs.height?';height:'+n.attrs.height:'')},name:'img'}]" />
-				<image class="_image" :src="lazyLoad&&!ctrl[i]?placeholder:n.attrs.src" :lazy-load="lazyLoad"
-				 :show-menu-by-longpress="!n.attrs.ignore" :data-i="i" :data-index="n.attrs.i" data-source="img" @load="loadImg"
-				 @error="error" />
-			</view>
-			<!--文本-->
-			<text v-else-if="n.type=='text'" decode>{{n.text}}</text>
-			<!--#ifndef MP-BAIDU-->
-			<text v-else-if="n.name=='br'">\n</text>
-			<!--#endif-->
-			<!--视频-->
-			<view v-else-if="((n.lazyLoad&&!n.attrs.autoplay)||(n.name=='video'&&!loadVideo))&&ctrl[i]==undefined" :id="n.attrs.id" :class="'_video '+(n.attrs.class||'')"
-			 :style="n.attrs.style" :data-i="i" @tap="_loadVideo" />
-			<video v-else-if="n.name=='video'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :autoplay="n.attrs.autoplay||ctrl[i]==0"
-			 :controls="n.attrs.controls" :loop="n.attrs.loop" :muted="n.attrs.muted" :poster="n.attrs.poster" :src="n.attrs.source[ctrl[i]||0]"
-			 :unit-id="n.attrs['unit-id']" :data-id="n.attrs.id" :data-i="i" data-source="video" @error="error" @play="play" />
-			<!--音频-->
-			<audio v-else-if="n.name=='audio'" :ref="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :author="n.attrs.author"
-			 :autoplay="n.attrs.autoplay" :controls="n.attrs.controls" :loop="n.attrs.loop" :name="n.attrs.name" :poster="n.attrs.poster"
-			 :src="n.attrs.source[ctrl[i]||0]" :data-i="i" :data-id="n.attrs.id" data-source="audio"
-			 @error.native="error" @play.native="play" />
-			<!--链接-->
-			<view v-else-if="n.name=='a'" :id="n.attrs.id" :class="'_a '+(n.attrs.class||'')" hover-class="_hover" :style="n.attrs.style"
-			 :data-attrs="n.attrs" @tap="linkpress">
-				<trees class="_span" c="_span" :nodes="n.children" />
-			</view>
-			<!--广告-->
-			<!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :unit-id="n.attrs['unit-id']" :appid="n.attrs.appid" :apid="n.attrs.apid" :type="n.attrs.type" :adpid="n.attrs.adpid" data-source="ad" @error="error" />-->
-			<!--列表-->
-			<view v-else-if="n.name=='li'" :id="n.attrs.id" :class="n.attrs.class" :style="(n.attrs.style||'')+';display:flex;flex-direction:row'">
-				<view v-if="n.type=='ol'" class="_ol-bef">{{n.num}}</view>
-				<view v-else class="_ul-bef">
-					<view v-if="n.floor%3==0" class="_ul-p1">█</view>
-					<view v-else-if="n.floor%3==2" class="_ul-p2" />
-					<view v-else class="_ul-p1" style="border-radius:50%">█</view>
-				</view>
-				<trees class="_li" c="_li" :nodes="n.children" :lazyLoad="lazyLoad" :loading="loading" />
-			</view>
-			<!--表格-->
-			<view v-else-if="n.name=='table'&&n.c" :id="n.attrs.id" :class="n.attrs.class" :style="(n.attrs.style||'')+';display:table'">
-				<view v-for="(tbody, o) in n.children" v-bind:key="o" :class="tbody.attrs.class" :style="(tbody.attrs.style||'')+(tbody.name[0]=='t'?';display:table-'+(tbody.name=='tr'?'row':'row-group'):'')">
-					<view v-for="(tr, p) in tbody.children" v-bind:key="p" :class="tr.attrs.class" :style="(tr.attrs.style||'')+(tr.name[0]=='t'?';display:table-'+(tr.name=='tr'?'row':'cell'):'')">
-						<trees v-if="tr.name=='td'" :nodes="tr.children" />
-						<trees v-else v-for="(td, q) in tr.children" v-bind:key="q" :class="td.attrs.class" :c="td.attrs.class" :style="(td.attrs.style||'')+(td.name[0]=='t'?';display:table-'+(td.name=='tr'?'row':'cell'):'')"
-						 :s="(td.attrs.style||'')+(td.name[0]=='t'?';display:table-'+(td.name=='tr'?'row':'cell'):'')" :nodes="td.children" />
-					</view>
-				</view>
-			</view>
-			<!--#ifdef APP-PLUS-->
-			<iframe v-else-if="n.name=='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen" :frameborder="n.attrs.frameborder"
-			 :width="n.attrs.width" :height="n.attrs.height" :src="n.attrs.src" />
-			<embed v-else-if="n.name=='embed'" :style="n.attrs.style" :width="n.attrs.width" :height="n.attrs.height" :src="n.attrs.src" />
-			<!--#endif-->
-			<!--富文本-->
-			<!--#ifdef MP-WEIXIN || MP-QQ || APP-PLUS-->
-			<rich-text v-else-if="handler.use(n)" :id="n.attrs.id" :class="'_p __'+n.name" :nodes="[n]" />
-			<!--#endif-->
-			<!--#ifndef MP-WEIXIN || MP-QQ || APP-PLUS-->
-			<rich-text v-else-if="!n.c" :id="n.attrs.id" :nodes="[n]" style="display:inline" />
-			<!--#endif-->
-			<trees v-else :class="(n.attrs.id||'')+' _'+n.name+' '+(n.attrs.class||'')" :c="(n.attrs.id||'')+' _'+n.name+' '+(n.attrs.class||'')"
-			 :style="n.attrs.style" :s="n.attrs.style" :nodes="n.children" :lazyLoad="lazyLoad" :loading="loading" />
-		</block>
-	</view>
-</template>
-<script module="handler" lang="wxs" src="./handler.wxs"></script>
-<script>
-	global.Parser = {};
-	import trees from './trees'
-	const errorImg = require('../libs/config.js').errorImg;
-	export default {
-		components: {
-			trees
-		},
-		name: 'trees',
-		data() {
-			return {
-				ctrl: [],
-				placeholder: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="300" height="225"/>',
-				errorImg,
-				loadVideo: typeof plus == 'undefined',
-				// #ifndef MP-ALIPAY
-				c: '',
-				s: ''
-				// #endif
-			}
-		},
-		props: {
-			nodes: Array,
-			lazyLoad: Boolean,
-			loading: String,
-			// #ifdef MP-ALIPAY
-			c: String,
-			s: String
-			// #endif
-		},
-		mounted() {
-			for (this.top = this.$parent; this.top.$options.name != 'parser'; this.top = this.top.$parent);
-			this.init();
-		},
-		// #ifdef APP-PLUS
-		beforeDestroy() {
-			this.observer && this.observer.disconnect();
-		},
-		// #endif
-		methods: {
-			init() {
-				for (var i = this.nodes.length, n; n = this.nodes[--i];) {
-					if (n.name == 'img') {
-						this.top.imgList.setItem(n.attrs.i, n.attrs['original-src'] || n.attrs.src);
-						// #ifdef APP-PLUS
-						if (this.lazyLoad && !this.observer) {
-							this.observer = uni.createIntersectionObserver(this).relativeToViewport({
-								top: 500,
-								bottom: 500
-							});
-							setTimeout(() => {
-								this.observer.observe('._img', res => {
-									if (res.intersectionRatio) {
-										for (var j = this.nodes.length; j--;)
-											if (this.nodes[j].name == 'img')
-												this.$set(this.ctrl, j, 1);
-										this.observer.disconnect();
-									}
-								})
-							}, 0)
-						}
-						// #endif
-					} else if (n.name == 'video' || n.name == 'audio') {
-						var ctx;
-						if (n.name == 'video') {
-							ctx = uni.createVideoContext(n.attrs.id
-								// #ifndef MP-BAIDU
-								, this
-								// #endif
-							);
-						} else if (this.$refs[n.attrs.id])
-							ctx = this.$refs[n.attrs.id][0];
-						if (ctx) {
-							ctx.id = n.attrs.id;
-							this.top.videoContexts.push(ctx);
-						}
-					}
-				}
-				// #ifdef APP-PLUS
-				// APP 上避免 video 错位需要延时渲染
-				setTimeout(() => {
-					this.loadVideo = true;
-				}, 1000)
-				// #endif
-			},
-			play(e) {
-				var contexts = this.top.videoContexts;
-				if (contexts.length > 1 && this.top.autopause)
-					for (var i = contexts.length; i--;)
-						if (contexts[i].id != e.currentTarget.dataset.id)
-							contexts[i].pause();
-			},
-			imgtap(e) {
-				var attrs = e.currentTarget.dataset.attrs;
-				if (!attrs.ignore) {
-					var preview = true,
-						data = {
-							id: e.target.id,
-							src: attrs.src,
-							ignore: () => preview = false
-						};
-					global.Parser.onImgtap && global.Parser.onImgtap(data);
-					this.top.$emit('imgtap', data);
-					if (preview) {
-						var urls = this.top.imgList,
-							current = urls[attrs.i] ? parseInt(attrs.i) : (urls = [attrs.src], 0);
-						uni.previewImage({
-							current,
-							urls
-						})
-					}
-				}
-			},
-			loadImg(e) {
-				var i = e.currentTarget.dataset.i;
-				if (this.lazyLoad && !this.ctrl[i]) {
-					// #ifdef QUICKAPP-WEBVIEW
-					this.$set(this.ctrl, i, 0);
-					this.$nextTick(function() {
-						// #endif
-						// #ifndef APP-PLUS
-						this.$set(this.ctrl, i, 1);
-						// #endif
-						// #ifdef QUICKAPP-WEBVIEW
-					})
-					// #endif
-				} else if (this.loading && this.ctrl[i] != 2) {
-					// #ifdef QUICKAPP-WEBVIEW
-					this.$set(this.ctrl, i, 0);
-					this.$nextTick(function() {
-						// #endif
-						this.$set(this.ctrl, i, 2);
-						// #ifdef QUICKAPP-WEBVIEW
-					})
-					// #endif
-				}
-			},
-			linkpress(e) {
-				var jump = true,
-					attrs = e.currentTarget.dataset.attrs;
-				attrs.ignore = () => jump = false;
-				global.Parser.onLinkpress && global.Parser.onLinkpress(attrs);
-				this.top.$emit('linkpress', attrs);
-				if (jump) {
-					// #ifdef MP
-					if (attrs['app-id']) {
-						return uni.navigateToMiniProgram({
-							appId: attrs['app-id'],
-							path: attrs.path
-						})
-					}
-					// #endif
-					if (attrs.href) {
-						if (attrs.href[0] == '#') {
-							if (this.top.useAnchor)
-								this.top.navigateTo({
-									id: attrs.href.substring(1)
-								})
-						} else if (attrs.href.indexOf('http') == 0 || attrs.href.indexOf('//') == 0) {
-							// #ifdef APP-PLUS
-							plus.runtime.openWeb(attrs.href);
-							// #endif
-							// #ifndef APP-PLUS
-							uni.setClipboardData({
-								data: attrs.href,
-								success: () =>
-									uni.showToast({
-										title: '链接已复制'
-									})
-							})
-							// #endif
-						} else
-							uni.navigateTo({
-								url: attrs.href,
-								fail() {
-									uni.switchTab({
-										url: attrs.href,
-									})
-								}
-							})
-					}
-				}
-			},
-			error(e) {
-				var target = e.currentTarget,
-					source = target.dataset.source,
-					i = target.dataset.i;
-				if (source == 'video' || source == 'audio') {
-					// 加载其他 source
-					var index = this.ctrl[i] ? this.ctrl[i].i + 1 : 1;
-					if (index < this.nodes[i].attrs.source.length)
-						this.$set(this.ctrl, i, index);
-					if (e.detail.__args__)
-						e.detail = e.detail.__args__[0];
-				} else if (errorImg && source == 'img') {
-					this.top.imgList.setItem(target.dataset.index, errorImg);
-					this.$set(this.ctrl, i, 3);
-				}
-				this.top && this.top.$emit('error', {
-					source,
-					target,
-					errMsg: e.detail.errMsg
-				});
-			},
-			_loadVideo(e) {
-				this.$set(this.ctrl, e.target.dataset.i, 0);
-			}
-		}
-	}
-</script>
-
-<style>
-	/* 在这里引入自定义样式 */
-
-	/* 链接和图片效果 */
-	._a {
-		display: inline;
-		padding: 1.5px 0 1.5px 0;
-		color: #366092;
-		word-break: break-all;
-	}
-
-	._hover {
-		text-decoration: underline;
-		opacity: 0.7;
-	}
-
-	._img {
-		display: inline-block;
-		max-width: 100%;
-		overflow: hidden;
-	}
-
-	/* #ifdef MP-WEIXIN */
-	:host {
-		display: inline;
-	}
-
-	/* #endif */
-
-	/* #ifndef MP-ALIPAY || APP-PLUS */
-	.interlayer {
-		display: inherit;
-		flex-direction: inherit;
-		flex-wrap: inherit;
-		align-content: inherit;
-		align-items: inherit;
-		justify-content: inherit;
-		width: 100%;
-		white-space: inherit;
-	}
-
-	/* #endif */
-
-	._b,
-	._strong {
-		font-weight: bold;
-	}
-
-	/* #ifndef MP-ALIPAY */
-	._blockquote,
-	._div,
-	._p,
-	._ol,
-	._ul,
-	._li {
-		display: block;
-	}
-	
-	/* #endif */
-
-	._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 {
-		display: block;
-		width: 100%;
-		height: 360px;
-		margin-top: -360px;
-		opacity: 0;
-	}
-
-	._ins {
-		text-decoration: underline;
-	}
-
-	._li {
-		flex: 1;
-		width: 0;
-	}
-
-	._ol-bef {
-		width: 36px;
-		margin-right: 5px;
-		text-align: right;
-	}
-
-	._ul-bef {
-		display: block;
-		margin: 0 12px 0 23px;
-		line-height: normal;
-	}
-
-	._ol-bef,
-	._ul-bef {
-		flex: none;
-		user-select: none;
-	}
-
-	._ul-p1 {
-		display: inline-block;
-		width: 0.3em;
-		height: 0.3em;
-		overflow: hidden;
-		line-height: 0.3em;
-	}
-
-	._ul-p2 {
-		display: inline-block;
-		width: 0.23em;
-		height: 0.23em;
-		border: 0.05em solid black;
-		border-radius: 50%;
-	}
-
-	._q::before {
-		content: '"';
-	}
-
-	._q::after {
-		content: '"';
-	}
-
-	._sub {
-		font-size: smaller;
-		vertical-align: sub;
-	}
-
-	._sup {
-		font-size: smaller;
-		vertical-align: super;
-	}
-
-	/* #ifdef MP-ALIPAY || APP-PLUS || QUICKAPP-WEBVIEW */
-	._abbr,
-	._b,
-	._code,
-	._del,
-	._em,
-	._i,
-	._ins,
-	._label,
-	._q,
-	._span,
-	._strong,
-	._sub,
-	._sup {
-		display: inline;
-	}
-
-	/* #endif */
-
-	/* #ifdef MP-WEIXIN || MP-QQ */
-	.__bdo,
-	.__bdi,
-	.__ruby,
-	.__rt {
-		display: inline-block;
-	}
-
-	/* #endif */
-	._video {
-		position: relative;
-		display: inline-block;
-		width: 300px;
-		height: 225px;
-		background-color: black;
-	}
-
-	._video::after {
-		position: absolute;
-		top: 50%;
-		left: 50%;
-		margin: -15px 0 0 -15px;
-		content: '';
-		border-color: transparent transparent transparent white;
-		border-style: solid;
-		border-width: 15px 0 15px 30px;
-	}
-</style>

+ 0 - 0
src/components/swiperBanner.vue → src/components/swiperBanner/index.vue


+ 0 - 40
src/components/tabbar.vue

@@ -1,40 +0,0 @@
-<template>
-  <div class="tabbar">
-    <u-tabbar
-	:value="value1"
-	@change="change1"
-	:fixed="false"
-	:placeholder="false"
-	:safeAreaInsetBottom="false"
->
-	<u-tabbar-item name="首页" text="首页" icon="home" @click="click1" />
-	<u-tabbar-item name="放映厅" text="放映厅" icon="photo" @click="click1" />
-	<u-tabbar-item name="直播" text="直播" icon="play-right" @click="click1" />
-	<u-tabbar-item name="我的" text="我的" icon="account" @click="click1" />
-</u-tabbar>
-  </div>
-</template>
-
-<script>
-export default {
-  name: "tabbar",
-  props: {},
-  components: {},
-  data() {
-    return {
-        value1: "首页"
-    };
-  },
-  methods: {
-    change1(){},
-    click1(){},
-  },
-  mounted() {},
-  watch: {},
-  computed: {},
-  filters: {},
-};
-</script>
-
-<style scoped lang='scss'>
-</style>

+ 27 - 27
src/pages/agreement/index.vue

@@ -1,43 +1,43 @@
 <template>
-  <view class="container">
-    <jyf-parser :html="content" class="mar_t50"></jyf-parser>
-  </view>
+    <view class="container">
+        <mp-html :content="content" class="mar_t50"></mp-html>
+    </view>
 </template>
 
 <script>
 import { post } from "@/request/api.js";
-import jyfParser from "@/components/jyf-parser/jyf-parser.vue";
+import mpHtml from "@/uni_modules/mp-html/components/mp-html/mp-html.vue"
 export default {
-  data() {
-    return {
-      content: "",
-    };
-  },
-  onLoad(da) {
-    this.loadData(da.type);
-	uni.setNavigationBarTitle({ title: decodeURI(da.tit) });
-  },
-  methods: {
-    loadData(type) {
-      post("v1/my/article", {type}).then((res) => {
-        if (res.code == 0) {
-          this.content = res.data.data.content;
-        }
-      });
+    data() {
+        return {
+            content: "",
+        };
+    },
+    onLoad(da) {
+        this.loadData(da.type);
+        uni.setNavigationBarTitle({ title: decodeURI(da.tit) });
+    },
+    methods: {
+        loadData(type) {
+            post("v1/my/article", { type }).then((res) => {
+                if (res.code == 0) {
+                    this.content = res.data.data.content;
+                }
+            });
+        },
+    },
+    components: {
+        mpHtml,
     },
-  },
-  components: {
-    jyfParser,
-  },
 };
 </script>
 
 <style lang="scss" scoped>
 // 用户须知
 .container {
-  border-top: 20rpx solid #f5f5f5;
-  padding: 0 20rpx;
-  box-sizing: border-box;
+    border-top: 20rpx solid #f5f5f5;
+    padding: 0 20rpx;
+    box-sizing: border-box;
 }
 // 用户须知-end
 </style>

+ 1 - 2
src/pages/index/index.vue

@@ -52,7 +52,6 @@
                             <text class="product-text" v-if="[3,4].includes(i.type)">赠<text class="corFE2C15">{{ i.give_cha_bao }}</text>茶宝</text>
                         </view>
                         <view class="product-txt" v-if="i.type == 1">赠送{{ i.give_integral + "批发券" }}</view>
-                        <!-- <view class="product-txt">赠送{{ i.give_integral ? i.give_integral + "批发券" : i.give_cha_bao + "茶宝" }}</view> -->
                         <view class="product-txt" v-if="[3,4].includes(i.type)">限时赠送<text class="corFE2C15">{{ i.teac }}</text>TeaC</view>
                         <view class="product-txt fenxiang" v-if="[3,4].includes(i.type)">
                             <text class="iconfont red">&#xe62b;</text>
@@ -68,7 +67,7 @@
 <script>
 let app = getApp();
 var appEv = app.$vm.$options;
-import swiperBanner from "@/components/swiperBanner"; //轮播
+import swiperBanner from "@/components/swiperBanner/index.vue"; //轮播
 import { post } from "@/request/api.js";
 export default {
     name: "Appindex",

+ 3 - 3
src/pages/notice/detail.vue

@@ -10,7 +10,7 @@
           时间: {{ $day(noticeDetail.add_time * 1000).format("YYYY-MM-DD HH:mm:ss") }}
       </span></view
     >
-    <jyf-parser :html="noticeDetail.content" class="mar_t50"></jyf-parser>
+    <mp-html :content="noticeDetail.content" class="mar_t50"></mp-html>
     <!-- 公告详情-end -->
   </view>
 </template>
@@ -19,7 +19,7 @@
 let app = getApp();
 var appEv = app.$vm.$options;
 import { post } from "@/request/api.js";
-import jyfParser from "@/components/jyf-parser/jyf-parser.vue";
+import mpHtml from "@/uni_modules/mp-html/components/mp-html/mp-html.vue"
 export default {
   data() {
     return {
@@ -43,7 +43,7 @@ export default {
     },
   },
   components: {
-    jyfParser,
+    mpHtml,
   },
 };
 </script>

+ 3 - 3
src/pages/pay-agreement/index.vue

@@ -1,6 +1,6 @@
 <template>
   <view class="container">
-    <jyf-parser :html="content" class="mar_t50"></jyf-parser>
+    <mp-html :content="content" class="mar_t50"></mp-html>
   </view>
 </template>
 
@@ -8,7 +8,7 @@
 let app = getApp();
 var appEv = app.$vm.$options;
 import { post } from "@/request/api.js";
-import jyfParser from "@/components/jyf-parser/jyf-parser.vue";
+import mpHtml from "@/uni_modules/mp-html/components/mp-html/mp-html.vue"
 export default {
   data() {
     return {
@@ -51,7 +51,7 @@ export default {
     },
   },
   components: {
-    jyfParser,
+    mpHtml,
   },
 };
 </script>

+ 4 - 4
src/pages/product/p_details.vue

@@ -50,7 +50,7 @@
         <view class="brief mar_t20">
             <view class="brief_title flex_r flex_ac">产品简介</view>
             <view class="brief_con">
-                <jyfParser :html="detail.goods_content" ref="jyf"></jyfParser>
+                <mp-html :content="detail.goods_content" ref="jyf"></mp-html>
                 <!-- <image :lazy-load="true" style="width: 100%;display: block;" v-for="(item,index) in detail.goodsDetailesImage" :key="index" :src="item" mode="widthFix"></image> -->
             </view>
         </view>
@@ -112,14 +112,14 @@ let page = 1;
 let app = getApp();
 var appEv = app.$vm.$options;
 import { post } from "@/request/api.js";
-import jyfParser from "@/components/jyf-parser/jyf-parser.vue";
-import swiperBanner from "@/components/swiperBanner";
+import mpHtml from "@/uni_modules/mp-html/components/mp-html/mp-html.vue"
+import swiperBanner from "@/components/swiperBanner/index.vue";
 import uniGoodsNav from "@/components/uni-goods-nav/uni-goods-nav.vue";
 import uniNumberBox from "@/components/uni-number-box/uni-number-box.vue";
 import authorizeModule from "@/components/authorize-module/index";
 export default {
     components: {
-        jyfParser,
+        mpHtml,
         uniGoodsNav,
         swiperBanner,
         uniNumberBox,

+ 67 - 45
src/pages/protocol/index.vue

@@ -1,64 +1,86 @@
 <template>
-	<view class="container">
-		
-		<!-- 顶部 -->
-		<!-- <view class="head mar_t20">
+    <view class="container">
+        <!-- 顶部 -->
+        <!-- <view class="head mar_t20">
 			
 		</view> -->
-		<!-- 顶部-end -->
-		
-		<!-- 内容 -->
-		<view class="content mar_t20">
-			<jyf-parser :html="detail.cont"></jyf-parser>
-			<jyf-parser :html="detail.content"></jyf-parser>
-		</view>
-		<!-- 内容-end -->
-	</view>
+        <!-- 顶部-end -->
+
+        <!-- 内容 -->
+        <view class="content mar_t20">
+            <mp-html :content="detail.cont"></mp-html>
+            <mp-html :content="detail.content"></mp-html>
+        </view>
+        <!-- 内容-end -->
+    </view>
 </template>
 
 <script>
-import jyfParser from '@/components/jyf-parser/jyf-parser.vue'
+import mpHtml from "@/uni_modules/mp-html/components/mp-html/mp-html.vue"
 import { post } from "@/request/api.js";
-	export default {
-		components:{
-			jyfParser
-		},
-		data() {
-			return {
-				detail:'',
-				type:''
-			};
-		},
-		onLoad:function(e){
-			this.type = e.type
-			this.loadData()
-		},
-		methods:{
-			loadData:function(){
-				let that = this;
-				let data = {
-					type:this.type
-				}
-				post("v1/ShuZiTeaYW/shop/getPurchaseAgreement",data).then(res => {
-					if(res.status == 200){
-						that.detail = res.data
-					}
-				})
-			}
-		}
-	}
+export default {
+    components: {
+        mpHtml,
+    },
+    data() {
+        return {
+            detail: "",
+            type: "",
+        };
+    },
+    onLoad: function (e) {
+        this.type = e.type;
+        this.loadData();
+    },
+    methods: {
+        loadData: function () {
+            let that = this;
+            let data = {
+                type: this.type,
+            };
+            post("v1/ShuZiTeaYW/shop/getPurchaseAgreement", data).then(
+                (res) => {
+                    if (res.status == 200) {
+                        that.detail = res.data;
+                    }
+                }
+            );
+        },
+    },
+};
 </script>
 
 <style lang="scss">
 // 页面配置
-page{background: #f5f5f5;}
+page {
+    background: #f5f5f5;
+}
 // 页面配置-end
 
 // 顶部
-.head{width: 100%;overflow: hidden;background: #fff;padding:40rpx 20rpx;box-sizing: border-box;font-size: 26rpx;color:#232323;font-family: "SourceHanSansCN-Medium";font-weight: 500;}
+.head {
+    width: 100%;
+    overflow: hidden;
+    background: #fff;
+    padding: 40rpx 20rpx;
+    box-sizing: border-box;
+    font-size: 26rpx;
+    color: #232323;
+    font-family: "SourceHanSansCN-Medium";
+    font-weight: 500;
+}
 // 顶部-end
 
 // 内容
-.content{width: 100%;overflow: hidden;background: #fff;padding:40rpx 20rpx;box-sizing: border-box;font-size: 24rpx;color:#363636;font-family: "SourceHanSansCN-Medium";}
+.content {
+    width: 100%;
+    overflow: hidden;
+    background: #fff;
+    padding: 40rpx 20rpx;
+    box-sizing: border-box;
+    font-size: 24rpx;
+    color: #363636;
+    font-family: "SourceHanSansCN-Medium";
+}
 // 内容-end
 </style>

+ 5 - 4
src/pagesB/hotel/hotelDetail.vue

@@ -38,11 +38,11 @@
             </div>
             <div class="p flex_r flex_jb flex_ac">
                 <span class="label">住客姓名</span>
-                <input v-model="qda.contactName" />
+                <input v-model="qda.contactName" placeholder="请填写住客真实姓名" placeholder-class="inp_pl"/>
             </div>
             <div class="p flex_r flex_jb flex_ac">
                 <span class="label">联系电话</span>
-                <input v-model="qda.contactMobile" />
+                <input v-model="qda.contactMobile" placeholder="请填写住客联系电话" placeholder-class="inp_pl"/>
             </div>
             <div class="p flex_r flex_js flex_ac">
                 <span class="label">最晚到店</span>
@@ -54,7 +54,7 @@
             </div>
             <div class="p flex_r flex_jb flex_ac">
                 <span class="label">备注</span>
-                <input v-model="qda.orderRemark" />
+                <input v-model="qda.orderRemark" placeholder-class="inp_pl"/>
             </div>
         </div>
         <div class="money card">
@@ -195,7 +195,7 @@ export default {
         this.getIntegral();
         this.qda = {
             roomNum: 1,
-            contactName: this.userinfo.nickname,
+            // contactName: this.userinfo.nickname,
             contactMobile: this.userinfo.mobile
         }
         this.roomNumf(1);
@@ -387,4 +387,5 @@ export default {
     text-align: center;
     line-height: 80rpx;
 }
+
 </style>

+ 4 - 4
src/pagesB/hotel/orderDetail.vue

@@ -48,16 +48,16 @@
             <div class="card">
                 <div class="tit">订单信息</div>
                 <div class="pli">
-                    <div class="label">订单编号</div>
+                    <div class="label">订单编号</div>
                     <span>{{ order.trade_no }}</span>
                 </div>
                 <div class="pli">
-                    <div class="label">磐河编号</div>
+                    <div class="label">平台编号:</div>
                     <span>{{ detail.orderNo }}</span>
                 </div>
                 <div class="pli">
-                    <div class="label">下单时间</div>
-                    <span>{{ detail.createTime }}</span>
+                    <div class="label">下单时间</div>
+                    <span>{{ order.create_time }}</span>
                 </div>
 
             </div>

+ 24 - 3
src/pagesB/scenicSpotTicket/index.vue

@@ -2,7 +2,7 @@
     <div class="scenicSpotTicket">
         <scroll-view @scrolltolower="scrolltolower" class="scroll-view" :scroll-y="true" :scroll-top="scrollTop" @scroll="scroll" :lower-threshold="100">
             <div class="head_box">
-                <uv-search v-model="qda.keyWord" @search="onsearch" @custom="onsearch" placeholder="景点、目的地址、景点主题..." />
+                <uni-easyinput prefixIcon="search" suffixIcon="搜索" v-model="qda.keyWord" placeholder="景点、目的地址、景点主题..." @confirm="onsearch" @change="onsearch" />
                 <div class="filter_box flex_r">
                     <div class="filter_item" @click="showAddress = true">
                         <span class="item_name">{{qda.cityName}}</span>
@@ -37,6 +37,10 @@
                     <div class="openTime">{{ i.openTime }}</div>
                 </div>
             </div>
+            <div class="onlist" v-if="onlist">
+                <image class="errimg" src="http://teaclub.oss-cn-chengdu.aliyuncs.com/CloudShop/head_pic/8ff923549b8ef026eeca56d23d5e4bdc3a69299epng" mode="widthFix" />
+                <div class="errmsg">没有搜索到景区喔~</div>
+            </div>
         </scroll-view>
         <div class="BackTop iconfont" @click="onBackTop" v-if="oldscrollTop > 500">&#xe632;</div>
         <h-address @select="selectaddress" v-show="showAddress" />
@@ -53,7 +57,6 @@
     </div>
 </template>
 <script>
-import uvSearch from "@/uni_modules/uv-search/components/uv-search/uv-search.vue";
 import hAddress from "@/pagesB/components/h-address/address.vue";
 import { post } from "@/request/api.js";
 import QQMapWX from '@/pagesB/static/js/qqmap-wx-jssdk.min.js';
@@ -62,7 +65,6 @@ export default {
     name: "scenicSpotTicket",
     props: {},
     components: {
-        uvSearch,
         hAddress
     },
     data() {
@@ -84,19 +86,24 @@ export default {
             ],
             scrollTop: 0,
             oldscrollTop: 0,
+            onlist:false
         };
     },
     methods: {
         // 获取列表
         getlist() {
             let da = Object.assign({}, this.qda);
+            uni.showLoading({ title: '' });
             post("local/ticket/scenicList", da).then((res) => {
                 if (res.code == 0) {
                     if (this.qda.pageIndex == 1) this.list = [];
                     let da = res.data.data.scenicList;
                     this.list = [...this.list, ...da];
                     this.listcount = res.data.data.count;
+                    if(da.length) this.onlist = false
+                    else this.onlist = true
                 }
+                uni.hideLoading();
             });
         },
         // 滚动到底部拉取数据
@@ -183,6 +190,9 @@ export default {
 .head_box {
     background-color: #fff;
     padding: 28rpx 32rpx;
+    .inp_search{
+        border: none;
+    }
 }
 
 .filter_box{
@@ -334,6 +344,17 @@ export default {
     border-radius: 50%;
     color: #666;
 }
+.onlist{
+    padding-top: 100rpx;
+    text-align: center;
+    .errimg{
+        width: 500rpx;
+    }
+    .errmsg{
+        font-size: 28rpx;
+        color: #999;
+    }
+}
 </style>
 <style>
 .uni-data-tree-input{

+ 4 - 3
src/pagesB/scenicSpotTicket/scenic.vue

@@ -43,7 +43,7 @@
             </div>
             <div class="scenic_msg" v-if="detail.scenicDescription">
                 <div class="title">景区介绍</div>
-                <div class="msg_con" v-html="detail.scenicDescription"></div>
+                <mp-html :content="detail.scenicDescription" class="msg_con" />
             </div>
         </div>
         <!-- 图片查看组件 -->
@@ -52,12 +52,13 @@
     </div>
 </template>
 <script>
+import mpHtml from "@/uni_modules/mp-html/components/mp-html/mp-html.vue"
 import preview from "@/pagesB/components/swiper-preview/index.vue";
 import { post } from "@/request/api.js";
 export default {
     name: "scenic",
     props: {},
-    components: { preview },
+    components: { preview, mpHtml },
     data() {
         return {
             query: {},
@@ -275,12 +276,12 @@ page {
         height: 30rpx;
         line-height: 30rpx;
         border-left: 6rpx solid #00B76C;
+        margin-bottom: 16rpx;
     }
 
     .msg_con {
         font-size: 25rpx;
         color: #666;
-        margin-top: 16rpx;
     }
 }
 </style>

+ 4 - 4
src/pagesB/scenicSpotTicket/scenicDetail.vue

@@ -23,15 +23,15 @@
             <div class="user_item" v-for="(i,s) in users" :key="s">
                 <div class="p flex_r flex_jb flex_ac">
                     <span class="label">出游人:</span>
-                    <input v-model="i.name" />
+                    <input v-model="i.name"  placeholder="请填写游客真实姓名" placeholder-class="inp_pl"/>
                 </div>
                 <div class="p flex_r flex_jb flex_ac">
                     <span class="label">手机号:</span>
-                    <input v-model="i.mobile" />
+                    <input v-model="i.mobile"  placeholder="请填写游客联系方式" placeholder-class="inp_pl"/>
                 </div>
                 <div class="p flex_r flex_jb flex_ac" v-if="[2,4].includes(D.touristInfoType)">
                     <span class="label">身份证:</span>
-                    <input v-model="i.cardNo" />
+                    <input v-model="i.cardNo"  placeholder="请填写与姓名一致的身份证号" placeholder-class="inp_pl"/>
                 </div>
             </div>
         </div>
@@ -195,7 +195,7 @@ export default {
     onLoad(da) {
         this.qda = { ...this.qda, ...da };
         this.users[0] = {
-            name: this.userinfo.nickname,
+            // name: this.userinfo.nickname,
             mobile: this.userinfo.mobile
         }
         this.getDetail(da);

+ 193 - 0
src/uni_modules/mp-html/README.md

@@ -0,0 +1,193 @@
+## 为减小组件包的大小,默认组件包中不包含编辑、latex 公式等扩展功能,需要使用扩展功能的请参考下方的 插件扩展 栏的说明
+
+## 功能介绍
+- 全端支持(含 `v3、NVUE`)
+- 支持丰富的标签(包括 `table`、`video`、`svg` 等)
+- 支持丰富的事件效果(自动预览图片、链接处理等)
+- 支持设置占位图(加载中、出错时、预览时)
+- 支持锚点跳转、长按复制等丰富功能
+- 支持大部分 *html* 实体
+- 丰富的插件(关键词搜索、内容编辑、`latex` 公式等)
+- 效率高、容错性强且轻量化
+
+查看 [功能介绍](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 | 链接被点击时 |
+| play | 音视频播放时 |
+
+查看 [事件](https://jin-yufeng.gitee.io/mp-html/#/basic/event) 了解更多
+
+## api
+组件实例上提供了一些 `api` 方法可供调用
+
+| 名称 | 作用 |
+|:---:|---|
+| in | 将锚点跳转的范围限定在一个 scroll-view 内 |
+| navigateTo | 锚点跳转 |
+| getText | 获取文本内容 |
+| getRect | 获取富文本内容的位置和大小 |
+| setContent | 设置富文本内容 |
+| imgList | 获取所有图片的数组 |
+| pauseMedia | 暂停播放音视频([2.2.2+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v222)) |
+| setPlaybackRate | 设置音视频播放速率([2.4.0+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v240)) |
+
+查看 [api](https://jin-yufeng.gitee.io/mp-html/#/advanced/api) 了解更多
+
+## 插件扩展  
+除基本功能外,本组件还提供了丰富的扩展,可按照需要选用
+
+| 名称 | 作用 |
+|:---:|---|
+| audio | 音乐播放器 |
+| editable | 富文本 **编辑**([示例项目](https://mp-html.oss-cn-hangzhou.aliyuncs.com/editable.zip)) |
+| emoji | 解析 emoji |
+| highlight | 代码块高亮显示 |
+| markdown | 渲染 markdown |
+| search | 关键词搜索 |
+| style | 匹配 style 标签中的样式 |
+| txv-video | 使用腾讯视频 |
+| img-cache | 图片缓存 by [@PentaTea](https://github.com/PentaTea) |
+| latex | 渲染 latex 公式 by [@Zeng-J](https://github.com/Zeng-J) |
+
+从插件市场导入的包中 **不含有** 扩展插件,使用插件需通过微信小程序 `富文本插件` 获取或参考以下方法进行打包:  
+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. 视频不支持全屏播放
+3. 如果在 `flex-direction: row` 的容器中使用,需要给组件设置宽度或设置 `flex: 1` 占满剩余宽度
+
+纯 `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://mp-html.oss-cn-hangzhou.aliyuncs.com/qrcode.jpg)
+
+## 问题反馈
+遇到问题时,请先查阅 [常见问题](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` 项目以及复现方式,对于 **描述不清**、**无法复现** 或重复的问题将不予回复  
+
+欢迎加入 `QQ` 交流群:  
+群1(已满):`699734691`  
+群2:`778239129`  
+
+查看 [问题反馈](https://jin-yufeng.gitee.io/mp-html/#/question/feedback) 了解更多

+ 498 - 0
src/uni_modules/mp-html/components/mp-html/mp-html.vue

@@ -0,0 +1,498 @@
+<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.4.2
+ * @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')
+  },
+  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 {Number} rate 播放速率
+     */
+    setPlaybackRate (rate) {
+      this.playbackRate = rate
+      for (let i = (this._videos || []).length; i--;) {
+        this._videos[i].playbackRate(rate)
+      }
+      // #ifdef APP-PLUS
+      const command = 'for(var e=document.getElementsByTagName("video"),i=e.length;i--;)e[i].playbackRate=' + rate
+      // #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')
+      })
+
+      if (this.lazyLoad || this.imgList._unloadimgs < this.imgList.length / 2) {
+        // 设置懒加载,每 350ms 获取高度,不变则认为加载完毕
+        let height = 0
+        const callback = rect => {
+          if (!rect || !rect.height) rect = {}
+          // 350ms 总高度无变化就触发 ready 事件
+          if (rect.height === height) {
+            this.$emit('ready', rect)
+          } else {
+            height = rect.height
+            setTimeout(() => {
+              this.getRect().then(callback).catch(callback)
+            }, 350)
+          }
+        }
+        this.getRect().then(callback).catch(callback)
+      } else {
+        // 未设置懒加载,等待所有图片加载完毕
+        if (!this.imgList._unloadimgs) {
+          this.getRect().then(rect => {
+            this.$emit('ready', rect)
+          }).catch(() => {
+            this.$emit('ready', {})
+          })
+        }
+      }
+      // #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).replace(/%22/g, '') + ',' + 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(() => {
+            this.$emit('ready', {})
+          })
+          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>

+ 576 - 0
src/uni_modules/mp-html/components/mp-html/node/node.vue

@@ -0,0 +1,576 @@
+<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'&&!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" />
+      <!-- 显示图片 -->
+      <!-- #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 && VUE2) -->
+      <!-- 表格中的图片,使用 rich-text 防止大小不正确 -->
+      <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" />
+      <!-- #endif -->
+      <!-- #ifndef H5 || APP-PLUS -->
+      <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" />
+      <!-- #endif -->
+      <!-- #ifdef APP-PLUS && VUE3 -->
+      <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" />
+      <!-- #endif -->
+      <!-- 文本 -->
+      <!-- #ifdef MP-WEIXIN -->
+      <text v-else-if="n.text" :user-select="opts[4]=='force'&&isiOS" decode>{{n.text}}</text>
+      <!-- #endif -->
+      <!-- #ifndef MP-WEIXIN || MP-BAIDU || MP-ALIPAY || MP-TOUTIAO -->
+      <text v-else-if="n.text" 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="'display:inline;'+n.f" :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: {},
+      // #ifdef MP-WEIXIN
+      isiOS: uni.getSystemInfoSync().system.includes('iOS')
+      // #endif
+    }
+  },
+  props: {
+    name: String,
+    attrs: {
+      type: Object,
+      default () {
+        return {}
+      }
+    },
+    childs: Array,
+    opts: Array
+  },
+  components: {
+
+    // #ifndef (H5 || APP-PLUS) && 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 () { return this },
+    // #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
+          if (this.root.playbackRate) {
+            ctx.playbackRate(this.root.playbackRate)
+          }
+          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)
+      }
+      this.checkReady()
+    },
+
+    /**
+     * @description 检查是否所有图片加载完毕
+     */
+    checkReady () {
+      if (this.root && !this.root.lazyLoad) {
+        this.root._unloadimgs -= 1
+        if (!this.root._unloadimgs) {
+          setTimeout(() => {
+            this.root.getRect().then(rect => {
+              this.root.$emit('ready', rect)
+            }).catch(() => {
+              this.root.$emit('ready', {})
+            })
+          }, 350)
+        }
+      }
+    },
+
+    /**
+     * @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)
+        }
+        this.checkReady()
+      }
+      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>

+ 1335 - 0
src/uni_modules/mp-html/components/mp-html/parser.js

@@ -0,0 +1,1335 @@
+/**
+ * @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 合并多个块级标签,加快长内容渲染
+ * @param {Array} nodes 要合并的标签数组
+ */
+function mergeNodes (nodes) {
+  let i = nodes.length - 1
+  for (let j = i; j >= -1; j--) {
+    if (j === -1 || nodes[j].c || !nodes[j].name || (nodes[j].name !== 'div' && nodes[j].name !== 'p' && nodes[j].name[0] !== 'h') || (nodes[j].attrs.style || '').includes('inline')) {
+      if (i - j >= 5) {
+        nodes.splice(j + 1, i - j, {
+          name: 'div',
+          attrs: {},
+          children: nodes.slice(j + 1, i + 1)
+        })
+      }
+      i = j - 1
+    }
+  }
+}
+
+/**
+ * @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.imgList._unloadimgs = 0
+  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()
+  }
+  if (this.nodes.length > 50) {
+    mergeNodes(this.nodes)
+  }
+  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 标签内大小写敏感
+    config.ignoreTags.style = undefined // svg 标签内 style 可用
+  }
+}
+
+/**
+ * @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
+            }
+            if (item.name === 'table' && !node.webp && !attrs.src.includes('cloud://')) {
+              if (!styleObj.display || styleObj.display.includes('inline')) {
+                node.t = 'inline-block'
+              } else {
+                node.t = styleObj.display
+              }
+              styleObj.display = undefined
+            }
+            // #ifndef H5 || APP-PLUS
+            const style = item.attrs.style || ''
+            if (style.includes('flex:') && !style.includes('flex:0') && !style.includes('flex: 0') && (!styleObj.width || parseInt(styleObj.width) > 100)) {
+              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)
+          if (!node.t) {
+            this.imgList._unloadimgs += 1
+          }
+          // #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
+    config.ignoreTags.style = true
+    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)
+    const bordercolor = styleObj['border-color']
+    const borderstyle = styleObj['border-style']
+    if (node.c) {
+      // padding 和 spacing 默认 2
+      if (isNaN(padding)) {
+        padding = 2
+      }
+      if (isNaN(spacing)) {
+        spacing = 2
+      }
+    }
+    if (border) {
+      attrs.style += `;border:${border}px ${borderstyle || 'solid'} ${bordercolor || '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 || ''
+            let 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 += ';display:flex'
+            start = style.indexOf('vertical-align')
+            if (start !== -1) {
+              const val = style.substr(start + 15, 10)
+              if (val.includes('middle')) {
+                style += ';align-items:center'
+              } else if (val.includes('bottom')) {
+                style += ';align-items:flex-end'
+              }
+            } else {
+              style += ';align-items:center'
+            }
+            // 设置水平对齐
+            start = style.indexOf('text-align')
+            if (start !== -1) {
+              const val = style.substr(start + 11, 10)
+              if (val.includes('center')) {
+                style += ';justify-content: center'
+              } else if (val.includes('right')) {
+                style += ';justify-content: right'
+              }
+            }
+            style = (border ? `;border:${border}px ${borderstyle || 'solid'} ${bordercolor || 'gray'}` + (spacing ? '' : ';border-right:0;border-bottom:0') : '') + (padding ? `;padding:${padding}px` : '') + ';' + style
+            // 处理列合并
+            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 ${borderstyle || 'solid'} ${bordercolor || '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.children)) && !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')) {
+    mergeNodes(children)
+  }
+  // #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 === ' ') {
+      if (flag) return
+      // #ifdef VUE3
+      else {
+        const parent = this.stack[this.stack.length - 1]
+        if (parent && parent.name[0] === 't') return
+      }
+      // #endif
+    }
+    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

文件差異過大導致無法顯示
+ 0 - 0
src/uni_modules/mp-html/static/app-plus/mp-html/js/handler.js


文件差異過大導致無法顯示
+ 0 - 0
src/uni_modules/mp-html/static/app-plus/mp-html/js/uni.webview.min.js


+ 1 - 0
src/uni_modules/mp-html/static/app-plus/mp-html/local.html

@@ -0,0 +1 @@
+<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>

+ 0 - 23
src/uni_modules/uv-icon/changelog.md

@@ -1,23 +0,0 @@
-## 1.0.9(2023-07-28)
-1. 修改几个对应错误图标的BUG
-## 1.0.8(2023-07-24)
-1. 优化 支持base64图片
-## 1.0.7(2023-07-17)
-1. 修复  uv-icon 恢复uv-empty相关的图标
-## 1.0.6(2023-07-13)
-1. 修复icon设置name属性对应图标错误的BUG
-## 1.0.5(2023-07-04)
-1. 更新图标,删除一些不常用的图标
-2. 删除base64,修改成ttf文件引入读取图标
-3. 自定义图标文档说明:https://www.uvui.cn/guide/customIcon.html
-## 1.0.4(2023-07-03)
-1. 修复主题颜色在APP不生效的BUG
-## 1.0.3(2023-05-24)
-1. 将线上ttf字体包替换成base64,避免加载时或者网络差时候显示白色方块
-## 1.0.2(2023-05-16)
-1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
-2. 优化部分功能
-## 1.0.1(2023-05-10)
-1. 修复小程序中异常显示
-## 1.0.0(2023-05-04)
-新发版

+ 0 - 160
src/uni_modules/uv-icon/components/uv-icon/icons.js

@@ -1,160 +0,0 @@
-export default {
-	'uvicon-level': 'e68f',
-	'uvicon-checkbox-mark': 'e659',
-	'uvicon-folder': 'e694',
-	'uvicon-movie': 'e67c',
-	'uvicon-star-fill': 'e61e',
-	'uvicon-star': 'e618',
-	'uvicon-phone-fill': 'e6ac',
-	'uvicon-phone': 'e6ba',
-	'uvicon-apple-fill': 'e635',
-	'uvicon-backspace': 'e64d',
-	'uvicon-attach': 'e640',
-	'uvicon-empty-data': 'e671',
-	'uvicon-empty-address': 'e68a',
-	'uvicon-empty-favor': 'e662',
-	'uvicon-empty-car': 'e657',
-	'uvicon-empty-order': 'e66b',
-	'uvicon-empty-list': 'e672',
-	'uvicon-empty-search': 'e677',
-	'uvicon-empty-permission': 'e67d',
-	'uvicon-empty-news': 'e67e',
-	'uvicon-empty-history': 'e685',
-	'uvicon-empty-coupon': 'e69b',
-	'uvicon-empty-page': 'e60e',
-	'uvicon-empty-wifi-off': 'e6cc',
-	'uvicon-reload': 'e627',
-	'uvicon-order': 'e695',
-	'uvicon-server-man': 'e601',
-	'uvicon-search': 'e632',
-	'uvicon-more-dot-fill': 'e66f',
-	'uvicon-scan': 'e631',
-	'uvicon-map': 'e665',
-	'uvicon-map-fill': 'e6a8',
-	'uvicon-tags': 'e621',
-	'uvicon-tags-fill': 'e613',
-	'uvicon-eye': 'e664',
-	'uvicon-eye-fill': 'e697',
-	'uvicon-eye-off': 'e69c',
-	'uvicon-eye-off-outline': 'e688',
-	'uvicon-mic': 'e66d',
-	'uvicon-mic-off': 'e691',
-	'uvicon-calendar': 'e65c',
-	'uvicon-trash': 'e623',
-	'uvicon-trash-fill': 'e6ce',
-	'uvicon-play-left': 'e6bf',
-	'uvicon-play-right': 'e6b3',
-	'uvicon-minus': 'e614',
-	'uvicon-plus': 'e625',
-	'uvicon-info-circle': 'e69f',
-	'uvicon-info-circle-fill': 'e6a7',
-	'uvicon-question-circle': 'e622',
-	'uvicon-question-circle-fill': 'e6bc',
-	'uvicon-close': 'e65a',
-	'uvicon-checkmark': 'e64a',
-	'uvicon-checkmark-circle': 'e643',
-	'uvicon-checkmark-circle-fill': 'e668',
-	'uvicon-setting': 'e602',
-	'uvicon-setting-fill': 'e6d0',
-	'uvicon-heart': 'e6a2',
-	'uvicon-heart-fill': 'e68b',
-	'uvicon-camera': 'e642',
-	'uvicon-camera-fill': 'e650',
-	'uvicon-more-circle': 'e69e',
-	'uvicon-more-circle-fill': 'e684',
-	'uvicon-chat': 'e656',
-	'uvicon-chat-fill': 'e63f',
-	'uvicon-bag': 'e647',
-	'uvicon-error-circle': 'e66e',
-	'uvicon-error-circle-fill': 'e655',
-	'uvicon-close-circle': 'e64e',
-	'uvicon-close-circle-fill': 'e666',
-	'uvicon-share': 'e629',
-	'uvicon-share-fill': 'e6bb',
-	'uvicon-share-square': 'e6c4',
-	'uvicon-shopping-cart': 'e6cb',
-	'uvicon-shopping-cart-fill': 'e630',
-	'uvicon-bell': 'e651',
-	'uvicon-bell-fill': 'e604',
-	'uvicon-list': 'e690',
-	'uvicon-list-dot': 'e6a9',
-	'uvicon-zhifubao-circle-fill': 'e617',
-	'uvicon-weixin-circle-fill': 'e6cd',
-	'uvicon-weixin-fill': 'e620',
-	'uvicon-qq-fill': 'e608',
-	'uvicon-qq-circle-fill': 'e6b9',
-	'uvicon-moments-circel-fill': 'e6c2',
-	'uvicon-moments': 'e6a0',
-	'uvicon-car': 'e64f',
-	'uvicon-car-fill': 'e648',
-	'uvicon-warning-fill': 'e6c7',
-	'uvicon-warning': 'e6c1',
-	'uvicon-clock-fill': 'e64b',
-	'uvicon-clock': 'e66c',
-	'uvicon-edit-pen': 'e65d',
-	'uvicon-edit-pen-fill': 'e679',
-	'uvicon-email': 'e673',
-	'uvicon-email-fill': 'e683',
-	'uvicon-minus-circle': 'e6a5',
-	'uvicon-plus-circle': 'e603',
-	'uvicon-plus-circle-fill': 'e611',
-	'uvicon-file-text': 'e687',
-	'uvicon-file-text-fill': 'e67f',
-	'uvicon-pushpin': 'e6d1',
-	'uvicon-pushpin-fill': 'e6b6',
-	'uvicon-grid': 'e68c',
-	'uvicon-grid-fill': 'e698',
-	'uvicon-play-circle': 'e6af',
-	'uvicon-play-circle-fill': 'e62a',
-	'uvicon-pause-circle-fill': 'e60c',
-	'uvicon-pause': 'e61c',
-	'uvicon-pause-circle': 'e696',
-	'uvicon-gift-fill': 'e6b0',
-	'uvicon-gift': 'e680',
-	'uvicon-kefu-ermai': 'e660',
-	'uvicon-server-fill': 'e610',
-	'uvicon-coupon-fill': 'e64c',
-	'uvicon-coupon': 'e65f',
-	'uvicon-integral': 'e693',
-	'uvicon-integral-fill': 'e6b1',
-	'uvicon-home-fill': 'e68e',
-	'uvicon-home': 'e67b',
-	'uvicon-account': 'e63a',
-	'uvicon-account-fill': 'e653',
-	'uvicon-thumb-down-fill': 'e628',
-	'uvicon-thumb-down': 'e60a',
-	'uvicon-thumb-up': 'e612',
-	'uvicon-thumb-up-fill': 'e62c',
-	'uvicon-lock-fill': 'e6a6',
-	'uvicon-lock-open': 'e68d',
-	'uvicon-lock-opened-fill': 'e6a1',
-	'uvicon-lock': 'e69d',
-	'uvicon-red-packet': 'e6c3',
-	'uvicon-photo-fill': 'e6b4',
-	'uvicon-photo': 'e60d',
-	'uvicon-volume-off-fill': 'e6c8',
-	'uvicon-volume-off': 'e6bd',
-	'uvicon-volume-fill': 'e624',
-	'uvicon-volume': 'e605',
-	'uvicon-download': 'e670',
-	'uvicon-arrow-up-fill': 'e636',
-	'uvicon-arrow-down-fill': 'e638',
-	'uvicon-play-left-fill': 'e6ae',
-	'uvicon-play-right-fill': 'e6ad',
-	'uvicon-arrow-downward': 'e634',
-	'uvicon-arrow-leftward': 'e63b',
-	'uvicon-arrow-rightward': 'e644',
-	'uvicon-arrow-upward': 'e641',
-	'uvicon-arrow-down': 'e63e',
-	'uvicon-arrow-right': 'e63c',
-	'uvicon-arrow-left': 'e646',
-	'uvicon-arrow-up': 'e633',
-	'uvicon-skip-back-left': 'e6c5',
-	'uvicon-skip-forward-right': 'e61f',
-	'uvicon-arrow-left-double': 'e637',
-	'uvicon-man': 'e675',
-	'uvicon-woman': 'e626',
-	'uvicon-en': 'e6b8',
-	'uvicon-twitte': 'e607',
-	'uvicon-twitter-circle-fill': 'e6cf'
-}

+ 0 - 90
src/uni_modules/uv-icon/components/uv-icon/props.js

@@ -1,90 +0,0 @@
-export default {
-	props: {
-		// 图标类名
-		name: {
-			type: String,
-			default: ''
-		},
-		// 图标颜色,可接受主题色
-		color: {
-			type: String,
-			default: '#606266'
-		},
-		// 字体大小,单位px
-		size: {
-			type: [String, Number],
-			default: '16px'
-		},
-		// 是否显示粗体
-		bold: {
-			type: Boolean,
-			default: false
-		},
-		// 点击图标的时候传递事件出去的index(用于区分点击了哪一个)
-		index: {
-			type: [String, Number],
-			default: null
-		},
-		// 触摸图标时的类名
-		hoverClass: {
-			type: String,
-			default: ''
-		},
-		// 自定义扩展前缀,方便用户扩展自己的图标库
-		customPrefix: {
-			type: String,
-			default: 'uvicon'
-		},
-		// 图标右边或者下面的文字
-		label: {
-			type: [String, Number],
-			default: ''
-		},
-		// label的位置,只能右边或者下边
-		labelPos: {
-			type: String,
-			default: 'right'
-		},
-		// label的大小
-		labelSize: {
-			type: [String, Number],
-			default: '15px'
-		},
-		// label的颜色
-		labelColor: {
-			type: String,
-			default: '#606266'
-		},
-		// label与图标的距离
-		space: {
-			type: [String, Number],
-			default: '3px'
-		},
-		// 图片的mode
-		imgMode: {
-			type: String,
-			default: ''
-		},
-		// 用于显示图片小图标时,图片的宽度
-		width: {
-			type: [String, Number],
-			default: ''
-		},
-		// 用于显示图片小图标时,图片的高度
-		height: {
-			type: [String, Number],
-			default: ''
-		},
-		// 用于解决某些情况下,让图标垂直居中的用途
-		top: {
-			type: [String, Number],
-			default: 0
-		},
-		// 是否阻止事件传播
-		stop: {
-			type: Boolean,
-			default: false
-		},
-		...uni.$uv?.props?.icon
-	}
-}

+ 0 - 221
src/uni_modules/uv-icon/components/uv-icon/uv-icon.vue

@@ -1,221 +0,0 @@
-<template>
-	<view
-	  class="uv-icon"
-	  @tap="clickHandler"
-	  :class="['uv-icon--' + labelPos]"
-	>
-		<image
-		  class="uv-icon__img"
-		  v-if="isImg"
-		  :src="name"
-		  :mode="imgMode"
-		  :style="[imgStyle, $uv.addStyle(customStyle)]"
-		></image>
-		<text
-		  v-else
-		  class="uv-icon__icon"
-		  :class="uClasses"
-		  :style="[iconStyle, $uv.addStyle(customStyle)]"
-		  :hover-class="hoverClass"
-		>{{icon}}</text>
-		<!-- 这里进行空字符串判断,如果仅仅是v-if="label",可能会出现传递0的时候,结果也无法显示 -->
-		<text
-		  v-if="label !== ''" 
-		  class="uv-icon__label"
-		  :style="{
-			color: labelColor,
-			fontSize: $uv.addUnit(labelSize),
-			marginLeft: labelPos == 'right' ? $uv.addUnit(space) : 0,
-			marginTop: labelPos == 'bottom' ? $uv.addUnit(space) : 0,
-			marginRight: labelPos == 'left' ? $uv.addUnit(space) : 0,
-			marginBottom: labelPos == 'top' ? $uv.addUnit(space) : 0
-		}"
-		>{{ label }}</text>
-	</view>
-</template>
-
-<script>
-	import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
-	import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
-	// #ifdef APP-NVUE
-	// nvue通过weex的dom模块引入字体,相关文档地址如下:
-	// https://weex.apache.org/zh/docs/modules/dom.html#addrule
-	import iconUrl from './uvicons.ttf';
-	const domModule = weex.requireModule('dom')
-	domModule.addRule('fontFace', {
-		'fontFamily': "uvicon-iconfont",
-		'src': "url('" + iconUrl + "')"
-	})
-	// #endif
-	// 引入图标名称,已经对应的unicode
-	import icons from './icons';
-	import props from './props.js';
-	/**
-	 * icon 图标
-	 * @description 基于字体的图标集,包含了大多数常见场景的图标。
-	 * @tutorial https://www.uvui.cn/components/icon.html
-	 * @property {String}			name			图标名称,见示例图标集
-	 * @property {String}			color			图标颜色,可接受主题色 (默认 color['uv-content-color'] )
-	 * @property {String | Number}	size			图标字体大小,单位px (默认 '16px' )
-	 * @property {Boolean}			bold			是否显示粗体 (默认 false )
-	 * @property {String | Number}	index			点击图标的时候传递事件出去的index(用于区分点击了哪一个)
-	 * @property {String}			hoverClass		图标按下去的样式类,用法同uni的view组件的hoverClass参数,详情见官网
-	 * @property {String}			customPrefix	自定义扩展前缀,方便用户扩展自己的图标库 (默认 'uicon' )
-	 * @property {String | Number}	label			图标右侧的label文字
-	 * @property {String}			labelPos		label相对于图标的位置,只能right或bottom (默认 'right' )
-	 * @property {String | Number}	labelSize		label字体大小,单位px (默认 '15px' )
-	 * @property {String}			labelColor		图标右侧的label文字颜色 ( 默认 color['uv-content-color'] )
-	 * @property {String | Number}	space			label与图标的距离,单位px (默认 '3px' )
-	 * @property {String}			imgMode			图片的mode
-	 * @property {String | Number}	width			显示图片小图标时的宽度
-	 * @property {String | Number}	height			显示图片小图标时的高度
-	 * @property {String | Number}	top				图标在垂直方向上的定位 用于解决某些情况下,让图标垂直居中的用途  (默认 0 )
-	 * @property {Boolean}			stop			是否阻止事件传播 (默认 false )
-	 * @property {Object}			customStyle		icon的样式,对象形式
-	 * @event {Function} click 点击图标时触发
-	 * @event {Function} touchstart 事件触摸时触发
-	 * @example <uv-icon name="photo" color="#2979ff" size="28"></uv-icon>
-	 */
-	export default {
-		name: 'uv-icon',
-		emits: ['click'],
-		mixins: [mpMixin, mixin, props],
-		data() {
-			return {
-				colorType: [
-					'primary',
-					'success',
-					'info',
-					'error',
-					'warning'
-				]
-			}
-		},
-		computed: {
-			uClasses() {
-				let classes = []
-				classes.push(this.customPrefix)
-				classes.push(this.customPrefix + '-' + this.name)
-				// 主题色,通过类配置
-				if (this.color && this.colorType.includes(this.color)) classes.push('uv-icon__icon--' + this.color)
-				// 阿里,头条,百度小程序通过数组绑定类名时,无法直接使用[a, b, c]的形式,否则无法识别
-				// 故需将其拆成一个字符串的形式,通过空格隔开各个类名
-				//#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
-				classes = classes.join(' ')
-				//#endif
-				return classes
-			},
-			iconStyle() {
-				let style = {}
-				style = {
-					fontSize: this.$uv.addUnit(this.size),
-					lineHeight: this.$uv.addUnit(this.size),
-					fontWeight: this.bold ? 'bold' : 'normal',
-					// 某些特殊情况需要设置一个到顶部的距离,才能更好的垂直居中
-					top: this.$uv.addUnit(this.top)
-				}
-				// 非主题色值时,才当作颜色值
-				if (this.color && !this.colorType.includes(this.color)) style.color = this.color
-				return style
-			},
-			// 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式
-			isImg() {
-				const isBase64 = this.name.indexOf('data:') > -1 && this.name.indexOf('base64') > -1;
-				return this.name.indexOf('/') !== -1 || isBase64;
-			},
-			imgStyle() {
-				let style = {}
-				// 如果设置width和height属性,则优先使用,否则使用size属性
-				style.width = this.width ? this.$uv.addUnit(this.width) : this.$uv.addUnit(this.size)
-				style.height = this.height ? this.$uv.addUnit(this.height) : this.$uv.addUnit(this.size)
-				return style
-			},
-			// 通过图标名,查找对应的图标
-			icon() {
-				// 如果内置的图标中找不到对应的图标,就直接返回name值,因为用户可能传入的是unicode代码
-				const code = icons['uvicon-' + this.name];
-				return code ? unescape(`%u${code}`) : ['uvicon'].indexOf(this.customPrefix) > -1 ? this.name : '';
-			}
-		},
-		methods: {
-			clickHandler(e) {
-				this.$emit('click', this.index)
-				// 是否阻止事件冒泡
-				this.stop && this.preventEvent(e)
-			}
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
-	@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
-	// 变量定义
-	$uv-icon-primary: $uv-primary !default;
-	$uv-icon-success: $uv-success !default;
-	$uv-icon-info: $uv-info !default;
-	$uv-icon-warning: $uv-warning !default;
-	$uv-icon-error: $uv-error !default;
-	$uv-icon-label-line-height: 1 !default;
-	/* #ifndef APP-NVUE */
-	// 非nvue下加载字体
-	@font-face {
-		font-family: 'uvicon-iconfont';
-		src: url('./uvicons.ttf') format('truetype');
-	}
-	/* #endif */
-	.uv-icon {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		align-items: center;
-		&--left {
-			flex-direction: row-reverse;
-			align-items: center;
-		}
-		&--right {
-			flex-direction: row;
-			align-items: center;
-		}
-		&--top {
-			flex-direction: column-reverse;
-			justify-content: center;
-		}
-		&--bottom {
-			flex-direction: column;
-			justify-content: center;
-		}
-		&__icon {
-			font-family: uvicon-iconfont;
-			position: relative;
-			@include flex;
-			align-items: center;
-			&--primary {
-				color: $uv-icon-primary;
-			}
-			&--success {
-				color: $uv-icon-success;
-			}
-			&--error {
-				color: $uv-icon-error;
-			}
-			&--warning {
-				color: $uv-icon-warning;
-			}
-			&--info {
-				color: $uv-icon-info;
-			}
-		}
-		&__img {
-			/* #ifndef APP-NVUE */
-			height: auto;
-			will-change: transform;
-			/* #endif */
-		}
-		&__label {
-			/* #ifndef APP-NVUE */
-			line-height: $uv-icon-label-line-height;
-			/* #endif */
-		}
-	}
-</style>

二進制
src/uni_modules/uv-icon/components/uv-icon/uvicons.ttf


+ 0 - 83
src/uni_modules/uv-icon/package.json

@@ -1,83 +0,0 @@
-{
-  "id": "uv-icon",
-  "displayName": "uv-icon 图标 全面兼容vue3+2、app、h5、小程序等多端",
-  "version": "1.0.9",
-  "description": "基于字体的图标集,包含了大多数常见场景的图标,支持自定义,支持自定义图片图标等。可自定义颜色、大小。",
-  "keywords": [
-    "uv-ui,uvui,uv-icon,icon,图标,字体图标"
-],
-  "repository": "",
-  "engines": {
-    "HBuilderX": "^3.1.0"
-  },
-  "dcloudext": {
-    "type": "component-vue",
-    "sale": {
-      "regular": {
-        "price": "0.00"
-      },
-      "sourcecode": {
-        "price": "0.00"
-      }
-    },
-    "contact": {
-      "qq": ""
-    },
-    "declaration": {
-      "ads": "无",
-      "data": "插件不采集任何数据",
-      "permissions": "无"
-    },
-    "npmurl": ""
-  },
-  "uni_modules": {
-    "dependencies": [
-			"uv-ui-tools"
-		],
-    "encrypt": [],
-    "platforms": {
-      "cloud": {
-        "tcb": "y",
-        "aliyun": "y"
-      },
-      "client": {
-        "Vue": {
-          "vue2": "y",
-          "vue3": "y"
-        },
-        "App": {
-          "app-vue": "y",
-          "app-nvue": "y"
-        },
-        "H5-mobile": {
-          "Safari": "y",
-          "Android Browser": "y",
-          "微信浏览器(Android)": "y",
-          "QQ浏览器(Android)": "y"
-        },
-        "H5-pc": {
-          "Chrome": "y",
-          "IE": "y",
-          "Edge": "y",
-          "Firefox": "y",
-          "Safari": "y"
-        },
-        "小程序": {
-          "微信": "y",
-          "阿里": "y",
-          "百度": "y",
-          "字节跳动": "y",
-          "QQ": "y",
-          "钉钉": "u",
-          "快手": "u",
-          "飞书": "u",
-          "京东": "u"
-        },
-        "快应用": {
-          "华为": "u",
-          "联盟": "u"
-        }
-      }
-    }
-  }
-}

+ 0 - 15
src/uni_modules/uv-icon/readme.md

@@ -1,15 +0,0 @@
-## uv-icon 图标库
-
-> **组件名:uv-icon**
-
-基于字体的图标集,包含了大多数常见场景的图标,支持自定义,支持自定义图片图标等。
-
-# <a href="https://www.uvui.cn/components/icon.html" target="_blank">查看文档</a>
-
-## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui)
-
-### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
-
-![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
-
-#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

+ 0 - 7
src/uni_modules/uv-loading-icon/changelog.md

@@ -1,7 +0,0 @@
-## 1.0.2(2023-06-27)
-优化
-## 1.0.1(2023-05-16)
-1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
-2. 优化部分功能
-## 1.0.0(2023-05-10)
-1. 新增uv-loading-icon组件

+ 0 - 60
src/uni_modules/uv-loading-icon/components/uv-loading-icon/props.js

@@ -1,60 +0,0 @@
-export default {
-	props: {
-		// 是否显示组件
-		show: {
-			type: Boolean,
-			default: true
-		},
-		// 颜色
-		color: {
-			type: String,
-			default: '#909193'
-		},
-		// 提示文字颜色
-		textColor: {
-			type: String,
-			default: '#909193'
-		},
-		// 文字和图标是否垂直排列
-		vertical: {
-			type: Boolean,
-			default: false
-		},
-		// 模式选择,circle-圆形,spinner-花朵形,semicircle-半圆形
-		mode: {
-			type: String,
-			default: 'spinner'
-		},
-		// 图标大小,单位默认px
-		size: {
-			type: [String, Number],
-			default: 24
-		},
-		// 文字大小
-		textSize: {
-			type: [String, Number],
-			default: 15
-		},
-		// 文字内容
-		text: {
-			type: [String, Number],
-			default: ''
-		},
-		// 动画模式 https://www.runoob.com/cssref/css3-pr-animation-timing-function.html
-		timingFunction: {
-			type: String,
-			default: 'linear'
-		},
-		// 动画执行周期时间
-		duration: {
-			type: [String, Number],
-			default: 1200
-		},
-		// mode=circle时的暗边颜色
-		inactiveColor: {
-			type: String,
-			default: ''
-		},
-		...uni.$uv?.props?.loadingIcon
-	}
-}

+ 0 - 346
src/uni_modules/uv-loading-icon/components/uv-loading-icon/uv-loading-icon.vue

@@ -1,346 +0,0 @@
-<template>
-	<view
-		class="uv-loading-icon"
-		:style="[$uv.addStyle(customStyle)]"
-		:class="[vertical && 'uv-loading-icon--vertical']"
-		v-if="show"
-	>
-		<view
-			v-if="!webviewHide"
-			class="uv-loading-icon__spinner"
-			:class="[`uv-loading-icon__spinner--${mode}`]"
-			ref="ani"
-			:style="{
-				color: color,
-				width: $uv.addUnit(size),
-				height: $uv.addUnit(size),
-				borderTopColor: color,
-				borderBottomColor: otherBorderColor,
-				borderLeftColor: otherBorderColor,
-				borderRightColor: otherBorderColor,
-				'animation-duration': `${duration}ms`,
-				'animation-timing-function': mode === 'semicircle' || mode === 'circle' ? timingFunction : ''
-			}"
-		>
-			<block v-if="mode === 'spinner'">
-				<!-- #ifndef APP-NVUE -->
-				<view
-					v-for="(item, index) in array12"
-					:key="index"
-					class="uv-loading-icon__dot"
-				>
-				</view>
-				<!-- #endif -->
-				<!-- #ifdef APP-NVUE -->
-				<!-- 此组件内部图标部分无法设置宽高,即使通过width和height配置了也无效 -->
-				<loading-indicator
-					v-if="!webviewHide"
-					class="uv-loading-indicator"
-					:animating="true"
-					:style="{
-						color: color,
-						width: $uv.addUnit(size),
-						height: $uv.addUnit(size)
-					}"
-				/>
-				<!-- #endif -->
-			</block>
-		</view>
-		<text
-			v-if="text"
-			class="uv-loading-icon__text"
-			:style="{
-				fontSize: $uv.addUnit(textSize),
-				color: textColor,
-			}"
-		>{{text}}</text>
-	</view>
-</template>
-
-<script>
-	import { colorGradient } from '@/uni_modules/uv-ui-tools/libs/function/colorGradient.js'
-	import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
-	import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
-	import props from './props.js';
-	// #ifdef APP-NVUE
-	const animation = weex.requireModule('animation');
-	// #endif
-	/**
-	 * loading 加载动画
-	 * @description 警此组件为一个小动画,目前用在uvui的loadmore加载更多和switch开关等组件的正在加载状态场景。
-	 * @tutorial https://www.uvui.cn/components/loading.html
-	 * @property {Boolean}			show			是否显示组件  (默认 true)
-	 * @property {String}			color			动画活动区域的颜色,只对 mode = flower 模式有效(默认#909193)
-	 * @property {String}			textColor		提示文本的颜色(默认#909193)
-	 * @property {Boolean}			vertical		文字和图标是否垂直排列 (默认 false )
-	 * @property {String}			mode			模式选择,见官网说明(默认 'circle' )
-	 * @property {String | Number}	size			加载图标的大小,单位px (默认 24 )
-	 * @property {String | Number}	textSize		文字大小(默认 15 )
-	 * @property {String | Number}	text			文字内容 
-	 * @property {String}			timingFunction	动画模式 (默认 'ease-in-out' )
-	 * @property {String | Number}	duration		动画执行周期时间(默认 1200)
-	 * @property {String}			inactiveColor	mode=circle时的暗边颜色 
-	 * @property {Object}			customStyle		定义需要用到的外部样式
-	 * @example <uv-loading mode="circle"></uv-loading>
-	 */
-	export default {
-		name: 'uv-loading-icon',
-		mixins: [mpMixin, mixin, props],
-		data() {
-			return {
-				// Array.form可以通过一个伪数组对象创建指定长度的数组
-				// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/from
-				array12: Array.from({
-					length: 12
-				}),
-				// 这里需要设置默认值为360,否则在安卓nvue上,会延迟一个duration周期后才执行
-				// 在iOS nvue上,则会一开始默认执行两个周期的动画
-				aniAngel: 360, // 动画旋转角度
-				webviewHide: false, // 监听webview的状态,如果隐藏了页面,则停止动画,以免性能消耗
-				loading: false, // 是否运行中,针对nvue使用
-			}
-		},
-		computed: {
-			// 当为circle类型时,给其另外三边设置一个更轻一些的颜色
-			// 之所以需要这么做的原因是,比如父组件传了color为红色,那么需要另外的三个边为浅红色
-			// 而不能是固定的某一个其他颜色(因为这个固定的颜色可能浅蓝,导致效果没有那么细腻良好)
-			otherBorderColor() {
-				const lightColor = colorGradient(this.color, '#ffffff', 100)[80]
-				if (this.mode === 'circle') {
-					return this.inactiveColor ? this.inactiveColor : lightColor
-				} else {
-					return 'transparent'
-				}
-			}
-		},
-		watch: {
-			show(n) {
-				// nvue中,show为true,且为非loading状态,就重新执行动画模块
-				// #ifdef APP-NVUE
-				if (n && !this.loading) {
-					setTimeout(() => {
-						this.startAnimate()
-					}, 30)
-				}
-				// #endif
-			}
-		},
-		mounted() {
-			this.init()
-		},
-		methods: {
-			init() {
-				setTimeout(() => {
-					// #ifdef APP-NVUE
-					this.show && this.nvueAnimate()
-					// #endif
-					// #ifdef APP-PLUS 
-					this.show && this.addEventListenerToWebview()
-					// #endif
-				}, 20)
-			},
-			// 监听webview的显示与隐藏
-			addEventListenerToWebview() {
-				// webview的堆栈
-				const pages = getCurrentPages()
-				// 当前页面
-				const page = pages[pages.length - 1]
-				// 当前页面的webview实例
-				const currentWebview = page.$getAppWebview()
-				// 监听webview的显示与隐藏,从而停止或者开始动画(为了性能)
-				currentWebview.addEventListener('hide', () => {
-					this.webviewHide = true
-				})
-				currentWebview.addEventListener('show', () => {
-					this.webviewHide = false
-				})
-			},
-			// #ifdef APP-NVUE
-			nvueAnimate() {
-				// nvue下,非spinner类型时才需要旋转,因为nvue的spinner类型,使用了weex的
-				// loading-indicator组件,自带旋转功能
-				this.mode !== 'spinner' && this.startAnimate()
-			},
-			// 执行nvue的animate模块动画
-			startAnimate() {
-				this.loading = true
-				const ani = this.$refs.ani
-				if (!ani) return
-				animation.transition(ani, {
-					// 进行角度旋转
-					styles: {
-						transform: `rotate(${this.aniAngel}deg)`,
-						transformOrigin: 'center center'
-					},
-					duration: this.duration,
-					timingFunction: this.timingFunction,
-					// delay: 10
-				}, () => {
-					// 每次增加360deg,为了让其重新旋转一周
-					this.aniAngel += 360
-					// 动画结束后,继续循环执行动画,需要同时判断webviewHide变量
-					// nvue安卓,页面隐藏后依然会继续执行startAnimate方法
-					this.show && !this.webviewHide ? this.startAnimate() : this.loading = false
-				})
-			}
-			// #endif
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
-	@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
-	$uv-loading-icon-color: #c8c9cc !default;
-	$uv-loading-icon-text-margin-left:4px !default;
-	$uv-loading-icon-text-color:$uv-content-color !default;
-	$uv-loading-icon-text-font-size:14px !default;
-	$uv-loading-icon-text-line-height:20px !default;
-	$uv-loading-width:30px !default;
-	$uv-loading-height:30px !default;
-	$uv-loading-max-width:100% !default;
-	$uv-loading-max-height:100% !default;
-	$uv-loading-semicircle-border-width: 2px !default;
-	$uv-loading-semicircle-border-color:transparent !default;
-	$uv-loading-semicircle-border-top-right-radius: 100px !default;
-	$uv-loading-semicircle-border-top-left-radius: 100px !default;
-	$uv-loading-semicircle-border-bottom-left-radius: 100px !default;
-	$uv-loading-semicircle-border-bottom-right-radiu: 100px !default;
-	$uv-loading-semicircle-border-style: solid !default;
-	$uv-loading-circle-border-top-right-radius: 100px !default;
-	$uv-loading-circle-border-top-left-radius: 100px !default;
-	$uv-loading-circle-border-bottom-left-radius: 100px !default;
-	$uv-loading-circle-border-bottom-right-radiu: 100px !default;
-	$uv-loading-circle-border-width:2px !default;
-	$uv-loading-circle-border-top-color:#e5e5e5 !default;
-	$uv-loading-circle-border-right-color:$uv-loading-circle-border-top-color !default;
-	$uv-loading-circle-border-bottom-color:$uv-loading-circle-border-top-color !default;
-	$uv-loading-circle-border-left-color:$uv-loading-circle-border-top-color !default;
-	$uv-loading-circle-border-style:solid !default;
-	$uv-loading-icon-host-font-size:0px !default;
-	$uv-loading-icon-host-line-height:1 !default;
-	$uv-loading-icon-vertical-margin:6px 0 0 !default;
-	$uv-loading-icon-dot-top:0 !default;
-	$uv-loading-icon-dot-left:0 !default;
-	$uv-loading-icon-dot-width:100% !default;
-	$uv-loading-icon-dot-height:100% !default;
-	$uv-loading-icon-dot-before-width:2px !default;
-	$uv-loading-icon-dot-before-height:25% !default;
-	$uv-loading-icon-dot-before-margin:0 auto !default;
-	$uv-loading-icon-dot-before-background-color:currentColor !default;
-	$uv-loading-icon-dot-before-border-radius:40% !default;
-
-	.uv-loading-icon {
-		/* #ifndef APP-NVUE */
-		// display: inline-flex;
-		/* #endif */
-		flex-direction: row;
-		align-items: center;
-		justify-content: center;
-		color: $uv-loading-icon-color;
-
-		&__text {
-			margin-left: $uv-loading-icon-text-margin-left;
-			color: $uv-loading-icon-text-color;
-			font-size: $uv-loading-icon-text-font-size;
-			line-height: $uv-loading-icon-text-line-height;
-		}
-
-		&__spinner {
-			width: $uv-loading-width;
-			height: $uv-loading-height;
-			position: relative;
-			/* #ifndef APP-NVUE */
-			box-sizing: border-box;
-			max-width: $uv-loading-max-width;
-			max-height: $uv-loading-max-height;
-			animation: uv-rotate 1s linear infinite;
-			/* #endif */
-		}
-
-		&__spinner--semicircle {
-			border-width: $uv-loading-semicircle-border-width;
-			border-color: $uv-loading-semicircle-border-color;
-			border-top-right-radius: $uv-loading-semicircle-border-top-right-radius;
-			border-top-left-radius: $uv-loading-semicircle-border-top-left-radius;
-			border-bottom-left-radius: $uv-loading-semicircle-border-bottom-left-radius;
-			border-bottom-right-radius: $uv-loading-semicircle-border-bottom-right-radiu;
-			border-style: $uv-loading-semicircle-border-style;
-		}
-
-		&__spinner--circle {
-			border-top-right-radius: $uv-loading-circle-border-top-right-radius;
-			border-top-left-radius: $uv-loading-circle-border-top-left-radius;
-			border-bottom-left-radius: $uv-loading-circle-border-bottom-left-radius;
-			border-bottom-right-radius: $uv-loading-circle-border-bottom-right-radiu;
-			border-width: $uv-loading-circle-border-width;
-			border-top-color: $uv-loading-circle-border-top-color;
-			border-right-color: $uv-loading-circle-border-right-color;
-			border-bottom-color: $uv-loading-circle-border-bottom-color;
-			border-left-color: $uv-loading-circle-border-left-color;
-			border-style: $uv-loading-circle-border-style;
-		}
-
-		&--vertical {
-			flex-direction: column
-		}
-	}
-
-	/* #ifndef APP-NVUE */
-	:host {
-		font-size: $uv-loading-icon-host-font-size;
-		line-height: $uv-loading-icon-host-line-height;
-	}
-
-	.uv-loading-icon {
-		&__spinner--spinner {
-			animation-timing-function: steps(12)
-		}
-
-		&__text:empty {
-			display: none
-		}
-
-		&--vertical &__text {
-			margin: $uv-loading-icon-vertical-margin;
-			color: $uv-content-color;
-		}
-
-		&__dot {
-			position: absolute;
-			top: $uv-loading-icon-dot-top;
-			left: $uv-loading-icon-dot-left;
-			width: $uv-loading-icon-dot-width;
-			height: $uv-loading-icon-dot-height;
-
-			&:before {
-				display: block;
-				width: $uv-loading-icon-dot-before-width;
-				height: $uv-loading-icon-dot-before-height;
-				margin: $uv-loading-icon-dot-before-margin;
-				background-color: $uv-loading-icon-dot-before-background-color;
-				border-radius: $uv-loading-icon-dot-before-border-radius;
-				content: " "
-			}
-		}
-	}
-
-	@for $i from 1 through 12 {
-		.uv-loading-icon__dot:nth-of-type(#{$i}) {
-			transform: rotate($i * 30deg);
-			opacity: 1 - 0.0625 * ($i - 1);
-		}
-	}
-
-	@keyframes uv-rotate {
-		0% {
-			transform: rotate(0deg)
-		}
-
-		to {
-			transform: rotate(1turn)
-		}
-	}
-
-	/* #endif */
-</style>

+ 0 - 87
src/uni_modules/uv-loading-icon/package.json

@@ -1,87 +0,0 @@
-{
-  "id": "uv-loading-icon",
-  "displayName": "uv-loading-icon 加载动画  全面兼容小程序、nvue、vue2、vue3等多端",
-  "version": "1.0.2",
-  "description": "uv-loading-icon 此组件为一个小动画,目前用在uv-ui的loadMore加载更多等组件的正在加载状态场景。",
-  "keywords": [
-    "uv-loading-icon",
-    "uvui",
-    "uv-ui",
-    "loading",
-    "加载动画"
-],
-  "repository": "",
-  "engines": {
-    "HBuilderX": "^3.1.0"
-  },
-  "dcloudext": {
-    "type": "component-vue",
-    "sale": {
-      "regular": {
-        "price": "0.00"
-      },
-      "sourcecode": {
-        "price": "0.00"
-      }
-    },
-    "contact": {
-      "qq": ""
-    },
-    "declaration": {
-    	"ads": "无",
-    	"data": "插件不采集任何数据",
-    	"permissions": "无"
-    },
-    "npmurl": ""
-  },
-  "uni_modules": {
-    "dependencies": [
-			"uv-ui-tools"
-		],
-    "encrypt": [],
-    "platforms": {
-			"cloud": {
-				"tcb": "y",
-				"aliyun": "y"
-			},
-			"client": {
-				"Vue": {
-					"vue2": "y",
-					"vue3": "y"
-				},
-				"App": {
-					"app-vue": "y",
-					"app-nvue": "y"
-				},
-				"H5-mobile": {
-					"Safari": "y",
-					"Android Browser": "y",
-					"微信浏览器(Android)": "y",
-					"QQ浏览器(Android)": "y"
-				},
-				"H5-pc": {
-					"Chrome": "y",
-					"IE": "y",
-					"Edge": "y",
-					"Firefox": "y",
-					"Safari": "y"
-				},
-				"小程序": {
-					"微信": "y",
-					"阿里": "y",
-					"百度": "y",
-					"字节跳动": "y",
-					"QQ": "y",
-					"钉钉": "u",
-					"快手": "u",
-					"飞书": "u",
-					"京东": "u"
-				},
-				"快应用": {
-					"华为": "u",
-					"联盟": "u"
-				}
-			}
-		}
-  }
-}

+ 0 - 11
src/uni_modules/uv-loading-icon/readme.md

@@ -1,11 +0,0 @@
-## LoadingIcon 加载动画
-
-> **组件名:uv-loading-icon**
-
-此组件为一个小动画,目前用在uv-ui的loadMore加载更多等组件的正在加载状态场景。
-
-### <a href="https://www.uvui.cn/components/loadingIcon.html" target="_blank">查看文档</a>
-
-### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
-
-#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

+ 0 - 15
src/uni_modules/uv-search/changelog.md

@@ -1,15 +0,0 @@
-## 1.0.6(2023-07-26)
-1. 增加boxStyle参数,方便控制输入框部分的样式
-## 1.0.5(2023-07-26)
-1. 增加prefix和suffix  前置和后置插槽
-## 1.0.4(2023-07-13)
-1. 修复value值清空不生效的BUG
-## 1.0.3(2023-07-13)
-1. 修复value/v-model更改不生效的BUG
-## 1.0.2(2023-07-03)
-去除无用的插槽
-## 1.0.1(2023-05-16)
-1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
-2. 优化部分功能
-## 1.0.0(2023-05-10)
-uv-search 搜索

+ 0 - 127
src/uni_modules/uv-search/components/uv-search/props.js

@@ -1,127 +0,0 @@
-export default {
-	props: {
-		value: {
-			type: String,
-			default: ''
-		},
-		modelValue: {
-			type: String,
-			default: ''
-		},
-		// 搜索框形状,round-圆形,square-方形
-		shape: {
-			type: String,
-			default: 'round'
-		},
-		// 搜索框背景色,默认值#f2f2f2
-		bgColor: {
-			type: String,
-			default: '#f2f2f2'
-		},
-		// 占位提示文字
-		placeholder: {
-			type: String,
-			default: '请输入关键字'
-		},
-		// 是否启用清除控件
-		clearabled: {
-			type: Boolean,
-			default: true
-		},
-		// 是否自动聚焦
-		focus: {
-			type: Boolean,
-			default: false
-		},
-		// 是否在搜索框右侧显示取消按钮
-		showAction: {
-			type: Boolean,
-			default: true
-		},
-		// 右边控件的样式
-		actionStyle: {
-			type: Object,
-			default: () => ({})
-		},
-		// 取消按钮文字
-		actionText: {
-			type: String,
-			default: '搜索'
-		},
-		// 输入框内容对齐方式,可选值为 left|center|right
-		inputAlign: {
-			type: String,
-			default: 'left'
-		},
-		// input输入框的样式,可以定义文字颜色,大小等,对象形式
-		inputStyle: {
-			type: Object,
-			default: () => ({})
-		},
-		// 是否禁用输入框
-		disabled: {
-			type: Boolean,
-			default: false
-		},
-		// 边框颜色
-		borderColor: {
-			type: String,
-			default: 'transparent'
-		},
-		// 搜索图标的颜色,默认同输入框字体颜色
-		searchIconColor: {
-			type: String,
-			default: '#909399'
-		},
-		// 输入框字体颜色
-		color: {
-			type: String,
-			default: '#606266'
-		},
-		// placeholder的颜色
-		placeholderColor: {
-			type: String,
-			default: '#909399'
-		},
-		// 左边输入框的图标,可以为uvui图标名称或图片路径
-		searchIcon: {
-			type: String,
-			default: 'search'
-		},
-		searchIconSize: {
-			type: [Number, String],
-			default: 22
-		},
-		// 组件与其他上下左右元素之间的距离,带单位的字符串形式,如"30px"、"30px 20px"等写法
-		margin: {
-			type: String,
-			default: '0'
-		},
-		// 开启showAction时,是否在input获取焦点时才显示
-		animation: {
-			type: Boolean,
-			default: false
-		},
-		// 输入框最大能输入的长度,-1为不限制长度(来自uniapp文档)
-		maxlength: {
-			type: [String, Number],
-			default: -1
-		},
-		// 搜索框高度,单位px
-		height: {
-			type: [String, Number],
-			default: 32
-		},
-		// 搜索框左侧文本
-		label: {
-			type: [String, Number, null],
-			default: null
-		},
-		// 搜索框扩展样式
-		boxStyle: {
-			type: [String, Object],
-			default: ()=>{}
-		},
-		...uni.$uv?.props?.search
-	}
-}

+ 0 - 295
src/uni_modules/uv-search/components/uv-search/uv-search.vue

@@ -1,295 +0,0 @@
-<template>
-	<view
-	  class="uv-search"
-	  @tap="clickHandler"
-	  :style="[{
-			margin: margin,
-		}, $uv.addStyle(customStyle)]"
-	>
-		<view
-		  class="uv-search__content"
-		  :style="{
-				backgroundColor: bgColor,
-				borderRadius: shape == 'round' ? '100px' : '4px',
-				borderColor: borderColor,
-			}"
-		>
-			<slot name="prefix">
-				<view class="uv-search__content__icon">
-					<uv-icon
-						@tap="clickIcon"
-					  :size="searchIconSize"
-					  :name="searchIcon"
-					  :color="searchIconColor ? searchIconColor : color"
-					></uv-icon>
-				</view>
-			</slot>
-			<input
-			  confirm-type="search"
-			  @blur="blur"
-			  :value="keyword"
-			  @confirm="search"
-			  @input="inputChange"
-			  :disabled="disabled"
-			  @focus="getFocus"
-			  :focus="focus"
-			  :maxlength="maxlength"
-			  placeholder-class="uv-search__content__input--placeholder"
-			  :placeholder="placeholder"
-			  :placeholder-style="`color: ${placeholderColor}`"
-			  class="uv-search__content__input"
-			  type="text"
-			  :style="[{
-					textAlign: inputAlign,
-					color: color,
-					backgroundColor: bgColor,
-					height: $uv.addUnit(height)
-				}, inputStyle]"
-			/>
-			<view
-			  class="uv-search__content__icon uv-search__content__close"
-			  v-if="keyword && clearabled && focused"
-			  @tap="clear"
-			>
-				<uv-icon
-				  name="close"
-				  size="11"
-				  color="#ffffff"
-					customStyle="line-height: 12px"
-				></uv-icon>
-			</view>
-			<slot name="suffix"></slot>
-		</view>
-		<text
-		  :style="[actionStyle]"
-		  class="uv-search__action"
-		  :class="[(showActionBtn || show) && 'uv-search__action--active']"
-		  @tap.stop.prevent="custom"
-		>{{ actionText }}</text>
-	</view>
-</template>
-
-<script>
-	import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
-	import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
-	import props from './props.js';
-	/**
-	 * search 搜索框
-	 * @description 搜索组件,集成了常见搜索框所需功能,用户可以一键引入,开箱即用。
-	 * @tutorial https://www.uvui.cn/components/search.html
-	 * @property {String}			value/v-model				输入框初始值
-	 * @property {String}			shape				搜索框形状,round-圆形,square-方形(默认 'round' )
-	 * @property {String}			bgColor				搜索框背景颜色(默认 '#f2f2f2' )
-	 * @property {String}			placeholder			占位文字内容(默认 '请输入关键字' )
-	 * @property {Boolean}			clearabled			是否启用清除控件(默认 true )
-	 * @property {Boolean}			focus				是否自动获得焦点(默认 false )
-	 * @property {Boolean}			showAction			是否显示右侧控件(默认 true )
-	 * @property {Object}			actionStyle			右侧控件的样式,对象形式
-	 * @property {String}			actionText			右侧控件文字(默认 '搜索' )
-	 * @property {String}			inputAlign			输入框内容水平对齐方式 (默认 'left' )
-	 * @property {Object}			inputStyle			自定义输入框样式,对象形式
-	 * @property {Boolean}			disabled			是否启用输入框(默认 false )
-	 * @property {String}			borderColor			边框颜色,配置了颜色,才会有边框 (默认 'transparent' )
-	 * @property {String}			searchIconColor		搜索图标的颜色,默认同输入框字体颜色 (默认 '#909399' )
-	 * @property {Number | String}	searchIconSize 搜索图标的字体,默认22
-	 * @property {String}			color				输入框字体颜色(默认 '#606266' )
-	 * @property {String}			placeholderColor	placeholder的颜色(默认 '#909399' )
-	 * @property {String}			searchIcon			输入框左边的图标,可以为uvui图标名称或图片路径  (默认 'search' )
-	 * @property {String}			margin				组件与其他上下左右元素之间的距离,带单位的字符串形式,如"30px"   (默认 '0' )
-	 * @property {Boolean} 			animation			是否开启动画,见上方说明(默认 false )
-	 * @property {String | Number}	maxlength			输入框最大能输入的长度,-1为不限制长度  (默认 '-1' )
-	 * @property {String | Number}	height				输入框高度,单位px(默认 64 )
-	 * @property {String | Number}	label				搜索框左边显示内容
-	 * @property {Object}			customStyle			定义需要用到的外部样式
-	 *
-	 * @event {Function} change 输入框内容发生变化时触发
-	 * @event {Function} search 用户确定搜索时触发,用户按回车键,或者手机键盘右下角的"搜索"键时触发
-	 * @event {Function} custom 用户点击右侧控件时触发
-	 * @event {Function} clear 用户点击清除按钮时触发
-	 * @example <uv-search placeholder="日照香炉生紫烟" v-model="keyword"></uv-search>
-	 */
-	export default {
-		name: "uv-search",
-		emits: ['click', 'input', 'change', 'clear', 'search', 'custom', 'focus', 'blur', 'clickIcon', 'update:modelValue'],
-		mixins: [mpMixin, mixin, props],
-		data() {
-			return {
-				keyword: '',
-				showClear: false, // 是否显示右边的清除图标
-				show: false,
-				// 标记input当前状态是否处于聚焦中,如果是,才会显示右侧的清除控件
-				focused: this.focus
-			};
-		},
-		created() {
-			this.keyword = this.value || this.modelValue;
-		},
-		watch: {
-			value(nVal){
-				this.keyword = nVal;
-			},
-			modelValue(nVal){
-				this.keyword = nVal;
-			}
-		},
-		computed: {
-			showActionBtn() {
-				return !this.animation && this.showAction
-			}
-		},
-		methods: {
-			keywordChange(){
-				this.$emit('input', this.keyword)
-				this.$emit('update:modelValue', this.keyword)
-				this.$emit('change', this.keyword);
-			},
-			// 目前HX2.6.9 v-model双向绑定无效,故监听input事件获取输入框内容的变化
-			inputChange(e) {
-				this.keyword = e.detail.value;
-				this.keywordChange();
-			},
-			// 清空输入
-			// 也可以作为用户通过this.$refs形式调用清空输入框内容
-			clear() {
-				this.keyword = '';
-				this.$nextTick(() => {
-					this.$emit('clear');
-				})
-				this.keywordChange();
-			},
-			// 确定搜索
-			search(e) {
-				this.$emit('search', e.detail.value);
-				try {
-					// 收起键盘
-					uni.hideKeyboard();
-				} catch (e) {}
-			},
-			// 点击右边自定义按钮的事件
-			custom() {
-				this.$emit('custom', this.keyword);
-				try {
-					// 收起键盘
-					uni.hideKeyboard();
-				} catch (e) {}
-			},
-			// 获取焦点
-			getFocus() {
-				this.focused = true;
-				// 开启右侧搜索按钮展开的动画效果
-				if (this.animation && this.showAction) this.show = true;
-				this.$emit('focus', this.keyword);
-			},
-			// 失去焦点
-			blur() {
-				// 最开始使用的是监听图标@touchstart事件,自从hx2.8.4后,此方法在微信小程序出错
-				// 这里改为监听点击事件,手点击清除图标时,同时也发生了@blur事件,导致图标消失而无法点击,这里做一个延时
-				setTimeout(() => {
-					this.focused = false;
-				}, 100)
-				this.show = false;
-				this.$emit('blur', this.keyword);
-			},
-			// 点击搜索框,只有disabled=true时才发出事件,因为禁止了输入,意味着是想跳转真正的搜索页
-			clickHandler() {
-				if (this.disabled) this.$emit('click');
-			},
-			// 点击左边图标
-			clickIcon() {
-				this.$emit('clickIcon');
-			}
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
-	@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
-	$uv-search-content-padding: 0 10px !default;
-	$uv-search-label-color: $uv-main-color !default;
-	$uv-search-label-font-size: 14px !default;
-	$uv-search-label-margin: 0 4px !default;
-	$uv-search-close-size: 20px !default;
-	$uv-search-close-radius: 100px !default;
-	$uv-search-close-bgColor: #C6C7CB !default;
-	$uv-search-close-transform: scale(0.82) !default;
-	$uv-search-input-font-size: 14px !default;
-	$uv-search-input-margin: 0 5px !default;
-	$uv-search-input-color: $uv-main-color !default;
-	$uv-search-input-placeholder-color: $uv-tips-color !default;
-	$uv-search-action-font-size: 14px !default;
-	$uv-search-action-color: $uv-main-color !default;
-	$uv-search-action-width: 0 !default;
-	$uv-search-action-active-width: 40px !default;
-	$uv-search-action-margin-left: 5px !default;
-	/* #ifdef H5 */
-	// iOS15在H5下,hx的某些版本,input type=search时,会多了一个搜索图标,进行移除
-	[type="search"]::-webkit-search-decoration {
-		display: none;
-	}
-	/* #endif */
-	.uv-search {
-		@include flex(row);
-		align-items: center;
-		flex: 1;
-		&__content {
-			@include flex;
-			align-items: center;
-			// padding: $uv-search-content-padding;
-			flex: 1;
-			justify-content: space-between;
-			border-width: 1px;
-			border-color: transparent;
-			border-style: solid;
-			overflow: hidden;
-			&__icon {
-				@include flex;
-				align-items: center;
-			}
-			&__label {
-				color: $uv-search-label-color;
-				font-size: $uv-search-label-font-size;
-				margin: $uv-search-label-margin;
-			}
-			&__close {
-				width: $uv-search-close-size;
-				height: $uv-search-close-size;
-				border-top-left-radius: $uv-search-close-radius;
-				border-top-right-radius: $uv-search-close-radius;
-				border-bottom-left-radius: $uv-search-close-radius;
-				border-bottom-right-radius: $uv-search-close-radius;
-				background-color: $uv-search-close-bgColor;
-				@include flex(row);
-				align-items: center;
-				justify-content: center;
-				transform: $uv-search-close-transform;
-			}
-			&__input {
-				flex: 1;
-				font-size: $uv-search-input-font-size;
-				line-height: 1;
-				margin: $uv-search-input-margin;
-				color: $uv-search-input-color;
-				&--placeholder {
-					color: $uv-search-input-placeholder-color;
-				}
-			}
-		}
-		&__action {
-			font-size: $uv-search-action-font-size;
-			color: $uv-search-action-color;
-			width: $uv-search-action-width;
-			overflow: hidden;
-			transition-property: width;
-			transition-duration: 0.3s;
-			/* #ifndef APP-NVUE */
-			white-space: nowrap;
-			/* #endif */
-			text-align: center;
-			&--active {
-				width: $uv-search-action-active-width;
-				margin-left: $uv-search-action-margin-left;
-			}
-		}
-	}
-</style>

+ 0 - 89
src/uni_modules/uv-search/package.json

@@ -1,89 +0,0 @@
-{
-  "id": "uv-search",
-  "displayName": "uv-search 搜索 全面兼容vue3+2、app、h5、小程序等多端",
-  "version": "1.0.6",
-  "description": "搜索组件,集成了常见搜索框所需功能,支持前后插槽,用户可以一键引入,开箱即用",
-  "keywords": [
-    "uv-search",
-    "uvui",
-    "uv-ui",
-    "search",
-    "搜索"
-],
-  "repository": "",
-  "engines": {
-    "HBuilderX": "^3.1.0"
-  },
-  "dcloudext": {
-    "type": "component-vue",
-    "sale": {
-      "regular": {
-        "price": "0.00"
-      },
-      "sourcecode": {
-        "price": "0.00"
-      }
-    },
-    "contact": {
-      "qq": ""
-    },
-    "declaration": {
-    	"ads": "无",
-    	"data": "插件不采集任何数据",
-    	"permissions": "无"
-    },
-    "npmurl": ""
-  },
-  "uni_modules": {
-    "dependencies": [
-			"uv-ui-tools",
-			"uv-icon",
-			"uv-loading-icon"
-		],
-    "encrypt": [],
-    "platforms": {
-			"cloud": {
-				"tcb": "y",
-				"aliyun": "y"
-			},
-			"client": {
-				"Vue": {
-					"vue2": "y",
-					"vue3": "y"
-				},
-				"App": {
-					"app-vue": "y",
-					"app-nvue": "y"
-				},
-				"H5-mobile": {
-					"Safari": "y",
-					"Android Browser": "y",
-					"微信浏览器(Android)": "y",
-					"QQ浏览器(Android)": "y"
-				},
-				"H5-pc": {
-					"Chrome": "y",
-					"IE": "y",
-					"Edge": "y",
-					"Firefox": "y",
-					"Safari": "y"
-				},
-				"小程序": {
-					"微信": "y",
-					"阿里": "y",
-					"百度": "y",
-					"字节跳动": "y",
-					"QQ": "y",
-					"钉钉": "u",
-					"快手": "u",
-					"飞书": "u",
-					"京东": "u"
-				},
-				"快应用": {
-					"华为": "u",
-					"联盟": "u"
-				}
-			}
-		}
-  }
-}

+ 0 - 19
src/uni_modules/uv-search/readme.md

@@ -1,19 +0,0 @@
-## Search 搜索 
-
-> **组件名:uv-search**
-
-搜索组件,集成了常见搜索框所需功能,支持前后插槽,用户可以一键引入,开箱即用。
-
-# <a href="https://www.uvui.cn/components/search.html" target="_blank">查看文档</a>
-
-## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <span style="font-size:14px;font-weight:700;">(请不要 下载插件ZIP)</span>
-
-### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
-
-<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
-
-![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
-
-</a>
-
-#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

+ 0 - 26
src/uni_modules/uv-ui-tools/changelog.md

@@ -1,26 +0,0 @@
-## 1.0.10(2023-08-01)
-1. 优化
-## 1.0.9(2023-06-28)
-优化openType.js
-## 1.0.8(2023-06-15)
-1. 修改支付宝报错的BUG
-## 1.0.7(2023-06-07)
-1. 解决微信小程序使用uvui提示 Some selectors are not allowed in component wxss, including tag name selectors, ID selectors, and attribute selectors
-2. 解决上述提示,需要在uni.scss配置$uvui-nvue-style: false; 然后在APP.vue下面引入uvui内置的基础样式:@import '@/uni_modules/uv-ui-tools/index.scss';
-## 1.0.6(2023-06-04)
-1.  uv-ui-tools 优化工具组件,兼容更多功能
-2.  小程序分享功能优化等
-## 1.0.5(2023-06-02)
-1. 修改扩展使用mixin中方法的问题
-## 1.0.4(2023-05-23)
-1. 兼容百度小程序修改bem函数
-## 1.0.3(2023-05-16)
-1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
-2. 优化部分功能
-## 1.0.2(2023-05-10)
-1. 增加Http请求封装
-2. 优化
-## 1.0.1(2023-05-04)
-1. 修改名称及备注
-## 1.0.0(2023-05-04)
-1. uv-ui工具集首次发布

+ 0 - 6
src/uni_modules/uv-ui-tools/components/uv-ui-tools/uv-ui-tools.vue

@@ -1,6 +0,0 @@
-<template>
-</template>
-<script>
-</script>
-<style>
-</style>

+ 0 - 77
src/uni_modules/uv-ui-tools/index.js

@@ -1,77 +0,0 @@
-// 全局挂载引入http相关请求拦截插件
-import Request from './libs/luch-request'
-
-// 引入全局mixin
-import mixin from './libs/mixin/mixin.js'
-// 小程序特有的mixin
-import mpMixin from './libs/mixin/mpMixin.js'
-// #ifdef MP
-import mpShare from '@/uni_modules/uv-ui-tools/libs/mixin/mpShare.js'
-// #endif
-
-// 路由封装
-import route from './libs/util/route.js'
-// 公共工具函数
-import * as index from './libs/function/index.js'
-// 防抖方法
-import debounce from './libs/function/debounce.js'
-// 节流方法
-import throttle from './libs/function/throttle.js'
-// 规则检验
-import * as test from './libs/function/test.js'
-
-// 颜色渐变相关,colorGradient-颜色渐变,hexToRgb-十六进制颜色转rgb颜色,rgbToHex-rgb转十六进制
-import * as colorGradient from './libs/function/colorGradient.js'
-
-// 配置信息
-import config from './libs/config/config.js'
-// 平台
-import platform from './libs/function/platform'
-
-const $uv = {
-	route,
-	config,
-	test,
-	throttle,
-	date: index.timeFormat, // 另名date
-	...index,
-	colorGradient: colorGradient.colorGradient,
-	hexToRgb: colorGradient.hexToRgb,
-	rgbToHex: colorGradient.rgbToHex,
-	colorToRgba: colorGradient.colorToRgba,
-	http: new Request(),
-	debounce,
-	throttle,
-	platform,
-	mixin,
-	mpMixin
-}
-uni.$uv = $uv;
-const install = (Vue,options={}) => {
-		// #ifndef APP-NVUE
-		Vue.mixin(mixin);
-		// #ifdef MP
-		if(options.mpShare){
-			Vue.mixin(mpShare);
-		}
-		// #endif
-		// #endif
-		// #ifdef VUE2
-		// 时间格式化,同时两个名称,date和timeFormat
-		Vue.filter('timeFormat', (timestamp, format) => uni.$uv.timeFormat(timestamp, format));
-		Vue.filter('date', (timestamp, format) => uni.$uv.timeFormat(timestamp, format));
-		// 将多久以前的方法,注入到全局过滤器
-		Vue.filter('timeFrom', (timestamp, format) => uni.$uv.timeFrom(timestamp, format));
-		// 同时挂载到uni和Vue.prototype中
-		// #ifndef APP-NVUE
-		// 只有vue,挂载到Vue.prototype才有意义,因为nvue中全局Vue.prototype和Vue.mixin是无效的
-		Vue.prototype.$uv = $uv;
-		// #endif
-		// #endif
-		// #ifdef VUE3
-		Vue.config.globalProperties.$uv = $uv;
-		// #endif
-}
-export default {
-	install
-}

+ 0 - 7
src/uni_modules/uv-ui-tools/index.scss

@@ -1,7 +0,0 @@
-// 引入公共基础类
-@import "./libs/css/common.scss";
-
-// 非nvue的样式
-/* #ifndef APP-NVUE */
-@import "./libs/css/vue.scss";
-/* #endif */

+ 0 - 34
src/uni_modules/uv-ui-tools/libs/config/config.js

@@ -1,34 +0,0 @@
-// 此版本发布于2023-07-30
-const version = '1.1.1'
-
-// 开发环境才提示,生产环境不会提示
-if (process.env.NODE_ENV === 'development') {
-	console.log(`\n %c uvui V${version} https://www.uvui.cn/ \n\n`, 'color: #ffffff; background: #3c9cff; padding:5px 0; border-radius: 5px;');
-}
-
-export default {
-    v: version,
-    version,
-    // 主题名称
-    type: [
-        'primary',
-        'success',
-        'info',
-        'error',
-        'warning'
-    ],
-    // 颜色部分,本来可以通过scss的:export导出供js使用,但是奈何nvue不支持
-    color: {
-        'uv-primary': '#2979ff',
-        'uv-warning': '#ff9900',
-        'uv-success': '#19be6b',
-        'uv-error': '#fa3534',
-        'uv-info': '#909399',
-        'uv-main-color': '#303133',
-        'uv-content-color': '#606266',
-        'uv-tips-color': '#909399',
-        'uv-light-color': '#c0c4cc'
-    },
-	// 默认单位,可以通过配置为rpx,那么在用于传入组件大小参数为数值时,就默认为rpx
-	unit: 'px'
-}

+ 0 - 32
src/uni_modules/uv-ui-tools/libs/css/color.scss

@@ -1,32 +0,0 @@
-$uv-main-color: #303133 !default;
-$uv-content-color: #606266 !default;
-$uv-tips-color: #909193 !default;
-$uv-light-color: #c0c4cc !default;
-$uv-border-color: #dadbde !default;
-$uv-bg-color: #f3f4f6 !default;
-$uv-disabled-color: #c8c9cc !default;
-
-$uv-primary: #3c9cff !default;
-$uv-primary-dark: #398ade !default;
-$uv-primary-disabled: #9acafc !default;
-$uv-primary-light: #ecf5ff !default;
-
-$uv-warning: #f9ae3d !default;
-$uv-warning-dark: #f1a532 !default;
-$uv-warning-disabled: #f9d39b !default;
-$uv-warning-light: #fdf6ec !default;
-
-$uv-success: #5ac725 !default;
-$uv-success-dark: #53c21d !default;
-$uv-success-disabled: #a9e08f !default;
-$uv-success-light: #f5fff0;
-
-$uv-error: #f56c6c !default;
-$uv-error-dark: #e45656 !default;
-$uv-error-disabled: #f7b2b2 !default;
-$uv-error-light: #fef0f0 !default;
-
-$uv-info: #909399 !default;
-$uv-info-dark: #767a82 !default;
-$uv-info-disabled: #c4c6c9 !default;
-$uv-info-light: #f4f4f5 !default;

+ 0 - 100
src/uni_modules/uv-ui-tools/libs/css/common.scss

@@ -1,100 +0,0 @@
-// 超出行数,自动显示行尾省略号,最多5行
-// 来自uvui的温馨提示:当您在控制台看到此报错,说明需要在App.vue的style标签加上【lang="scss"】
-@for $i from 1 through 5 {
-	.uv-line-#{$i} {
-		/* #ifdef APP-NVUE */
-		// nvue下,可以直接使用lines属性,这是weex特有样式
-		lines: $i;
-		text-overflow: ellipsis;
-		overflow: hidden;
-		flex: 1;
-		/* #endif */
-
-		/* #ifndef APP-NVUE */
-		// vue下,单行和多行显示省略号需要单独处理
-		@if $i == '1' {
-			overflow: hidden;
-			white-space: nowrap;
-			text-overflow: ellipsis;
-		} @else {
-			display: -webkit-box!important;
-			overflow: hidden;
-			text-overflow: ellipsis;
-			word-break: break-all;
-			-webkit-line-clamp: $i;
-			-webkit-box-orient: vertical!important;
-		}
-		/* #endif */
-	}
-}
-$uv-bordercolor: #dadbde;
-@if variable-exists(uv-border-color) {
-	$uv-bordercolor: $uv-border-color;
-}
-
-// 此处加上!important并非随意乱用,而是因为目前*.nvue页面编译到H5时,
-// App.vue的样式会被uni-app的view元素的自带border属性覆盖,导致无效
-// 综上,这是uni-app的缺陷导致我们为了多端兼容,而必须要加上!important
-// 移动端兼容性较好,直接使用0.5px去实现细边框,不使用伪元素形式实现
-.uv-border {
-	border-width: 0.5px!important;
-	border-color: $uv-bordercolor!important;
-    border-style: solid;
-}
-
-.uv-border-top {
-	border-top-width: 0.5px!important;
-	border-color: $uv-bordercolor!important;
-    border-top-style: solid;
-}
-
-.uv-border-left {
-	border-left-width: 0.5px!important;
-	border-color: $uv-bordercolor!important;
-    border-left-style: solid;
-}
-
-.uv-border-right {
-	border-right-width: 0.5px!important;
-	border-color: $uv-bordercolor!important;
-    border-right-style: solid;
-}
-
-.uv-border-bottom {
-	border-bottom-width: 0.5px!important;
-	border-color: $uv-bordercolor!important;
-    border-bottom-style: solid;
-}
-
-.uv-border-top-bottom {
-	border-top-width: 0.5px!important;
-	border-bottom-width: 0.5px!important;
-	border-color: $uv-bordercolor!important;
-    border-top-style: solid;
-    border-bottom-style: solid;
-}
-
-// 去除button的所有默认样式,让其表现跟普通的view、text元素一样
-.uv-reset-button {
-	padding: 0;
-	background-color: transparent;
-	/* #ifndef APP-PLUS */
-	font-size: inherit;
-	line-height: inherit;
-	color: inherit;
-	/* #endif */
-	/* #ifdef APP-NVUE */
-	border-width: 0;
-	/* #endif */
-}
-
-/* #ifndef APP-NVUE */
-.uv-reset-button::after {
-   border: none;
-}
-/* #endif */
-
-.uv-hover-class {
-	opacity: 0.7;
-}
-

+ 0 - 23
src/uni_modules/uv-ui-tools/libs/css/components.scss

@@ -1,23 +0,0 @@
-@mixin flex($direction: row) {
-	/* #ifndef APP-NVUE */
-	display: flex;
-	/* #endif */
-	flex-direction: $direction;
-}
-
-/* #ifndef APP-NVUE */
-// 由于uvui是基于nvue环境进行开发的,此环境中普通元素默认为flex-direction: column;
-// 所以在非nvue中,需要对元素进行重置为flex-direction: column; 否则可能会表现异常
-$uvui-nvue-style: true !default;
-@if $uvui-nvue-style == true {
-	view, scroll-view, swiper-item {
-		display: flex;
-		flex-direction: column;
-		flex-shrink: 0;
-		flex-grow: 0;
-		flex-basis: auto;
-		align-items: stretch;
-		align-content: flex-start;
-	}
-}
-/* #endif */

+ 0 - 111
src/uni_modules/uv-ui-tools/libs/css/variable.scss

@@ -1,111 +0,0 @@
-// 超出行数,自动显示行尾省略号,最多5行
-// 来自uvui的温馨提示:当您在控制台看到此报错,说明需要在App.vue的style标签加上【lang="scss"】
-@if variable-exists(show-lines) {
-	@for $i from 1 through 5 {
-		.uv-line-#{$i} {
-			/* #ifdef APP-NVUE */
-			// nvue下,可以直接使用lines属性,这是weex特有样式
-			lines: $i;
-			text-overflow: ellipsis;
-			overflow: hidden;
-			flex: 1;
-			/* #endif */
-
-			/* #ifndef APP-NVUE */
-			// vue下,单行和多行显示省略号需要单独处理
-			@if $i == '1' {
-				overflow: hidden;
-				white-space: nowrap;
-				text-overflow: ellipsis;
-			} @else {
-				display: -webkit-box!important;
-				overflow: hidden;
-				text-overflow: ellipsis;
-				word-break: break-all;
-				-webkit-line-clamp: $i;
-				-webkit-box-orient: vertical!important;
-			}
-			/* #endif */
-		}
-	}
-}
-@if variable-exists(show-border) {
-	$uv-bordercolor: #dadbde;
-	@if variable-exists(uv-border-color) {
-		$uv-bordercolor: $uv-border-color;
-	}
-	// 此处加上!important并非随意乱用,而是因为目前*.nvue页面编译到H5时,
-	// App.vue的样式会被uni-app的view元素的自带border属性覆盖,导致无效
-	// 综上,这是uni-app的缺陷导致我们为了多端兼容,而必须要加上!important
-	// 移动端兼容性较好,直接使用0.5px去实现细边框,不使用伪元素形式实现
-	@if variable-exists(show-border-surround) {
-		.uv-border {
-			border-width: 0.5px!important;
-			border-color: $uv-bordercolor!important;
-			border-style: solid;
-		}
-	}
-	@if variable-exists(show-border-top) {
-		.uv-border-top {
-			border-top-width: 0.5px!important;
-			border-color: $uv-bordercolor!important;
-			border-top-style: solid;
-		}
-	}
-	@if variable-exists(show-border-left) {
-		.uv-border-left {
-			border-left-width: 0.5px!important;
-			border-color: $uv-bordercolor!important;
-			border-left-style: solid;
-		}
-	}
-	@if variable-exists(show-border-right) {
-		.uv-border-right {
-			border-right-width: 0.5px!important;
-			border-color: $uv-bordercolor!important;
-			border-right-style: solid;
-		}
-	}
-	@if variable-exists(show-border-bottom) {
-		.uv-border-bottom {
-			border-bottom-width: 0.5px!important;
-			border-color: $uv-bordercolor!important;
-				border-bottom-style: solid;
-		}
-	}
-	@if variable-exists(show-border-top-bottom) {
-		.uv-border-top-bottom {
-			border-top-width: 0.5px!important;
-			border-bottom-width: 0.5px!important;
-			border-color: $uv-bordercolor!important;
-			border-top-style: solid;
-			border-bottom-style: solid;
-		}
-	}
-}
-@if variable-exists(show-reset-button) {
-	// 去除button的所有默认样式,让其表现跟普通的view、text元素一样
-	.uv-reset-button {
-		padding: 0;
-		background-color: transparent;
-		/* #ifndef APP-PLUS */
-		font-size: inherit;
-		line-height: inherit;
-		color: inherit;
-		/* #endif */
-		/* #ifdef APP-NVUE */
-		border-width: 0;
-		/* #endif */
-	}
-
-	/* #ifndef APP-NVUE */
-	.uv-reset-button::after {
-		 border: none;
-	}
-	/* #endif */
-}
-@if variable-exists(show-hover) {
-	.uv-hover-class {
-		opacity: 0.7;
-	}
-}

+ 0 - 40
src/uni_modules/uv-ui-tools/libs/css/vue.scss

@@ -1,40 +0,0 @@
-// 历遍生成4个方向的底部安全区
-@each $d in top, right, bottom, left {
-	.uv-safe-area-inset-#{$d} {
-		padding-#{$d}: 0;
-		padding-#{$d}: constant(safe-area-inset-#{$d});  
-		padding-#{$d}: env(safe-area-inset-#{$d});  
-	}
-}
-
-//提升H5端uni.toast()的层级,避免被uvui的modal等遮盖
-/* #ifdef H5 */
-uni-toast {
-    z-index: 10090;
-}
-uni-toast .uni-toast {
-   z-index: 10090;
-}
-/* #endif */
-
-// 隐藏scroll-view的滚动条
-::-webkit-scrollbar {
-    display: none;  
-    width: 0 !important;  
-    height: 0 !important;  
-    -webkit-appearance: none;  
-    background: transparent;  
-}
-
-$uvui-nvue-style: true !default;
-@if $uvui-nvue-style == false {
-	view, scroll-view, swiper-item {
-		display: flex;
-		flex-direction: column;
-		flex-shrink: 0;
-		flex-grow: 0;
-		flex-basis: auto;
-		align-items: stretch;
-		align-content: flex-start;
-	}
-}

+ 0 - 134
src/uni_modules/uv-ui-tools/libs/function/colorGradient.js

@@ -1,134 +0,0 @@
-/**
- * 求两个颜色之间的渐变值
- * @param {string} startColor 开始的颜色
- * @param {string} endColor 结束的颜色
- * @param {number} step 颜色等分的份额
- * */
-function colorGradient(startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10) {
-    const startRGB = hexToRgb(startColor, false) // 转换为rgb数组模式
-    const startR = startRGB[0]
-    const startG = startRGB[1]
-    const startB = startRGB[2]
-
-    const endRGB = hexToRgb(endColor, false)
-    const endR = endRGB[0]
-    const endG = endRGB[1]
-    const endB = endRGB[2]
-
-    const sR = (endR - startR) / step // 总差值
-    const sG = (endG - startG) / step
-    const sB = (endB - startB) / step
-    const colorArr = []
-    for (let i = 0; i < step; i++) {
-        // 计算每一步的hex值
-        let hex = rgbToHex(`rgb(${Math.round((sR * i + startR))},${Math.round((sG * i + startG))},${Math.round((sB
-			* i + startB))})`)
-        // 确保第一个颜色值为startColor的值
-        if (i === 0) hex = rgbToHex(startColor)
-        // 确保最后一个颜色值为endColor的值
-        if (i === step - 1) hex = rgbToHex(endColor)
-        colorArr.push(hex)
-    }
-    return colorArr
-}
-
-// 将hex表示方式转换为rgb表示方式(这里返回rgb数组模式)
-function hexToRgb(sColor, str = true) {
-    const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
-    sColor = String(sColor).toLowerCase()
-    if (sColor && reg.test(sColor)) {
-        if (sColor.length === 4) {
-            let sColorNew = '#'
-            for (let i = 1; i < 4; i += 1) {
-                sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
-            }
-            sColor = sColorNew
-        }
-        // 处理六位的颜色值
-        const sColorChange = []
-        for (let i = 1; i < 7; i += 2) {
-            sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`))
-        }
-        if (!str) {
-            return sColorChange
-        }
-        return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`
-    } if (/^(rgb|RGB)/.test(sColor)) {
-        const arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
-        return arr.map((val) => Number(val))
-    }
-    return sColor
-}
-
-// 将rgb表示方式转换为hex表示方式
-function rgbToHex(rgb) {
-    const _this = rgb
-    const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
-    if (/^(rgb|RGB)/.test(_this)) {
-        const aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
-        let strHex = '#'
-        for (let i = 0; i < aColor.length; i++) {
-            let hex = Number(aColor[i]).toString(16)
-            hex = String(hex).length == 1 ? `${0}${hex}` : hex // 保证每个rgb的值为2位
-            if (hex === '0') {
-                hex += hex
-            }
-            strHex += hex
-        }
-        if (strHex.length !== 7) {
-            strHex = _this
-        }
-        return strHex
-    } if (reg.test(_this)) {
-        const aNum = _this.replace(/#/, '').split('')
-        if (aNum.length === 6) {
-            return _this
-        } if (aNum.length === 3) {
-            let numHex = '#'
-            for (let i = 0; i < aNum.length; i += 1) {
-                numHex += (aNum[i] + aNum[i])
-            }
-            return numHex
-        }
-    } else {
-        return _this
-    }
-}
-
-/**
-* JS颜色十六进制转换为rgb或rgba,返回的格式为 rgba(255,255,255,0.5)字符串
-* sHex为传入的十六进制的色值
-* alpha为rgba的透明度
-*/
-function colorToRgba(color, alpha) {
-    color = rgbToHex(color)
-    // 十六进制颜色值的正则表达式
-    const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
-    /* 16进制颜色转为RGB格式 */
-    let sColor = String(color).toLowerCase()
-    if (sColor && reg.test(sColor)) {
-        if (sColor.length === 4) {
-            let sColorNew = '#'
-            for (let i = 1; i < 4; i += 1) {
-                sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
-            }
-            sColor = sColorNew
-        }
-        // 处理六位的颜色值
-        const sColorChange = []
-        for (let i = 1; i < 7; i += 2) {
-            sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`))
-        }
-        // return sColorChange.join(',')
-        return `rgba(${sColorChange.join(',')},${alpha})`
-    }
-
-    return sColor
-}
-
-export {
-    colorGradient,
-    hexToRgb,
-    rgbToHex,
-    colorToRgba
-}

+ 0 - 29
src/uni_modules/uv-ui-tools/libs/function/debounce.js

@@ -1,29 +0,0 @@
-let timeout = null
-
-/**
- * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
- *
- * @param {Function} func 要执行的回调函数
- * @param {Number} wait 延时的时间
- * @param {Boolean} immediate 是否立即执行
- * @return null
- */
-function debounce(func, wait = 500, immediate = false) {
-    // 清除定时器
-    if (timeout !== null) clearTimeout(timeout)
-    // 立即执行,此类情况一般用不到
-    if (immediate) {
-        const callNow = !timeout
-        timeout = setTimeout(() => {
-            timeout = null
-        }, wait)
-        if (callNow) typeof func === 'function' && func()
-    } else {
-        // 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
-        timeout = setTimeout(() => {
-            typeof func === 'function' && func()
-        }, wait)
-    }
-}
-
-export default debounce

+ 0 - 167
src/uni_modules/uv-ui-tools/libs/function/digit.js

@@ -1,167 +0,0 @@
-let _boundaryCheckingState = true; // 是否进行越界检查的全局开关
-
-/**
- * 把错误的数据转正
- * @private
- * @example strip(0.09999999999999998)=0.1
- */
-function strip(num, precision = 15) {
-  return +parseFloat(Number(num).toPrecision(precision));
-}
-
-/**
- * Return digits length of a number
- * @private
- * @param {*number} num Input number
- */
-function digitLength(num) {
-  // Get digit length of e
-  const eSplit = num.toString().split(/[eE]/);
-  const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);
-  return len > 0 ? len : 0;
-}
-
-/**
- * 把小数转成整数,如果是小数则放大成整数
- * @private
- * @param {*number} num 输入数
- */
-function float2Fixed(num) {
-  if (num.toString().indexOf('e') === -1) {
-    return Number(num.toString().replace('.', ''));
-  }
-  const dLen = digitLength(num);
-  return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);
-}
-
-/**
- * 检测数字是否越界,如果越界给出提示
- * @private
- * @param {*number} num 输入数
- */
-function checkBoundary(num) {
-  if (_boundaryCheckingState) {
-    if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
-      console.warn(`${num} 超出了精度限制,结果可能不正确`);
-    }
-  }
-}
-
-/**
- * 把递归操作扁平迭代化
- * @param {number[]} arr 要操作的数字数组
- * @param {function} operation 迭代操作
- * @private
- */
-function iteratorOperation(arr, operation) {
-  const [num1, num2, ...others] = arr;
-  let res = operation(num1, num2);
-
-  others.forEach((num) => {
-    res = operation(res, num);
-  });
-
-  return res;
-}
-
-/**
- * 高精度乘法
- * @export
- */
-export function times(...nums) {
-  if (nums.length > 2) {
-    return iteratorOperation(nums, times);
-  }
-
-  const [num1, num2] = nums;
-  const num1Changed = float2Fixed(num1);
-  const num2Changed = float2Fixed(num2);
-  const baseNum = digitLength(num1) + digitLength(num2);
-  const leftValue = num1Changed * num2Changed;
-
-  checkBoundary(leftValue);
-
-  return leftValue / Math.pow(10, baseNum);
-}
-
-/**
- * 高精度加法
- * @export
- */
-export function plus(...nums) {
-  if (nums.length > 2) {
-    return iteratorOperation(nums, plus);
-  }
-
-  const [num1, num2] = nums;
-  // 取最大的小数位
-  const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
-  // 把小数都转为整数然后再计算
-  return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
-}
-
-/**
- * 高精度减法
- * @export
- */
-export function minus(...nums) {
-  if (nums.length > 2) {
-    return iteratorOperation(nums, minus);
-  }
-
-  const [num1, num2] = nums;
-  const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
-  return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
-}
-
-/**
- * 高精度除法
- * @export
- */
-export function divide(...nums) {
-  if (nums.length > 2) {
-    return iteratorOperation(nums, divide);
-  }
-
-  const [num1, num2] = nums;
-  const num1Changed = float2Fixed(num1);
-  const num2Changed = float2Fixed(num2);
-  checkBoundary(num1Changed);
-  checkBoundary(num2Changed);
-  // 重要,这里必须用strip进行修正
-  return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
-}
-
-/**
- * 四舍五入
- * @export
- */
-export function round(num, ratio) {
-  const base = Math.pow(10, ratio);
-  let result = divide(Math.round(Math.abs(times(num, base))), base);
-  if (num < 0 && result !== 0) {
-    result = times(result, -1);
-  }
-  // 位数不足则补0
-  return result;
-}
-
-/**
- * 是否进行边界检查,默认开启
- * @param flag 标记开关,true 为开启,false 为关闭,默认为 true
- * @export
- */
-export function enableBoundaryChecking(flag = true) {
-  _boundaryCheckingState = flag;
-}
-
-
-export default {
-  times,
-  plus,
-  minus,
-  divide,
-  round,
-  enableBoundaryChecking,
-};
-

+ 0 - 734
src/uni_modules/uv-ui-tools/libs/function/index.js

@@ -1,734 +0,0 @@
-import { number, empty } from './test.js'
-import { round } from './digit.js'
-/**
- * @description 如果value小于min,取min;如果value大于max,取max
- * @param {number} min
- * @param {number} max
- * @param {number} value
- */
-function range(min = 0, max = 0, value = 0) {
-	return Math.max(min, Math.min(max, Number(value)))
-}
-
-/**
- * @description 用于获取用户传递值的px值  如果用户传递了"xxpx"或者"xxrpx",取出其数值部分,如果是"xxxrpx"还需要用过uni.upx2px进行转换
- * @param {number|string} value 用户传递值的px值
- * @param {boolean} unit
- * @returns {number|string}
- */
-function getPx(value, unit = false) {
-	if (number(value)) {
-		return unit ? `${value}px` : Number(value)
-	}
-	// 如果带有rpx,先取出其数值部分,再转为px值
-	if (/(rpx|upx)$/.test(value)) {
-		return unit ? `${uni.upx2px(parseInt(value))}px` : Number(uni.upx2px(parseInt(value)))
-	}
-	return unit ? `${parseInt(value)}px` : parseInt(value)
-}
-
-/**
- * @description 进行延时,以达到可以简写代码的目的 比如: await uni.$uv.sleep(20)将会阻塞20ms
- * @param {number} value 堵塞时间 单位ms 毫秒
- * @returns {Promise} 返回promise
- */
-function sleep(value = 30) {
-	return new Promise((resolve) => {
-		setTimeout(() => {
-			resolve()
-		}, value)
-	})
-}
-/**
- * @description 运行期判断平台
- * @returns {string} 返回所在平台(小写)
- * @link 运行期判断平台 https://uniapp.dcloud.io/frame?id=判断平台
- */
-function os() {
-	return uni.getSystemInfoSync().platform.toLowerCase()
-}
-/**
- * @description 获取系统信息同步接口
- * @link 获取系统信息同步接口 https://uniapp.dcloud.io/api/system/info?id=getsysteminfosync
- */
-function sys() {
-	return uni.getSystemInfoSync()
-}
-
-/**
- * @description 取一个区间数
- * @param {Number} min 最小值
- * @param {Number} max 最大值
- */
-function random(min, max) {
-	if (min >= 0 && max > 0 && max >= min) {
-		const gab = max - min + 1
-		return Math.floor(Math.random() * gab + min)
-	}
-	return 0
-}
-
-/**
- * @param {Number} len uuid的长度
- * @param {Boolean} firstU 将返回的首字母置为"u"
- * @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
- */
-function guid(len = 32, firstU = true, radix = null) {
-	const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
-	const uuid = []
-	radix = radix || chars.length
-
-	if (len) {
-		// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
-		for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
-	} else {
-		let r
-		// rfc4122标准要求返回的uuid中,某些位为固定的字符
-		uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
-		uuid[14] = '4'
-
-		for (let i = 0; i < 36; i++) {
-			if (!uuid[i]) {
-				r = 0 | Math.random() * 16
-				uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]
-			}
-		}
-	}
-	// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
-	if (firstU) {
-		uuid.shift()
-		return `u${uuid.join('')}`
-	}
-	return uuid.join('')
-}
-
-/**
-* @description 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法
-   this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx
-   这里默认值等于undefined有它的含义,因为最顶层元素(组件)的$parent就是undefined,意味着不传name
-   值(默认为undefined),就是查找最顶层的$parent
-*  @param {string|undefined} name 父组件的参数名
-*/
-function $parent(name = undefined) {
-	let parent = this.$parent
-	// 通过while历遍,这里主要是为了H5需要多层解析的问题
-	while (parent) {
-		// 父组件
-		if (parent.$options && parent.$options.name !== name) {
-			// 如果组件的name不相等,继续上一级寻找
-			parent = parent.$parent
-		} else {
-			return parent
-		}
-	}
-	return false
-}
-
-/**
- * @description 样式转换
- * 对象转字符串,或者字符串转对象
- * @param {object | string} customStyle 需要转换的目标
- * @param {String} target 转换的目的,object-转为对象,string-转为字符串
- * @returns {object|string}
- */
-function addStyle(customStyle, target = 'object') {
-	// 字符串转字符串,对象转对象情形,直接返回
-	if (empty(customStyle) || typeof(customStyle) === 'object' && target === 'object' || target === 'string' &&
-		typeof(customStyle) === 'string') {
-		return customStyle
-	}
-	// 字符串转对象
-	if (target === 'object') {
-		// 去除字符串样式中的两端空格(中间的空格不能去掉,比如padding: 20px 0如果去掉了就错了),空格是无用的
-		customStyle = trim(customStyle)
-		// 根据";"将字符串转为数组形式
-		const styleArray = customStyle.split(';')
-		const style = {}
-		// 历遍数组,拼接成对象
-		for (let i = 0; i < styleArray.length; i++) {
-			// 'font-size:20px;color:red;',如此最后字符串有";"的话,会导致styleArray最后一个元素为空字符串,这里需要过滤
-			if (styleArray[i]) {
-				const item = styleArray[i].split(':')
-				style[trim(item[0])] = trim(item[1])
-			}
-		}
-		return style
-	}
-	// 这里为对象转字符串形式
-	let string = ''
-	for (const i in customStyle) {
-		// 驼峰转为中划线的形式,否则css内联样式,无法识别驼峰样式属性名
-		const key = i.replace(/([A-Z])/g, '-$1').toLowerCase()
-		string += `${key}:${customStyle[i]};`
-	}
-	// 去除两端空格
-	return trim(string)
-}
-
-/**
- * @description 添加单位,如果有rpx,upx,%,px等单位结尾或者值为auto,直接返回,否则加上px单位结尾
- * @param {string|number} value 需要添加单位的值
- * @param {string} unit 添加的单位名 比如px
- */
-function addUnit(value = 'auto', unit = uni?.$uv?.config?.unit ? uni?.$uv?.config?.unit : 'px') {
-	value = String(value)
-	// 用uvui内置验证规则中的number判断是否为数值
-	return number(value) ? `${value}${unit}` : value
-}
-
-/**
- * @description 深度克隆
- * @param {object} obj 需要深度克隆的对象
- * @param cache 缓存
- * @returns {*} 克隆后的对象或者原值(不是对象)
- */
-function deepClone(obj, cache = new WeakMap()) {
-	if (obj === null || typeof obj !== 'object') return obj;
-	if (cache.has(obj)) return cache.get(obj);
-	let clone;
-	if (obj instanceof Date) {
-		clone = new Date(obj.getTime());
-	} else if (obj instanceof RegExp) {
-		clone = new RegExp(obj);
-	} else if (obj instanceof Map) {
-		clone = new Map(Array.from(obj, ([key, value]) => [key, deepClone(value, cache)]));
-	} else if (obj instanceof Set) {
-		clone = new Set(Array.from(obj, value => deepClone(value, cache)));
-	} else if (Array.isArray(obj)) {
-		clone = obj.map(value => deepClone(value, cache));
-	} else if (Object.prototype.toString.call(obj) === '[object Object]') {
-		clone = Object.create(Object.getPrototypeOf(obj));
-		cache.set(obj, clone);
-		for (const [key, value] of Object.entries(obj)) {
-			clone[key] = deepClone(value, cache);
-		}
-	} else {
-		clone = Object.assign({}, obj);
-	}
-	cache.set(obj, clone);
-	return clone;
-}
-
-/**
- * @description JS对象深度合并
- * @param {object} target 需要拷贝的对象
- * @param {object} source 拷贝的来源对象
- * @returns {object|boolean} 深度合并后的对象或者false(入参有不是对象)
- */
-function deepMerge(target = {}, source = {}) {
-	target = deepClone(target)
-	if (typeof target !== 'object' || target === null || typeof source !== 'object' || source === null) return target;
-	const merged = Array.isArray(target) ? target.slice() : Object.assign({}, target);
-	for (const prop in source) {
-		if (!source.hasOwnProperty(prop)) continue;
-		const sourceValue = source[prop];
-		const targetValue = merged[prop];
-		if (sourceValue instanceof Date) {
-			merged[prop] = new Date(sourceValue);
-		} else if (sourceValue instanceof RegExp) {
-			merged[prop] = new RegExp(sourceValue);
-		} else if (sourceValue instanceof Map) {
-			merged[prop] = new Map(sourceValue);
-		} else if (sourceValue instanceof Set) {
-			merged[prop] = new Set(sourceValue);
-		} else if (typeof sourceValue === 'object' && sourceValue !== null) {
-			merged[prop] = deepMerge(targetValue, sourceValue);
-		} else {
-			merged[prop] = sourceValue;
-		}
-	}
-	return merged;
-}
-
-/**
- * @description error提示
- * @param {*} err 错误内容
- */
-function error(err) {
-	// 开发环境才提示,生产环境不会提示
-	if (process.env.NODE_ENV === 'development') {
-		console.error(`uvui提示:${err}`)
-	}
-}
-
-/**
- * @description 打乱数组
- * @param {array} array 需要打乱的数组
- * @returns {array} 打乱后的数组
- */
-function randomArray(array = []) {
-	// 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0
-	return array.sort(() => Math.random() - 0.5)
-}
-
-// padStart 的 polyfill,因为某些机型或情况,还无法支持es7的padStart,比如电脑版的微信小程序
-// 所以这里做一个兼容polyfill的兼容处理
-if (!String.prototype.padStart) {
-	// 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解
-	String.prototype.padStart = function(maxLength, fillString = ' ') {
-		if (Object.prototype.toString.call(fillString) !== '[object String]') {
-			throw new TypeError(
-				'fillString must be String'
-			)
-		}
-		const str = this
-		// 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉
-		if (str.length >= maxLength) return String(str)
-
-		const fillLength = maxLength - str.length
-		let times = Math.ceil(fillLength / fillString.length)
-		while (times >>= 1) {
-			fillString += fillString
-			if (times === 1) {
-				fillString += fillString
-			}
-		}
-		return fillString.slice(0, fillLength) + str
-	}
-}
-
-/**
- * @description 格式化时间
- * @param {String|Number} dateTime 需要格式化的时间戳
- * @param {String} fmt 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
- * @returns {string} 返回格式化后的字符串
- */
-function timeFormat(dateTime = null, formatStr = 'yyyy-mm-dd') {
-	let date
-	// 若传入时间为假值,则取当前时间
-	if (!dateTime) {
-		date = new Date()
-	}
-	// 若为unix秒时间戳,则转为毫秒时间戳(逻辑有点奇怪,但不敢改,以保证历史兼容)
-	else if (/^\d{10}$/.test(dateTime?.toString().trim())) {
-		date = new Date(dateTime * 1000)
-	}
-	// 若用户传入字符串格式时间戳,new Date无法解析,需做兼容
-	else if (typeof dateTime === 'string' && /^\d+$/.test(dateTime.trim())) {
-		date = new Date(Number(dateTime))
-	}
-	// 处理平台性差异,在Safari/Webkit中,new Date仅支持/作为分割符的字符串时间
-	// 处理 '2022-07-10 01:02:03',跳过 '2022-07-10T01:02:03'
-	else if (typeof dateTime === 'string' && dateTime.includes('-') && !dateTime.includes('T')) {
-		date = new Date(dateTime.replace(/-/g, '/'))
-	}
-	// 其他都认为符合 RFC 2822 规范
-	else {
-		date = new Date(dateTime)
-	}
-
-	const timeSource = {
-		'y': date.getFullYear().toString(), // 年
-		'm': (date.getMonth() + 1).toString().padStart(2, '0'), // 月
-		'd': date.getDate().toString().padStart(2, '0'), // 日
-		'h': date.getHours().toString().padStart(2, '0'), // 时
-		'M': date.getMinutes().toString().padStart(2, '0'), // 分
-		's': date.getSeconds().toString().padStart(2, '0') // 秒
-		// 有其他格式化字符需求可以继续添加,必须转化成字符串
-	}
-
-	for (const key in timeSource) {
-		const [ret] = new RegExp(`${key}+`).exec(formatStr) || []
-		if (ret) {
-			// 年可能只需展示两位
-			const beginIndex = key === 'y' && ret.length === 2 ? 2 : 0
-			formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex))
-		}
-	}
-
-	return formatStr
-}
-
-/**
- * @description 时间戳转为多久之前
- * @param {String|Number} timestamp 时间戳
- * @param {String|Boolean} format
- * 格式化规则如果为时间格式字符串,超出一定时间范围,返回固定的时间格式;
- * 如果为布尔值false,无论什么时间,都返回多久以前的格式
- * @returns {string} 转化后的内容
- */
-function timeFrom(timestamp = null, format = 'yyyy-mm-dd') {
-	if (timestamp == null) timestamp = Number(new Date())
-	timestamp = parseInt(timestamp)
-	// 判断用户输入的时间戳是秒还是毫秒,一般前端js获取的时间戳是毫秒(13位),后端传过来的为秒(10位)
-	if (timestamp.toString().length == 10) timestamp *= 1000
-	let timer = (new Date()).getTime() - timestamp
-	timer = parseInt(timer / 1000)
-	// 如果小于5分钟,则返回"刚刚",其他以此类推
-	let tips = ''
-	switch (true) {
-		case timer < 300:
-			tips = '刚刚'
-			break
-		case timer >= 300 && timer < 3600:
-			tips = `${parseInt(timer / 60)}分钟前`
-			break
-		case timer >= 3600 && timer < 86400:
-			tips = `${parseInt(timer / 3600)}小时前`
-			break
-		case timer >= 86400 && timer < 2592000:
-			tips = `${parseInt(timer / 86400)}天前`
-			break
-		default:
-			// 如果format为false,则无论什么时间戳,都显示xx之前
-			if (format === false) {
-				if (timer >= 2592000 && timer < 365 * 86400) {
-					tips = `${parseInt(timer / (86400 * 30))}个月前`
-				} else {
-					tips = `${parseInt(timer / (86400 * 365))}年前`
-				}
-			} else {
-				tips = timeFormat(timestamp, format)
-			}
-	}
-	return tips
-}
-
-/**
- * @description 去除空格
- * @param String str 需要去除空格的字符串
- * @param String pos both(左右)|left|right|all 默认both
- */
-function trim(str, pos = 'both') {
-	str = String(str)
-	if (pos == 'both') {
-		return str.replace(/^\s+|\s+$/g, '')
-	}
-	if (pos == 'left') {
-		return str.replace(/^\s*/, '')
-	}
-	if (pos == 'right') {
-		return str.replace(/(\s*$)/g, '')
-	}
-	if (pos == 'all') {
-		return str.replace(/\s+/g, '')
-	}
-	return str
-}
-
-/**
- * @description 对象转url参数
- * @param {object} data,对象
- * @param {Boolean} isPrefix,是否自动加上"?"
- * @param {string} arrayFormat 规则 indices|brackets|repeat|comma
- */
-function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
-	const prefix = isPrefix ? '?' : ''
-	const _result = []
-	if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets'
-	for (const key in data) {
-		const value = data[key]
-		// 去掉为空的参数
-		if (['', undefined, null].indexOf(value) >= 0) {
-			continue
-		}
-		// 如果值为数组,另行处理
-		if (value.constructor === Array) {
-			// e.g. {ids: [1, 2, 3]}
-			switch (arrayFormat) {
-				case 'indices':
-					// 结果: ids[0]=1&ids[1]=2&ids[2]=3
-					for (let i = 0; i < value.length; i++) {
-						_result.push(`${key}[${i}]=${value[i]}`)
-					}
-					break
-				case 'brackets':
-					// 结果: ids[]=1&ids[]=2&ids[]=3
-					value.forEach((_value) => {
-						_result.push(`${key}[]=${_value}`)
-					})
-					break
-				case 'repeat':
-					// 结果: ids=1&ids=2&ids=3
-					value.forEach((_value) => {
-						_result.push(`${key}=${_value}`)
-					})
-					break
-				case 'comma':
-					// 结果: ids=1,2,3
-					let commaStr = ''
-					value.forEach((_value) => {
-						commaStr += (commaStr ? ',' : '') + _value
-					})
-					_result.push(`${key}=${commaStr}`)
-					break
-				default:
-					value.forEach((_value) => {
-						_result.push(`${key}[]=${_value}`)
-					})
-			}
-		} else {
-			_result.push(`${key}=${value}`)
-		}
-	}
-	return _result.length ? prefix + _result.join('&') : ''
-}
-
-/**
- * 显示消息提示框
- * @param {String} title 提示的内容,长度与 icon 取值有关。
- * @param {Number} duration 提示的延迟时间,单位毫秒,默认:2000
- */
-function toast(title, duration = 2000) {
-	uni.showToast({
-		title: String(title),
-		icon: 'none',
-		duration
-	})
-}
-
-/**
- * @description 根据主题type值,获取对应的图标
- * @param {String} type 主题名称,primary|info|error|warning|success
- * @param {boolean} fill 是否使用fill填充实体的图标
- */
-function type2icon(type = 'success', fill = false) {
-	// 如果非预置值,默认为success
-	if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success'
-	let iconName = ''
-	// 目前(2019-12-12),info和primary使用同一个图标
-	switch (type) {
-		case 'primary':
-			iconName = 'info-circle'
-			break
-		case 'info':
-			iconName = 'info-circle'
-			break
-		case 'error':
-			iconName = 'close-circle'
-			break
-		case 'warning':
-			iconName = 'error-circle'
-			break
-		case 'success':
-			iconName = 'checkmark-circle'
-			break
-		default:
-			iconName = 'checkmark-circle'
-	}
-	// 是否是实体类型,加上-fill,在icon组件库中,实体的类名是后面加-fill的
-	if (fill) iconName += '-fill'
-	return iconName
-}
-
-/**
- * @description 数字格式化
- * @param {number|string} number 要格式化的数字
- * @param {number} decimals 保留几位小数
- * @param {string} decimalPoint 小数点符号
- * @param {string} thousandsSeparator 千分位符号
- * @returns {string} 格式化后的数字
- */
-function priceFormat(number, decimals = 0, decimalPoint = '.', thousandsSeparator = ',') {
-	number = (`${number}`).replace(/[^0-9+-Ee.]/g, '')
-	const n = !isFinite(+number) ? 0 : +number
-	const prec = !isFinite(+decimals) ? 0 : Math.abs(decimals)
-	const sep = (typeof thousandsSeparator === 'undefined') ? ',' : thousandsSeparator
-	const dec = (typeof decimalPoint === 'undefined') ? '.' : decimalPoint
-	let s = ''
-
-	s = (prec ? round(n, prec) + '' : `${Math.round(n)}`).split('.')
-	const re = /(-?\d+)(\d{3})/
-	while (re.test(s[0])) {
-		s[0] = s[0].replace(re, `$1${sep}$2`)
-	}
-
-	if ((s[1] || '').length < prec) {
-		s[1] = s[1] || ''
-		s[1] += new Array(prec - s[1].length + 1).join('0')
-	}
-	return s.join(dec)
-}
-
-/**
- * @description 获取duration值
- * 如果带有ms或者s直接返回,如果大于一定值,认为是ms单位,小于一定值,认为是s单位
- * 比如以30位阈值,那么300大于30,可以理解为用户想要的是300ms,而不是想花300s去执行一个动画
- * @param {String|number} value 比如: "1s"|"100ms"|1|100
- * @param {boolean} unit  提示: 如果是false 默认返回number
- * @return {string|number}
- */
-function getDuration(value, unit = true) {
-	const valueNum = parseInt(value)
-	if (unit) {
-		if (/s$/.test(value)) return value
-		return value > 30 ? `${value}ms` : `${value}s`
-	}
-	if (/ms$/.test(value)) return valueNum
-	if (/s$/.test(value)) return valueNum > 30 ? valueNum : valueNum * 1000
-	return valueNum
-}
-
-/**
- * @description 日期的月或日补零操作
- * @param {String} value 需要补零的值
- */
-function padZero(value) {
-	return `00${value}`.slice(-2)
-}
-
-/**
- * @description 在uv-form的子组件内容发生变化,或者失去焦点时,尝试通知uv-form执行校验方法
- * @param {*} instance
- * @param {*} event
- */
-function formValidate(instance, event) {
-	const formItem = $parent.call(instance, 'uv-form-item')
-	const form = $parent.call(instance, 'uv-form')
-	// 如果发生变化的input或者textarea等,其父组件中有uv-form-item或者uv-form等,就执行form的validate方法
-	// 同时将form-item的pros传递给form,让其进行精确对象验证
-	if (formItem && form) {
-		form.validateField(formItem.prop, () => {}, event)
-	}
-}
-
-/**
- * @description 获取某个对象下的属性,用于通过类似'a.b.c'的形式去获取一个对象的的属性的形式
- * @param {object} obj 对象
- * @param {string} key 需要获取的属性字段
- * @returns {*}
- */
-function getProperty(obj, key) {
-	if (!obj) {
-		return
-	}
-	if (typeof key !== 'string' || key === '') {
-		return ''
-	}
-	if (key.indexOf('.') !== -1) {
-		const keys = key.split('.')
-		let firstObj = obj[keys[0]] || {}
-
-		for (let i = 1; i < keys.length; i++) {
-			if (firstObj) {
-				firstObj = firstObj[keys[i]]
-			}
-		}
-		return firstObj
-	}
-	return obj[key]
-}
-
-/**
- * @description 设置对象的属性值,如果'a.b.c'的形式进行设置
- * @param {object} obj 对象
- * @param {string} key 需要设置的属性
- * @param {string} value 设置的值
- */
-function setProperty(obj, key, value) {
-	if (!obj) {
-		return
-	}
-	// 递归赋值
-	const inFn = function(_obj, keys, v) {
-		// 最后一个属性key
-		if (keys.length === 1) {
-			_obj[keys[0]] = v
-			return
-		}
-		// 0~length-1个key
-		while (keys.length > 1) {
-			const k = keys[0]
-			if (!_obj[k] || (typeof _obj[k] !== 'object')) {
-				_obj[k] = {}
-			}
-			const key = keys.shift()
-			// 自调用判断是否存在属性,不存在则自动创建对象
-			inFn(_obj[k], keys, v)
-		}
-	}
-
-	if (typeof key !== 'string' || key === '') {
-
-	} else if (key.indexOf('.') !== -1) { // 支持多层级赋值操作
-		const keys = key.split('.')
-		inFn(obj, keys, value)
-	} else {
-		obj[key] = value
-	}
-}
-
-/**
- * @description 获取当前页面路径
- */
-function page() {
-	const pages = getCurrentPages();
-	const route = pages[pages.length - 1]?.route;
-	// 某些特殊情况下(比如页面进行redirectTo时的一些时机),pages可能为空数组
-	return `/${route ? route : ''}`
-}
-
-/**
- * @description 获取当前路由栈实例数组
- */
-function pages() {
-	const pages = getCurrentPages()
-	return pages
-}
-
-/**
- * 获取页面历史栈指定层实例
- * @param back {number} [0] - 0或者负数,表示获取历史栈的哪一层,0表示获取当前页面实例,-1 表示获取上一个页面实例。默认0。
- */
-function getHistoryPage(back = 0) {
-	const pages = getCurrentPages()
-	const len = pages.length
-	return pages[len - 1 + back]
-}
-
-
-
-/**
- * @description 修改uvui内置属性值
- * @param {object} props 修改内置props属性
- * @param {object} config 修改内置config属性
- * @param {object} color 修改内置color属性
- * @param {object} zIndex 修改内置zIndex属性
- */
-function setConfig({
-	props = {},
-	config = {},
-	color = {},
-	zIndex = {}
-}) {
-	const {
-		deepMerge,
-	} = uni.$uv
-	uni.$uv.config = deepMerge(uni.$uv.config, config)
-	uni.$uv.props = deepMerge(uni.$uv.props, props)
-	uni.$uv.color = deepMerge(uni.$uv.color, color)
-	uni.$uv.zIndex = deepMerge(uni.$uv.zIndex, zIndex)
-}
-
-export {
-	range,
-	getPx,
-	sleep,
-	os,
-	sys,
-	random,
-	guid,
-	$parent,
-	addStyle,
-	addUnit,
-	deepClone,
-	deepMerge,
-	error,
-	randomArray,
-	timeFormat,
-	timeFrom,
-	trim,
-	queryParams,
-	toast,
-	type2icon,
-	priceFormat,
-	getDuration,
-	padZero,
-	formValidate,
-	getProperty,
-	setProperty,
-	page,
-	pages,
-	getHistoryPage,
-	setConfig
-}

+ 0 - 75
src/uni_modules/uv-ui-tools/libs/function/platform.js

@@ -1,75 +0,0 @@
-/**
- * 注意:
- * 此部分内容,在vue-cli模式下,需要在vue.config.js加入如下内容才有效:
- * module.exports = {
- *     transpileDependencies: ['uview-v2']
- * }
- */
-
-let platform = 'none'
-
-// #ifdef VUE3
-platform = 'vue3'
-// #endif
-
-// #ifdef VUE2
-platform = 'vue2'
-// #endif
-
-// #ifdef APP-PLUS
-platform = 'plus'
-// #endif
-
-// #ifdef APP-NVUE
-platform = 'nvue'
-// #endif
-
-// #ifdef H5
-platform = 'h5'
-// #endif
-
-// #ifdef MP-WEIXIN
-platform = 'weixin'
-// #endif
-
-// #ifdef MP-ALIPAY
-platform = 'alipay'
-// #endif
-
-// #ifdef MP-BAIDU
-platform = 'baidu'
-// #endif
-
-// #ifdef MP-TOUTIAO
-platform = 'toutiao'
-// #endif
-
-// #ifdef MP-QQ
-platform = 'qq'
-// #endif
-
-// #ifdef MP-KUAISHOU
-platform = 'kuaishou'
-// #endif
-
-// #ifdef MP-360
-platform = '360'
-// #endif
-
-// #ifdef MP
-platform = 'mp'
-// #endif
-
-// #ifdef QUICKAPP-WEBVIEW
-platform = 'quickapp-webview'
-// #endif
-
-// #ifdef QUICKAPP-WEBVIEW-HUAWEI
-platform = 'quickapp-webview-huawei'
-// #endif
-
-// #ifdef QUICKAPP-WEBVIEW-UNION
-platform = 'quckapp-webview-union'
-// #endif
-
-export default platform

+ 0 - 287
src/uni_modules/uv-ui-tools/libs/function/test.js

@@ -1,287 +0,0 @@
-/**
- * 验证电子邮箱格式
- */
-function email(value) {
-    return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value)
-}
-
-/**
- * 验证手机格式
- */
-function mobile(value) {
-    return /^1([3589]\d|4[5-9]|6[1-2,4-7]|7[0-8])\d{8}$/.test(value)
-}
-
-/**
- * 验证URL格式
- */
-function url(value) {
-    return /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z].[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/
-        .test(value)
-}
-
-/**
- * 验证日期格式
- */
-function date(value) {
-    if (!value) return false
-    // 判断是否数值或者字符串数值(意味着为时间戳),转为数值,否则new Date无法识别字符串时间戳
-    if (number(value)) value = +value
-    return !/Invalid|NaN/.test(new Date(value).toString())
-}
-
-/**
- * 验证ISO类型的日期格式
- */
-function dateISO(value) {
-    return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
-}
-
-/**
- * 验证十进制数字
- */
-function number(value) {
-    return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
-}
-
-/**
- * 验证字符串
- */
-function string(value) {
-    return typeof value === 'string'
-}
-
-/**
- * 验证整数
- */
-function digits(value) {
-    return /^\d+$/.test(value)
-}
-
-/**
- * 验证身份证号码
- */
-function idCard(value) {
-    return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
-        value
-    )
-}
-
-/**
- * 是否车牌号
- */
-function carNo(value) {
-    // 新能源车牌
-    const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/
-    // 旧车牌
-    const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/
-    if (value.length === 7) {
-        return creg.test(value)
-    } if (value.length === 8) {
-        return xreg.test(value)
-    }
-    return false
-}
-
-/**
- * 金额,只允许2位小数
- */
-function amount(value) {
-    // 金额,只允许保留两位小数
-    return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value)
-}
-
-/**
- * 中文
- */
-function chinese(value) {
-    const reg = /^[\u4e00-\u9fa5]+$/gi
-    return reg.test(value)
-}
-
-/**
- * 只能输入字母
- */
-function letter(value) {
-    return /^[a-zA-Z]*$/.test(value)
-}
-
-/**
- * 只能是字母或者数字
- */
-function enOrNum(value) {
-    // 英文或者数字
-    const reg = /^[0-9a-zA-Z]*$/g
-    return reg.test(value)
-}
-
-/**
- * 验证是否包含某个值
- */
-function contains(value, param) {
-    return value.indexOf(param) >= 0
-}
-
-/**
- * 验证一个值范围[min, max]
- */
-function range(value, param) {
-    return value >= param[0] && value <= param[1]
-}
-
-/**
- * 验证一个长度范围[min, max]
- */
-function rangeLength(value, param) {
-    return value.length >= param[0] && value.length <= param[1]
-}
-
-/**
- * 是否固定电话
- */
-function landline(value) {
-    const reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/
-    return reg.test(value)
-}
-
-/**
- * 判断是否为空
- */
-function empty(value) {
-    switch (typeof value) {
-    case 'undefined':
-        return true
-    case 'string':
-        if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true
-        break
-    case 'boolean':
-        if (!value) return true
-        break
-    case 'number':
-        if (value === 0 || isNaN(value)) return true
-        break
-    case 'object':
-        if (value === null || value.length === 0) return true
-        for (const i in value) {
-            return false
-        }
-        return true
-    }
-    return false
-}
-
-/**
- * 是否json字符串
- */
-function jsonString(value) {
-    if (typeof value === 'string') {
-        try {
-            const obj = JSON.parse(value)
-            if (typeof obj === 'object' && obj) {
-                return true
-            }
-            return false
-        } catch (e) {
-            return false
-        }
-    }
-    return false
-}
-
-/**
- * 是否数组
- */
-function array(value) {
-    if (typeof Array.isArray === 'function') {
-        return Array.isArray(value)
-    }
-    return Object.prototype.toString.call(value) === '[object Array]'
-}
-
-/**
- * 是否对象
- */
-function object(value) {
-    return Object.prototype.toString.call(value) === '[object Object]'
-}
-
-/**
- * 是否短信验证码
- */
-function code(value, len = 6) {
-    return new RegExp(`^\\d{${len}}$`).test(value)
-}
-
-/**
- * 是否函数方法
- * @param {Object} value
- */
-function func(value) {
-    return typeof value === 'function'
-}
-
-/**
- * 是否promise对象
- * @param {Object} value
- */
-function promise(value) {
-    return object(value) && func(value.then) && func(value.catch)
-}
-
-/** 是否图片格式
- * @param {Object} value
- */
-function image(value) {
-    const newValue = value.split('?')[0]
-    const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i
-    return IMAGE_REGEXP.test(newValue)
-}
-
-/**
- * 是否视频格式
- * @param {Object} value
- */
-function video(value) {
-    const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i
-    return VIDEO_REGEXP.test(value)
-}
-
-/**
- * 是否为正则对象
- * @param {Object}
- * @return {Boolean}
- */
-function regExp(o) {
-    return o && Object.prototype.toString.call(o) === '[object RegExp]'
-}
-
-export {
-    email,
-    mobile,
-    url,
-    date,
-    dateISO,
-    number,
-    digits,
-    idCard,
-    carNo,
-    amount,
-    chinese,
-    letter,
-    enOrNum,
-    contains,
-    range,
-    rangeLength,
-    empty,
-    jsonString,
-    landline,
-    object,
-    array,
-    code,
-    func,
-    promise,
-    video,
-    image,
-    regExp,
-    string
-}

+ 0 - 30
src/uni_modules/uv-ui-tools/libs/function/throttle.js

@@ -1,30 +0,0 @@
-let timer; let
-    flag
-/**
- * 节流原理:在一定时间内,只能触发一次
- *
- * @param {Function} func 要执行的回调函数
- * @param {Number} wait 延时的时间
- * @param {Boolean} immediate 是否立即执行
- * @return null
- */
-function throttle(func, wait = 500, immediate = true) {
-    if (immediate) {
-        if (!flag) {
-            flag = true
-            // 如果是立即执行,则在wait毫秒内开始时执行
-            typeof func === 'function' && func()
-            timer = setTimeout(() => {
-                flag = false
-            }, wait)
-        }
-    } else if (!flag) {
-        flag = true
-        // 如果是非立即执行,则在wait毫秒内的结束处执行
-        timer = setTimeout(() => {
-            flag = false
-            typeof func === 'function' && func()
-        }, wait)
-    }
-}
-export default throttle

+ 0 - 97
src/uni_modules/uv-ui-tools/libs/luch-request/adapters/index.js

@@ -1,97 +0,0 @@
-import buildURL from '../helpers/buildURL'
-import buildFullPath from '../core/buildFullPath'
-import settle from '../core/settle'
-import { isUndefined } from '../utils'
-
-/**
- * 返回可选值存在的配置
- * @param {Array} keys - 可选值数组
- * @param {Object} config2 - 配置
- * @return {{}} - 存在的配置项
- */
-const mergeKeys = (keys, config2) => {
-    const config = {}
-    keys.forEach((prop) => {
-        if (!isUndefined(config2[prop])) {
-            config[prop] = config2[prop]
-        }
-    })
-    return config
-}
-export default (config) => new Promise((resolve, reject) => {
-    const fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params)
-    const _config = {
-        url: fullPath,
-        header: config.header,
-        complete: (response) => {
-            config.fullPath = fullPath
-            response.config = config
-            try {
-                // 对可能字符串不是json 的情况容错
-                if (typeof response.data === 'string') {
-                    response.data = JSON.parse(response.data)
-                }
-                // eslint-disable-next-line no-empty
-            } catch (e) {
-            }
-            settle(resolve, reject, response)
-        }
-    }
-    let requestTask
-    if (config.method === 'UPLOAD') {
-        delete _config.header['content-type']
-        delete _config.header['Content-Type']
-        const otherConfig = {
-        // #ifdef MP-ALIPAY
-            fileType: config.fileType,
-            // #endif
-            filePath: config.filePath,
-            name: config.name
-        }
-        const optionalKeys = [
-        // #ifdef APP-PLUS || H5
-            'files',
-            // #endif
-            // #ifdef H5
-            'file',
-            // #endif
-            // #ifdef H5 || APP-PLUS
-            'timeout',
-            // #endif
-            'formData'
-        ]
-        requestTask = uni.uploadFile({ ..._config, ...otherConfig, ...mergeKeys(optionalKeys, config) })
-    } else if (config.method === 'DOWNLOAD') {
-        // #ifdef H5 || APP-PLUS
-        if (!isUndefined(config.timeout)) {
-            _config.timeout = config.timeout
-        }
-        // #endif
-        requestTask = uni.downloadFile(_config)
-    } else {
-        const optionalKeys = [
-            'data',
-            'method',
-            // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
-            'timeout',
-            // #endif
-            'dataType',
-            // #ifndef MP-ALIPAY
-            'responseType',
-            // #endif
-            // #ifdef APP-PLUS
-            'sslVerify',
-            // #endif
-            // #ifdef H5
-            'withCredentials',
-            // #endif
-            // #ifdef APP-PLUS
-            'firstIpv4'
-        // #endif
-        ]
-        requestTask = uni.request({ ..._config, ...mergeKeys(optionalKeys, config) })
-    }
-    if (config.getTask) {
-        config.getTask(requestTask, config)
-    }
-})

+ 0 - 50
src/uni_modules/uv-ui-tools/libs/luch-request/core/InterceptorManager.js

@@ -1,50 +0,0 @@
-'use strict'
-
-function InterceptorManager() {
-    this.handlers = []
-}
-
-/**
- * Add a new interceptor to the stack
- *
- * @param {Function} fulfilled The function to handle `then` for a `Promise`
- * @param {Function} rejected The function to handle `reject` for a `Promise`
- *
- * @return {Number} An ID used to remove interceptor later
- */
-InterceptorManager.prototype.use = function use(fulfilled, rejected) {
-    this.handlers.push({
-        fulfilled,
-        rejected
-    })
-    return this.handlers.length - 1
-}
-
-/**
- * Remove an interceptor from the stack
- *
- * @param {Number} id The ID that was returned by `use`
- */
-InterceptorManager.prototype.eject = function eject(id) {
-    if (this.handlers[id]) {
-        this.handlers[id] = null
-    }
-}
-
-/**
- * Iterate over all the registered interceptors
- *
- * This method is particularly useful for skipping over any
- * interceptors that may have become `null` calling `eject`.
- *
- * @param {Function} fn The function to call for each interceptor
- */
-InterceptorManager.prototype.forEach = function forEach(fn) {
-    this.handlers.forEach((h) => {
-        if (h !== null) {
-            fn(h)
-        }
-    })
-}
-
-export default InterceptorManager

+ 0 - 198
src/uni_modules/uv-ui-tools/libs/luch-request/core/Request.js

@@ -1,198 +0,0 @@
-/**
- * @Class Request
- * @description luch-request http请求插件
- * @version 3.0.7
- * @Author lu-ch
- * @Date 2021-09-04
- * @Email webwork.s@qq.com
- * 文档: https://www.quanzhan.co/luch-request/
- * github: https://github.com/lei-mu/luch-request
- * DCloud: http://ext.dcloud.net.cn/plugin?id=392
- * HBuilderX: beat-3.0.4 alpha-3.0.4
- */
-
-import dispatchRequest from './dispatchRequest'
-import InterceptorManager from './InterceptorManager'
-import mergeConfig from './mergeConfig'
-import defaults from './defaults'
-import { isPlainObject } from '../utils'
-import clone from '../utils/clone'
-
-export default class Request {
-    /**
-   * @param {Object} arg - 全局配置
-   * @param {String} arg.baseURL - 全局根路径
-   * @param {Object} arg.header - 全局header
-   * @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - 全局默认请求方式
-   * @param {String} arg.dataType = [json] - 全局默认的dataType
-   * @param {String} arg.responseType = [text|arraybuffer] - 全局默认的responseType。支付宝小程序不支持
-   * @param {Object} arg.custom - 全局默认的自定义参数
-   * @param {Number} arg.timeout - 全局默认的超时时间,单位 ms。默认60000。H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序
-   * @param {Boolean} arg.sslVerify - 全局默认的是否验证 ssl 证书。默认true.仅App安卓端支持(HBuilderX 2.3.3+)
-   * @param {Boolean} arg.withCredentials - 全局默认的跨域请求时是否携带凭证(cookies)。默认false。仅H5支持(HBuilderX 2.6.15+)
-   * @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
-   * @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
-   */
-    constructor(arg = {}) {
-        if (!isPlainObject(arg)) {
-            arg = {}
-            console.warn('设置全局参数必须接收一个Object')
-        }
-        this.config = clone({ ...defaults, ...arg })
-        this.interceptors = {
-            request: new InterceptorManager(),
-            response: new InterceptorManager()
-        }
-    }
-
-    /**
-   * @Function
-   * @param {Request~setConfigCallback} f - 设置全局默认配置
-   */
-    setConfig(f) {
-        this.config = f(this.config)
-    }
-
-    middleware(config) {
-        config = mergeConfig(this.config, config)
-        const chain = [dispatchRequest, undefined]
-        let promise = Promise.resolve(config)
-
-        this.interceptors.request.forEach((interceptor) => {
-            chain.unshift(interceptor.fulfilled, interceptor.rejected)
-        })
-
-        this.interceptors.response.forEach((interceptor) => {
-            chain.push(interceptor.fulfilled, interceptor.rejected)
-        })
-
-        while (chain.length) {
-            promise = promise.then(chain.shift(), chain.shift())
-        }
-
-        return promise
-    }
-
-    /**
-   * @Function
-   * @param {Object} config - 请求配置项
-   * @prop {String} options.url - 请求路径
-   * @prop {Object} options.data - 请求参数
-   * @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
-   * @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
-   * @prop {Object} [options.header = config.header] - 请求header
-   * @prop {Object} [options.method = config.method] - 请求方法
-   * @returns {Promise<unknown>}
-   */
-    request(config = {}) {
-        return this.middleware(config)
-    }
-
-    get(url, options = {}) {
-        return this.middleware({
-            url,
-            method: 'GET',
-            ...options
-        })
-    }
-
-    post(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'POST',
-            ...options
-        })
-    }
-
-    // #ifndef MP-ALIPAY
-    put(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'PUT',
-            ...options
-        })
-    }
-
-    // #endif
-
-    // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
-    delete(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'DELETE',
-            ...options
-        })
-    }
-
-    // #endif
-
-    // #ifdef H5 || MP-WEIXIN
-    connect(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'CONNECT',
-            ...options
-        })
-    }
-
-    // #endif
-
-    // #ifdef  H5 || MP-WEIXIN || MP-BAIDU
-    head(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'HEAD',
-            ...options
-        })
-    }
-
-    // #endif
-
-    // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
-    options(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'OPTIONS',
-            ...options
-        })
-    }
-
-    // #endif
-
-    // #ifdef H5 || MP-WEIXIN
-    trace(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'TRACE',
-            ...options
-        })
-    }
-
-    // #endif
-
-    upload(url, config = {}) {
-        config.url = url
-        config.method = 'UPLOAD'
-        return this.middleware(config)
-    }
-
-    download(url, config = {}) {
-        config.url = url
-        config.method = 'DOWNLOAD'
-        return this.middleware(config)
-    }
-}
-
-/**
- * setConfig回调
- * @return {Object} - 返回操作后的config
- * @callback Request~setConfigCallback
- * @param {Object} config - 全局默认config
- */

+ 0 - 20
src/uni_modules/uv-ui-tools/libs/luch-request/core/buildFullPath.js

@@ -1,20 +0,0 @@
-'use strict'
-
-import isAbsoluteURL from '../helpers/isAbsoluteURL'
-import combineURLs from '../helpers/combineURLs'
-
-/**
- * Creates a new URL by combining the baseURL with the requestedURL,
- * only when the requestedURL is not already an absolute URL.
- * If the requestURL is absolute, this function returns the requestedURL untouched.
- *
- * @param {string} baseURL The base URL
- * @param {string} requestedURL Absolute or relative URL to combine
- * @returns {string} The combined full path
- */
-export default function buildFullPath(baseURL, requestedURL) {
-    if (baseURL && !isAbsoluteURL(requestedURL)) {
-        return combineURLs(baseURL, requestedURL)
-    }
-    return requestedURL
-}

+ 0 - 29
src/uni_modules/uv-ui-tools/libs/luch-request/core/defaults.js

@@ -1,29 +0,0 @@
-/**
- * 默认的全局配置
- */
-
-export default {
-    baseURL: '',
-    header: {},
-    method: 'GET',
-    dataType: 'json',
-    // #ifndef MP-ALIPAY
-    responseType: 'text',
-    // #endif
-    custom: {},
-    // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
-    timeout: 60000,
-    // #endif
-    // #ifdef APP-PLUS
-    sslVerify: true,
-    // #endif
-    // #ifdef H5
-    withCredentials: false,
-    // #endif
-    // #ifdef APP-PLUS
-    firstIpv4: false,
-    // #endif
-    validateStatus: function validateStatus(status) {
-        return status >= 200 && status < 300
-    }
-}

+ 0 - 3
src/uni_modules/uv-ui-tools/libs/luch-request/core/dispatchRequest.js

@@ -1,3 +0,0 @@
-import adapter from '../adapters/index'
-
-export default (config) => adapter(config)

+ 0 - 103
src/uni_modules/uv-ui-tools/libs/luch-request/core/mergeConfig.js

@@ -1,103 +0,0 @@
-import { deepMerge, isUndefined } from '../utils'
-
-/**
- * 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局
- * @param {Array} keys - 配置项
- * @param {Object} globalsConfig - 当前的全局配置
- * @param {Object} config2 - 局部配置
- * @return {{}}
- */
-const mergeKeys = (keys, globalsConfig, config2) => {
-    const config = {}
-    keys.forEach((prop) => {
-        if (!isUndefined(config2[prop])) {
-            config[prop] = config2[prop]
-        } else if (!isUndefined(globalsConfig[prop])) {
-            config[prop] = globalsConfig[prop]
-        }
-    })
-    return config
-}
-/**
- *
- * @param globalsConfig - 当前实例的全局配置
- * @param config2 - 当前的局部配置
- * @return - 合并后的配置
- */
-export default (globalsConfig, config2 = {}) => {
-    const method = config2.method || globalsConfig.method || 'GET'
-    let config = {
-        baseURL: globalsConfig.baseURL || '',
-        method,
-        url: config2.url || '',
-        params: config2.params || {},
-        custom: { ...(globalsConfig.custom || {}), ...(config2.custom || {}) },
-        header: deepMerge(globalsConfig.header || {}, config2.header || {})
-    }
-    const defaultToConfig2Keys = ['getTask', 'validateStatus']
-    config = { ...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2) }
-
-    // eslint-disable-next-line no-empty
-    if (method === 'DOWNLOAD') {
-    // #ifdef H5 || APP-PLUS
-        if (!isUndefined(config2.timeout)) {
-            config.timeout = config2.timeout
-        } else if (!isUndefined(globalsConfig.timeout)) {
-            config.timeout = globalsConfig.timeout
-        }
-    // #endif
-    } else if (method === 'UPLOAD') {
-        delete config.header['content-type']
-        delete config.header['Content-Type']
-        const uploadKeys = [
-            // #ifdef APP-PLUS || H5
-            'files',
-            // #endif
-            // #ifdef MP-ALIPAY
-            'fileType',
-            // #endif
-            // #ifdef H5
-            'file',
-            // #endif
-            'filePath',
-            'name',
-            // #ifdef H5 || APP-PLUS
-            'timeout',
-            // #endif
-            'formData'
-        ]
-        uploadKeys.forEach((prop) => {
-            if (!isUndefined(config2[prop])) {
-                config[prop] = config2[prop]
-            }
-        })
-        // #ifdef H5 || APP-PLUS
-        if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
-            config.timeout = globalsConfig.timeout
-        }
-    // #endif
-    } else {
-        const defaultsKeys = [
-            'data',
-            // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
-            'timeout',
-            // #endif
-            'dataType',
-            // #ifndef MP-ALIPAY
-            'responseType',
-            // #endif
-            // #ifdef APP-PLUS
-            'sslVerify',
-            // #endif
-            // #ifdef H5
-            'withCredentials',
-            // #endif
-            // #ifdef APP-PLUS
-            'firstIpv4'
-            // #endif
-        ]
-        config = { ...config, ...mergeKeys(defaultsKeys, globalsConfig, config2) }
-    }
-
-    return config
-}

+ 0 - 16
src/uni_modules/uv-ui-tools/libs/luch-request/core/settle.js

@@ -1,16 +0,0 @@
-/**
- * Resolve or reject a Promise based on response status.
- *
- * @param {Function} resolve A function that resolves the promise.
- * @param {Function} reject A function that rejects the promise.
- * @param {object} response The response.
- */
-export default function settle(resolve, reject, response) {
-    const { validateStatus } = response.config
-    const status = response.statusCode
-    if (status && (!validateStatus || validateStatus(status))) {
-        resolve(response)
-    } else {
-        reject(response)
-    }
-}

+ 0 - 69
src/uni_modules/uv-ui-tools/libs/luch-request/helpers/buildURL.js

@@ -1,69 +0,0 @@
-'use strict'
-
-import * as utils from '../utils'
-
-function encode(val) {
-    return encodeURIComponent(val)
-        .replace(/%40/gi, '@')
-        .replace(/%3A/gi, ':')
-        .replace(/%24/g, '$')
-        .replace(/%2C/gi, ',')
-        .replace(/%20/g, '+')
-        .replace(/%5B/gi, '[')
-        .replace(/%5D/gi, ']')
-}
-
-/**
- * Build a URL by appending params to the end
- *
- * @param {string} url The base of the url (e.g., http://www.google.com)
- * @param {object} [params] The params to be appended
- * @returns {string} The formatted url
- */
-export default function buildURL(url, params) {
-    /* eslint no-param-reassign:0 */
-    if (!params) {
-        return url
-    }
-
-    let serializedParams
-    if (utils.isURLSearchParams(params)) {
-        serializedParams = params.toString()
-    } else {
-        const parts = []
-
-        utils.forEach(params, (val, key) => {
-            if (val === null || typeof val === 'undefined') {
-                return
-            }
-
-            if (utils.isArray(val)) {
-                key = `${key}[]`
-            } else {
-                val = [val]
-            }
-
-            utils.forEach(val, (v) => {
-                if (utils.isDate(v)) {
-                    v = v.toISOString()
-                } else if (utils.isObject(v)) {
-                    v = JSON.stringify(v)
-                }
-                parts.push(`${encode(key)}=${encode(v)}`)
-            })
-        })
-
-        serializedParams = parts.join('&')
-    }
-
-    if (serializedParams) {
-        const hashmarkIndex = url.indexOf('#')
-        if (hashmarkIndex !== -1) {
-            url = url.slice(0, hashmarkIndex)
-        }
-
-        url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
-    }
-
-    return url
-}

+ 0 - 14
src/uni_modules/uv-ui-tools/libs/luch-request/helpers/combineURLs.js

@@ -1,14 +0,0 @@
-'use strict'
-
-/**
- * Creates a new URL by combining the specified URLs
- *
- * @param {string} baseURL The base URL
- * @param {string} relativeURL The relative URL
- * @returns {string} The combined URL
- */
-export default function combineURLs(baseURL, relativeURL) {
-    return relativeURL
-        ? `${baseURL.replace(/\/+$/, '')}/${relativeURL.replace(/^\/+/, '')}`
-        : baseURL
-}

+ 0 - 14
src/uni_modules/uv-ui-tools/libs/luch-request/helpers/isAbsoluteURL.js

@@ -1,14 +0,0 @@
-'use strict'
-
-/**
- * Determines whether the specified URL is absolute
- *
- * @param {string} url The URL to test
- * @returns {boolean} True if the specified URL is absolute, otherwise false
- */
-export default function isAbsoluteURL(url) {
-    // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
-    // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
-    // by any combination of letters, digits, plus, period, or hyphen.
-    return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
-}

+ 0 - 116
src/uni_modules/uv-ui-tools/libs/luch-request/index.d.ts

@@ -1,116 +0,0 @@
-type AnyObject = Record<string | number | symbol, any>
-type HttpPromise<T> = Promise<HttpResponse<T>>;
-type Tasks = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask
-export interface RequestTask {
-  abort: () => void;
-  offHeadersReceived: () => void;
-  onHeadersReceived: () => void;
-}
-export interface HttpRequestConfig<T = Tasks> {
-  /** 请求基地址 */
-  baseURL?: string;
-  /** 请求服务器接口地址 */
-  url?: string;
-
-  /** 请求查询参数,自动拼接为查询字符串 */
-  params?: AnyObject;
-  /** 请求体参数 */
-  data?: AnyObject;
-
-  /** 文件对应的 key */
-  name?: string;
-  /** HTTP 请求中其他额外的 form data */
-  formData?: AnyObject;
-  /** 要上传文件资源的路径。 */
-  filePath?: string;
-  /** 需要上传的文件列表。使用 files 时,filePath 和 name 不生效,App、H5( 2.6.15+) */
-  files?: Array<{
-    name?: string;
-    file?: File;
-    uri: string;
-  }>;
-  /** 要上传的文件对象,仅H5(2.6.15+)支持 */
-  file?: File;
-
-  /** 请求头信息 */
-  header?: AnyObject;
-  /** 请求方式 */
-  method?: "GET" | "POST" | "PUT" | "DELETE" | "CONNECT" | "HEAD" | "OPTIONS" | "TRACE" | "UPLOAD" | "DOWNLOAD";
-  /** 如果设为 json,会尝试对返回的数据做一次 JSON.parse */
-  dataType?: string;
-  /** 设置响应的数据类型,支付宝小程序不支持 */
-  responseType?: "text" | "arraybuffer";
-  /** 自定义参数 */
-  custom?: AnyObject;
-  /** 超时时间,仅微信小程序(2.10.0)、支付宝小程序支持 */
-  timeout?: number;
-  /** DNS解析时优先使用ipv4,仅 App-Android 支持 (HBuilderX 2.8.0+) */
-  firstIpv4?: boolean;
-  /** 验证 ssl 证书 仅5+App安卓端支持(HBuilderX 2.3.3+) */
-  sslVerify?: boolean;
-  /** 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+) */
-  withCredentials?: boolean;
-
-  /** 返回当前请求的task, options。请勿在此处修改options。 */
-  getTask?: (task: T, options: HttpRequestConfig<T>) => void;
-  /**  全局自定义验证器 */
-  validateStatus?: (statusCode: number) => boolean | void;
-}
-export interface HttpResponse<T = any> {
-  config: HttpRequestConfig;
-  statusCode: number;
-  cookies: Array<string>;
-  data: T;
-  errMsg: string;
-  header: AnyObject;
-}
-export interface HttpUploadResponse<T = any> {
-  config: HttpRequestConfig;
-  statusCode: number;
-  data: T;
-  errMsg: string;
-}
-export interface HttpDownloadResponse extends HttpResponse {
-  tempFilePath: string;
-}
-export interface HttpError {
-  config: HttpRequestConfig;
-  statusCode?: number;
-  cookies?: Array<string>;
-  data?: any;
-  errMsg: string;
-  header?: AnyObject;
-}
-export interface HttpInterceptorManager<V, E = V> {
-  use(
-    onFulfilled?: (config: V) => Promise<V> | V,
-    onRejected?: (config: E) => Promise<E> | E
-  ): void;
-  eject(id: number): void;
-}
-export abstract class HttpRequestAbstract {
-  constructor(config?: HttpRequestConfig);
-  config: HttpRequestConfig;
-  interceptors: {
-    request: HttpInterceptorManager<HttpRequestConfig, HttpRequestConfig>;
-    response: HttpInterceptorManager<HttpResponse, HttpError>;
-  }
-  middleware<T = any>(config: HttpRequestConfig): HttpPromise<T>;
-  request<T = any>(config: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  get<T = any>(url: string, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  upload<T = any>(url: string, config?: HttpRequestConfig<UniApp.UploadTask>): HttpPromise<T>;
-  delete<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  head<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  post<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  put<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  connect<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  options<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  trace<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-
-  download(url: string, config?: HttpRequestConfig<UniApp.DownloadTask>): Promise<HttpDownloadResponse>;
-
-  setConfig(onSend: (config: HttpRequestConfig) => HttpRequestConfig): void;
-}
-
-declare class HttpRequest extends HttpRequestAbstract { }
-export default HttpRequest;

+ 0 - 3
src/uni_modules/uv-ui-tools/libs/luch-request/index.js

@@ -1,3 +0,0 @@
-import Request from './core/Request'
-
-export default Request

+ 0 - 131
src/uni_modules/uv-ui-tools/libs/luch-request/utils.js

@@ -1,131 +0,0 @@
-'use strict'
-
-// utils is a library of generic helper functions non-specific to axios
-
-const { toString } = Object.prototype
-
-/**
- * Determine if a value is an Array
- *
- * @param {Object} val The value to test
- * @returns {boolean} True if value is an Array, otherwise false
- */
-export function isArray(val) {
-    return toString.call(val) === '[object Array]'
-}
-
-/**
- * Determine if a value is an Object
- *
- * @param {Object} val The value to test
- * @returns {boolean} True if value is an Object, otherwise false
- */
-export function isObject(val) {
-    return val !== null && typeof val === 'object'
-}
-
-/**
- * Determine if a value is a Date
- *
- * @param {Object} val The value to test
- * @returns {boolean} True if value is a Date, otherwise false
- */
-export function isDate(val) {
-    return toString.call(val) === '[object Date]'
-}
-
-/**
- * Determine if a value is a URLSearchParams object
- *
- * @param {Object} val The value to test
- * @returns {boolean} True if value is a URLSearchParams object, otherwise false
- */
-export function isURLSearchParams(val) {
-    return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
-}
-
-/**
- * Iterate over an Array or an Object invoking a function for each item.
- *
- * If `obj` is an Array callback will be called passing
- * the value, index, and complete array for each item.
- *
- * If 'obj' is an Object callback will be called passing
- * the value, key, and complete object for each property.
- *
- * @param {Object|Array} obj The object to iterate
- * @param {Function} fn The callback to invoke for each item
- */
-export function forEach(obj, fn) {
-    // Don't bother if no value provided
-    if (obj === null || typeof obj === 'undefined') {
-        return
-    }
-
-    // Force an array if not already something iterable
-    if (typeof obj !== 'object') {
-    /* eslint no-param-reassign:0 */
-        obj = [obj]
-    }
-
-    if (isArray(obj)) {
-    // Iterate over array values
-        for (let i = 0, l = obj.length; i < l; i++) {
-            fn.call(null, obj[i], i, obj)
-        }
-    } else {
-    // Iterate over object keys
-        for (const key in obj) {
-            if (Object.prototype.hasOwnProperty.call(obj, key)) {
-                fn.call(null, obj[key], key, obj)
-            }
-        }
-    }
-}
-
-/**
- * 是否为boolean 值
- * @param val
- * @returns {boolean}
- */
-export function isBoolean(val) {
-    return typeof val === 'boolean'
-}
-
-/**
- * 是否为真正的对象{} new Object
- * @param {any} obj - 检测的对象
- * @returns {boolean}
- */
-export function isPlainObject(obj) {
-    return Object.prototype.toString.call(obj) === '[object Object]'
-}
-
-/**
- * Function equal to merge with the difference being that no reference
- * to original objects is kept.
- *
- * @see merge
- * @param {Object} obj1 Object to merge
- * @returns {Object} Result of all merge properties
- */
-export function deepMerge(/* obj1, obj2, obj3, ... */) {
-    const result = {}
-    function assignValue(val, key) {
-        if (typeof result[key] === 'object' && typeof val === 'object') {
-            result[key] = deepMerge(result[key], val)
-        } else if (typeof val === 'object') {
-            result[key] = deepMerge({}, val)
-        } else {
-            result[key] = val
-        }
-    }
-    for (let i = 0, l = arguments.length; i < l; i++) {
-        forEach(arguments[i], assignValue)
-    }
-    return result
-}
-
-export function isUndefined(val) {
-    return typeof val === 'undefined'
-}

+ 0 - 264
src/uni_modules/uv-ui-tools/libs/luch-request/utils/clone.js

@@ -1,264 +0,0 @@
-/* eslint-disable */
-var clone = (function() {
-  'use strict';
-
-  function _instanceof(obj, type) {
-    return type != null && obj instanceof type;
-  }
-
-  var nativeMap;
-  try {
-    nativeMap = Map;
-  } catch(_) {
-    // maybe a reference error because no `Map`. Give it a dummy value that no
-    // value will ever be an instanceof.
-    nativeMap = function() {};
-  }
-
-  var nativeSet;
-  try {
-    nativeSet = Set;
-  } catch(_) {
-    nativeSet = function() {};
-  }
-
-  var nativePromise;
-  try {
-    nativePromise = Promise;
-  } catch(_) {
-    nativePromise = function() {};
-  }
-
-  /**
-   * Clones (copies) an Object using deep copying.
-   *
-   * This function supports circular references by default, but if you are certain
-   * there are no circular references in your object, you can save some CPU time
-   * by calling clone(obj, false).
-   *
-   * Caution: if `circular` is false and `parent` contains circular references,
-   * your program may enter an infinite loop and crash.
-   *
-   * @param `parent` - the object to be cloned
-   * @param `circular` - set to true if the object to be cloned may contain
-   *    circular references. (optional - true by default)
-   * @param `depth` - set to a number if the object is only to be cloned to
-   *    a particular depth. (optional - defaults to Infinity)
-   * @param `prototype` - sets the prototype to be used when cloning an object.
-   *    (optional - defaults to parent prototype).
-   * @param `includeNonEnumerable` - set to true if the non-enumerable properties
-   *    should be cloned as well. Non-enumerable properties on the prototype
-   *    chain will be ignored. (optional - false by default)
-   */
-  function clone(parent, circular, depth, prototype, includeNonEnumerable) {
-    if (typeof circular === 'object') {
-      depth = circular.depth;
-      prototype = circular.prototype;
-      includeNonEnumerable = circular.includeNonEnumerable;
-      circular = circular.circular;
-    }
-    // maintain two arrays for circular references, where corresponding parents
-    // and children have the same index
-    var allParents = [];
-    var allChildren = [];
-
-    var useBuffer = typeof Buffer != 'undefined';
-
-    if (typeof circular == 'undefined')
-      circular = true;
-
-    if (typeof depth == 'undefined')
-      depth = Infinity;
-
-    // recurse this function so we don't reset allParents and allChildren
-    function _clone(parent, depth) {
-      // cloning null always returns null
-      if (parent === null)
-        return null;
-
-      if (depth === 0)
-        return parent;
-
-      var child;
-      var proto;
-      if (typeof parent != 'object') {
-        return parent;
-      }
-
-      if (_instanceof(parent, nativeMap)) {
-        child = new nativeMap();
-      } else if (_instanceof(parent, nativeSet)) {
-        child = new nativeSet();
-      } else if (_instanceof(parent, nativePromise)) {
-        child = new nativePromise(function (resolve, reject) {
-          parent.then(function(value) {
-            resolve(_clone(value, depth - 1));
-          }, function(err) {
-            reject(_clone(err, depth - 1));
-          });
-        });
-      } else if (clone.__isArray(parent)) {
-        child = [];
-      } else if (clone.__isRegExp(parent)) {
-        child = new RegExp(parent.source, __getRegExpFlags(parent));
-        if (parent.lastIndex) child.lastIndex = parent.lastIndex;
-      } else if (clone.__isDate(parent)) {
-        child = new Date(parent.getTime());
-      } else if (useBuffer && Buffer.isBuffer(parent)) {
-        if (Buffer.from) {
-          // Node.js >= 5.10.0
-          child = Buffer.from(parent);
-        } else {
-          // Older Node.js versions
-          child = new Buffer(parent.length);
-          parent.copy(child);
-        }
-        return child;
-      } else if (_instanceof(parent, Error)) {
-        child = Object.create(parent);
-      } else {
-        if (typeof prototype == 'undefined') {
-          proto = Object.getPrototypeOf(parent);
-          child = Object.create(proto);
-        }
-        else {
-          child = Object.create(prototype);
-          proto = prototype;
-        }
-      }
-
-      if (circular) {
-        var index = allParents.indexOf(parent);
-
-        if (index != -1) {
-          return allChildren[index];
-        }
-        allParents.push(parent);
-        allChildren.push(child);
-      }
-
-      if (_instanceof(parent, nativeMap)) {
-        parent.forEach(function(value, key) {
-          var keyChild = _clone(key, depth - 1);
-          var valueChild = _clone(value, depth - 1);
-          child.set(keyChild, valueChild);
-        });
-      }
-      if (_instanceof(parent, nativeSet)) {
-        parent.forEach(function(value) {
-          var entryChild = _clone(value, depth - 1);
-          child.add(entryChild);
-        });
-      }
-
-      for (var i in parent) {
-        var attrs = Object.getOwnPropertyDescriptor(parent, i);
-        if (attrs) {
-          child[i] = _clone(parent[i], depth - 1);
-        }
-
-        try {
-          var objProperty = Object.getOwnPropertyDescriptor(parent, i);
-          if (objProperty.set === 'undefined') {
-            // no setter defined. Skip cloning this property
-            continue;
-          }
-          child[i] = _clone(parent[i], depth - 1);
-        } catch(e){
-          if (e instanceof TypeError) {
-            // when in strict mode, TypeError will be thrown if child[i] property only has a getter
-            // we can't do anything about this, other than inform the user that this property cannot be set.
-            continue
-          } else if (e instanceof ReferenceError) {
-            //this may happen in non strict mode
-            continue
-          }
-        }
-
-      }
-
-      if (Object.getOwnPropertySymbols) {
-        var symbols = Object.getOwnPropertySymbols(parent);
-        for (var i = 0; i < symbols.length; i++) {
-          // Don't need to worry about cloning a symbol because it is a primitive,
-          // like a number or string.
-          var symbol = symbols[i];
-          var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
-          if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
-            continue;
-          }
-          child[symbol] = _clone(parent[symbol], depth - 1);
-          Object.defineProperty(child, symbol, descriptor);
-        }
-      }
-
-      if (includeNonEnumerable) {
-        var allPropertyNames = Object.getOwnPropertyNames(parent);
-        for (var i = 0; i < allPropertyNames.length; i++) {
-          var propertyName = allPropertyNames[i];
-          var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
-          if (descriptor && descriptor.enumerable) {
-            continue;
-          }
-          child[propertyName] = _clone(parent[propertyName], depth - 1);
-          Object.defineProperty(child, propertyName, descriptor);
-        }
-      }
-
-      return child;
-    }
-
-    return _clone(parent, depth);
-  }
-
-  /**
-   * Simple flat clone using prototype, accepts only objects, usefull for property
-   * override on FLAT configuration object (no nested props).
-   *
-   * USE WITH CAUTION! This may not behave as you wish if you do not know how this
-   * works.
-   */
-  clone.clonePrototype = function clonePrototype(parent) {
-    if (parent === null)
-      return null;
-
-    var c = function () {};
-    c.prototype = parent;
-    return new c();
-  };
-
-// private utility functions
-
-  function __objToStr(o) {
-    return Object.prototype.toString.call(o);
-  }
-  clone.__objToStr = __objToStr;
-
-  function __isDate(o) {
-    return typeof o === 'object' && __objToStr(o) === '[object Date]';
-  }
-  clone.__isDate = __isDate;
-
-  function __isArray(o) {
-    return typeof o === 'object' && __objToStr(o) === '[object Array]';
-  }
-  clone.__isArray = __isArray;
-
-  function __isRegExp(o) {
-    return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
-  }
-  clone.__isRegExp = __isRegExp;
-
-  function __getRegExpFlags(re) {
-    var flags = '';
-    if (re.global) flags += 'g';
-    if (re.ignoreCase) flags += 'i';
-    if (re.multiline) flags += 'm';
-    return flags;
-  }
-  clone.__getRegExpFlags = __getRegExpFlags;
-
-  return clone;
-})();
-
-export default clone

+ 0 - 13
src/uni_modules/uv-ui-tools/libs/mixin/button.js

@@ -1,13 +0,0 @@
-export default {
-    props: {
-        lang: String,
-        sessionFrom: String,
-        sendMessageTitle: String,
-        sendMessagePath: String,
-        sendMessageImg: String,
-        showMessageCard: Boolean,
-        appParameter: String,
-        formType: String,
-        openType: String
-    }
-}

+ 0 - 152
src/uni_modules/uv-ui-tools/libs/mixin/mixin.js

@@ -1,152 +0,0 @@
-import * as index from '../function/index.js';
-import * as test from '../function/test.js';
-export default {
-	// 定义每个组件都可能需要用到的外部样式以及类名
-	props: {
-		// 每个组件都有的父组件传递的样式,可以为字符串或者对象形式
-		customStyle: {
-			type: [Object, String],
-			default: () => ({})
-		},
-		customClass: {
-			type: String,
-			default: ''
-		},
-		// 跳转的页面路径
-		url: {
-			type: String,
-			default: ''
-		},
-		// 页面跳转的类型
-		linkType: {
-			type: String,
-			default: 'navigateTo'
-		}
-	},
-	data() {
-		return {}
-	},
-	onLoad() {
-		// getRect挂载到$uv上,因为这方法需要使用in(this),所以无法把它独立成一个单独的文件导出
-		this.$uv.getRect = this.$uvGetRect
-	},
-	created() {
-		// 组件当中,只有created声明周期,为了能在组件使用,故也在created中将方法挂载到$uv
-		this.$uv.getRect = this.$uvGetRect
-	},
-	computed: {
-		$uv() {
-			return {
-				...index,
-				test
-			}
-		},
-		/**
-		 * 生成bem规则类名
-		 * 由于微信小程序,H5,nvue之间绑定class的差异,无法通过:class="[bem()]"的形式进行同用
-		 * 故采用如下折中做法,最后返回的是数组(一般平台)或字符串(支付宝和字节跳动平台),类似['a', 'b', 'c']或'a b c'的形式
-		 * @param {String} name 组件名称
-		 * @param {Array} fixed 一直会存在的类名
-		 * @param {Array} change 会根据变量值为true或者false而出现或者隐藏的类名
-		 * @returns {Array|string}
-		 */
-		bem() {
-			return function(name, fixed, change) {
-				// 类名前缀
-				const prefix = `uv-${name}--`
-				const classes = {}
-				if (fixed) {
-					fixed.map((item) => {
-						// 这里的类名,会一直存在
-						classes[prefix + this[item]] = true
-					})
-				}
-				if (change) {
-					change.map((item) => {
-						// 这里的类名,会根据this[item]的值为true或者false,而进行添加或者移除某一个类
-						this[item] ? (classes[prefix + item] = this[item]) : (delete classes[prefix + item])
-					})
-				}
-				return Object.keys(classes)
-					// 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
-					// #ifdef MP-ALIPAY || MP-TOUTIAO || MP-LARK || MP-BAIDU
-					.join(' ')
-				// #endif
-			}
-		}
-	},
-	methods: {
-		// 跳转某一个页面
-		openPage(urlKey = 'url') {
-			const url = this[urlKey]
-			if (url) {
-				// 执行类似uni.navigateTo的方法
-				uni[this.linkType]({
-					url
-				})
-			}
-		},
-		// 查询节点信息
-		// 目前此方法在支付宝小程序中无法获取组件跟接点的尺寸,为支付宝的bug(2020-07-21)
-		// 解决办法为在组件根部再套一个没有任何作用的view元素
-		$uvGetRect(selector, all) {
-			return new Promise((resolve) => {
-				uni.createSelectorQuery()
-					.in(this)[all ? 'selectAll' : 'select'](selector)
-					.boundingClientRect((rect) => {
-						if (all && Array.isArray(rect) && rect.length) {
-							resolve(rect)
-						}
-						if (!all && rect) {
-							resolve(rect)
-						}
-					})
-					.exec()
-			})
-		},
-		getParentData(parentName = '') {
-			// 避免在created中去定义parent变量
-			if (!this.parent) this.parent = {}
-			// 这里的本质原理是,通过获取父组件实例(也即类似uv-radio的父组件uv-radio-group的this)
-			// 将父组件this中对应的参数,赋值给本组件(uv-radio的this)的parentData对象中对应的属性
-			// 之所以需要这么做,是因为所有端中,头条小程序不支持通过this.parent.xxx去监听父组件参数的变化
-			// 此处并不会自动更新子组件的数据,而是依赖父组件uv-radio-group去监听data的变化,手动调用更新子组件的方法去重新获取
-			this.parent = this.$uv.$parent.call(this, parentName)
-			if (this.parent.children) {
-				// 如果父组件的children不存在本组件的实例,才将本实例添加到父组件的children中
-				this.parent.children.indexOf(this) === -1 && this.parent.children.push(this)
-			}
-			if (this.parent && this.parentData) {
-				// 历遍parentData中的属性,将parent中的同名属性赋值给parentData
-				Object.keys(this.parentData).map((key) => {
-					this.parentData[key] = this.parent[key]
-				})
-			}
-		},
-		// 阻止事件冒泡
-		preventEvent(e) {
-			e && typeof(e.stopPropagation) === 'function' && e.stopPropagation()
-		},
-		// 空操作
-		noop(e) {
-			this.preventEvent(e)
-		}
-	},
-	onReachBottom() {
-		uni.$emit('uvOnReachBottom')
-	},
-	beforeDestroy() {
-		// 判断当前页面是否存在parent和chldren,一般在checkbox和checkbox-group父子联动的场景会有此情况
-		// 组件销毁时,移除子组件在父组件children数组中的实例,释放资源,避免数据混乱
-		if (this.parent && test.array(this.parent.children)) {
-			// 组件销毁时,移除父组件中的children数组中对应的实例
-			const childrenList = this.parent.children
-			childrenList.map((child, index) => {
-				// 如果相等,则移除
-				if (child === this) {
-					childrenList.splice(index, 1)
-				}
-			})
-		}
-	}
-}

+ 0 - 8
src/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js

@@ -1,8 +0,0 @@
-export default {
-    // #ifdef MP-WEIXIN
-    // 将自定义节点设置成虚拟的(去掉自定义组件包裹层),更加接近Vue组件的表现,能更好的使用flex属性
-    options: {
-        virtualHost: true
-    }
-    // #endif
-}

+ 0 - 13
src/uni_modules/uv-ui-tools/libs/mixin/mpShare.js

@@ -1,13 +0,0 @@
-export default {
-	onLoad() {
-	    // 设置默认的转发参数
-	    uni.$uv.mpShare = {
-	        title: '', // 默认为小程序名称
-	        path: '', // 默认为当前页面路径
-	        imageUrl: '' // 默认为当前页面的截图
-	    }
-	},
-	onShareAppMessage() {
-	    return uni.$uv.mpShare
-	}
-}

+ 0 - 44
src/uni_modules/uv-ui-tools/libs/mixin/openType.js

@@ -1,44 +0,0 @@
-export default {
-    props: {
-        openType: String
-    },
-		emits: ['getphonenumber','getuserinfo','error','opensetting','launchapp','contact','chooseavatar','addgroupapp','chooseaddress','subscribe','login','im'],
-    methods: {
-        onGetPhoneNumber(event) {
-            this.$emit('getphonenumber', event.detail)
-        },
-        onGetUserInfo(event) {
-            this.$emit('getuserinfo', event.detail)
-        },
-        onError(event) {
-            this.$emit('error', event.detail)
-        },
-        onOpenSetting(event) {
-            this.$emit('opensetting', event.detail)
-        },
-        onLaunchApp(event) {
-            this.$emit('launchapp', event.detail)
-        },
-        onContact(event) {
-            this.$emit('contact', event.detail)
-        },
-        onChooseavatar(event) {
-            this.$emit('chooseavatar', event.detail)
-        },
-        onAddgroupapp(event) {
-            this.$emit('addgroupapp', event.detail)
-        },
-        onChooseaddress(event) {
-            this.$emit('chooseaddress', event.detail)
-        },
-        onSubscribe(event) {
-            this.$emit('subscribe', event.detail)
-        },
-        onLogin(event) {
-            this.$emit('login', event.detail)
-        },
-        onIm(event) {
-            this.$emit('im', event.detail)
-        }
-    }
-}

+ 0 - 59
src/uni_modules/uv-ui-tools/libs/mixin/touch.js

@@ -1,59 +0,0 @@
-const MIN_DISTANCE = 10
-
-function getDirection(x, y) {
-    if (x > y && x > MIN_DISTANCE) {
-        return 'horizontal'
-    }
-    if (y > x && y > MIN_DISTANCE) {
-        return 'vertical'
-    }
-    return ''
-}
-
-export default {
-    methods: {
-        getTouchPoint(e) {
-            if (!e) {
-                return {
-                    x: 0,
-                    y: 0
-                }
-            } if (e.touches && e.touches[0]) {
-                return {
-                    x: e.touches[0].pageX,
-                    y: e.touches[0].pageY
-                }
-            } if (e.changedTouches && e.changedTouches[0]) {
-                return {
-                    x: e.changedTouches[0].pageX,
-                    y: e.changedTouches[0].pageY
-                }
-            }
-            return {
-                x: e.clientX || 0,
-                y: e.clientY || 0
-            }
-        },
-        resetTouchStatus() {
-            this.direction = ''
-            this.deltaX = 0
-            this.deltaY = 0
-            this.offsetX = 0
-            this.offsetY = 0
-        },
-        touchStart(event) {
-            this.resetTouchStatus()
-            const touch = this.getTouchPoint(event)
-            this.startX = touch.x
-            this.startY = touch.y
-        },
-        touchMove(event) {
-            const touch = this.getTouchPoint(event)
-            this.deltaX = touch.x - this.startX
-            this.deltaY = touch.y - this.startY
-            this.offsetX = Math.abs(this.deltaX)
-            this.offsetY = Math.abs(this.deltaY)
-            this.direction =				this.direction || getDirection(this.offsetX, this.offsetY)
-        }
-    }
-}

+ 0 - 218
src/uni_modules/uv-ui-tools/libs/util/dayjs.js

@@ -1,218 +0,0 @@
-var __getOwnPropNames = Object.getOwnPropertyNames;
-var __commonJS = (cb, mod) => function __require() {
-  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
-};
-
-// C:/Users/LP/Downloads/uvui-plus_3.1.27_example/node_modules/dayjs/dayjs.min.js
-var require_dayjs_min = __commonJS({
-  "C:/Users/LP/Downloads/uvui-plus_3.1.27_example/node_modules/dayjs/dayjs.min.js"(exports, module) {
-    !function(t, e) {
-      "object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).dayjs = e();
-    }(exports, function() {
-      "use strict";
-      var t = 1e3, e = 6e4, n = 36e5, r = "millisecond", i = "second", s = "minute", u = "hour", a = "day", o = "week", f = "month", h = "quarter", c = "year", d = "date", l = "Invalid Date", $ = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/, y = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g, M = { name: "en", weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), ordinal: function(t2) {
-        var e2 = ["th", "st", "nd", "rd"], n2 = t2 % 100;
-        return "[" + t2 + (e2[(n2 - 20) % 10] || e2[n2] || e2[0]) + "]";
-      } }, m = function(t2, e2, n2) {
-        var r2 = String(t2);
-        return !r2 || r2.length >= e2 ? t2 : "" + Array(e2 + 1 - r2.length).join(n2) + t2;
-      }, v = { s: m, z: function(t2) {
-        var e2 = -t2.utcOffset(), n2 = Math.abs(e2), r2 = Math.floor(n2 / 60), i2 = n2 % 60;
-        return (e2 <= 0 ? "+" : "-") + m(r2, 2, "0") + ":" + m(i2, 2, "0");
-      }, m: function t2(e2, n2) {
-        if (e2.date() < n2.date())
-          return -t2(n2, e2);
-        var r2 = 12 * (n2.year() - e2.year()) + (n2.month() - e2.month()), i2 = e2.clone().add(r2, f), s2 = n2 - i2 < 0, u2 = e2.clone().add(r2 + (s2 ? -1 : 1), f);
-        return +(-(r2 + (n2 - i2) / (s2 ? i2 - u2 : u2 - i2)) || 0);
-      }, a: function(t2) {
-        return t2 < 0 ? Math.ceil(t2) || 0 : Math.floor(t2);
-      }, p: function(t2) {
-        return { M: f, y: c, w: o, d: a, D: d, h: u, m: s, s: i, ms: r, Q: h }[t2] || String(t2 || "").toLowerCase().replace(/s$/, "");
-      }, u: function(t2) {
-        return void 0 === t2;
-      } }, g = "en", D = {};
-      D[g] = M;
-      var p = function(t2) {
-        return t2 instanceof _;
-      }, S = function t2(e2, n2, r2) {
-        var i2;
-        if (!e2)
-          return g;
-        if ("string" == typeof e2) {
-          var s2 = e2.toLowerCase();
-          D[s2] && (i2 = s2), n2 && (D[s2] = n2, i2 = s2);
-          var u2 = e2.split("-");
-          if (!i2 && u2.length > 1)
-            return t2(u2[0]);
-        } else {
-          var a2 = e2.name;
-          D[a2] = e2, i2 = a2;
-        }
-        return !r2 && i2 && (g = i2), i2 || !r2 && g;
-      }, w = function(t2, e2) {
-        if (p(t2))
-          return t2.clone();
-        var n2 = "object" == typeof e2 ? e2 : {};
-        return n2.date = t2, n2.args = arguments, new _(n2);
-      }, O = v;
-      O.l = S, O.i = p, O.w = function(t2, e2) {
-        return w(t2, { locale: e2.$L, utc: e2.$u, x: e2.$x, $offset: e2.$offset });
-      };
-      var _ = function() {
-        function M2(t2) {
-          this.$L = S(t2.locale, null, true), this.parse(t2);
-        }
-        var m2 = M2.prototype;
-        return m2.parse = function(t2) {
-          this.$d = function(t3) {
-            var e2 = t3.date, n2 = t3.utc;
-            if (null === e2)
-              return new Date(NaN);
-            if (O.u(e2))
-              return new Date();
-            if (e2 instanceof Date)
-              return new Date(e2);
-            if ("string" == typeof e2 && !/Z$/i.test(e2)) {
-              var r2 = e2.match($);
-              if (r2) {
-                var i2 = r2[2] - 1 || 0, s2 = (r2[7] || "0").substring(0, 3);
-                return n2 ? new Date(Date.UTC(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2)) : new Date(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2);
-              }
-            }
-            return new Date(e2);
-          }(t2), this.$x = t2.x || {}, this.init();
-        }, m2.init = function() {
-          var t2 = this.$d;
-          this.$y = t2.getFullYear(), this.$M = t2.getMonth(), this.$D = t2.getDate(), this.$W = t2.getDay(), this.$H = t2.getHours(), this.$m = t2.getMinutes(), this.$s = t2.getSeconds(), this.$ms = t2.getMilliseconds();
-        }, m2.$utils = function() {
-          return O;
-        }, m2.isValid = function() {
-          return !(this.$d.toString() === l);
-        }, m2.isSame = function(t2, e2) {
-          var n2 = w(t2);
-          return this.startOf(e2) <= n2 && n2 <= this.endOf(e2);
-        }, m2.isAfter = function(t2, e2) {
-          return w(t2) < this.startOf(e2);
-        }, m2.isBefore = function(t2, e2) {
-          return this.endOf(e2) < w(t2);
-        }, m2.$g = function(t2, e2, n2) {
-          return O.u(t2) ? this[e2] : this.set(n2, t2);
-        }, m2.unix = function() {
-          return Math.floor(this.valueOf() / 1e3);
-        }, m2.valueOf = function() {
-          return this.$d.getTime();
-        }, m2.startOf = function(t2, e2) {
-          var n2 = this, r2 = !!O.u(e2) || e2, h2 = O.p(t2), l2 = function(t3, e3) {
-            var i2 = O.w(n2.$u ? Date.UTC(n2.$y, e3, t3) : new Date(n2.$y, e3, t3), n2);
-            return r2 ? i2 : i2.endOf(a);
-          }, $2 = function(t3, e3) {
-            return O.w(n2.toDate()[t3].apply(n2.toDate("s"), (r2 ? [0, 0, 0, 0] : [23, 59, 59, 999]).slice(e3)), n2);
-          }, y2 = this.$W, M3 = this.$M, m3 = this.$D, v2 = "set" + (this.$u ? "UTC" : "");
-          switch (h2) {
-            case c:
-              return r2 ? l2(1, 0) : l2(31, 11);
-            case f:
-              return r2 ? l2(1, M3) : l2(0, M3 + 1);
-            case o:
-              var g2 = this.$locale().weekStart || 0, D2 = (y2 < g2 ? y2 + 7 : y2) - g2;
-              return l2(r2 ? m3 - D2 : m3 + (6 - D2), M3);
-            case a:
-            case d:
-              return $2(v2 + "Hours", 0);
-            case u:
-              return $2(v2 + "Minutes", 1);
-            case s:
-              return $2(v2 + "Seconds", 2);
-            case i:
-              return $2(v2 + "Milliseconds", 3);
-            default:
-              return this.clone();
-          }
-        }, m2.endOf = function(t2) {
-          return this.startOf(t2, false);
-        }, m2.$set = function(t2, e2) {
-          var n2, o2 = O.p(t2), h2 = "set" + (this.$u ? "UTC" : ""), l2 = (n2 = {}, n2[a] = h2 + "Date", n2[d] = h2 + "Date", n2[f] = h2 + "Month", n2[c] = h2 + "FullYear", n2[u] = h2 + "Hours", n2[s] = h2 + "Minutes", n2[i] = h2 + "Seconds", n2[r] = h2 + "Milliseconds", n2)[o2], $2 = o2 === a ? this.$D + (e2 - this.$W) : e2;
-          if (o2 === f || o2 === c) {
-            var y2 = this.clone().set(d, 1);
-            y2.$d[l2]($2), y2.init(), this.$d = y2.set(d, Math.min(this.$D, y2.daysInMonth())).$d;
-          } else
-            l2 && this.$d[l2]($2);
-          return this.init(), this;
-        }, m2.set = function(t2, e2) {
-          return this.clone().$set(t2, e2);
-        }, m2.get = function(t2) {
-          return this[O.p(t2)]();
-        }, m2.add = function(r2, h2) {
-          var d2, l2 = this;
-          r2 = Number(r2);
-          var $2 = O.p(h2), y2 = function(t2) {
-            var e2 = w(l2);
-            return O.w(e2.date(e2.date() + Math.round(t2 * r2)), l2);
-          };
-          if ($2 === f)
-            return this.set(f, this.$M + r2);
-          if ($2 === c)
-            return this.set(c, this.$y + r2);
-          if ($2 === a)
-            return y2(1);
-          if ($2 === o)
-            return y2(7);
-          var M3 = (d2 = {}, d2[s] = e, d2[u] = n, d2[i] = t, d2)[$2] || 1, m3 = this.$d.getTime() + r2 * M3;
-          return O.w(m3, this);
-        }, m2.subtract = function(t2, e2) {
-          return this.add(-1 * t2, e2);
-        }, m2.format = function(t2) {
-          var e2 = this, n2 = this.$locale();
-          if (!this.isValid())
-            return n2.invalidDate || l;
-          var r2 = t2 || "YYYY-MM-DDTHH:mm:ssZ", i2 = O.z(this), s2 = this.$H, u2 = this.$m, a2 = this.$M, o2 = n2.weekdays, f2 = n2.months, h2 = function(t3, n3, i3, s3) {
-            return t3 && (t3[n3] || t3(e2, r2)) || i3[n3].slice(0, s3);
-          }, c2 = function(t3) {
-            return O.s(s2 % 12 || 12, t3, "0");
-          }, d2 = n2.meridiem || function(t3, e3, n3) {
-            var r3 = t3 < 12 ? "AM" : "PM";
-            return n3 ? r3.toLowerCase() : r3;
-          }, $2 = { YY: String(this.$y).slice(-2), YYYY: this.$y, M: a2 + 1, MM: O.s(a2 + 1, 2, "0"), MMM: h2(n2.monthsShort, a2, f2, 3), MMMM: h2(f2, a2), D: this.$D, DD: O.s(this.$D, 2, "0"), d: String(this.$W), dd: h2(n2.weekdaysMin, this.$W, o2, 2), ddd: h2(n2.weekdaysShort, this.$W, o2, 3), dddd: o2[this.$W], H: String(s2), HH: O.s(s2, 2, "0"), h: c2(1), hh: c2(2), a: d2(s2, u2, true), A: d2(s2, u2, false), m: String(u2), mm: O.s(u2, 2, "0"), s: String(this.$s), ss: O.s(this.$s, 2, "0"), SSS: O.s(this.$ms, 3, "0"), Z: i2 };
-          return r2.replace(y, function(t3, e3) {
-            return e3 || $2[t3] || i2.replace(":", "");
-          });
-        }, m2.utcOffset = function() {
-          return 15 * -Math.round(this.$d.getTimezoneOffset() / 15);
-        }, m2.diff = function(r2, d2, l2) {
-          var $2, y2 = O.p(d2), M3 = w(r2), m3 = (M3.utcOffset() - this.utcOffset()) * e, v2 = this - M3, g2 = O.m(this, M3);
-          return g2 = ($2 = {}, $2[c] = g2 / 12, $2[f] = g2, $2[h] = g2 / 3, $2[o] = (v2 - m3) / 6048e5, $2[a] = (v2 - m3) / 864e5, $2[u] = v2 / n, $2[s] = v2 / e, $2[i] = v2 / t, $2)[y2] || v2, l2 ? g2 : O.a(g2);
-        }, m2.daysInMonth = function() {
-          return this.endOf(f).$D;
-        }, m2.$locale = function() {
-          return D[this.$L];
-        }, m2.locale = function(t2, e2) {
-          if (!t2)
-            return this.$L;
-          var n2 = this.clone(), r2 = S(t2, e2, true);
-          return r2 && (n2.$L = r2), n2;
-        }, m2.clone = function() {
-          return O.w(this.$d, this);
-        }, m2.toDate = function() {
-          return new Date(this.valueOf());
-        }, m2.toJSON = function() {
-          return this.isValid() ? this.toISOString() : null;
-        }, m2.toISOString = function() {
-          return this.$d.toISOString();
-        }, m2.toString = function() {
-          return this.$d.toUTCString();
-        }, M2;
-      }(), T = _.prototype;
-      return w.prototype = T, [["$ms", r], ["$s", i], ["$m", s], ["$H", u], ["$W", a], ["$M", f], ["$y", c], ["$D", d]].forEach(function(t2) {
-        T[t2[1]] = function(e2) {
-          return this.$g(e2, t2[0], t2[1]);
-        };
-      }), w.extend = function(t2, e2) {
-        return t2.$i || (t2(e2, _, w), t2.$i = true), w;
-      }, w.locale = S, w.isDayjs = p, w.unix = function(t2) {
-        return w(1e3 * t2);
-      }, w.en = D[g], w.Ls = D, w.p = {}, w;
-    });
-  }
-});
-export default require_dayjs_min();
-//# sourceMappingURL=dayjs.js.map

+ 0 - 124
src/uni_modules/uv-ui-tools/libs/util/route.js

@@ -1,124 +0,0 @@
-/**
- * 路由跳转方法,该方法相对于直接使用uni.xxx的好处是使用更加简单快捷
- * 并且带有路由拦截功能
- */
-	import { queryParams, deepMerge,page } from '@/uni_modules/uv-ui-tools/libs/function/index.js'
-class Router {
-	constructor() {
-		// 原始属性定义
-		this.config = {
-			type: 'navigateTo',
-			url: '',
-			delta: 1, // navigateBack页面后退时,回退的层数
-			params: {}, // 传递的参数
-			animationType: 'pop-in', // 窗口动画,只在APP有效
-			animationDuration: 300, // 窗口动画持续时间,单位毫秒,只在APP有效
-			intercept: false // 是否需要拦截
-		}
-		// 因为route方法是需要对外赋值给另外的对象使用,同时route内部有使用this,会导致route失去上下文
-		// 这里在构造函数中进行this绑定
-		this.route = this.route.bind(this)
-	}
-
-	// 判断url前面是否有"/",如果没有则加上,否则无法跳转
-	addRootPath(url) {
-		return url[0] === '/' ? url : `/${url}`
-	}
-
-	// 整合路由参数
-	mixinParam(url, params) {
-		url = url && this.addRootPath(url)
-
-		// 使用正则匹配,主要依据是判断是否有"/","?","="等,如“/page/index/index?name=mary"
-		// 如果有url中有get参数,转换后无需带上"?"
-		let query = ''
-		if (/.*\/.*\?.*=.*/.test(url)) {
-			// object对象转为get类型的参数
-			query = queryParams(params, false)
-			// 因为已有get参数,所以后面拼接的参数需要带上"&"隔开
-			return url += `&${query}`
-		}
-		// 直接拼接参数,因为此处url中没有后面的query参数,也就没有"?/&"之类的符号
-		query = queryParams(params)
-		return url += query
-	}
-
-	// 对外的方法名称
-	async route(options = {}, params = {}) {
-		// 合并用户的配置和内部的默认配置
-		let mergeConfig = {}
-
-		if (typeof options === 'string') {
-			// 如果options为字符串,则为route(url, params)的形式
-			mergeConfig.url = this.mixinParam(options, params)
-			mergeConfig.type = 'navigateTo'
-		} else {
-			mergeConfig = deepMerge(this.config, options)
-			// 否则正常使用mergeConfig中的url和params进行拼接
-			mergeConfig.url = this.mixinParam(options.url, options.params)
-		}
-
-		// 如果本次跳转的路径和本页面路径一致,不执行跳转,防止用户快速点击跳转按钮,造成多次跳转同一个页面的问题
-		if (mergeConfig.url === page()) return
-
-		if (params.intercept) {
-			this.config.intercept = params.intercept
-		}
-		// params参数也带给拦截器
-		mergeConfig.params = params
-		// 合并内外部参数
-		mergeConfig = deepMerge(this.config, mergeConfig)
-		// 判断用户是否定义了拦截器
-		if (typeof routeIntercept === 'function') {
-			// 定一个promise,根据用户执行resolve(true)或者resolve(false)来决定是否进行路由跳转
-			const isNext = await new Promise((resolve, reject) => {
-				routeIntercept(mergeConfig, resolve)
-			})
-			// 如果isNext为true,则执行路由跳转
-			isNext && this.openPage(mergeConfig)
-		} else {
-			this.openPage(mergeConfig)
-		}
-	}
-
-	// 执行路由跳转
-	openPage(config) {
-		// 解构参数
-		const {
-			url,
-			type,
-			delta,
-			animationType,
-			animationDuration
-		} = config
-		if (config.type == 'navigateTo' || config.type == 'to') {
-			uni.navigateTo({
-				url,
-				animationType,
-				animationDuration
-			})
-		}
-		if (config.type == 'redirectTo' || config.type == 'redirect') {
-			uni.redirectTo({
-				url
-			})
-		}
-		if (config.type == 'switchTab' || config.type == 'tab') {
-			uni.switchTab({
-				url
-			})
-		}
-		if (config.type == 'reLaunch' || config.type == 'launch') {
-			uni.reLaunch({
-				url
-			})
-		}
-		if (config.type == 'navigateBack' || config.type == 'back') {
-			uni.navigateBack({
-				delta
-			})
-		}
-	}
-}
-
-export default (new Router()).route

+ 0 - 81
src/uni_modules/uv-ui-tools/package.json

@@ -1,81 +0,0 @@
-{
-  "id": "uv-ui-tools",
-  "displayName": "uv-ui-tools 工具集 全面兼容vue3+2、app、h5、小程序等多端",
-  "version": "1.0.10",
-  "description": "uv-ui-tools,集成工具库,强大的Http请求封装,清晰的文档说明,开箱即用。方便使用,可以全局使用",
-  "keywords": [
-    "uv-ui-tools,uv-ui组件库,工具集,uvui,uView2.x"
-],
-  "repository": "",
-  "engines": {
-    "HBuilderX": "^3.1.0"
-  },
-  "dcloudext": {
-    "type": "component-vue",
-    "sale": {
-      "regular": {
-        "price": "0.00"
-      },
-      "sourcecode": {
-        "price": "0.00"
-      }
-    },
-    "contact": {
-      "qq": ""
-    },
-    "declaration": {
-      "ads": "无",
-      "data": "插件不采集任何数据",
-      "permissions": "无"
-    },
-    "npmurl": ""
-  },
-  "uni_modules": {
-    "dependencies": [],
-    "encrypt": [],
-    "platforms": {
-      "cloud": {
-        "tcb": "y",
-        "aliyun": "y"
-      },
-      "client": {
-        "Vue": {
-          "vue2": "y",
-          "vue3": "y"
-        },
-        "App": {
-          "app-vue": "y",
-          "app-nvue": "y"
-        },
-        "H5-mobile": {
-          "Safari": "y",
-          "Android Browser": "y",
-          "微信浏览器(Android)": "y",
-          "QQ浏览器(Android)": "y"
-        },
-        "H5-pc": {
-          "Chrome": "y",
-          "IE": "y",
-          "Edge": "y",
-          "Firefox": "y",
-          "Safari": "y"
-        },
-        "小程序": {
-          "微信": "y",
-          "阿里": "y",
-          "百度": "y",
-          "字节跳动": "y",
-          "QQ": "y",
-          "钉钉": "y",
-          "快手": "y",
-          "飞书": "y",
-          "京东": "y"
-        },
-        "快应用": {
-          "华为": "y",
-          "联盟": "y"
-        }
-      }
-    }
-  }
-}

+ 0 - 23
src/uni_modules/uv-ui-tools/readme.md

@@ -1,23 +0,0 @@
-## uv-ui-tools 工具集
-
-> **组件名:uv-ui-tools**
-
-uv-ui工具集成,包括网络Http请求、便捷工具、节流防抖、对象操作、时间格式化、路由跳转、全局唯一标识符、规则校验等等。
-
-该组件推荐配合[uv-ui组件库](https://www.uvui.cn/components/intro.html)使用,单独下载也可以在自己项目中使用,需要做相应的配置,可查看文档。强烈推荐使用[uv-ui组件库](https://www.uvui.cn/components/intro.html),导入组件都会自动导入`uv-ui-tools`。需要在自己的项目中使用请参考[扩展配置](https://www.uvui.cn/components/setting.html)。
-
-uv-ui破釜沉舟之兼容vue3+2、app、h5、多端小程序的uni-app生态框架,大部分组件基于uView2.x,在经过改进后全面支持vue3,部分组件做了进一步的优化,修复大量BUG,支持单独导入,方便开发者选择导入需要的组件。开箱即用,灵活配置。
-
-# <a href="https://www.uvui.cn/js/intro.html" target="_blank">查看文档</a>
-
-## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
-
-### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
-
-<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
-
-![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
-
-</a>
-
-#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

+ 0 - 43
src/uni_modules/uv-ui-tools/theme.scss

@@ -1,43 +0,0 @@
-// 此文件为uvUI的主题变量,这些变量目前只能通过uni.scss引入才有效,另外由于
-// uni.scss中引入的样式会同时混入到全局样式文件和单独每一个页面的样式中,造成微信程序包太大,
-// 故uni.scss只建议放scss变量名相关样式,其他的样式可以通过main.js或者App.vue引入
-
-$uv-main-color: #303133;
-$uv-content-color: #606266;
-$uv-tips-color: #909193;
-$uv-light-color: #c0c4cc;
-$uv-border-color: #dadbde;
-$uv-bg-color: #f3f4f6;
-$uv-disabled-color: #c8c9cc;
-
-$uv-primary: #3c9cff;
-$uv-primary-dark: #398ade;
-$uv-primary-disabled: #9acafc;
-$uv-primary-light: #ecf5ff;
-
-$uv-warning: #f9ae3d;
-$uv-warning-dark: #f1a532;
-$uv-warning-disabled: #f9d39b;
-$uv-warning-light: #fdf6ec;
-
-$uv-success: #5ac725;
-$uv-success-dark: #53c21d;
-$uv-success-disabled: #a9e08f;
-$uv-success-light: #f5fff0;
-
-$uv-error: #f56c6c;
-$uv-error-dark: #e45656;
-$uv-error-disabled: #f7b2b2;
-$uv-error-light: #fef0f0;
-
-$uv-info: #909399;
-$uv-info-dark: #767a82;
-$uv-info-disabled: #c4c6c9;
-$uv-info-light: #f4f4f5;
-
-@mixin flex($direction: row) {
-	/* #ifndef APP-NVUE */
-	display: flex;
-	/* #endif */
-	flex-direction: $direction;
-}

部分文件因文件數量過多而無法顯示