chubiao преди 1 година
родител
ревизия
b6db5d6e94

+ 366 - 96
common/base64.js

@@ -1,96 +1,366 @@
-(function(a) {
-	if ("object" == typeof exports && "undefined" != typeof module) module.exports = a();
-	else if ("function" == typeof define && define.amd) define([], a);
-	else {
-		var b;
-		b = "undefined" == typeof window ? "undefined" == typeof global ? "undefined" == typeof self ? this : self :
-			global : window, b.base64js = a()
-	}
-})(function() {
-	return function() {
-		function b(d, e, g) {
-			function a(j, i) {
-				if (!e[j]) {
-					if (!d[j]) {
-						var f = "function" == typeof require && require;
-						if (!i && f) return f(j, !0);
-						if (h) return h(j, !0);
-						var c = new Error("Cannot find module '" + j + "'");
-						throw c.code = "MODULE_NOT_FOUND", c
-					}
-					var k = e[j] = {
-						exports: {}
-					};
-					d[j][0].call(k.exports, function(b) {
-						var c = d[j][1][b];
-						return a(c || b)
-					}, k, k.exports, b, d, e, g)
-				}
-				return e[j].exports
-			}
-			for (var h = "function" == typeof require && require, c = 0; c < g.length; c++) a(g[c]);
-			return a
-		}
-		return b
-	}()({
-		"/": [function(a, b, c) {
-			'use strict';
-
-			function d(a) {
-				var b = a.length;
-				if (0 < b % 4) throw new Error("Invalid string. Length must be a multiple of 4");
-				var c = a.indexOf("="); - 1 === c && (c = b);
-				var d = c === b ? 0 : 4 - c % 4;
-				return [c, d]
-			}
-
-			function e(a, b, c) {
-				return 3 * (b + c) / 4 - c
-			}
-
-			function f(a) {
-				var b, c, f = d(a),
-					g = f[0],
-					h = f[1],
-					j = new m(e(a, g, h)),
-					k = 0,
-					n = 0 < h ? g - 4 : g;
-				for (c = 0; c < n; c += 4) b = l[a.charCodeAt(c)] << 18 | l[a.charCodeAt(c + 1)] <<
-					12 | l[a.charCodeAt(c + 2)] << 6 | l[a.charCodeAt(c + 3)], j[k++] = 255 & b >>
-					16, j[k++] = 255 & b >> 8, j[k++] = 255 & b;
-				return 2 === h && (b = l[a.charCodeAt(c)] << 2 | l[a.charCodeAt(c + 1)] >> 4, j[
-					k++] = 255 & b), 1 === h && (b = l[a.charCodeAt(c)] << 10 | l[a.charCodeAt(
-					c + 1)] << 4 | l[a.charCodeAt(c + 2)] >> 2, j[k++] = 255 & b >> 8, j[
-					k++] = 255 & b), j
-			}
-
-			function g(a) {
-				return k[63 & a >> 18] + k[63 & a >> 12] + k[63 & a >> 6] + k[63 & a]
-			}
-
-			function h(a, b, c) {
-				for (var d, e = [], f = b; f < c; f += 3) d = (16711680 & a[f] << 16) + (65280 & a[
-					f + 1] << 8) + (255 & a[f + 2]), e.push(g(d));
-				return e.join("")
-			}
-
-			function j(a) {
-				for (var b, c = a.length, d = c % 3, e = [], f = 16383, g = 0, j = c - d; g <
-					j; g += f) e.push(h(a, g, g + f > j ? j : g + f));
-				return 1 === d ? (b = a[c - 1], e.push(k[b >> 2] + k[63 & b << 4] + "==")) : 2 ===
-					d && (b = (a[c - 2] << 8) + a[c - 1], e.push(k[b >> 10] + k[63 & b >> 4] + k[
-						63 & b << 2] + "=")), e.join("")
-			}
-			c.byteLength = function(a) {
-				var b = d(a),
-					c = b[0],
-					e = b[1];
-				return 3 * (c + e) / 4 - e
-			}, c.toByteArray = f, c.fromByteArray = j;
-			for (var k = [], l = [], m = "undefined" == typeof Uint8Array ? Array : Uint8Array, n =
-					"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", o = 0, p = n
-					.length; o < p; ++o) k[o] = n[o], l[n.charCodeAt(o)] = o;
-			l[45] = 62, l[95] = 63
-		}, {}]
-	}, {}, [])("/")
-});
+if (Uint8Array)
+{
+  var _slice = Uint8Array.prototype.slice;
+
+  try {
+    // Can't be used with DOM elements in IE < 9
+    _slice.call(document.documentElement);
+  } catch (e) { // Fails in IE < 9
+
+    // This will work for genuine arrays, array-like objects,
+    // NamedNodeMap (attributes, entities, notations),
+    // NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
+    // and will not fail on other DOM objects (as do DOM elements in IE < 9)
+    Uint8Array.prototype.slice = function(begin, end) {
+      // IE < 9 gets unhappy with an undefined end argument
+      end = (typeof end !== 'undefined') ? end : this.length;
+
+      // For native Array objects, we use the native slice function
+      if (Object.prototype.toString.call(this) === '[object Array]'){
+        return _slice.call(this, begin, end);
+      }
+
+      // For array like object we handle it ourselves.
+      var i, cloned = [],
+        size, len = this.length;
+
+      // Handle negative value for "begin"
+      var start = begin || 0;
+      start = (start >= 0) ? start : Math.max(0, len + start);
+
+      // Handle negative value for "end"
+      var upTo = (typeof end == 'number') ? Math.min(end, len) : len;
+      if (end < 0) {
+        upTo = len + end;
+      }
+
+      // Actual expected size of the slice
+      size = upTo - start;
+
+      if (size > 0) {
+        cloned = new Array(size);
+        if (this.charAt) {
+          for (i = 0; i < size; i++) {
+            cloned[i] = this.charAt(start + i);
+          }
+        } else {
+          for (i = 0; i < size; i++) {
+            cloned[i] = this[start + i];
+          }
+        }
+      }
+
+      return cloned;
+    };
+  }
+if (!Uint8Array.from) {
+  Uint8Array.from = (function () {
+    var toStr = Object.prototype.toString;
+    var isCallable = function (fn) {
+      return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
+    };
+    var toInteger = function (value) {
+      var number = Number(value);
+      if (isNaN(number)) { return 0; }
+      if (number === 0 || !isFinite(number)) { return number; }
+      return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
+    };
+    var maxSafeInteger = Math.pow(2, 53) - 1;
+    var toLength = function (value) {
+      var len = toInteger(value);
+      return Math.min(Math.max(len, 0), maxSafeInteger);
+    };
+    var toItems = function (value) {
+      // support set
+      if (value.size > 0 && value.values) {
+        var values = value.values();
+        var it = values.next();
+        var o = [];
+        while (!it.done) {
+          o.push(it.value);
+          it = values.next();
+        }
+        return o;
+      }
+      return Object(value);
+    };
+    // The length property of the from method is 1.
+    return function from(arrayLike/*, mapFn, thisArg */) {
+      // 1. Let C be the this value.
+      var C = this;
+
+      // 2. Let items be ToObject(arrayLike).
+      var items = toItems(arrayLike);
+
+      // 3. ReturnIfAbrupt(items).
+      if (arrayLike == null) {
+        throw new TypeError("Array.from requires an array-like object - not null or undefined");
+      }
+
+      // 4. If mapfn is undefined, then let mapping be false.
+      var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
+      var T;
+      if (typeof mapFn !== 'undefined') {
+        // 5. else
+        // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
+        if (!isCallable(mapFn)) {
+          throw new TypeError('Array.from: when provided, the second argument must be a function');
+        }
+
+        // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
+        if (arguments.length > 2) {
+          T = arguments[2];
+        }
+      }
+
+      // 10. Let lenValue be Get(items, "length").
+      // 11. Let len be ToLength(lenValue).
+      var len = toLength(items.length);
+
+      // 13. If IsConstructor(C) is true, then
+      // 13. a. Let A be the result of calling the [[Construct]] internal method
+      // of C with an argument list containing the single item len.
+      // 14. a. Else, Let A be ArrayCreate(len).
+      var A = isCallable(C) ? Object(new C(len)) : new Array(len);
+
+      // 16. Let k be 0.
+      var k = 0;
+      // 17. Repeat, while k < len�� (also steps a - h)
+      var kValue;
+      while (k < len) {
+        kValue = items[k];
+        if (mapFn) {
+          A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
+        } else {
+          A[k] = kValue;
+        }
+        k += 1;
+      }
+      // 18. Let putStatus be Put(A, "length", len, true).
+      A.length = len;
+      // 20. Return A.
+      return A;
+    };
+  }());
+}
+}
+;(function (global, factory) {
+    typeof exports === 'object' && typeof module !== 'undefined'
+        ? module.exports = factory(global)
+        : typeof define === 'function' && define.amd
+        ? define(factory) : factory(global)
+}((
+    typeof self !== 'undefined' ? self
+        : typeof window !== 'undefined' ? window
+        : typeof global !== 'undefined' ? global
+: this
+), function(global) {
+    'use strict';
+    // existing version for noConflict()
+    global = global || {};
+    var _Base64 = global.Base64;
+    var version = "2.6.2";
+    // constants
+    var b64chars
+        = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+    var b64tab = function(bin) {
+        var t = {};
+        for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i;
+        return t;
+    }(b64chars);
+    var fromCharCode = String.fromCharCode;
+    // encoder stuff
+    var cb_utob = function(c) {
+        if (c.length < 2) {
+            var cc = c.charCodeAt(0);
+            return cc < 0x80 ? c
+                : cc < 0x800 ? (fromCharCode(0xc0 | (cc >>> 6))
+                                + fromCharCode(0x80 | (cc & 0x3f)))
+                : (fromCharCode(0xe0 | ((cc >>> 12) & 0x0f))
+                    + fromCharCode(0x80 | ((cc >>>  6) & 0x3f))
+                    + fromCharCode(0x80 | ( cc         & 0x3f)));
+        } else {
+            var cc = 0x10000
+                + (c.charCodeAt(0) - 0xD800) * 0x400
+                + (c.charCodeAt(1) - 0xDC00);
+            return (fromCharCode(0xf0 | ((cc >>> 18) & 0x07))
+                    + fromCharCode(0x80 | ((cc >>> 12) & 0x3f))
+                    + fromCharCode(0x80 | ((cc >>>  6) & 0x3f))
+                    + fromCharCode(0x80 | ( cc         & 0x3f)));
+        }
+    };
+    var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
+    var utob = function(u) {
+        return u.replace(re_utob, cb_utob);
+    };
+    var cb_encode = function(ccc) {
+        var padlen = [0, 2, 1][ccc.length % 3],
+        ord = ccc.charCodeAt(0) << 16
+            | ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8)
+            | ((ccc.length > 2 ? ccc.charCodeAt(2) : 0)),
+        chars = [
+            b64chars.charAt( ord >>> 18),
+            b64chars.charAt((ord >>> 12) & 63),
+            padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63),
+            padlen >= 1 ? '=' : b64chars.charAt(ord & 63)
+        ];
+        return chars.join('');
+    };
+    var btoa = global.btoa && typeof global.btoa == 'function'
+        ? function(b){ return global.btoa(b) } : function(b) {
+        if (b.match(/[^\x00-\xFF]/)) throw new RangeError(
+            'The string contains invalid characters.'
+        );
+        return b.replace(/[\s\S]{1,3}/g, cb_encode);
+    };
+    var _encode = function(u) {
+        return btoa(utob(String(u)));
+    };
+    var mkUriSafe = function (b64) {
+        return b64.replace(/[+\/]/g, function(m0) {
+            return m0 == '+' ? '-' : '_';
+        }).replace(/=/g, '');
+    };
+    var encode = function(u, urisafe) {
+        return urisafe ? mkUriSafe(_encode(u)) : _encode(u);
+    };
+    var encodeURI = function(u) { return encode(u, true) };
+    var fromUint8Array;
+    if (global.Uint8Array) fromUint8Array = function(a, urisafe) {
+        // return btoa(fromCharCode.apply(null, a));
+        var b64 = '';
+        for (var i = 0, l = a.length; i < l; i += 3) {
+            var a0 = a[i], a1 = a[i+1], a2 = a[i+2];
+            var ord = a0 << 16 | a1 << 8 | a2;
+            b64 +=    b64chars.charAt( ord >>> 18)
+                +     b64chars.charAt((ord >>> 12) & 63)
+                + ( typeof a1 != 'undefined'
+                    ? b64chars.charAt((ord >>>  6) & 63) : '=')
+                + ( typeof a2 != 'undefined'
+                    ? b64chars.charAt( ord         & 63) : '=');
+        }
+        return urisafe ? mkUriSafe(b64) : b64;
+    };
+    // decoder stuff
+    var re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g;
+    var cb_btou = function(cccc) {
+        switch(cccc.length) {
+        case 4:
+            var cp = ((0x07 & cccc.charCodeAt(0)) << 18)
+                |    ((0x3f & cccc.charCodeAt(1)) << 12)
+                |    ((0x3f & cccc.charCodeAt(2)) <<  6)
+                |     (0x3f & cccc.charCodeAt(3)),
+            offset = cp - 0x10000;
+            return (fromCharCode((offset  >>> 10) + 0xD800)
+                    + fromCharCode((offset & 0x3FF) + 0xDC00));
+        case 3:
+            return fromCharCode(
+                ((0x0f & cccc.charCodeAt(0)) << 12)
+                    | ((0x3f & cccc.charCodeAt(1)) << 6)
+                    |  (0x3f & cccc.charCodeAt(2))
+            );
+        default:
+            return  fromCharCode(
+                ((0x1f & cccc.charCodeAt(0)) << 6)
+                    |  (0x3f & cccc.charCodeAt(1))
+            );
+        }
+    };
+    var btou = function(b) {
+        return b.replace(re_btou, cb_btou);
+    };
+    var cb_decode = function(cccc) {
+        var len = cccc.length,
+        padlen = len % 4,
+        n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0)
+            | (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0)
+            | (len > 2 ? b64tab[cccc.charAt(2)] <<  6 : 0)
+            | (len > 3 ? b64tab[cccc.charAt(3)]       : 0),
+        chars = [
+            fromCharCode( n >>> 16),
+            fromCharCode((n >>>  8) & 0xff),
+            fromCharCode( n         & 0xff)
+        ];
+        chars.length -= [0, 0, 2, 1][padlen];
+        return chars.join('');
+    };
+    var _atob = global.atob && typeof global.atob == 'function'
+        ? function(a){ return global.atob(a) } : function(a){
+        return a.replace(/\S{1,4}/g, cb_decode);
+    };
+    var atob = function(a) {
+        return _atob(String(a).replace(/[^A-Za-z0-9\+\/]/g, ''));
+    };
+    var _decode = function(a) { return btou(_atob(a)) };
+    var decode = function(a){
+        return _decode(
+            String(a).replace(/[-_]/g, function(m0) {
+                return m0 == '-' ? '+' : '/'
+            }).replace(/[^A-Za-z0-9\+\/]/g, '')
+        );
+    };
+    var toUint8Array;
+    if (global.Uint8Array) toUint8Array = function(a) {
+         return Uint8Array.from(atob(a), function(c) {
+            return c.charCodeAt(0);
+        });
+    };
+    var noConflict = function() {
+        var Base64 = global.Base64;
+        global.Base64 = _Base64;
+        return Base64;
+    };
+    // export Base64
+    global.Base64 = {
+        VERSION: version,
+        atob: atob,
+        btoa: btoa,
+        fromBase64: decode,
+        toBase64: encode,
+        utob: utob,
+        encode: encode,
+        encodeURI: encodeURI,
+        btou: btou,
+        decode: decode,
+        noConflict: noConflict,
+        fromUint8Array: fromUint8Array,
+        toUint8Array: toUint8Array
+    };
+    // if ES5 is available, make Base64.extendString() available
+    if (typeof Object.defineProperty === 'function') {
+        var noEnum = function(v){
+            return {value:v,enumerable:false,writable:true,configurable:true};
+        };
+        global.Base64.extendString = function () {
+            Object.defineProperty(
+                String.prototype, 'fromBase64', noEnum(function () {
+                    return decode(this)
+                }));
+            Object.defineProperty(
+                String.prototype, 'toBase64', noEnum(function (urisafe) {
+                    return encode(this, urisafe)
+                }));
+            Object.defineProperty(
+                String.prototype, 'toBase64URI', noEnum(function () {
+                    return encode(this, true)
+                }));
+        };
+    }
+    //
+    // export Base64 to the namespace
+    //
+    if (global['Meteor']) { // Meteor.js
+        Base64 = global.Base64;
+    }
+    // module.exports and AMD are mutually exclusive.
+    // module.exports has precedence.
+    if (typeof module !== 'undefined' && module.exports) {
+        module.exports.Base64 = global.Base64;
+    }
+    else if (typeof define === 'function' && define.amd) {
+        // AMD. Register as an anonymous module.
+        define([], function(){ return global.Base64 });
+    }
+    // that's it!
+    return {Base64: global.Base64}
+}));

+ 234 - 0
common/crypto-js/aes.js

@@ -0,0 +1,234 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var BlockCipher = C_lib.BlockCipher;
+	    var C_algo = C.algo;
+
+	    // Lookup tables
+	    var SBOX = [];
+	    var INV_SBOX = [];
+	    var SUB_MIX_0 = [];
+	    var SUB_MIX_1 = [];
+	    var SUB_MIX_2 = [];
+	    var SUB_MIX_3 = [];
+	    var INV_SUB_MIX_0 = [];
+	    var INV_SUB_MIX_1 = [];
+	    var INV_SUB_MIX_2 = [];
+	    var INV_SUB_MIX_3 = [];
+
+	    // Compute lookup tables
+	    (function () {
+	        // Compute double table
+	        var d = [];
+	        for (var i = 0; i < 256; i++) {
+	            if (i < 128) {
+	                d[i] = i << 1;
+	            } else {
+	                d[i] = (i << 1) ^ 0x11b;
+	            }
+	        }
+
+	        // Walk GF(2^8)
+	        var x = 0;
+	        var xi = 0;
+	        for (var i = 0; i < 256; i++) {
+	            // Compute sbox
+	            var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
+	            sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
+	            SBOX[x] = sx;
+	            INV_SBOX[sx] = x;
+
+	            // Compute multiplication
+	            var x2 = d[x];
+	            var x4 = d[x2];
+	            var x8 = d[x4];
+
+	            // Compute sub bytes, mix columns tables
+	            var t = (d[sx] * 0x101) ^ (sx * 0x1010100);
+	            SUB_MIX_0[x] = (t << 24) | (t >>> 8);
+	            SUB_MIX_1[x] = (t << 16) | (t >>> 16);
+	            SUB_MIX_2[x] = (t << 8)  | (t >>> 24);
+	            SUB_MIX_3[x] = t;
+
+	            // Compute inv sub bytes, inv mix columns tables
+	            var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
+	            INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8);
+	            INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16);
+	            INV_SUB_MIX_2[sx] = (t << 8)  | (t >>> 24);
+	            INV_SUB_MIX_3[sx] = t;
+
+	            // Compute next counter
+	            if (!x) {
+	                x = xi = 1;
+	            } else {
+	                x = x2 ^ d[d[d[x8 ^ x2]]];
+	                xi ^= d[d[xi]];
+	            }
+	        }
+	    }());
+
+	    // Precomputed Rcon lookup
+	    var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
+
+	    /**
+	     * AES block cipher algorithm.
+	     */
+	    var AES = C_algo.AES = BlockCipher.extend({
+	        _doReset: function () {
+	            var t;
+
+	            // Skip reset of nRounds has been set before and key did not change
+	            if (this._nRounds && this._keyPriorReset === this._key) {
+	                return;
+	            }
+
+	            // Shortcuts
+	            var key = this._keyPriorReset = this._key;
+	            var keyWords = key.words;
+	            var keySize = key.sigBytes / 4;
+
+	            // Compute number of rounds
+	            var nRounds = this._nRounds = keySize + 6;
+
+	            // Compute number of key schedule rows
+	            var ksRows = (nRounds + 1) * 4;
+
+	            // Compute key schedule
+	            var keySchedule = this._keySchedule = [];
+	            for (var ksRow = 0; ksRow < ksRows; ksRow++) {
+	                if (ksRow < keySize) {
+	                    keySchedule[ksRow] = keyWords[ksRow];
+	                } else {
+	                    t = keySchedule[ksRow - 1];
+
+	                    if (!(ksRow % keySize)) {
+	                        // Rot word
+	                        t = (t << 8) | (t >>> 24);
+
+	                        // Sub word
+	                        t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
+
+	                        // Mix Rcon
+	                        t ^= RCON[(ksRow / keySize) | 0] << 24;
+	                    } else if (keySize > 6 && ksRow % keySize == 4) {
+	                        // Sub word
+	                        t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
+	                    }
+
+	                    keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t;
+	                }
+	            }
+
+	            // Compute inv key schedule
+	            var invKeySchedule = this._invKeySchedule = [];
+	            for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) {
+	                var ksRow = ksRows - invKsRow;
+
+	                if (invKsRow % 4) {
+	                    var t = keySchedule[ksRow];
+	                } else {
+	                    var t = keySchedule[ksRow - 4];
+	                }
+
+	                if (invKsRow < 4 || ksRow <= 4) {
+	                    invKeySchedule[invKsRow] = t;
+	                } else {
+	                    invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^
+	                                               INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]];
+	                }
+	            }
+	        },
+
+	        encryptBlock: function (M, offset) {
+	            this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX);
+	        },
+
+	        decryptBlock: function (M, offset) {
+	            // Swap 2nd and 4th rows
+	            var t = M[offset + 1];
+	            M[offset + 1] = M[offset + 3];
+	            M[offset + 3] = t;
+
+	            this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX);
+
+	            // Inv swap 2nd and 4th rows
+	            var t = M[offset + 1];
+	            M[offset + 1] = M[offset + 3];
+	            M[offset + 3] = t;
+	        },
+
+	        _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {
+	            // Shortcut
+	            var nRounds = this._nRounds;
+
+	            // Get input, add round key
+	            var s0 = M[offset]     ^ keySchedule[0];
+	            var s1 = M[offset + 1] ^ keySchedule[1];
+	            var s2 = M[offset + 2] ^ keySchedule[2];
+	            var s3 = M[offset + 3] ^ keySchedule[3];
+
+	            // Key schedule row counter
+	            var ksRow = 4;
+
+	            // Rounds
+	            for (var round = 1; round < nRounds; round++) {
+	                // Shift rows, sub bytes, mix columns, add round key
+	                var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++];
+	                var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++];
+	                var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++];
+	                var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++];
+
+	                // Update state
+	                s0 = t0;
+	                s1 = t1;
+	                s2 = t2;
+	                s3 = t3;
+	            }
+
+	            // Shift rows, sub bytes, add round key
+	            var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++];
+	            var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++];
+	            var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++];
+	            var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++];
+
+	            // Set output
+	            M[offset]     = t0;
+	            M[offset + 1] = t1;
+	            M[offset + 2] = t2;
+	            M[offset + 3] = t3;
+	        },
+
+	        keySize: 256/32
+	    });
+
+	    /**
+	     * Shortcut functions to the cipher's object interface.
+	     *
+	     * @example
+	     *
+	     *     var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);
+	     *     var plaintext  = CryptoJS.AES.decrypt(ciphertext, key, cfg);
+	     */
+	    C.AES = BlockCipher._createHelper(AES);
+	}());
+
+
+	return CryptoJS.AES;
+
+}));

Файловите разлики са ограничени, защото са твърде много
+ 6059 - 0
common/crypto-js/crypto-js.js


+ 9 - 0
common/num.js

@@ -0,0 +1,9 @@
+// 十进制转二进制
+export function decimalToBinary(decimal) {
+	let binary = '';
+	while (decimal > 0) {
+		binary = (decimal % 2) + binary;
+		decimal = Math.floor(decimal / 2);
+	}
+	return binary;
+}

+ 278 - 247
common/sm4.js

@@ -1,161 +1,8 @@
-import base64js from "./base64.js"
-(function(r) {
-	if (typeof exports === "object" && typeof module !== "undefined") {
-		module.exports = r()
-	} else {
-		if (typeof define === "function" && define.amd) {
-			define([], r)
-		} else {
-			var e;
-			if (typeof window !== "undefined") {
-				e = window
-			} else {
-				if (typeof global !== "undefined") {
-					e = global
-				} else {
-					if (typeof self !== "undefined") {
-						e = self
-					} else {
-						e = this
-					}
-				}
-			}
-			e.base64js = r()
-		}
-	}
-})(function() {
-	var r, e, t;
-	return function r(e, t, n) {
-		function o(i, a) {
-			if (!t[i]) {
-				if (!e[i]) {
-					var u = typeof require == "function" && require;
-					if (!a && u) {
-						return u(i, !0)
-					}
-					if (f) {
-						return f(i, !0)
-					}
-					var d = new Error("Cannot find module '" + i + "'");
-					throw d.code = "MODULE_NOT_FOUND", d
-				}
-				var c = t[i] = {
-					exports: {}
-				};
-				e[i][0].call(c.exports, function(r) {
-					var t = e[i][1][r];
-					return o(t ? t : r)
-				}, c, c.exports, r, e, t, n)
-			}
-			return t[i].exports
-		}
-		var f = typeof require == "function" && require;
-		for (var i = 0; i < n.length; i++) {
-			o(n[i])
-		}
-		return o
-	}({
-		"/": [function(r, e, t) {
-			t.byteLength = c;
-			t.toByteArray = v;
-			t.fromByteArray = s;
-			var n = [];
-			var o = [];
-			var f = typeof Uint8Array !== "undefined" ? Uint8Array : Array;
-			var i = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-			for (var a = 0, u = i.length; a < u; ++a) {
-				n[a] = i[a];
-				o[i.charCodeAt(a)] = a
-			}
-			o["-".charCodeAt(0)] = 62;
-			o["_".charCodeAt(0)] = 63;
-
-			function d(r) {
-				var e = r.length;
-				if (e % 4 > 0) {
-					throw new Error("Invalid string. Length must be a multiple of 4")
-				}
-				return r[e - 2] === "=" ? 2 : r[e - 1] === "=" ? 1 : 0
-			}
-
-			function c(r) {
-				return r.length * 3 / 4 - d(r)
-			}
-
-			function v(r) {
-				var e, t, n, i, a;
-				var u = r.length;
-				i = d(r);
-				a = new f(u * 3 / 4 - i);
-				t = i > 0 ? u - 4 : u;
-				var c = 0;
-				for (e = 0; e < t; e += 4) {
-					n = o[r.charCodeAt(e)] << 18 | o[r.charCodeAt(e + 1)] << 12 | o[r.charCodeAt(e +
-						2)] << 6 | o[r.charCodeAt(e + 3)];
-					a[c++] = n >> 16 & 255;
-					a[c++] = n >> 8 & 255;
-					a[c++] = n & 255
-				}
-				if (i === 2) {
-					n = o[r.charCodeAt(e)] << 2 | o[r.charCodeAt(e + 1)] >> 4;
-					a[c++] = n & 255
-				} else {
-					if (i === 1) {
-						n = o[r.charCodeAt(e)] << 10 | o[r.charCodeAt(e + 1)] << 4 | o[r.charCodeAt(
-							e + 2)] >> 2;
-						a[c++] = n >> 8 & 255;
-						a[c++] = n & 255
-					}
-				}
-				return a
-			}
-
-			function l(r) {
-				return n[r >> 18 & 63] + n[r >> 12 & 63] + n[r >> 6 & 63] + n[r & 63]
-			}
-
-			function h(r, e, t) {
-				var n;
-				var o = [];
-				for (var f = e; f < t; f += 3) {
-					n = (r[f] << 16) + (r[f + 1] << 8) + r[f + 2];
-					o.push(l(n))
-				}
-				return o.join("")
-			}
-
-			function s(r) {
-				var e;
-				var t = r.length;
-				var o = t % 3;
-				var f = "";
-				var i = [];
-				var a = 16383;
-				for (var u = 0, d = t - o; u < d; u += a) {
-					i.push(h(r, u, u + a > d ? d : u + a))
-				}
-				if (o === 1) {
-					e = r[t - 1];
-					f += n[e >> 2];
-					f += n[e << 4 & 63];
-					f += "=="
-				} else {
-					if (o === 2) {
-						e = (r[t - 2] << 8) + r[t - 1];
-						f += n[e >> 10];
-						f += n[e >> 4 & 63];
-						f += n[e << 2 & 63];
-						f += "="
-					}
-				}
-				i.push(f);
-				return i.join("")
-			}
-		}, {}]
-	}, {}, [])("/")
-});
-
-// const base64js = require('base64-js').Base64
+import CryptoJS from './crypto-js/crypto-js.js'
+var Base64 = Base64 || require('@/common/base64.js').Base64;
+import {
+	getToken
+} from './auth.js'
 /**
  * 国密SM4加密算法
  */
@@ -225,7 +72,6 @@ function SM4() {
 		return this.SHL(x, n) | x >> (32 - n);
 	}
 
-
 	this.sm4Lt = function(ka) {
 		var bb = 0;
 		var c = 0;
@@ -260,8 +106,6 @@ function SM4() {
 		return rk;
 	}
 
-
-
 	this.sm4Sbox = function(inch) {
 		var i = inch & 0xFF;
 		var retVal = SboxTable[i];
@@ -279,7 +123,6 @@ function SM4() {
 		}
 		ctx.mode = this.SM4_ENCRYPT;
 		this.sm4_setkey(ctx.sk, key);
-
 	};
 	//生成解密密钥
 	this.sm4_setkey_dec = function(ctx, key) {
@@ -291,7 +134,8 @@ function SM4() {
 			Error("key error!");
 		}
 
-		ctx.mode = this.SM4_DECRYPT;
+		var i = 0;
+		ctx.mode = 0;
 		this.sm4_setkey(ctx.sk, key);
 		ctx.sk = ctx.sk.reverse();
 	}
@@ -351,13 +195,14 @@ function SM4() {
 	}
 
 	this.sm4_crypt_ecb = function(ctx, input) {
+
 		if (input == null) {
 			alert("input is null!");
 		}
+
 		if ((ctx.isPadding) && (ctx.mode == this.SM4_ENCRYPT)) {
 			input = this.padding(input, this.SM4_ENCRYPT);
 		}
-
 		var i = 0;
 		var length = input.length;
 		var bous = new Array();
@@ -368,7 +213,6 @@ function SM4() {
 			bous = bous.concat(out);
 			i++;
 		}
-
 		var output = bous;
 		if (ctx.isPadding && ctx.mode == this.SM4_DECRYPT) {
 			output = this.padding(output, this.SM4_DECRYPT);
@@ -420,7 +264,7 @@ function SM4() {
 				var out1 = new Array(16);
 				var ins = input.slice(k * 16, (16 * (k + 1)));
 				temp = ins.slice(0, 16);
-				sm4_one_round(ctx.sk, ins, out);
+				this.sm4_one_round(ctx.sk, ins, out);
 				for (i = 0; i < 16; i++) {
 					out1[i] = (out[i] ^ iv[i]);
 				}
@@ -444,13 +288,10 @@ function SM4() {
 	}
 }
 
-
 function SM4Util() {
-
-	this.secretKey = "11HDESAAHIHHUGDZ";
-	//this.iv = "UISwD9fW6cFh9SNS";
+	this.secretKey = "";
 	this.iv = "";
-	//this.hexString = false;
+	this.hexString = false;
 	//加密_ECB
 	this.encryptData_ECB = function(plainText) {
 		try {
@@ -461,8 +302,7 @@ function SM4Util() {
 			var keyBytes = stringToByte(this.secretKey);
 			sm4.sm4_setkey_enc(ctx, keyBytes);
 			var encrypted = sm4.sm4_crypt_ecb(ctx, stringToByte(plainText));
-
-			var cipherText = base64js.fromByteArray(encrypted);
+			var cipherText = Base64.fromUint8Array(encrypted);
 			if (cipherText != null && cipherText.trim().length > 0) {
 				cipherText.replace(/(\s*|\t|\r|\n)/g, "");
 			}
@@ -475,19 +315,30 @@ function SM4Util() {
 	}
 	//解密_ECB
 	this.decryptData_ECB = function(cipherText) {
-		try {
-			var sm4 = new SM4();
-			var ctx = new SM4_Context();
-			ctx.isPadding = true;
-			ctx.mode = sm4.SM4_DECRYPT;
-			var keyBytes = stringToByte(this.secretKey);
-			sm4.sm4_setkey_dec(ctx, keyBytes);
-			var decrypted = sm4.sm4_crypt_ecb(ctx, base64js.toByteArray(cipherText));
-			return utf8ByteToUnicodeStr(decrypted);
-		} catch (e) {
-			console.log(e)
-			console.error(e);
-			return null;
+		if (cipherText) {
+			try {
+				var sm4 = new SM4();
+				var ctx = new SM4_Context();
+				ctx.isPadding = true;
+				ctx.mode = sm4.SM4_ENCRYPT;
+				var keyBytes = stringToByte(this.secretKey);
+				sm4.sm4_setkey_dec(ctx, keyBytes);
+				if (typeof cipherText === 'string') {
+					var decrypted = sm4.sm4_crypt_ecb(ctx, Base64.toUint8Array(cipherText));
+					return byteToString(decrypted);
+				} else if (cipherText instanceof Array) {
+					let decrypted = []
+					cipherText.forEach((item) => {
+						let str = sm4.sm4_crypt_ecb(ctx, Base64.toUint8Array(item))
+						decrypted.push(byteToString(str))
+					})
+					return decrypted;
+				}
+
+			} catch (e) {
+				console.error(e);
+				return null;
+			}
 		}
 	}
 
@@ -503,7 +354,7 @@ function SM4Util() {
 
 			sm4.sm4_setkey_enc(ctx, keyBytes);
 			var encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, stringToByte(plainText));
-			var cipherText = base64js.fromByteArray(encrypted);
+			var cipherText = Base64.fromUint8Array(encrypted);
 			if (cipherText != null && cipherText.trim().length > 0) {
 				cipherText.replace(/(\s*|\t|\r|\n)/g, "");
 			}
@@ -513,8 +364,25 @@ function SM4Util() {
 			return null;
 		}
 	}
+	//解密_CBC
+	this.decryptData_CBC = function(cipherText) {
+		try {
+			var sm4 = new SM4();
+			var ctx = new SM4_Context();
+			ctx.isPadding = true;
+			ctx.mode = sm4.SM4_ENCRYPT;
+			var keyBytes = stringToByte(this.secretKey);
+			var ivBytes = stringToByte(this.iv);
+			sm4.sm4_setkey_dec(ctx, keyBytes);
+			var decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Base64.toUint8Array(cipherText));
+			return byteToString(decrypted);
+		} catch (e) {
+			console.error(e);
+			return null;
+		}
+	}
 
-	var stringToByte = function(str) {
+	function stringToByte(str) {
 		var bytes = new Array();
 		var len, c;
 		len = str.length;
@@ -535,14 +403,11 @@ function SM4Util() {
 			} else {
 				bytes.push(c & 0xFF);
 			}
-
 		}
-		// console.log('bytes: '+bytes)
 		return bytes;
 	}
 
-
-	var byteToString = function(arr) {
+	function byteToString(arr) {
 		if (typeof arr === 'string') {
 			return arr;
 		}
@@ -555,7 +420,9 @@ function SM4Util() {
 				var bytesLength = v[0].length;
 				var store = _arr[i].toString(2).slice(7 - bytesLength);
 				for (var st = 1; st < bytesLength; st++) {
-					store += _arr[st + i].toString(2).slice(2);
+					if (_arr[st + i]) {
+						store += _arr[st + i].toString(2).slice(2);
+					}
 				}
 				str += String.fromCharCode(parseInt(store, 2));
 				i += bytesLength - 1;
@@ -565,64 +432,228 @@ function SM4Util() {
 		}
 		return str;
 	}
+};
 
-	function utf8ByteToUnicodeStr(utf8Bytes) {
-		var unicodeStr = "";
-		for (var pos = 0; pos < utf8Bytes.length;) {
-			var flag = utf8Bytes[pos];
-			var unicode = 0;
-			if ((flag >>> 7) === 0) {
-				unicodeStr += String.fromCharCode(utf8Bytes[pos]);
-				pos += 1;
-
-			} else if ((flag & 0xFC) === 0xFC) {
-				unicode = (utf8Bytes[pos] & 0x3) << 30;
-				unicode |= (utf8Bytes[pos + 1] & 0x3F) << 24;
-				unicode |= (utf8Bytes[pos + 2] & 0x3F) << 18;
-				unicode |= (utf8Bytes[pos + 3] & 0x3F) << 12;
-				unicode |= (utf8Bytes[pos + 4] & 0x3F) << 6;
-				unicode |= (utf8Bytes[pos + 5] & 0x3F);
-				unicodeStr += String.fromCharCode(unicode);
-				pos += 6;
-
-			} else if ((flag & 0xF8) === 0xF8) {
-				unicode = (utf8Bytes[pos] & 0x7) << 24;
-				unicode |= (utf8Bytes[pos + 1] & 0x3F) << 18;
-				unicode |= (utf8Bytes[pos + 2] & 0x3F) << 12;
-				unicode |= (utf8Bytes[pos + 3] & 0x3F) << 6;
-				unicode |= (utf8Bytes[pos + 4] & 0x3F);
-				unicodeStr += String.fromCharCode(unicode);
-				pos += 5;
-
-			} else if ((flag & 0xF0) === 0xF0) {
-				unicode = (utf8Bytes[pos] & 0xF) << 18;
-				unicode |= (utf8Bytes[pos + 1] & 0x3F) << 12;
-				unicode |= (utf8Bytes[pos + 2] & 0x3F) << 6;
-				unicode |= (utf8Bytes[pos + 3] & 0x3F);
-				unicodeStr += String.fromCharCode(unicode);
-				pos += 4;
-
-			} else if ((flag & 0xE0) === 0xE0) {
-				unicode = (utf8Bytes[pos] & 0x1F) << 12;;
-				unicode |= (utf8Bytes[pos + 1] & 0x3F) << 6;
-				unicode |= (utf8Bytes[pos + 2] & 0x3F);
-				unicodeStr += String.fromCharCode(unicode);
-				pos += 3;
-
-			} else if ((flag & 0xC0) === 0xC0) { //110
-				unicode = (utf8Bytes[pos] & 0x3F) << 6;
-				unicode |= (utf8Bytes[pos + 1] & 0x3F);
-				unicodeStr += String.fromCharCode(unicode);
-				pos += 2;
+function getsm4Key() {
+	var token = getToken()
+	if (token == null || token.length == 0) token = '1234567887654321'
+	return CryptoJS.MD5(token).toString().toUpperCase().substr(16, 16)
+}
 
+function getsm4Iv() {
+	var token = getToken()
+	if (token == null || token.length == 0) token = '1234567887654321'
+	return CryptoJS.MD5(CryptoJS.MD5(token).toString()).toString().toUpperCase().substr(16, 16)
+}
+
+function getsm4Keydef() {
+	var token = '1234567887654321'
+	return token
+}
+
+function getsm4Ivdef() {
+	var token = '1234567887654321'
+	return CryptoJS.MD5(CryptoJS.MD5(token).toString()).toString().toUpperCase().substr(16, 16)
+}
+
+function maskA(str, cd) {
+	let cdc = str.length - 2 * cd;
+	if (cdc > 0) {
+		var reptext = ''
+		for (let k = 0; k < cdc; k++) {
+			reptext = reptext + '✱'
+		}
+		return str.substr(0, cd) + reptext + str.substr(str.length - cd);
+	} else
+		return str;
+}
+
+function mask(str, type) {
+	return str;
+	let strcd = str != null ? str.length : 0;
+	if (strcd > 0) {
+		if (type == 1) //姓名
+		{
+			if (strcd > 1) {
+				let cdc = strcd - 1;
+				var reptext = ''
+				for (let k = 0; k < cdc; k++) {
+					reptext = reptext + '✱'
+				}
+				return reptext + str.substr(cdc)
 			} else {
-				unicodeStr += String.fromCharCode(utf8Bytes[pos]);
-				pos += 1;
+				return str
 			}
+		} else if (type == 2) //身份证号
+		{
+			if (strcd == 18) {
+				return str.substr(0, 3) + '✱✱✱✱✱' + str.substr(8, 1) + '✱✱✱✱✱✱✱' + str.substr(16, 1) + '✱';
+			} else {
+				return maskA(str, 1);
+			}
+		} else if (type == 3) //手机号
+		{
+			if (strcd == 11) {
+				return str.substr(0, 2) + '✱✱✱✱✱✱✱✱' + str.substr(10, 1);
+			} else {
+				return maskA(str, 2);
+			}
+		} else if (type == 4) //住址
+		{
+			return maskA(str, 2);
+		} else if (type == 5) //邮件地址
+		{
+			return maskA(str, 2);
+		} else if (type == 6) {
+			return maskA(str, 1);
+		} else //其他
+		{
+			return str;
 		}
-		return unicodeStr;
+	} else {
+		return str
 	}
-};
-module.exports = {
-	s4: new SM4Util()
+}
+
+function maskArr(arr, type) {
+	return arr;
+	let res = []
+	arr.forEach((str) => {
+		let strcd = str != null ? str.length : 0;
+		if (strcd > 0) {
+			if (type == 1) //姓名
+			{
+				if (strcd > 1) {
+					let cdc = strcd - 1;
+					var reptext = ''
+					for (let k = 0; k < cdc; k++) {
+						reptext = reptext + '✱'
+					}
+					res.push(reptext + str.substr(cdc))
+				} else {
+					res.push(str)
+				}
+			} else if (type == 2) //身份证号
+			{
+				if (strcd == 18) {
+					res.push(str.substr(0, 3) + '✱✱✱✱✱' + str.substr(8, 1) + '✱✱✱✱✱✱✱' + str.substr(16, 1) +
+						'✱')
+				} else {
+					res.push(maskA(str, 1))
+				}
+			} else if (type == 3) //手机号
+			{
+				if (strcd == 11) {
+					res.push(str.substr(0, 2) + '✱✱✱✱✱✱✱✱' + str.substr(10, 1))
+				} else {
+					res.push(maskA(str, 2))
+				}
+			} else if (type == 4) //住址
+			{
+				res.push(maskA(str, 2))
+			} else if (type == 5) //邮件地址
+			{
+				res.push(maskA(str, 2))
+			} else if (type == 6) //邮件地址
+			{
+				res.push(maskA(str, 1))
+			} else {
+				res.push(str)
+			}
+		} else {
+			res.push(str)
+		}
+	})
+	return res
+}
+
+export function encrypt_ECB(data) {
+	var s4 = new SM4Util();
+	s4.secretKey = getsm4Key();
+	return s4.encryptData_ECB(data);
+}
+
+export function encrypt_ECBdef(data) {
+	var s4 = new SM4Util();
+	s4.secretKey = getsm4Keydef();
+	return s4.encryptData_ECB(data);
+}
+export function encrypt_ECBA(data, key) {
+	var s4 = new SM4Util();
+	s4.secretKey = key;
+	return s4.encryptData_ECB(data);
+}
+export function decrypt_ECB(data) {
+	var s4 = new SM4Util();
+	s4.secretKey = getsm4Key();
+	return s4.decryptData_ECB(data);
+}
+
+export function decrypt_ECBdef(data) {
+	var s4 = new SM4Util();
+	s4.secretKey = getsm4Keydef();
+	return s4.decryptData_ECB(data);
+}
+
+
+export function masks(str, type) {
+	return mask(str, type);
+}
+
+export function encrypt_CBC(data) {
+	var s4 = new SM4Util();
+	s4.secretKey = getsm4Key();
+	s4.iv = getsm4Iv();
+	return s4.encryptData_CBC(data);
+}
+export function encrypt_CBCdef(data) {
+	var s4 = new SM4Util();
+	s4.secretKey = getsm4Keydef();
+	s4.iv = getsm4Ivdef();
+	return s4.encryptData_CBC(data);
+}
+export function decrypt_CBC(data) {
+	var s4 = new SM4Util();
+	s4.secretKey = getsm4Key();
+	s4.iv = getsm4Iv();
+	return s4.decryptData_CBC(data);
+}
+export function decrypt_CBCdef(data) {
+	var s4 = new SM4Util();
+	s4.secretKey = getsm4Keydef();
+	s4.iv = getsm4Ivdef();
+	return s4.decryptData_CBC(data);
+}
+
+
+export function decryptData_ECB(rowdata, fields, hides) {
+	if (rowdata) {
+		var s4 = new SM4Util();
+		s4.secretKey = getsm4Key();
+		for (let j = 0; j < fields.length; j++) {
+			if (rowdata[fields[j]] != null) {
+				let zfc = s4.decryptData_ECB(rowdata[fields[j]]);
+				zfc instanceof Array ? rowdata[fields[j]] = maskArr(zfc, hides[j]) : rowdata[fields[j]] = mask(zfc,
+					hides[j])
+			}
+		}
+	}
+	return rowdata
+}
+
+export function decryptRowData_ECB(rowdata, fields, hides) {
+	if (rowdata && rowdata.length > 0) {
+		var s4 = new SM4Util();
+		s4.secretKey = getsm4Key();
+		for (let i = 0; i < rowdata.length; i++) {
+			for (let j = 0; j < fields.length; j++) {
+				if (rowdata[i][fields[j]] != null) {
+					let srcs = rowdata[i][fields[j]]
+					let zfc = s4.decryptData_ECB(srcs);
+					rowdata[i][fields[j]] = mask(zfc, hides[j]);
+				}
+			}
+		}
+	}
+	return rowdata
 }

+ 1 - 3
pages.json

@@ -35,9 +35,7 @@
     {
       "path": "pages/my/index",
       "style": {
-        "navigationBarTitleText": "个人中心",
-        "enablePullDownRefresh": true,
-        "onReachBottomDistance": 100 //距离底部100像素时,触发加载更多功能
+        "navigationBarTitleText": "个人中心"
       }
 		},
     {

+ 38 - 61
pages/index/index.vue

@@ -1,14 +1,11 @@
 <template>
 	<view class="page-main">
-		<next-indexed-xlist :dataList="dataList" :showAvatar="true" isInterlock @itemclick="itemclick">
-			<!--这是默认插槽,额外添加部分-->
-			<!--    <view class="content-block">
-                <view class="title"><text>历史记录:</text></view>
-                <view class="btn"><text>朝阳区</text></view>
-                <view class="btn"><text>东城区</text></view>
-                <view class="btn"><text>海淀区</text></view>
-            </view> -->
-		</next-indexed-xlist>
+		<uni-list :border="true">
+			<uni-list-item :title="item.xm" :note="item.sjhm" showArrow v-for="(item,index) in dataList" :key="index"
+				:thumb="item.tx" :rightText="item.age" thumb-size="lg" link="navigateTo"
+				:to="`/pages/lr/index?item=`+JSON.stringify(item)" />
+		</uni-list>
+		<uni-load-more :status="status" :content-text="contentText" @clickLoadMore="clickLoadMore" />
 		<navigator url="/pages/lr/index">
 			<image src="../../static/image/add.png" class="floating-button"></image>
 		</navigator>
@@ -21,23 +18,23 @@
 	} from '@/api/lr.js'
 	import config from '@/config.js'
 	import {
-		s4
+		decryptRowData_ECB
 	} from '@/common/sm4.js'
 	export default {
 		data() {
 			return {
+				status: 'more',
+				contentText: {
+					contentdown: '查看更多',
+					contentrefresh: '加载中',
+					contentnomore: '没有更多'
+				},
 				form: {
 					pageNum: 1,
-					pageSize: 9999,
+					pageSize: 10,
 				},
-				dataList: [
-					// 	{
-					// 	id: '1',
-					// 	name: '刘**',
-					// 	phone: '181****5576',
-					// 	img: 'https://img1.baidu.com/it/u=1016138010,1907110459&fm=253&fmt=auto&app=138&f=JPEG?w=300&h=300'
-					// },
-				]
+				total: 0,
+				dataList: []
 			}
 
 		},
@@ -45,25 +42,34 @@
 			this.getList()
 		},
 		onLoad() {},
-		onReady() {},
 		methods: {
 			getList() {
 				List(this.form).then(res => {
-					res.rows.map(e => {
-						console.log(e)
-						this.dataList.push({
-							id: e.id,
-							name: s4.decryptData_ECB(e.xm),
-							phone: e.sjhm,
-							img: e.tx ? config.baseUrl + e.tx : config.baseUrl + config.head
-						})
-					})
+					let list = decryptRowData_ECB(res.rows, ['xm', 'zjhm', 'sjhm', 'jhrsjhm', 'xjd'], [1, 2,
+						3, 3, 4
+					])
+					list.forEach(item => {
+						item.tx = item.tx ? config.baseUrl + item.tx : config.baseUrl + config.head;
+					});
+					this.dataList.push(...list)
+					console.log("列表数据", this.dataList)
 
-					console.log("wwwwwwwwwww", this.dataList)
+					this.total = res.total
+					console.log("总数", this.total, this.dataList.length)
+					if (this.total > this.dataList.length) {
+						this.status = 'more'
+					} else {
+						this.status = 'noMore'
+					}
 				})
 			},
-			itemclick(e) {
-				console.log('点击列表回调:', e)
+			clickLoadMore(e) {
+				if (this.total > this.dataList.length) {
+					this.status = 'loading'
+					this.form.pageNum += 1
+					this.getList()
+				}
+
 			}
 		}
 	}
@@ -74,35 +80,6 @@
 
 
 <style lang="scss" scoped>
-	.content-block {
-		display: flex;
-		flex-direction: row;
-		justify-content: flex-start;
-		background-color: #fff;
-
-		.title {
-			color: #333;
-			padding: 20rpx;
-			margin-right: 20rpx;
-			display: flex;
-			flex-direction: column;
-			justify-content: center;
-		}
-
-		.btn {
-			color: #ccc;
-			padding: 10rpx;
-			border: 1rpx solid #ccc;
-			border-radius: 10rpx;
-			margin: 20rpx 10rpx;
-			font-size: 28rpx;
-			display: flex;
-			flex-direction: column;
-			justify-content: center;
-
-		}
-	}
-
 	.floating-button {
 		position: fixed;
 		bottom: 20px;

+ 46 - 21
pages/lr/index.vue

@@ -11,7 +11,8 @@
 				<uni-forms ref="baseForm" :modelValue="baseFormData" :rules="rules">
 					<view v-if="active==0">
 						<uni-forms-item label="照片">
-							<uni-file-picker limit="1" fileMediatype="image" @select="select" />
+							<uni-file-picker limit="1" v-model="baseFormData.head" fileMediatype="image"
+								@select="select" />
 						</uni-forms-item>
 						<uni-forms-item label="姓名" required name="xm">
 							<uni-easyinput v-model="baseFormData.xm" placeholder="请输入姓名" />
@@ -227,6 +228,9 @@
 	import {
 		Save
 	} from '@/api/lr.js'
+	import {
+		decimalToBinary
+	} from '@/common/num.js'
 	export default {
 		data() {
 			return {
@@ -706,7 +710,11 @@
 			}
 
 		},
-		onLoad() {
+		onLoad(option) {
+			this.baseFormData = JSON.parse(option.item)
+			if (this.baseFormData.xm) {
+				this.bsFormatTo()
+			}
 			this.myAmapFunT = new amapFile.AMapWX({
 				key: config.gaodeKey
 			})
@@ -798,12 +806,12 @@
 			},
 			// 数组转2进制
 			formatInt2(value) {
-				let xqaix = value.toString(2)
+				let xqaix = decimalToBinary(value).split('')
 				let result = []
 				if (xqaix != 0) {
 					xqaix.forEach((e, i) => {
 						if (e == 1) {
-							result.push(i)
+							result.push(i.toString())
 						}
 					})
 				}
@@ -890,46 +898,63 @@
 					})
 				}
 			},
-			bsFormatTo(data) {
-				this.baseFormData.xqahData = this.formatInt2(this.baseFormData.xqah)
-				this.baseFormData.jntcData = this.formatInt2(this.baseFormData.jntc)
-				this.baseFormData.tkflData = this.formatInt2(this.baseFormData.tkfl)
-
+			bsFormatTo() {
+				console.log("数据组装", this.baseFormData)
+				if (this.baseFormData.xqah) {
+					this.baseFormData.xqahData = this.formatInt2(this.baseFormData.xqah)
+				}
+				if (this.baseFormData.jntc) {
+					this.baseFormData.jntcData = this.formatInt2(this.baseFormData.jntc)
+				}
+				if (this.baseFormData.tkfl) {
+					this.baseFormData.tkflData = this.formatInt2(this.baseFormData.tkfl)
+				}
+				if (this.baseFormData.csrq) {
+					let riqi = this.baseFormData.csrq
+					let riqi1 = riqi.slice(0, 4) + '-' + riqi.slice(4)
+					this.baseFormData.csrq = riqi1.slice(0, 7) + '-' + riqi1.slice(7)
+				}
+				if (this.baseFormData.tx) {
+					this.baseFormData.head = this.baseFormData.tx
+					this.baseFormData.head = 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/shuijiao-small.jpg'
+					console.log("wwwwwwwwwwwwwwwwwwwwww", this.baseFormData.head)
+				}
 
-				if (data.daIsSjxtbs == '1') {
+				this.baseFormData.bs = []
+				if (this.baseFormData.daIsSjxtbs == '1') {
 					this.baseFormData.bs.push('0')
 				}
-				if (data.daIsHxxtbs == '1') {
+				if (this.baseFormData.daIsHxxtbs == '1') {
 					this.baseFormData.bs.push('1')
 				}
-				if (data.daIsXhxtbs == '1') {
+				if (this.baseFormData.daIsXhxtbs == '1') {
 					this.baseFormData.bs.push('2')
 				}
-				if (data.daIsXhxtbsb == '1') {
+				if (this.baseFormData.daIsXhxtbsb == '1') {
 					this.baseFormData.bs.push('3')
 				}
-				if (data.daIsMnxtbs == '1') {
+				if (this.baseFormData.daIsMnxtbs == '1') {
 					this.baseFormData.bs.push('4')
 				}
-				if (data.daIsYdxtbs == '1') {
+				if (this.baseFormData.daIsYdxtbs == '1') {
 					this.baseFormData.bs.push('5')
 				}
-				if (data.daIsSzxtbs == '1') {
+				if (this.baseFormData.daIsSzxtbs == '1') {
 					this.baseFormData.bs.push('6')
 				}
-				if (data.daIsNfmxtbs == '1') {
+				if (this.baseFormData.daIsNfmxtbs == '1') {
 					this.baseFormData.bs.push('7')
 				}
-				if (data.daIsZlbs == '1') {
+				if (this.baseFormData.daIsZlbs == '1') {
 					this.baseFormData.bs.push('8')
 				}
-				if (data.daIsXnxgbs == '1') {
+				if (this.baseFormData.daIsXnxgbs == '1') {
 					this.baseFormData.bs.push('9')
 				}
-				if (data.daIsTnbs == '1') {
+				if (this.baseFormData.daIsTnbs == '1') {
 					this.baseFormData.bs.push('10')
 				}
-				if (data.daIsTfbs == '1') {
+				if (this.baseFormData.daIsTfbs == '1') {
 					this.baseFormData.bs.push('11')
 				}
 			}

+ 33 - 0
uni_modules/uni-badge/changelog.md

@@ -0,0 +1,33 @@
+## 1.2.2(2023-01-28)
+- 修复 运行/打包 控制台警告问题
+## 1.2.1(2022-09-05)
+- 修复 当 text 超过 max-num 时,badge 的宽度计算是根据 text 的长度计算,更改为 css 计算实际展示宽度,详见:[https://ask.dcloud.net.cn/question/150473](https://ask.dcloud.net.cn/question/150473)
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge)
+## 1.1.7(2021-11-08)
+- 优化 升级ui
+- 修改 size 属性默认值调整为 small
+- 修改 type 属性,默认值调整为 error,info 替换 default
+## 1.1.6(2021-09-22)
+- 修复 在字节小程序上样式不生效的 bug
+## 1.1.5(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.4(2021-07-29)
+- 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性
+## 1.1.3(2021-06-24)
+- 优化 示例项目
+## 1.1.1(2021-05-12)
+- 新增 组件示例地址
+## 1.1.0(2021-05-12)
+- 新增 uni-badge 的 absolute 属性,支持定位
+- 新增 uni-badge 的 offset 属性,支持定位偏移
+- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点
+- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+
+- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式
+## 1.0.7(2021-05-07)
+- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug
+- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug
+- 新增 uni-badge 属性 custom-style, 支持自定义样式
+## 1.0.6(2021-02-04)
+- 调整为uni_modules目录规范

+ 268 - 0
uni_modules/uni-badge/components/uni-badge/uni-badge.vue

@@ -0,0 +1,268 @@
+<template>
+	<view class="uni-badge--x">
+		<slot />
+		<text v-if="text" :class="classNames" :style="[positionStyle, customStyle, dotStyle]"
+			class="uni-badge" @click="onClick()">{{displayValue}}</text>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Badge 数字角标
+	 * @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=21
+	 * @property {String} text 角标内容
+	 * @property {String} size = [normal|small] 角标内容
+	 * @property {String} type = [info|primary|success|warning|error] 颜色类型
+	 * 	@value info 灰色
+	 * 	@value primary 蓝色
+	 * 	@value success 绿色
+	 * 	@value warning 黄色
+	 * 	@value error 红色
+	 * @property {String} inverted = [true|false] 是否无需背景颜色
+	 * @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
+	 * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上
+	 * 	@value rightTop 右上
+	 * 	@value rightBottom 右下
+	 * 	@value leftTop 左上
+	 * 	@value leftBottom 左下
+	 * @property {Array[number]} offset	距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px
+	 * @property {String} isDot = [true|false] 是否显示为一个小点
+	 * @event {Function} click 点击 Badge 触发事件
+	 * @example <uni-badge text="1"></uni-badge>
+	 */
+
+	export default {
+		name: 'UniBadge',
+		emits: ['click'],
+		props: {
+			type: {
+				type: String,
+				default: 'error'
+			},
+			inverted: {
+				type: Boolean,
+				default: false
+			},
+			isDot: {
+				type: Boolean,
+				default: false
+			},
+			maxNum: {
+				type: Number,
+				default: 99
+			},
+			absolute: {
+				type: String,
+				default: ''
+			},
+			offset: {
+				type: Array,
+				default () {
+					return [0, 0]
+				}
+			},
+			text: {
+				type: [String, Number],
+				default: ''
+			},
+			size: {
+				type: String,
+				default: 'small'
+			},
+			customStyle: {
+				type: Object,
+				default () {
+					return {}
+				}
+			}
+		},
+		data() {
+			return {};
+		},
+		computed: {
+			width() {
+				return String(this.text).length * 8 + 12
+			},
+			classNames() {
+				const {
+					inverted,
+					type,
+					size,
+					absolute
+				} = this
+				return [
+					inverted ? 'uni-badge--' + type + '-inverted' : '',
+					'uni-badge--' + type,
+					'uni-badge--' + size,
+					absolute ? 'uni-badge--absolute' : ''
+				].join(' ')
+			},
+			positionStyle() {
+				if (!this.absolute) return {}
+				let w = this.width / 2,
+					h = 10
+				if (this.isDot) {
+					w = 5
+					h = 5
+				}
+				const x = `${- w  + this.offset[0]}px`
+				const y = `${- h + this.offset[1]}px`
+
+				const whiteList = {
+					rightTop: {
+						right: x,
+						top: y
+					},
+					rightBottom: {
+						right: x,
+						bottom: y
+					},
+					leftBottom: {
+						left: x,
+						bottom: y
+					},
+					leftTop: {
+						left: x,
+						top: y
+					}
+				}
+				const match = whiteList[this.absolute]
+				return match ? match : whiteList['rightTop']
+			},
+			dotStyle() {
+				if (!this.isDot) return {}
+				return {
+					width: '10px',
+					minWidth: '0',
+					height: '10px',
+					padding: '0',
+					borderRadius: '10px'
+				}
+			},
+			displayValue() {
+				const {
+					isDot,
+					text,
+					maxNum
+				} = this
+				return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
+			}
+		},
+		methods: {
+			onClick() {
+				this.$emit('click');
+			}
+		}
+	};
+</script>
+
+<style lang="scss" >
+	$uni-primary: #2979ff !default;
+	$uni-success: #4cd964 !default;
+	$uni-warning: #f0ad4e !default;
+	$uni-error: #dd524d !default;
+	$uni-info: #909399 !default;
+
+
+	$bage-size: 12px;
+	$bage-small: scale(0.8);
+
+	.uni-badge--x {
+		/* #ifdef APP-NVUE */
+		// align-self: flex-start;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: inline-block;
+		/* #endif */
+		position: relative;
+	}
+
+	.uni-badge--absolute {
+		position: absolute;
+	}
+
+	.uni-badge--small {
+		transform: $bage-small;
+		transform-origin: center center;
+	}
+
+	.uni-badge {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		overflow: hidden;
+		box-sizing: border-box;
+		font-feature-settings: "tnum";
+		min-width: 20px;
+		/* #endif */
+		justify-content: center;
+		flex-direction: row;
+		height: 20px;
+		padding: 0 4px;
+		line-height: 18px;
+		color: #fff;
+		border-radius: 100px;
+		background-color: $uni-info;
+		background-color: transparent;
+		border: 1px solid #fff;
+		text-align: center;
+		font-family: 'Helvetica Neue', Helvetica, sans-serif;
+		font-size: $bage-size;
+		/* #ifdef H5 */
+		z-index: 999;
+		cursor: pointer;
+		/* #endif */
+
+		&--info {
+			color: #fff;
+			background-color: $uni-info;
+		}
+
+		&--primary {
+			background-color: $uni-primary;
+		}
+
+		&--success {
+			background-color: $uni-success;
+		}
+
+		&--warning {
+			background-color: $uni-warning;
+		}
+
+		&--error {
+			background-color: $uni-error;
+		}
+
+		&--inverted {
+			padding: 0 5px 0 0;
+			color: $uni-info;
+		}
+
+		&--info-inverted {
+			color: $uni-info;
+			background-color: transparent;
+		}
+
+		&--primary-inverted {
+			color: $uni-primary;
+			background-color: transparent;
+		}
+
+		&--success-inverted {
+			color: $uni-success;
+			background-color: transparent;
+		}
+
+		&--warning-inverted {
+			color: $uni-warning;
+			background-color: transparent;
+		}
+
+		&--error-inverted {
+			color: $uni-error;
+			background-color: transparent;
+		}
+
+	}
+</style>

+ 85 - 0
uni_modules/uni-badge/package.json

@@ -0,0 +1,85 @@
+{
+  "id": "uni-badge",
+  "displayName": "uni-badge 数字角标",
+  "version": "1.2.2",
+  "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
+  "keywords": [
+    "",
+    "badge",
+    "uni-ui",
+    "uniui",
+    "数字角标",
+    "徽章"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 10 - 0
uni_modules/uni-badge/readme.md

@@ -0,0 +1,10 @@
+## Badge 数字角标
+> **组件名:uni-badge**
+> 代码块: `uBadge`
+
+数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景,
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-badge)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+

+ 2 - 0
uni_modules/uni-icons/changelog.md

@@ -1,3 +1,5 @@
+## 2.0.9(2024-01-12)
+fix: 修复图标大小默认值错误的问题
 ## 2.0.8(2023-12-14)
 - 修复 项目未使用 ts 情况下,打包报错的bug
 ## 2.0.7(2023-12-14)

+ 1 - 1
uni_modules/uni-icons/components/uni-icons/uni-icons.uvue

@@ -30,7 +30,7 @@
 			},
 			size: {
 				type: Object,
-				default: 24
+				default: 16
 			},
 			fontFamily: {
 				type: String,

+ 1 - 1
uni_modules/uni-icons/components/uni-icons/uni-icons.vue

@@ -50,7 +50,7 @@
 			},
 			size: {
 				type: [Number, String],
-				default: 24
+				default: 16
 			},
 			customPrefix: {
 				type: String,

+ 1 - 1
uni_modules/uni-icons/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-icons",
   "displayName": "uni-icons 图标",
-  "version": "2.0.8",
+  "version": "2.0.9",
   "description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。",
   "keywords": [
     "uni-ui",

+ 46 - 0
uni_modules/uni-list/changelog.md

@@ -0,0 +1,46 @@
+## 1.2.14(2023-04-14)
+- 优化 uni-list-chat 具名插槽`header` 非app端套一层元素,方便使用时通过外层元素定位实现样式修改
+## 1.2.13(2023-03-03)
+- uni-list-chat 新增 支持具名插槽`header`
+## 1.2.12(2023-02-01)
+- 新增 列表图标新增 customPrefix 属性 ,用法 [详见](https://uniapp.dcloud.net.cn/component/uniui/uni-icons.html#icons-props)
+## 1.2.11(2023-01-31)
+- 修复 无反馈效果呈现的bug
+## 1.2.9(2022-11-22)
+- 修复 uni-list-chat 在vue3下跳转报错的bug
+## 1.2.8(2022-11-21)
+- 修复 uni-list-chat avatar属性 值为本地路径时错误的问题
+## 1.2.7(2022-11-21)
+- 修复 uni-list-chat avatar属性 在腾讯云版uniCloud下错误的问题
+## 1.2.6(2022-11-18)
+- 修复 uni-list-chat note属性 支持:“草稿”字样功能 文本少1位的问题
+## 1.2.5(2022-11-15)
+- 修复 uni-list-item 的 customStyle 属性 padding值在 H5端 无效的bug
+## 1.2.4(2022-11-15)
+- 修复 uni-list-item 的 customStyle 属性 padding值在nvue(vue2)下无效的bug
+## 1.2.3(2022-11-14)
+- uni-list-chat 新增 avatar 支持 fileId
+## 1.2.2(2022-11-11)
+- uni-list 新增属性 render-reverse 详情参考:[https://uniapp.dcloud.net.cn/component/list.html](https://uniapp.dcloud.net.cn/component/list.html)
+- uni-list-chat note属性 支持:“草稿”字样 加红显示 详情参考uni-im:[https://ext.dcloud.net.cn/plugin?name=uni-im](https://ext.dcloud.net.cn/plugin?name=uni-im)
+- uni-list-item 新增属性 customStyle 支持设置padding、backgroundColor
+## 1.2.1(2022-03-30)
+- 删除无用文件
+## 1.2.0(2021-11-23)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-list](https://uniapp.dcloud.io/component/uniui/uni-list)
+## 1.1.3(2021-08-30)
+- 修复 在vue3中to属性在发行应用的时候报错的bug
+## 1.1.2(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 1.1.1(2021-07-21)
+- 修复 与其他组件嵌套使用时,点击失效的Bug
+## 1.1.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.17(2021-05-12)
+- 新增 组件示例地址
+## 1.0.16(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 1.0.15(2021-02-05)
+- 调整为uni_modules目录规范
+- 修复 uni-list-chat 角标显示不正常的问题

+ 107 - 0
uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue

@@ -0,0 +1,107 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<cell>
+		<!-- #endif -->
+		<view class="uni-list-ad">
+			<view v-if="borderShow" :class="{'uni-list--border':border,'uni-list-item--first':isFirstChild}"></view>
+			<ad style="width: 200px;height: 300px;border-width: 1px;border-color: red;border-style: solid;" adpid="1111111111"
+			 unit-id="" appid="" apid="" type="feed" @error="aderror" @close="closeAd"></ad>
+		</view>
+		<!-- #ifdef APP-NVUE -->
+	</cell>
+	<!-- #endif -->
+
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const dom = uni.requireNativePlugin('dom');
+	// #endif
+	export default {
+		name: 'UniListAd',
+		props: {
+			title: {
+				type: String,
+				default: '',
+
+			}
+		},
+		// inject: ['list'],
+		data() {
+			return {
+				isFirstChild: false,
+				border: false,
+				borderShow: true,
+			}
+		},
+
+		mounted() {
+			this.list = this.getForm()
+			if (this.list) {
+				if (!this.list.firstChildAppend) {
+					this.list.firstChildAppend = true
+					this.isFirstChild = true
+				}
+				this.border = this.list.border
+			}
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniList') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			aderror(e) {
+				console.log("aderror: " + JSON.stringify(e.detail));
+			},
+			closeAd(e) {
+				this.borderShow = false
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-list-ad {
+		position: relative;
+		border: 1px red solid;
+	}
+
+	.uni-list--border {
+		position: relative;
+		padding-bottom: 1px;
+		/* #ifdef APP-PLUS */
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		/* #endif */
+		margin-left: $uni-spacing-row-lg;
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-list--border:after {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(.5);
+		transform: scaleY(.5);
+		background-color: $uni-border-color;
+	}
+
+	.uni-list-item--first:after {
+		height: 0px;
+	}
+
+	/* #endif */
+</style>

+ 58 - 0
uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss

@@ -0,0 +1,58 @@
+/**
+ * 这里是 uni-list 组件内置的常用样式变量
+ * 如果需要覆盖样式,这里提供了基本的组件样式变量,您可以尝试修改这里的变量,去完成样式替换,而不用去修改源码
+ *
+ */
+
+// 背景色
+$background-color : #fff;
+// 分割线颜色
+$divide-line-color : #e5e5e5;
+
+// 默认头像大小,如需要修改此值,注意同步修改 js 中的值 const avatarWidth = xx ,目前只支持方形头像
+// nvue 页面不支持修改头像大小
+$avatar-width : 45px ;
+
+// 头像边框
+$avatar-border-radius: 5px;
+$avatar-border-color: #eee;
+$avatar-border-width: 1px;
+
+// 标题文字样式
+$title-size : 16px;
+$title-color : #3b4144;
+$title-weight : normal;
+
+// 描述文字样式
+$note-size : 12px;
+$note-color : #999;
+$note-weight : normal;
+
+// 右侧额外内容默认样式
+$right-text-size : 12px;
+$right-text-color : #999;
+$right-text-weight : normal;
+
+// 角标样式
+// nvue 页面不支持修改圆点位置以及大小
+// 角标在左侧时,角标的位置,默认为 0 ,负数左/下移动,正数右/上移动
+$badge-left: 0px;
+$badge-top: 0px;
+
+// 显示圆点时,圆点大小
+$dot-width: 10px;
+$dot-height: 10px;
+
+// 显示角标时,角标大小和字体大小
+$badge-size : 18px;
+$badge-font : 12px;
+// 显示角标时,角标前景色
+$badge-color : #fff;
+// 显示角标时,角标背景色
+$badge-background-color : #ff5a5f;
+// 显示角标时,角标左右间距
+$badge-space : 6px;
+
+// 状态样式
+// 选中颜色
+$hover : #f5f5f5;

+ 593 - 0
uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue

@@ -0,0 +1,593 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<cell>
+		<!-- #endif -->
+		<view :hover-class="!clickable && !link ? '' : 'uni-list-chat--hover'" class="uni-list-chat" @click.stop="onClick">
+			<view :class="{ 'uni-list--border': border, 'uni-list-chat--first': isFirstChild }"></view>
+			<view class="uni-list-chat__container">
+				<view class="uni-list-chat__header-warp">
+					<view v-if="avatarCircle || avatarList.length === 0" class="uni-list-chat__header" :class="{ 'header--circle': avatarCircle }">
+						<image class="uni-list-chat__header-image" :class="{ 'header--circle': avatarCircle }" :src="avatarUrl" mode="aspectFill"></image>
+					</view>
+					<!-- 头像组 -->
+					<view v-else class="uni-list-chat__header">
+						<view v-for="(item, index) in avatarList" :key="index" class="uni-list-chat__header-box" :class="computedAvatar"
+						 :style="{ width: imageWidth + 'px', height: imageWidth + 'px' }">
+							<image class="uni-list-chat__header-image" :style="{ width: imageWidth + 'px', height: imageWidth + 'px' }" :src="item.url"
+							 mode="aspectFill"></image>
+						</view>
+					</view>
+				</view>
+				<!-- #ifndef APP -->
+				<view class="slot-header">
+				<!-- #endif -->
+					<slot name="header"></slot>
+				<!-- #ifndef APP -->
+				</view>
+				<!-- #endif -->
+				<view v-if="badgeText && badgePositon === 'left'" class="uni-list-chat__badge uni-list-chat__badge-pos" :class="[isSingle]">
+					<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
+				</view>
+				<view class="uni-list-chat__content">
+					<view class="uni-list-chat__content-main">
+						<text class="uni-list-chat__content-title uni-ellipsis">{{ title }}</text>
+						<view style="flex-direction: row;">
+							<text class="draft" v-if="isDraft">[草稿]</text>
+							<text class="uni-list-chat__content-note uni-ellipsis">{{isDraft?note.slice(14):note}}</text>
+						</view>
+					</view>
+					<view class="uni-list-chat__content-extra">
+						<slot>
+							<text class="uni-list-chat__content-extra-text">{{ time }}</text>
+							<view v-if="badgeText && badgePositon === 'right'" class="uni-list-chat__badge" :class="[isSingle, badgePositon === 'right' ? 'uni-list-chat--right' : '']">
+								<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
+							</view>
+						</slot>
+					</view>
+				</view>
+			</view>
+		</view>
+		<!-- #ifdef APP-NVUE -->
+	</cell>
+	<!-- #endif -->
+</template>
+
+<script>
+	// 头像大小
+	const avatarWidth = 45;
+
+	/**
+	 * ListChat 聊天列表
+	 * @description 聊天列表,用于创建聊天类列表
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+	 * @property {String} 	title 							标题
+	 * @property {String} 	note 							描述
+	 * @property {Boolean} 	clickable = [true|false] 		是否开启点击反馈,默认为false
+	 * @property {String} 	badgeText						数字角标内容
+	 * @property {String}  	badgePositon = [left|right]		角标位置,默认为 right
+	 * @property {String} 	link = [false|navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈,默认为false
+	 *  @value false	 	不开启
+	 *  @value navigateTo 	同 uni.navigateTo()
+	 * 	@value redirectTo 	同 uni.redirectTo()
+	 * 	@value reLaunch   	同 uni.reLaunch()
+	 * 	@value switchTab  	同 uni.switchTab()
+	 * @property {String | PageURIString} 	to  			跳转目标页面
+	 * @property {String} 	time							右侧时间显示
+	 * @property {Boolean} 	avatarCircle = [true|false]		是否显示圆形头像,默认为false
+	 * @property {String} 	avatar							头像地址,avatarCircle 不填时生效
+	 * @property {Array} 	avatarList 						头像组,格式为 [{url:''}]
+	 * @event {Function} 	click 							点击 uniListChat 触发事件
+	 */
+	export default {
+		name: 'UniListChat',
+		emits:['click'],
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			note: {
+				type: String,
+				default: ''
+			},
+			clickable: {
+				type: Boolean,
+				default: false
+			},
+			link: {
+				type: [Boolean, String],
+				default: false
+			},
+			to: {
+				type: String,
+				default: ''
+			},
+			badgeText: {
+				type: [String, Number],
+				default: ''
+			},
+			badgePositon: {
+				type: String,
+				default: 'right'
+			},
+			time: {
+				type: String,
+				default: ''
+			},
+			avatarCircle: {
+				type: Boolean,
+				default: false
+			},
+			avatar: {
+				type: String,
+				default: ''
+			},
+			avatarList: {
+				type: Array,
+				default () {
+					return [];
+				}
+			}
+		},
+		// inject: ['list'],
+		computed: {
+			isDraft(){
+				return this.note.slice(0,14) == '[uni-im-draft]'
+			},
+			isSingle() {
+				if (this.badgeText === 'dot') {
+					return 'uni-badge--dot';
+				} else {
+					const badgeText = this.badgeText.toString();
+					if (badgeText.length > 1) {
+						return 'uni-badge--complex';
+					} else {
+						return 'uni-badge--single';
+					}
+				}
+			},
+			computedAvatar() {
+				if (this.avatarList.length > 4) {
+					this.imageWidth = avatarWidth * 0.31;
+					return 'avatarItem--3';
+				} else if (this.avatarList.length > 1) {
+					this.imageWidth = avatarWidth * 0.47;
+					return 'avatarItem--2';
+				} else {
+					this.imageWidth = avatarWidth;
+					return 'avatarItem--1';
+				}
+			}
+		},
+		watch: {
+			avatar:{
+				handler(avatar) {
+					if(avatar.substr(0,8) == 'cloud://'){
+						uniCloud.getTempFileURL({
+							fileList: [avatar]
+						}).then(res=>{
+							// console.log(res);
+							// 兼容uniCloud私有化部署
+							let fileList = res.fileList || res.result.fileList
+							this.avatarUrl = fileList[0].tempFileURL
+						})
+					}else{
+						this.avatarUrl = avatar
+					}
+				},
+				immediate: true
+			}
+		},
+		data() {
+			return {
+				isFirstChild: false,
+				border: true,
+				// avatarList: 3,
+				imageWidth: 50,
+				avatarUrl:''
+			};
+		},
+		mounted() {
+			this.list = this.getForm()
+			if (this.list) {
+				if (!this.list.firstChildAppend) {
+					this.list.firstChildAppend = true;
+					this.isFirstChild = true;
+				}
+				this.border = this.list.border;
+			}
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniList') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			onClick() {
+				if (this.to !== '') {
+					this.openPage();
+					return;
+				}
+
+				if (this.clickable || this.link) {
+					this.$emit('click', {
+						data: {}
+					});
+				}
+			},
+			openPage() {
+				if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
+					this.pageApi(this.link);
+				} else {
+					this.pageApi('navigateTo');
+				}
+			},
+			pageApi(api) {
+				let callback = {
+					url: this.to,
+					success: res => {
+						this.$emit('click', {
+							data: res
+						});
+					},
+					fail: err => {
+						this.$emit('click', {
+							data: err
+						});
+					}
+				}
+				switch (api) {
+					case 'navigateTo':
+						uni.navigateTo(callback)
+						break
+					case 'redirectTo':
+						uni.redirectTo(callback)
+						break
+					case 'reLaunch':
+						uni.reLaunch(callback)
+						break
+					case 'switchTab':
+						uni.switchTab(callback)
+						break
+					default:
+					uni.navigateTo(callback)
+				}
+			}
+		}
+	};
+</script>
+
+<style lang="scss" >
+	$uni-font-size-lg:16px;
+	$uni-spacing-row-sm: 5px;
+	$uni-spacing-row-base: 10px;
+	$uni-spacing-row-lg: 15px;
+	$background-color: #fff;
+	$divide-line-color: #e5e5e5;
+	$avatar-width: 45px;
+	$avatar-border-radius: 5px;
+	$avatar-border-color: #eee;
+	$avatar-border-width: 1px;
+	$title-size: 16px;
+	$title-color: #3b4144;
+	$title-weight: normal;
+	$note-size: 12px;
+	$note-color: #999;
+	$note-weight: normal;
+	$right-text-size: 12px;
+	$right-text-color: #999;
+	$right-text-weight: normal;
+	$badge-left: 0px;
+	$badge-top: 0px;
+	$dot-width: 10px;
+	$dot-height: 10px;
+	$badge-size: 18px;
+	$badge-font: 12px;
+	$badge-color: #fff;
+	$badge-background-color: #ff5a5f;
+	$badge-space: 6px;
+	$hover: #f5f5f5;
+
+	.uni-list-chat {
+		font-size: $uni-font-size-lg;
+		position: relative;
+		flex-direction: column;
+		justify-content: space-between;
+		background-color: $background-color;
+	}
+
+	// .uni-list-chat--disabled {
+	// 	opacity: 0.3;
+	// }
+
+	.uni-list-chat--hover {
+		background-color: $hover;
+	}
+
+	.uni-list--border {
+		position: relative;
+		margin-left: $uni-spacing-row-lg;
+		/* #ifdef APP-PLUS */
+		border-top-color: $divide-line-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		/* #endif */
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-list--border:after {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(0.5);
+		transform: scaleY(0.5);
+		background-color: $divide-line-color;
+	}
+
+	.uni-list-item--first:after {
+		height: 0px;
+	}
+
+	/* #endif */
+
+	.uni-list-chat--first {
+		border-top-width: 0px;
+	}
+
+	.uni-ellipsis {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		/* #endif */
+	}
+
+	.uni-ellipsis-2 {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		text-overflow: ellipsis;
+		display: -webkit-box;
+		-webkit-line-clamp: 2;
+		-webkit-box-orient: vertical;
+		/* #endif */
+
+		/* #ifdef APP-NVUE */
+		lines: 2;
+		/* #endif */
+	}
+
+	.uni-list-chat__container {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex: 1;
+		padding: $uni-spacing-row-base $uni-spacing-row-lg;
+		position: relative;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__header-warp {
+		position: relative;
+	}
+
+	.uni-list-chat__header {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		align-content: center;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		flex-wrap: wrap-reverse;
+		/* #ifdef APP-NVUE */
+		width: 50px;
+		height: 50px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		width: $avatar-width;
+		height: $avatar-width;
+		/* #endif */
+
+		border-radius: $avatar-border-radius;
+		border-color: $avatar-border-color;
+		border-width: $avatar-border-width;
+		border-style: solid;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__header-box {
+		/* #ifndef APP-PLUS */
+		box-sizing: border-box;
+		display: flex;
+		width: $avatar-width;
+		height: $avatar-width;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		width: 50px;
+		height: 50px;
+		/* #endif */
+		overflow: hidden;
+		border-radius: 2px;
+	}
+
+	.uni-list-chat__header-image {
+		margin: 1px;
+		/* #ifdef APP-NVUE */
+		width: 50px;
+		height: 50px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		width: $avatar-width;
+		height: $avatar-width;
+		/* #endif */
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-list-chat__header-image {
+		display: block;
+		width: 100%;
+		height: 100%;
+	}
+
+	.avatarItem--1 {
+		width: 100%;
+		height: 100%;
+	}
+
+	.avatarItem--2 {
+		width: 47%;
+		height: 47%;
+	}
+
+	.avatarItem--3 {
+		width: 32%;
+		height: 32%;
+	}
+
+	/* #endif */
+	.header--circle {
+		border-radius: 50%;
+	}
+
+	.uni-list-chat__content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex: 1;
+		overflow: hidden;
+		padding: 2px 0;
+	}
+
+	.uni-list-chat__content-main {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: space-between;
+		padding-left: $uni-spacing-row-base;
+		flex: 1;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__content-title {
+		font-size: $title-size;
+		color: $title-color;
+		font-weight: $title-weight;
+		overflow: hidden;
+	}
+
+	.draft ,.uni-list-chat__content-note {
+		margin-top: 3px;
+		color: $note-color;
+		font-size: $note-size;
+		font-weight: $title-weight;
+		overflow: hidden;
+	}
+	.draft{
+		color: #eb3a41;
+		/* #ifndef APP-NVUE */
+		flex-shrink: 0;
+		/* #endif */
+		padding-right: 3px;
+	}
+
+	.uni-list-chat__content-extra {
+		/* #ifndef APP-NVUE */
+		flex-shrink: 0;
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: space-between;
+		align-items: flex-end;
+		margin-left: 5px;
+	}
+
+	.uni-list-chat__content-extra-text {
+		color: $right-text-color;
+		font-size: $right-text-size;
+		font-weight: $right-text-weight;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__badge-pos {
+		position: absolute;
+		/* #ifdef APP-NVUE */
+		left: 55px;
+		top: 3px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		left: calc(#{$avatar-width} + 10px - #{$badge-space} + #{$badge-left});
+		top: calc(#{$uni-spacing-row-base}/ 2 + 1px + #{$badge-top});
+		/* #endif */
+	}
+
+	.uni-list-chat__badge {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		border-radius: 100px;
+		background-color: $badge-background-color;
+	}
+
+	.uni-list-chat__badge-text {
+		color: $badge-color;
+		font-size: $badge-font;
+	}
+
+	.uni-badge--single {
+		/* #ifndef APP-NVUE */
+		// left: calc(#{$avatar-width} + 7px + #{$badge-left});
+		/* #endif */
+		width: $badge-size;
+		height: $badge-size;
+	}
+
+	.uni-badge--complex {
+		/* #ifdef APP-NVUE */
+		left: 50px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		width: auto;
+		/* #endif */
+		height: $badge-size;
+		padding: 0 $badge-space;
+	}
+
+	.uni-badge--dot {
+		/* #ifdef APP-NVUE */
+		left: 60px;
+		top: 6px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		left: calc(#{$avatar-width} + 15px - #{$dot-width}/ 2 + 1px + #{$badge-left});
+		/* #endif */
+		width: $dot-width;
+		height: $dot-height;
+		padding: 0;
+	}
+
+	.uni-list-chat--right {
+		/* #ifdef APP-NVUE */
+		left: 0;
+		/* #endif */
+	}
+</style>

+ 534 - 0
uni_modules/uni-list/components/uni-list-item/uni-list-item.vue

@@ -0,0 +1,534 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<cell :keep-scroll-position="keepScrollPosition">
+		<!-- #endif -->
+		<view :class="{ 'uni-list-item--disabled': disabled }" :style="{'background-color':customStyle.backgroundColor}"
+			:hover-class="(!clickable && !link) || disabled || showSwitch ? '' : 'uni-list-item--hover'"
+			class="uni-list-item" @click="onClick">
+			<view v-if="!isFirstChild" class="border--left" :class="{ 'uni-list--border': border }"></view>
+			<view class="uni-list-item__container"
+				:class="{ 'container--right': showArrow || link, 'flex--direction': direction === 'column'}"
+				:style="{paddingTop:padding.top,paddingLeft:padding.left,paddingRight:padding.right,paddingBottom:padding.bottom}">
+				<slot name="header">
+					<view class="uni-list-item__header">
+						<view v-if="thumb" class="uni-list-item__icon">
+							<image :src="thumb" class="uni-list-item__icon-img" :class="['uni-list--' + thumbSize]" />
+						</view>
+						<view v-else-if="showExtraIcon" class="uni-list-item__icon">
+							<uni-icons :customPrefix="extraIcon.customPrefix" :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" />
+						</view>
+					</view>
+				</slot>
+				<slot name="body">
+					<view class="uni-list-item__content"
+						:class="{ 'uni-list-item__content--center': thumb || showExtraIcon || showBadge || showSwitch }">
+						<text v-if="title" class="uni-list-item__content-title"
+							:class="[ellipsis !== 0 && ellipsis <= 2 ? 'uni-ellipsis-' + ellipsis : '']">{{ title }}</text>
+						<text v-if="note" class="uni-list-item__content-note">{{ note }}</text>
+					</view>
+				</slot>
+				<slot name="footer">
+					<view v-if="rightText || showBadge || showSwitch" class="uni-list-item__extra"
+						:class="{ 'flex--justify': direction === 'column' }">
+						<text v-if="rightText" class="uni-list-item__extra-text">{{ rightText }}</text>
+						<uni-badge v-if="showBadge" :type="badgeType" :text="badgeText" :custom-style="badgeStyle" />
+						<switch v-if="showSwitch" :disabled="disabled" :checked="switchChecked"
+							@change="onSwitchChange" />
+					</view>
+				</slot>
+			</view>
+			<uni-icons v-if="showArrow || link" :size="16" class="uni-icon-wrapper" color="#bbb" type="arrowright" />
+		</view>
+		<!-- #ifdef APP-NVUE -->
+	</cell>
+	<!-- #endif -->
+</template>
+
+<script>
+	/**
+	 * ListItem 列表子组件
+	 * @description 列表子组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+	 * @property {String} 	title 							标题
+	 * @property {String} 	note 							描述
+	 * @property {String} 	thumb 							左侧缩略图,若thumb有值,则不会显示扩展图标
+	 * @property {String}  	thumbSize = [lg|base|sm]		略缩图大小
+	 * 	@value 	 lg			大图
+	 * 	@value 	 base		一般
+	 * 	@value 	 sm			小图
+	 * @property {String} 	badgeText						数字角标内容
+	 * @property {String} 	badgeType 						数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)
+	 * @property {Object}   badgeStyle           数字角标样式
+	 * @property {String} 	rightText 						右侧文字内容
+	 * @property {Boolean} 	disabled = [true|false]			是否禁用
+	 * @property {Boolean} 	clickable = [true|false] 		是否开启点击反馈
+	 * @property {String} 	link = [navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈
+	 *  @value 	navigateTo 	同 uni.navigateTo()
+	 * 	@value redirectTo 	同 uni.redirectTo()
+	 * 	@value reLaunch   	同 uni.reLaunch()
+	 * 	@value switchTab  	同 uni.switchTab()
+	 * @property {String | PageURIString} 	to  			跳转目标页面
+	 * @property {Boolean} 	showBadge = [true|false] 		是否显示数字角标
+	 * @property {Boolean} 	showSwitch = [true|false] 		是否显示Switch
+	 * @property {Boolean} 	switchChecked = [true|false] 	Switch是否被选中
+	 * @property {Boolean} 	showExtraIcon = [true|false] 	左侧是否显示扩展图标
+	 * @property {Object} 	extraIcon 						扩展图标参数,格式为 {color: '#4cd964',size: '22',type: 'spinner'}
+	 * @property {String} 	direction = [row|column]		排版方向
+	 * @value row 			水平排列
+	 * @value column 		垂直排列
+	 * @event {Function} 	click 							点击 uniListItem 触发事件
+	 * @event {Function} 	switchChange 					点击切换 Switch 时触发
+	 */
+	export default {
+		name: 'UniListItem',
+		emits: ['click', 'switchChange'],
+		props: {
+			direction: {
+				type: String,
+				default: 'row'
+			},
+			title: {
+				type: String,
+				default: ''
+			},
+			note: {
+				type: String,
+				default: ''
+			},
+			ellipsis: {
+				type: [Number, String],
+				default: 0
+			},
+			disabled: {
+				type: [Boolean, String],
+				default: false
+			},
+			clickable: {
+				type: Boolean,
+				default: false
+			},
+			showArrow: {
+				type: [Boolean, String],
+				default: false
+			},
+			link: {
+				type: [Boolean, String],
+				default: false
+			},
+			to: {
+				type: String,
+				default: ''
+			},
+			showBadge: {
+				type: [Boolean, String],
+				default: false
+			},
+			showSwitch: {
+				type: [Boolean, String],
+				default: false
+			},
+			switchChecked: {
+				type: [Boolean, String],
+				default: false
+			},
+			badgeText: {
+				type: String,
+				default: ''
+			},
+			badgeType: {
+				type: String,
+				default: 'success'
+			},
+			badgeStyle: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			rightText: {
+				type: String,
+				default: ''
+			},
+			thumb: {
+				type: String,
+				default: ''
+			},
+			thumbSize: {
+				type: String,
+				default: 'base'
+			},
+			showExtraIcon: {
+				type: [Boolean, String],
+				default: false
+			},
+			extraIcon: {
+				type: Object,
+				default () {
+					return {
+						type: '',
+						color: '#000000',
+						size: 20,
+						customPrefix: ''
+					};
+				}
+			},
+			border: {
+				type: Boolean,
+				default: true
+			},
+			customStyle: {
+				type: Object,
+				default () {
+					return {
+						padding: '',
+						backgroundColor: '#FFFFFF'
+					}
+				}
+			},
+			keepScrollPosition: {
+				type: Boolean,
+				default: false
+			}
+		},
+		watch: {
+			'customStyle.padding': {
+				handler(padding) {
+					if(typeof padding == 'number'){
+						padding += ''
+					}
+					let paddingArr = padding.split(' ')
+					if (paddingArr.length === 1) {
+						const allPadding = paddingArr[0]
+						this.padding = {
+							"top": allPadding,
+							"right": allPadding,
+							"bottom": allPadding,
+							"left": allPadding
+						}
+					} else if (paddingArr.length === 2) {
+						const [verticalPadding, horizontalPadding] = paddingArr;
+						this.padding = {
+							"top": verticalPadding,
+							"right": horizontalPadding,
+							"bottom": verticalPadding,
+							"left": horizontalPadding
+						}
+					} else if (paddingArr.length === 4) {
+							const [topPadding, rightPadding, bottomPadding, leftPadding] = paddingArr;
+							this.padding = {
+								"top": topPadding,
+								"right": rightPadding,
+								"bottom": bottomPadding,
+								"left": leftPadding
+							}
+					}
+				},
+				immediate: true
+			}
+		},
+		// inject: ['list'],
+		data() {
+			return {
+				isFirstChild: false,
+				padding: {
+					top: "",
+					right: "",
+					bottom: "",
+					left: ""
+				}
+			};
+		},
+		mounted() {
+			this.list = this.getForm()
+			// 判断是否存在 uni-list 组件
+			if (this.list) {
+				if (!this.list.firstChildAppend) {
+					this.list.firstChildAppend = true;
+					this.isFirstChild = true;
+				}
+			}
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniList') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			onClick() {
+				if (this.to !== '') {
+					this.openPage();
+					return;
+				}
+				if (this.clickable || this.link) {
+					this.$emit('click', {
+						data: {}
+					});
+				}
+			},
+			onSwitchChange(e) {
+				this.$emit('switchChange', e.detail);
+			},
+			openPage() {
+				if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
+					this.pageApi(this.link);
+				} else {
+					this.pageApi('navigateTo');
+				}
+			},
+			pageApi(api) {
+				let callback = {
+					url: this.to,
+					success: res => {
+						this.$emit('click', {
+							data: res
+						});
+					},
+					fail: err => {
+						this.$emit('click', {
+							data: err
+						});
+					}
+				}
+				switch (api) {
+					case 'navigateTo':
+						uni.navigateTo(callback)
+						break
+					case 'redirectTo':
+						uni.redirectTo(callback)
+						break
+					case 'reLaunch':
+						uni.reLaunch(callback)
+						break
+					case 'switchTab':
+						uni.switchTab(callback)
+						break
+					default:
+						uni.navigateTo(callback)
+				}
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	$uni-font-size-sm:12px;
+	$uni-font-size-base:14px;
+	$uni-font-size-lg:16px;
+	$uni-spacing-col-lg: 12px;
+	$uni-spacing-row-lg: 15px;
+	$uni-img-size-sm:20px;
+	$uni-img-size-base:26px;
+	$uni-img-size-lg:40px;
+	$uni-border-color:#e5e5e5;
+	$uni-bg-color-hover:#f1f1f1;
+	$uni-text-color-grey:#999;
+	$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
+
+	.uni-list-item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		font-size: $uni-font-size-lg;
+		position: relative;
+		justify-content: space-between;
+		align-items: center;
+		background-color: #fff;
+		flex-direction: row;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-list-item--disabled {
+		opacity: 0.3;
+	}
+
+	.uni-list-item--hover {
+		background-color: $uni-bg-color-hover !important;
+	}
+
+	.uni-list-item__container {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		padding: $list-item-pd;
+		padding-left: $uni-spacing-row-lg;
+		flex: 1;
+		overflow: hidden;
+		// align-items: center;
+	}
+
+	.container--right {
+		padding-right: 0;
+	}
+
+	// .border--left {
+	// 	margin-left: $uni-spacing-row-lg;
+	// }
+	.uni-list--border {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		/* #ifdef APP-NVUE */
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		/* #endif */
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-list--border:after {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(0.5);
+		transform: scaleY(0.5);
+		background-color: $uni-border-color;
+	}
+
+	/* #endif */
+	.uni-list-item__content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		padding-right: 8px;
+		flex: 1;
+		color: #3b4144;
+		// overflow: hidden;
+		flex-direction: column;
+		justify-content: space-between;
+		overflow: hidden;
+	}
+
+	.uni-list-item__content--center {
+		justify-content: center;
+	}
+
+	.uni-list-item__content-title {
+		font-size: $uni-font-size-base;
+		color: #3b4144;
+		overflow: hidden;
+	}
+
+	.uni-list-item__content-note {
+		margin-top: 6rpx;
+		color: $uni-text-color-grey;
+		font-size: $uni-font-size-sm;
+		overflow: hidden;
+	}
+
+	.uni-list-item__extra {
+		// width: 25%;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: flex-end;
+		align-items: center;
+	}
+
+	.uni-list-item__header {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+	}
+
+	.uni-list-item__icon {
+		margin-right: 18rpx;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.uni-list-item__icon-img {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		height: $uni-img-size-base;
+		width: $uni-img-size-base;
+		margin-right: 10px;
+	}
+
+	.uni-icon-wrapper {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		padding: 0 10px;
+	}
+
+	.flex--direction {
+		flex-direction: column;
+		/* #ifndef APP-NVUE */
+		align-items: initial;
+		/* #endif */
+	}
+
+	.flex--justify {
+		/* #ifndef APP-NVUE */
+		justify-content: initial;
+		/* #endif */
+	}
+
+	.uni-list--lg {
+		height: $uni-img-size-lg;
+		width: $uni-img-size-lg;
+	}
+
+	.uni-list--base {
+		height: $uni-img-size-base;
+		width: $uni-img-size-base;
+	}
+
+	.uni-list--sm {
+		height: $uni-img-size-sm;
+		width: $uni-img-size-sm;
+	}
+
+	.uni-list-item__extra-text {
+		color: $uni-text-color-grey;
+		font-size: $uni-font-size-sm;
+	}
+
+	.uni-ellipsis-1 {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		text-overflow: ellipsis;
+		/* #endif */
+	}
+
+	.uni-ellipsis-2 {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		text-overflow: ellipsis;
+		display: -webkit-box;
+		-webkit-line-clamp: 2;
+		-webkit-box-orient: vertical;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 2;
+		text-overflow: ellipsis;
+		/* #endif */
+	}
+</style>

+ 123 - 0
uni_modules/uni-list/components/uni-list/uni-list.vue

@@ -0,0 +1,123 @@
+<template>
+	<!-- #ifndef APP-NVUE -->
+	<view class="uni-list uni-border-top-bottom">
+		<view v-if="border" class="uni-list--border-top"></view>
+		<slot />
+		<view v-if="border" class="uni-list--border-bottom"></view>
+	</view>
+	<!-- #endif -->
+	<!-- #ifdef APP-NVUE -->
+	<list :bounce="false" :scrollable="true" show-scrollbar :render-reverse="renderReverse" @scroll="scroll" class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop"
+		loadmoreoffset="15">
+		<slot />
+	</list>
+	<!-- #endif -->
+</template>
+
+<script>
+	/**
+	 * List 列表
+	 * @description 列表组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+	 * @property {String} 	border = [true|false] 		标题
+	 */
+	export default {
+		name: 'uniList',
+		'mp-weixin': {
+			options: {
+				multipleSlots: false
+			}
+		},
+		props: {
+			stackFromEnd:{
+				type: Boolean,
+				default:false
+			},
+			enableBackToTop: {
+				type: [Boolean, String],
+				default: false
+			},
+			scrollY: {
+				type: [Boolean, String],
+				default: false
+			},
+			border: {
+				type: Boolean,
+				default: true
+			},
+			renderReverse:{
+				type: Boolean,
+				default: false
+			}
+		},
+		// provide() {
+		// 	return {
+		// 		list: this
+		// 	};
+		// },
+		created() {
+			this.firstChildAppend = false;
+		},
+		methods: {
+			loadMore(e) {
+				this.$emit('scrolltolower');
+			},
+			scroll(e) {
+				this.$emit('scroll', e);
+			}
+		}
+	};
+</script>
+<style lang="scss">
+	$uni-bg-color:#ffffff;
+	$uni-border-color:#e5e5e5;
+
+	.uni-list {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		background-color: $uni-bg-color;
+		position: relative;
+		flex-direction: column;
+	}
+
+	.uni-list--border {
+		position: relative;
+		/* #ifdef APP-NVUE */
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		border-bottom-color: $uni-border-color;
+		border-bottom-style: solid;
+		border-bottom-width: 0.5px;
+		/* #endif */
+		z-index: -1;
+	}
+
+	/* #ifndef APP-NVUE */
+
+	.uni-list--border-top {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		-webkit-transform: scaleY(0.5);
+		transform: scaleY(0.5);
+		background-color: $uni-border-color;
+		z-index: 1;
+	}
+
+	.uni-list--border-bottom {
+		position: absolute;
+		bottom: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		-webkit-transform: scaleY(0.5);
+		transform: scaleY(0.5);
+		background-color: $uni-border-color;
+	}
+
+	/* #endif */
+</style>

+ 65 - 0
uni_modules/uni-list/components/uni-list/uni-refresh.vue

@@ -0,0 +1,65 @@
+<template>
+    <!-- #ifdef APP-NVUE -->
+    <refresh :display="display" @refresh="onrefresh" @pullingdown="onpullingdown">
+        <slot />
+    </refresh>
+    <!-- #endif -->
+    <!-- #ifndef APP-NVUE -->
+    <view ref="uni-refresh" class="uni-refresh" v-show="isShow">
+        <slot />
+    </view>
+    <!-- #endif -->
+</template>
+
+<script>
+    export default {
+        name: 'UniRefresh',
+        props: {
+            display: {
+                type: [String],
+                default: "hide"
+            }
+        },
+        data() {
+            return {
+                pulling: false
+            }
+        },
+        computed: {
+            isShow() {
+                if (this.display === "show" || this.pulling === true) {
+                    return true;
+                }
+                return false;
+            }
+        },
+        created() {},
+        methods: {
+            onchange(value) {
+                this.pulling = value;
+            },
+            onrefresh(e) {
+                this.$emit("refresh", e);
+            },
+            onpullingdown(e) {
+                // #ifdef APP-NVUE
+                this.$emit("pullingdown", e);
+                // #endif
+                // #ifndef APP-NVUE
+                var detail = {
+                    viewHeight: 90,
+                    pullingDistance: e.height
+                }
+                this.$emit("pullingdown", detail);
+                // #endif
+            }
+        }
+    }
+</script>
+
+<style>
+    .uni-refresh {
+        height: 0;
+        overflow: hidden;
+    }
+</style>

+ 87 - 0
uni_modules/uni-list/components/uni-list/uni-refresh.wxs

@@ -0,0 +1,87 @@
+var pullDown = {
+    threshold: 95,
+    maxHeight: 200,
+    callRefresh: 'onrefresh',
+    callPullingDown: 'onpullingdown',
+    refreshSelector: '.uni-refresh'
+};
+
+function ready(newValue, oldValue, ownerInstance, instance) {
+    var state = instance.getState()
+    state.canPullDown = newValue;
+    // console.log(newValue);
+}
+
+function touchStart(e, instance) {
+    var state = instance.getState();
+    state.refreshInstance = instance.selectComponent(pullDown.refreshSelector);
+    state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined);
+    if (!state.canPullDown) {
+        return
+    }
+
+    // console.log("touchStart");
+
+    state.height = 0;
+    state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY;
+    state.refreshInstance.setStyle({
+        'height': 0
+    });
+    state.refreshInstance.callMethod("onchange", true);
+}
+
+function touchMove(e, ownerInstance) {
+    var instance = e.instance;
+    var state = instance.getState();
+    if (!state.canPullDown) {
+        return
+    }
+
+    var oldHeight = state.height;
+    var endY = e.touches[0].pageY || e.changedTouches[0].pageY;
+    var height = endY - state.touchStartY;
+    if (height > pullDown.maxHeight) {
+        return;
+    }
+
+    var refreshInstance = state.refreshInstance;
+    refreshInstance.setStyle({
+        'height': height + 'px'
+    });
+
+    height = height < pullDown.maxHeight ? height : pullDown.maxHeight;
+    state.height = height;
+    refreshInstance.callMethod(pullDown.callPullingDown, {
+        height: height
+    });
+}
+
+function touchEnd(e, ownerInstance) {
+    var state = e.instance.getState();
+    if (!state.canPullDown) {
+        return
+    }
+
+    state.refreshInstance.callMethod("onchange", false);
+
+    var refreshInstance = state.refreshInstance;
+    if (state.height > pullDown.threshold) {
+        refreshInstance.callMethod(pullDown.callRefresh);
+        return;
+    }
+
+    refreshInstance.setStyle({
+        'height': 0
+    });
+}
+
+function propObserver(newValue, oldValue, instance) {
+    pullDown = newValue;
+}
+
+module.exports = {
+    touchmove: touchMove,
+    touchstart: touchStart,
+    touchend: touchEnd,
+    propObserver: propObserver
+}

+ 88 - 0
uni_modules/uni-list/package.json

@@ -0,0 +1,88 @@
+{
+  "id": "uni-list",
+  "displayName": "uni-list 列表",
+  "version": "1.2.14",
+  "description": "List 组件 ,帮助使用者快速构建列表。",
+  "keywords": [
+    "",
+    "uni-ui",
+    "uniui",
+    "列表",
+    "",
+    "list"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": [
+      "uni-badge",
+      "uni-icons"
+    ],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 346 - 0
uni_modules/uni-list/readme.md

@@ -0,0 +1,346 @@
+## List 列表
+> **组件名:uni-list**
+> 代码块: `uList`、`uListItem`
+> 关联组件:`uni-list-item`、`uni-badge`、`uni-icons`、`uni-list-chat`、`uni-list-ad`
+
+
+List 列表组件,包含基本列表样式、可扩展插槽机制、长列表性能优化、多端兼容。
+
+在vue页面里,它默认使用页面级滚动。在app-nvue页面里,它默认使用原生list组件滚动。这样的长列表,在滚动出屏幕外后,系统会回收不可见区域的渲染内存资源,不会造成滚动越长手机越卡的问题。
+
+uni-list组件是父容器,里面的核心是uni-list-item子组件,它代表列表中的一个可重复行,子组件可以无限循环。
+
+uni-list-item有很多风格,uni-list-item组件通过内置的属性,满足一些常用的场景。当内置属性不满足需求时,可以通过扩展插槽来自定义列表内容。
+
+内置属性可以覆盖的场景包括:导航列表、设置列表、小图标列表、通信录列表、聊天记录列表。
+
+涉及很多大图或丰富内容的列表,比如类今日头条的新闻列表、类淘宝的电商列表,需要通过扩展插槽实现。
+
+下文均有样例给出。
+
+uni-list不包含下拉刷新和上拉翻页。上拉翻页另见组件:[uni-load-more](https://ext.dcloud.net.cn/plugin?id=29)
+
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+> **注意事项**
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 组件需要依赖 `sass` 插件 ,请自行手动安装
+> - 组件内部依赖 `'uni-icons'` 、`uni-badge` 组件
+> - `uni-list` 和 `uni-list-item` 需要配套使用,暂不支持单独使用 `uni-list-item`
+> - 只有开启点击反馈后,会有点击选中效果
+> - 使用插槽时,可以完全自定义内容
+> - note 、rightText 属性暂时没做限制,不支持文字溢出隐藏,使用时应该控制长度显示或通过默认插槽自行扩展
+> - 支付宝小程序平台需要在支付宝小程序开发者工具里开启 component2 编译模式,开启方式: 详情 --> 项目配置 --> 启用 component2 编译
+> - 如果需要修改 `switch`、`badge` 样式,请使用插槽自定义
+> - 在 `HBuilderX` 低版本中,可能会出现组件显示 `undefined` 的问题,请升级最新的 `HBuilderX` 或者 `cli`
+> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
+ 
+
+### 基本用法 
+
+- 设置 `title` 属性,可以显示列表标题
+- 设置 `disabled` 属性,可以禁用当前项
+
+```html
+<uni-list>
+	<uni-list-item  title="列表文字" ></uni-list-item>
+	<uni-list-item :disabled="true" title="列表禁用状态" ></uni-list-item>
+</uni-list>
+			 
+```
+
+### 多行内容显示
+
+- 设置 `note` 属性 ,可以在第二行显示描述文本信息
+
+```html
+<uni-list>
+	<uni-list-item title="列表文字" note="列表描述信息"></uni-list-item>
+	<uni-list-item :disabled="true" title="列表文字" note="列表禁用状态"></uni-list-item>
+</uni-list>
+
+```
+
+### 右侧显示角标、switch
+
+- 设置 `show-badge` 属性 ,可以显示角标内容
+- 设置 `show-switch` 属性,可以显示 switch 开关
+
+```html
+<uni-list>
+	<uni-list-item  title="列表右侧显示角标" :show-badge="true" badge-text="12" ></uni-list-item>
+	<uni-list-item title="列表右侧显示 switch"  :show-switch="true"  @switchChange="switchChange" ></uni-list-item>
+</uni-list>
+
+```
+
+### 左侧显示略缩图、图标  
+
+- 设置 `thumb` 属性 ,可以在列表左侧显示略缩图
+- 设置 `show-extra-icon` 属性,并指定 `extra-icon` 可以在左侧显示图标
+
+```html
+ <uni-list>
+ 	<uni-list-item title="列表左侧带略缩图" note="列表描述信息" thumb="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png"
+ 	 thumb-size="lg" rightText="右侧文字"></uni-list-item>
+ 	<uni-list-item :show-extra-icon="true" :extra-icon="extraIcon1" title="列表左侧带扩展图标" ></uni-list-item>
+</uni-list>
+```
+
+### 开启点击反馈和右侧箭头
+- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件
+- 设置 `link` 属性,会自动开启点击反馈,并给列表右侧添加一个箭头
+- 设置 `to` 属性,可以跳转页面,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo`
+
+```html
+
+<uni-list>
+	<uni-list-item title="开启点击反馈" clickable  @click="onClick" ></uni-list-item>
+	<uni-list-item title="默认 navigateTo 方式跳转页面" link to="/pages/vue/index/index" @click="onClick($event,1)" ></uni-list-item>
+	<uni-list-item title="reLaunch 方式跳转页面" link="reLaunch" to="/pages/vue/index/index" @click="onClick($event,1)" ></uni-list-item>
+</uni-list>
+
+```
+
+
+### 聊天列表示例
+- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件
+- 设置 `link` 属性,会自动开启点击反馈,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo`
+- 设置 `to` 属性,可以跳转页面
+- `time` 属性,通常会设置成时间显示,但是这个属性不仅仅可以设置时间,你可以传入任何文本,注意文本长度可能会影响显示
+- `avatar` 和 `avatarList` 属性同时只会有一个生效,同时设置的话,`avatarList` 属性的长度大于1 ,`avatar` 属性将失效
+- 可以通过默认插槽自定义列表右侧内容
+
+```html
+
+<uni-list>
+	<uni-list :border="true">
+		<!-- 显示圆形头像 -->
+		<uni-list-chat :avatar-circle="true" title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" ></uni-list-chat>
+		<!-- 右侧带角标 -->
+		<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-text="12" :badge-style="{backgroundColor:'#FF80AB'}"></uni-list-chat>
+		<!-- 头像显示圆点 -->
+		<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"></uni-list-chat>
+		<!-- 头像显示角标 -->
+		<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="99"></uni-list-chat>
+		<!-- 显示多头像 -->
+		<uni-list-chat title="uni-app" :avatar-list="avatarList" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"></uni-list-chat>
+		<!-- 自定义右侧内容 -->
+		<uni-list-chat title="uni-app" :avatar-list="avatarList" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot">
+			<view class="chat-custom-right">
+				<text class="chat-custom-text">刚刚</text>
+				<!-- 需要使用 uni-icons 请自行引入 -->
+				<uni-icons type="star-filled" color="#999" size="18"></uni-icons>
+			</view>
+		</uni-list-chat>
+	</uni-list>
+</uni-list>
+
+```
+
+```javascript
+
+export default {
+	components: {},
+	data() {
+		return {
+			avatarList: [{
+				url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png'
+			}, {
+				url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png'
+			}, {
+				url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png'
+			}]
+		}
+	}
+}
+
+```
+
+
+```css
+
+.chat-custom-right {
+	flex: 1;
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	flex-direction: column;
+	justify-content: space-between;
+	align-items: flex-end;
+}
+
+.chat-custom-text {
+	font-size: 12px;
+	color: #999;
+}
+
+```
+
+## API
+
+### List Props
+
+属性名			|类型		|默认值		|	说明																									
+:-:				|:-:		|:-:		|	:-:	
+border			|Boolean	|true		|	是否显示边框
+
+
+### ListItem Props
+
+属性名			|类型		|默认值		|	说明																					
+:-:				|:-:		|:-:		|	:-:	
+title			|String		|-			|	标题
+note			|String		|-			|	描述
+ellipsis		|Number		|0			|	title 是否溢出隐藏,可选值,0:默认;  1:显示一行;	2:显示两行;【nvue 暂不支持】
+thumb			|String		|-			|	左侧缩略图,若thumb有值,则不会显示扩展图标
+thumbSize		|String 	|medium 	|	略缩图尺寸,可选值,lg:大图;  medium:一般;	sm:小图;
+showBadge		|Boolean	|false		|	是否显示数字角标	
+badgeText		|String		|-			|	数字角标内容
+badgeType		|String		|-			|	数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)	
+badgeStyle  |Object   |-      | 数字角标样式,使用uni-badge的custom-style参数
+rightText		|String		|-			|	右侧文字内容
+disabled		|Boolean	|false		|	是否禁用	
+showArrow 		|Boolean	|true		|	是否显示箭头图标			
+link			|String 	|navigateTo	|	新页面跳转方式,可选值见下表
+to				|String		|-			|	新页面跳转地址,如填写此属性,click 会返回页面是否跳转成功			
+clickable		|Boolean	|false		|	是否开启点击反馈
+showSwitch	    |Boolean	|false		|	是否显示Switch																			
+switchChecked	|Boolean	|false		|	Switch是否被选中																			
+showExtraIcon   |Boolean	|false		|	左侧是否显示扩展图标																		
+extraIcon		|Object		|-			|	扩展图标参数,格式为 ``{color: '#4cd964',size: '22',type: 'spinner'}``,参考 [uni-icons](https://ext.dcloud.net.cn/plugin?id=28)	
+direction		| String	|row		|	排版方向,可选值,row:水平排列;  column:垂直排列; 3个插槽是水平排还是垂直排,也受此属性控制
+
+
+#### Link Options
+
+属性名				|	说明
+:-:					|	:-:
+navigateTo 	| 	同 uni.navigateTo()
+redirectTo 	|	同 uni.reLaunch()
+reLaunch		|	同 uni.reLaunch()
+switchTab  	|	同 uni.switchTab()
+
+### ListItem Events
+
+事件称名			|说明									|返回参数			
+:-:				|:-:									|:-:				
+click			|点击 uniListItem 触发事件,需开启点击反馈	|-					
+switchChange	|点击切换 Switch 时触发,需显示 switch		|e={value:checked}	
+
+
+
+### ListItem Slots
+
+名称	 	|	说明					
+:-:		|	:-:						
+header	|	左/上内容插槽,可完全自定义默认显示
+body	|	中间内容插槽,可完全自定义中间内容				
+footer	|	右/下内容插槽,可完全自定义右侧内容		
+
+
+> **通过插槽扩展**
+> 需要注意的是当使用插槽时,内置样式将会失效,只保留排版样式,此时的样式需要开发者自己实现
+> 如果	`uni-list-item` 组件内置属性样式无法满足需求,可以使用插槽来自定义uni-list-item里的内容。
+> uni-list-item提供了3个可扩展的插槽:`header`、`body`、`footer`
+> - 当 `direction` 属性为 `row` 时表示水平排列,此时 `header` 表示列表的左边部分,`body` 表示列表的中间部分,`footer` 表示列表的右边部分
+> - 当 `direction` 属性为 `column` 时表示垂直排列,此时 `header` 表示列表的上边部分,`body` 表示列表的中间部分,`footer` 表示列表的下边部分
+> 开发者可以只用1个插槽,也可以3个一起使用。在插槽中可自主编写view标签,实现自己所需的效果。
+
+	
+**示例**
+
+```html
+<uni-list>
+	<uni-list-item title="自定义右侧插槽" note="列表描述信息" link>
+		<template slot="header">
+			<image class="slot-image" src="/static/logo.png" mode="widthFix"></image>
+		</template>
+	</uni-list-item>
+	<uni-list-item>
+		<!-- 自定义 header -->
+		<view slot="header" class="slot-box"><image class="slot-image" src="/static/logo.png" mode="widthFix"></image></view>
+		<!-- 自定义 body -->
+		<text slot="body" class="slot-box slot-text">自定义插槽</text>
+		<!-- 自定义 footer-->
+		<template slot="footer">
+			<image class="slot-image" src="/static/logo.png" mode="widthFix"></image>
+		</template>
+	</uni-list-item>
+</uni-list>
+```
+
+
+
+
+
+### ListItemChat Props
+
+属性名			|类型		|默认值		|	说明																		
+:-:				|:-:		|:-:		|	:-:	
+title 			|String		|-			|	标题
+note 			|String		|-			|	描述
+clickable		|Boolean	|false		|	是否开启点击反馈
+badgeText		|String		|-			|	数字角标内容,设置为 `dot` 将显示圆点
+badgePositon 	|String		|right		|	角标位置
+link			|String 	|navigateTo	|	是否展示右侧箭头并开启点击反馈,可选值见下表
+clickable		|Boolean	|false		|	是否开启点击反馈
+to				|String		|-			|	跳转页面地址,如填写此属性,click 会返回页面是否跳转成功	
+time			|String 	|-			|	右侧时间显示
+avatarCircle 	|Boolean 	|false		|	是否显示圆形头像
+avatar			|String 	|-			|	头像地址,avatarCircle 不填时生效
+avatarList 		|Array	 	|-			|	头像组,格式为 [{url:''}]
+
+#### Link Options
+
+属性名		|	说明
+:-:			|	:-:
+navigateTo 	| 	同 uni.navigateTo()
+redirectTo 	|	同 uni.reLaunch()
+reLaunch	|	同 uni.reLaunch()
+switchTab  	|	同 uni.switchTab()
+
+### ListItemChat Slots
+
+名称	 	|	说明					
+:-		|	:-						
+default	|	自定义列表右侧内容(包括时间和角标显示)
+
+### ListItemChat Events
+事件称名			|	说明						|	返回参数			
+:-:				|	:-:						|	:-:	
+@click			|	点击 uniListChat 触发事件	|	{data:{}}	,如有 to 属性,会返回页面跳转信息	
+
+
+
+
+
+
+## 基于uni-list扩展的页面模板
+
+通过扩展插槽,可实现多种常见样式的列表
+
+**新闻列表类**
+
+1. 云端一体混合布局:[https://ext.dcloud.net.cn/plugin?id=2546](https://ext.dcloud.net.cn/plugin?id=2546)
+2. 云端一体垂直布局,大图模式:[https://ext.dcloud.net.cn/plugin?id=2583](https://ext.dcloud.net.cn/plugin?id=2583)
+3. 云端一体垂直布局,多行图文混排:[https://ext.dcloud.net.cn/plugin?id=2584](https://ext.dcloud.net.cn/plugin?id=2584)
+4. 云端一体垂直布局,多图模式:[https://ext.dcloud.net.cn/plugin?id=2585](https://ext.dcloud.net.cn/plugin?id=2585)
+5. 云端一体水平布局,左图右文:[https://ext.dcloud.net.cn/plugin?id=2586](https://ext.dcloud.net.cn/plugin?id=2586)
+6. 云端一体水平布局,左文右图:[https://ext.dcloud.net.cn/plugin?id=2587](https://ext.dcloud.net.cn/plugin?id=2587)
+7. 云端一体垂直布局,无图模式,主标题+副标题:[https://ext.dcloud.net.cn/plugin?id=2588](https://ext.dcloud.net.cn/plugin?id=2588)
+
+**商品列表类**
+
+1. 云端一体列表/宫格视图互切:[https://ext.dcloud.net.cn/plugin?id=2651](https://ext.dcloud.net.cn/plugin?id=2651)
+2. 云端一体列表(宫格模式):[https://ext.dcloud.net.cn/plugin?id=2671](https://ext.dcloud.net.cn/plugin?id=2671)
+3. 云端一体列表(列表模式):[https://ext.dcloud.net.cn/plugin?id=2672](https://ext.dcloud.net.cn/plugin?id=2672)
+
+## 组件示例
+
+点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/list/list](https://hellouniapp.dcloud.net.cn/pages/extUI/list/list)