commit 8a250d974ffc23db60854c827a9b1aecd00ff6ce
Author: liudan <18634735655@163.com>
Date: Tue Dec 10 19:29:15 2024 +0800
1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..17fa7b4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/unpackage
+/utils/request-1.js
diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json
new file mode 100644
index 0000000..a7540fc
--- /dev/null
+++ b/.hbuilderx/launch.json
@@ -0,0 +1,28 @@
+{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+ // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+ "version": "0.0",
+ "configurations": [{
+ "app-plus" :
+ {
+ "launchtype" : "remote"
+ },
+ "default" :
+ {
+ "launchtype" : "remote"
+ },
+ "h5" :
+ {
+ "launchtype" : "remote"
+ },
+ "mp-alipay" :
+ {
+ "launchtype" : "remote"
+ },
+ "mp-weixin" :
+ {
+ "launchtype" : "remote"
+ },
+ "type" : "uniCloud"
+ }
+ ]
+}
diff --git a/.vite/deps/_metadata.json b/.vite/deps/_metadata.json
new file mode 100644
index 0000000..19e020d
--- /dev/null
+++ b/.vite/deps/_metadata.json
@@ -0,0 +1,13 @@
+{
+ "hash": "4ae7f80a",
+ "browserHash": "741dc287",
+ "optimized": {
+ "weixin-js-sdk": {
+ "src": "../../node_modules/weixin-js-sdk/index.js",
+ "file": "weixin-js-sdk.js",
+ "fileHash": "8d88497e",
+ "needsInterop": true
+ }
+ },
+ "chunks": {}
+}
\ No newline at end of file
diff --git a/.vite/deps/package.json b/.vite/deps/package.json
new file mode 100644
index 0000000..7c34deb
--- /dev/null
+++ b/.vite/deps/package.json
@@ -0,0 +1 @@
+{"type":"module"}
\ No newline at end of file
diff --git a/.vite/deps/weixin-js-sdk.js b/.vite/deps/weixin-js-sdk.js
new file mode 100644
index 0000000..b1c90eb
--- /dev/null
+++ b/.vite/deps/weixin-js-sdk.js
@@ -0,0 +1,766 @@
+var __getOwnPropNames = Object.getOwnPropertyNames;
+var __commonJS = (cb, mod) => function __require() {
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
+};
+
+// ../../../../www/@hbuilder/yoshop2-pro/node_modules/weixin-js-sdk/index.js
+var require_weixin_js_sdk = __commonJS({
+ "../../../../www/@hbuilder/yoshop2-pro/node_modules/weixin-js-sdk/index.js"(exports, module) {
+ !function(e, n) {
+ module.exports = n(e);
+ }(window, function(o, e) {
+ if (!o.jWeixin) {
+ var n, c = {
+ config: "preVerifyJSAPI",
+ onMenuShareTimeline: "menu:share:timeline",
+ onMenuShareAppMessage: "menu:share:appmessage",
+ onMenuShareQQ: "menu:share:qq",
+ onMenuShareWeibo: "menu:share:weiboApp",
+ onMenuShareQZone: "menu:share:QZone",
+ previewImage: "imagePreview",
+ getLocation: "geoLocation",
+ openProductSpecificView: "openProductViewWithPid",
+ addCard: "batchAddCard",
+ openCard: "batchViewCard",
+ chooseWXPay: "getBrandWCPayRequest",
+ openEnterpriseRedPacket: "getRecevieBizHongBaoRequest",
+ startSearchBeacons: "startMonitoringBeacons",
+ stopSearchBeacons: "stopMonitoringBeacons",
+ onSearchBeacons: "onBeaconsInRange",
+ consumeAndShareCard: "consumedShareCard",
+ openAddress: "editAddress"
+ }, a = function() {
+ var e2 = {};
+ for (var n2 in c)
+ e2[c[n2]] = n2;
+ return e2;
+ }(), i = o.document, t = i.title, r = navigator.userAgent.toLowerCase(), s = navigator.platform.toLowerCase(), d = !(!s.match("mac") && !s.match("win")), u = -1 != r.indexOf("wxdebugger"), l = -1 != r.indexOf("micromessenger"), p = -1 != r.indexOf("android"), f = -1 != r.indexOf("iphone") || -1 != r.indexOf("ipad"), m = (n = r.match(/micromessenger\/(\d+\.\d+\.\d+)/) || r.match(/micromessenger\/(\d+\.\d+)/)) ? n[1] : "", g = {
+ initStartTime: L(),
+ initEndTime: 0,
+ preVerifyStartTime: 0,
+ preVerifyEndTime: 0
+ }, h = {
+ version: 1,
+ appId: "",
+ initTime: 0,
+ preVerifyTime: 0,
+ networkType: "",
+ isPreVerifyOk: 1,
+ systemType: f ? 1 : p ? 2 : -1,
+ clientVersion: m,
+ url: encodeURIComponent(location.href)
+ }, v = {}, S = { _completes: [] }, y = { state: 0, data: {} };
+ O(function() {
+ g.initEndTime = L();
+ });
+ var I = false, _ = [], w = {
+ config: function(e2) {
+ B("config", v = e2);
+ var t2 = false !== v.check;
+ O(function() {
+ if (t2)
+ M(
+ c.config,
+ {
+ verifyJsApiList: C(v.jsApiList),
+ verifyOpenTagList: C(v.openTagList)
+ },
+ function() {
+ S._complete = function(e4) {
+ g.preVerifyEndTime = L(), y.state = 1, y.data = e4;
+ }, S.success = function(e4) {
+ h.isPreVerifyOk = 0;
+ }, S.fail = function(e4) {
+ S._fail ? S._fail(e4) : y.state = -1;
+ };
+ var t3 = S._completes;
+ return t3.push(function() {
+ !function() {
+ if (!(d || u || v.debug || m < "6.0.2" || h.systemType < 0)) {
+ var i3 = new Image();
+ h.appId = v.appId, h.initTime = g.initEndTime - g.initStartTime, h.preVerifyTime = g.preVerifyEndTime - g.preVerifyStartTime, w.getNetworkType({
+ isInnerInvoke: true,
+ success: function(e4) {
+ h.networkType = e4.networkType;
+ var n3 = "https://open.weixin.qq.com/sdk/report?v=" + h.version + "&o=" + h.isPreVerifyOk + "&s=" + h.systemType + "&c=" + h.clientVersion + "&a=" + h.appId + "&n=" + h.networkType + "&i=" + h.initTime + "&p=" + h.preVerifyTime + "&u=" + h.url;
+ i3.src = n3;
+ }
+ });
+ }
+ }();
+ }), S.complete = function(e4) {
+ for (var n3 = 0, i3 = t3.length; n3 < i3; ++n3)
+ t3[n3]();
+ S._completes = [];
+ }, S;
+ }()
+ ), g.preVerifyStartTime = L();
+ else {
+ y.state = 1;
+ for (var e3 = S._completes, n2 = 0, i2 = e3.length; n2 < i2; ++n2)
+ e3[n2]();
+ S._completes = [];
+ }
+ }), w.invoke || (w.invoke = function(e3, n2, i2) {
+ o.WeixinJSBridge && WeixinJSBridge.invoke(e3, x(n2), i2);
+ }, w.on = function(e3, n2) {
+ o.WeixinJSBridge && WeixinJSBridge.on(e3, n2);
+ });
+ },
+ ready: function(e2) {
+ 0 != y.state ? e2() : (S._completes.push(e2), !l && v.debug && e2());
+ },
+ error: function(e2) {
+ m < "6.0.2" || (-1 == y.state ? e2(y.data) : S._fail = e2);
+ },
+ checkJsApi: function(e2) {
+ M(
+ "checkJsApi",
+ { jsApiList: C(e2.jsApiList) },
+ (e2._complete = function(e3) {
+ if (p) {
+ var n2 = e3.checkResult;
+ n2 && (e3.checkResult = JSON.parse(n2));
+ }
+ e3 = function(e4) {
+ var n3 = e4.checkResult;
+ for (var i2 in n3) {
+ var t2 = a[i2];
+ t2 && (n3[t2] = n3[i2], delete n3[i2]);
+ }
+ return e4;
+ }(e3);
+ }, e2)
+ );
+ },
+ onMenuShareTimeline: function(e2) {
+ P(
+ c.onMenuShareTimeline,
+ {
+ complete: function() {
+ M(
+ "shareTimeline",
+ {
+ title: e2.title || t,
+ desc: e2.title || t,
+ img_url: e2.imgUrl || "",
+ link: e2.link || location.href,
+ type: e2.type || "link",
+ data_url: e2.dataUrl || ""
+ },
+ e2
+ );
+ }
+ },
+ e2
+ );
+ },
+ onMenuShareAppMessage: function(n2) {
+ P(
+ c.onMenuShareAppMessage,
+ {
+ complete: function(e2) {
+ "favorite" === e2.scene ? M("sendAppMessage", {
+ title: n2.title || t,
+ desc: n2.desc || "",
+ link: n2.link || location.href,
+ img_url: n2.imgUrl || "",
+ type: n2.type || "link",
+ data_url: n2.dataUrl || ""
+ }) : M(
+ "sendAppMessage",
+ {
+ title: n2.title || t,
+ desc: n2.desc || "",
+ link: n2.link || location.href,
+ img_url: n2.imgUrl || "",
+ type: n2.type || "link",
+ data_url: n2.dataUrl || ""
+ },
+ n2
+ );
+ }
+ },
+ n2
+ );
+ },
+ onMenuShareQQ: function(e2) {
+ P(
+ c.onMenuShareQQ,
+ {
+ complete: function() {
+ M(
+ "shareQQ",
+ {
+ title: e2.title || t,
+ desc: e2.desc || "",
+ img_url: e2.imgUrl || "",
+ link: e2.link || location.href
+ },
+ e2
+ );
+ }
+ },
+ e2
+ );
+ },
+ onMenuShareWeibo: function(e2) {
+ P(
+ c.onMenuShareWeibo,
+ {
+ complete: function() {
+ M(
+ "shareWeiboApp",
+ {
+ title: e2.title || t,
+ desc: e2.desc || "",
+ img_url: e2.imgUrl || "",
+ link: e2.link || location.href
+ },
+ e2
+ );
+ }
+ },
+ e2
+ );
+ },
+ onMenuShareQZone: function(e2) {
+ P(
+ c.onMenuShareQZone,
+ {
+ complete: function() {
+ M(
+ "shareQZone",
+ {
+ title: e2.title || t,
+ desc: e2.desc || "",
+ img_url: e2.imgUrl || "",
+ link: e2.link || location.href
+ },
+ e2
+ );
+ }
+ },
+ e2
+ );
+ },
+ updateTimelineShareData: function(e2) {
+ M(
+ "updateTimelineShareData",
+ { title: e2.title, link: e2.link, imgUrl: e2.imgUrl },
+ e2
+ );
+ },
+ updateAppMessageShareData: function(e2) {
+ M(
+ "updateAppMessageShareData",
+ { title: e2.title, desc: e2.desc, link: e2.link, imgUrl: e2.imgUrl },
+ e2
+ );
+ },
+ startRecord: function(e2) {
+ M("startRecord", {}, e2);
+ },
+ stopRecord: function(e2) {
+ M("stopRecord", {}, e2);
+ },
+ onVoiceRecordEnd: function(e2) {
+ P("onVoiceRecordEnd", e2);
+ },
+ playVoice: function(e2) {
+ M("playVoice", { localId: e2.localId }, e2);
+ },
+ pauseVoice: function(e2) {
+ M("pauseVoice", { localId: e2.localId }, e2);
+ },
+ stopVoice: function(e2) {
+ M("stopVoice", { localId: e2.localId }, e2);
+ },
+ onVoicePlayEnd: function(e2) {
+ P("onVoicePlayEnd", e2);
+ },
+ uploadVoice: function(e2) {
+ M(
+ "uploadVoice",
+ {
+ localId: e2.localId,
+ isShowProgressTips: 0 == e2.isShowProgressTips ? 0 : 1
+ },
+ e2
+ );
+ },
+ downloadVoice: function(e2) {
+ M(
+ "downloadVoice",
+ {
+ serverId: e2.serverId,
+ isShowProgressTips: 0 == e2.isShowProgressTips ? 0 : 1
+ },
+ e2
+ );
+ },
+ translateVoice: function(e2) {
+ M(
+ "translateVoice",
+ {
+ localId: e2.localId,
+ isShowProgressTips: 0 == e2.isShowProgressTips ? 0 : 1
+ },
+ e2
+ );
+ },
+ chooseImage: function(e2) {
+ M(
+ "chooseImage",
+ {
+ scene: "1|2",
+ count: e2.count || 9,
+ sizeType: e2.sizeType || ["original", "compressed"],
+ sourceType: e2.sourceType || ["album", "camera"]
+ },
+ (e2._complete = function(e3) {
+ if (p) {
+ var n2 = e3.localIds;
+ try {
+ n2 && (e3.localIds = JSON.parse(n2));
+ } catch (e4) {
+ }
+ }
+ }, e2)
+ );
+ },
+ getLocation: function(e2) {
+ },
+ previewImage: function(e2) {
+ M(c.previewImage, { current: e2.current, urls: e2.urls }, e2);
+ },
+ uploadImage: function(e2) {
+ M(
+ "uploadImage",
+ {
+ localId: e2.localId,
+ isShowProgressTips: 0 == e2.isShowProgressTips ? 0 : 1
+ },
+ e2
+ );
+ },
+ downloadImage: function(e2) {
+ M(
+ "downloadImage",
+ {
+ serverId: e2.serverId,
+ isShowProgressTips: 0 == e2.isShowProgressTips ? 0 : 1
+ },
+ e2
+ );
+ },
+ getLocalImgData: function(e2) {
+ false === I ? (I = true, M(
+ "getLocalImgData",
+ { localId: e2.localId },
+ (e2._complete = function(e3) {
+ if (I = false, 0 < _.length) {
+ var n2 = _.shift();
+ wx.getLocalImgData(n2);
+ }
+ }, e2)
+ )) : _.push(e2);
+ },
+ getNetworkType: function(e2) {
+ M(
+ "getNetworkType",
+ {},
+ (e2._complete = function(e3) {
+ e3 = function(e4) {
+ var n2 = e4.errMsg;
+ e4.errMsg = "getNetworkType:ok";
+ var i2 = e4.subtype;
+ if (delete e4.subtype, i2)
+ e4.networkType = i2;
+ else {
+ var t2 = n2.indexOf(":"), o2 = n2.substring(t2 + 1);
+ switch (o2) {
+ case "wifi":
+ case "edge":
+ case "wwan":
+ e4.networkType = o2;
+ break;
+ default:
+ e4.errMsg = "getNetworkType:fail";
+ }
+ }
+ return e4;
+ }(e3);
+ }, e2)
+ );
+ },
+ openLocation: function(e2) {
+ M(
+ "openLocation",
+ {
+ latitude: e2.latitude,
+ longitude: e2.longitude,
+ name: e2.name || "",
+ address: e2.address || "",
+ scale: e2.scale || 28,
+ infoUrl: e2.infoUrl || ""
+ },
+ e2
+ );
+ },
+ getLocation: function(e2) {
+ M(
+ c.getLocation,
+ { type: (e2 = e2 || {}).type || "wgs84" },
+ (e2._complete = function(e3) {
+ delete e3.type;
+ }, e2)
+ );
+ },
+ hideOptionMenu: function(e2) {
+ M("hideOptionMenu", {}, e2);
+ },
+ showOptionMenu: function(e2) {
+ M("showOptionMenu", {}, e2);
+ },
+ closeWindow: function(e2) {
+ M("closeWindow", {}, e2 = e2 || {});
+ },
+ hideMenuItems: function(e2) {
+ M("hideMenuItems", { menuList: e2.menuList }, e2);
+ },
+ showMenuItems: function(e2) {
+ M("showMenuItems", { menuList: e2.menuList }, e2);
+ },
+ hideAllNonBaseMenuItem: function(e2) {
+ M("hideAllNonBaseMenuItem", {}, e2);
+ },
+ showAllNonBaseMenuItem: function(e2) {
+ M("showAllNonBaseMenuItem", {}, e2);
+ },
+ scanQRCode: function(e2) {
+ M(
+ "scanQRCode",
+ {
+ needResult: (e2 = e2 || {}).needResult || 0,
+ scanType: e2.scanType || ["qrCode", "barCode"]
+ },
+ (e2._complete = function(e3) {
+ if (f) {
+ var n2 = e3.resultStr;
+ if (n2) {
+ var i2 = JSON.parse(n2);
+ e3.resultStr = i2 && i2.scan_code && i2.scan_code.scan_result;
+ }
+ }
+ }, e2)
+ );
+ },
+ openAddress: function(e2) {
+ M(
+ c.openAddress,
+ {},
+ (e2._complete = function(e3) {
+ e3 = function(e4) {
+ return e4.postalCode = e4.addressPostalCode, delete e4.addressPostalCode, e4.provinceName = e4.proviceFirstStageName, delete e4.proviceFirstStageName, e4.cityName = e4.addressCitySecondStageName, delete e4.addressCitySecondStageName, e4.countryName = e4.addressCountiesThirdStageName, delete e4.addressCountiesThirdStageName, e4.detailInfo = e4.addressDetailInfo, delete e4.addressDetailInfo, e4;
+ }(e3);
+ }, e2)
+ );
+ },
+ openProductSpecificView: function(e2) {
+ M(
+ c.openProductSpecificView,
+ {
+ pid: e2.productId,
+ view_type: e2.viewType || 0,
+ ext_info: e2.extInfo
+ },
+ e2
+ );
+ },
+ addCard: function(e2) {
+ for (var n2 = e2.cardList, i2 = [], t2 = 0, o2 = n2.length; t2 < o2; ++t2) {
+ var r2 = n2[t2], a2 = { card_id: r2.cardId, card_ext: r2.cardExt };
+ i2.push(a2);
+ }
+ M(
+ c.addCard,
+ { card_list: i2 },
+ (e2._complete = function(e3) {
+ var n3 = e3.card_list;
+ if (n3) {
+ for (var i3 = 0, t3 = (n3 = JSON.parse(n3)).length; i3 < t3; ++i3) {
+ var o3 = n3[i3];
+ o3.cardId = o3.card_id, o3.cardExt = o3.card_ext, o3.isSuccess = !!o3.is_succ, delete o3.card_id, delete o3.card_ext, delete o3.is_succ;
+ }
+ e3.cardList = n3, delete e3.card_list;
+ }
+ }, e2)
+ );
+ },
+ chooseCard: function(e2) {
+ M(
+ "chooseCard",
+ {
+ app_id: v.appId,
+ location_id: e2.shopId || "",
+ sign_type: e2.signType || "SHA1",
+ card_id: e2.cardId || "",
+ card_type: e2.cardType || "",
+ card_sign: e2.cardSign,
+ time_stamp: e2.timestamp + "",
+ nonce_str: e2.nonceStr
+ },
+ (e2._complete = function(e3) {
+ e3.cardList = e3.choose_card_info, delete e3.choose_card_info;
+ }, e2)
+ );
+ },
+ openCard: function(e2) {
+ for (var n2 = e2.cardList, i2 = [], t2 = 0, o2 = n2.length; t2 < o2; ++t2) {
+ var r2 = n2[t2], a2 = { card_id: r2.cardId, code: r2.code };
+ i2.push(a2);
+ }
+ M(c.openCard, { card_list: i2 }, e2);
+ },
+ consumeAndShareCard: function(e2) {
+ M(
+ c.consumeAndShareCard,
+ { consumedCardId: e2.cardId, consumedCode: e2.code },
+ e2
+ );
+ },
+ chooseWXPay: function(e2) {
+ M(c.chooseWXPay, V(e2), e2);
+ },
+ openEnterpriseRedPacket: function(e2) {
+ M(c.openEnterpriseRedPacket, V(e2), e2);
+ },
+ startSearchBeacons: function(e2) {
+ M(c.startSearchBeacons, { ticket: e2.ticket }, e2);
+ },
+ stopSearchBeacons: function(e2) {
+ M(c.stopSearchBeacons, {}, e2);
+ },
+ onSearchBeacons: function(e2) {
+ P(c.onSearchBeacons, e2);
+ },
+ openEnterpriseChat: function(e2) {
+ M(
+ "openEnterpriseChat",
+ { useridlist: e2.userIds, chatname: e2.groupName },
+ e2
+ );
+ },
+ launchMiniProgram: function(e2) {
+ M(
+ "launchMiniProgram",
+ {
+ targetAppId: e2.targetAppId,
+ path: function(e3) {
+ if ("string" == typeof e3 && 0 < e3.length) {
+ var n2 = e3.split("?")[0], i2 = e3.split("?")[1];
+ return n2 += ".html", void 0 !== i2 ? n2 + "?" + i2 : n2;
+ }
+ }(e2.path),
+ envVersion: e2.envVersion
+ },
+ e2
+ );
+ },
+ openBusinessView: function(e2) {
+ M(
+ "openBusinessView",
+ {
+ businessType: e2.businessType,
+ queryString: e2.queryString || "",
+ envVersion: e2.envVersion
+ },
+ (e2._complete = function(n2) {
+ if (p) {
+ var e3 = n2.extraData;
+ if (e3)
+ try {
+ n2.extraData = JSON.parse(e3);
+ } catch (e4) {
+ n2.extraData = {};
+ }
+ }
+ }, e2)
+ );
+ },
+ miniProgram: {
+ navigateBack: function(e2) {
+ e2 = e2 || {}, O(function() {
+ M(
+ "invokeMiniProgramAPI",
+ { name: "navigateBack", arg: { delta: e2.delta || 1 } },
+ e2
+ );
+ });
+ },
+ navigateTo: function(e2) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI",
+ { name: "navigateTo", arg: { url: e2.url } },
+ e2
+ );
+ });
+ },
+ redirectTo: function(e2) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI",
+ { name: "redirectTo", arg: { url: e2.url } },
+ e2
+ );
+ });
+ },
+ switchTab: function(e2) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI",
+ { name: "switchTab", arg: { url: e2.url } },
+ e2
+ );
+ });
+ },
+ reLaunch: function(e2) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI",
+ { name: "reLaunch", arg: { url: e2.url } },
+ e2
+ );
+ });
+ },
+ postMessage: function(e2) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI",
+ { name: "postMessage", arg: e2.data || {} },
+ e2
+ );
+ });
+ },
+ getEnv: function(e2) {
+ O(function() {
+ e2({ miniprogram: "miniprogram" === o.__wxjs_environment });
+ });
+ }
+ }
+ }, T = 1, k = {};
+ return i.addEventListener(
+ "error",
+ function(e2) {
+ if (!p) {
+ var n2 = e2.target, i2 = n2.tagName, t2 = n2.src;
+ if ("IMG" == i2 || "VIDEO" == i2 || "AUDIO" == i2 || "SOURCE" == i2) {
+ if (-1 != t2.indexOf("wxlocalresource://")) {
+ e2.preventDefault(), e2.stopPropagation();
+ var o2 = n2["wx-id"];
+ if (o2 || (o2 = T++, n2["wx-id"] = o2), k[o2])
+ return;
+ k[o2] = true, wx.ready(function() {
+ wx.getLocalImgData({
+ localId: t2,
+ success: function(e3) {
+ n2.src = e3.localData;
+ }
+ });
+ });
+ }
+ }
+ }
+ },
+ true
+ ), i.addEventListener(
+ "load",
+ function(e2) {
+ if (!p) {
+ var n2 = e2.target, i2 = n2.tagName;
+ n2.src;
+ if ("IMG" == i2 || "VIDEO" == i2 || "AUDIO" == i2 || "SOURCE" == i2) {
+ var t2 = n2["wx-id"];
+ t2 && (k[t2] = false);
+ }
+ }
+ },
+ true
+ ), e && (o.wx = o.jWeixin = w), w;
+ }
+ function M(n2, e2, i2) {
+ o.WeixinJSBridge ? WeixinJSBridge.invoke(n2, x(e2), function(e3) {
+ A(n2, e3, i2);
+ }) : B(n2, i2);
+ }
+ function P(n2, i2, t2) {
+ o.WeixinJSBridge ? WeixinJSBridge.on(n2, function(e2) {
+ t2 && t2.trigger && t2.trigger(e2), A(n2, e2, i2);
+ }) : B(n2, t2 || i2);
+ }
+ function x(e2) {
+ return (e2 = e2 || {}).appId = v.appId, e2.verifyAppId = v.appId, e2.verifySignType = "sha1", e2.verifyTimestamp = v.timestamp + "", e2.verifyNonceStr = v.nonceStr, e2.verifySignature = v.signature, e2;
+ }
+ function V(e2) {
+ return {
+ timeStamp: e2.timestamp + "",
+ nonceStr: e2.nonceStr,
+ package: e2.package,
+ paySign: e2.paySign,
+ signType: e2.signType || "SHA1"
+ };
+ }
+ function A(e2, n2, i2) {
+ "openEnterpriseChat" != e2 && "openBusinessView" !== e2 || (n2.errCode = n2.err_code), delete n2.err_code, delete n2.err_desc, delete n2.err_detail;
+ var t2 = n2.errMsg;
+ t2 || (t2 = n2.err_msg, delete n2.err_msg, t2 = function(e3, n3) {
+ var i3 = e3, t3 = a[i3];
+ t3 && (i3 = t3);
+ var o3 = "ok";
+ if (n3) {
+ var r2 = n3.indexOf(":");
+ "confirm" == (o3 = n3.substring(r2 + 1)) && (o3 = "ok"), "failed" == o3 && (o3 = "fail"), -1 != o3.indexOf("failed_") && (o3 = o3.substring(7)), -1 != o3.indexOf("fail_") && (o3 = o3.substring(5)), "access denied" != (o3 = (o3 = o3.replace(/_/g, " ")).toLowerCase()) && "no permission to execute" != o3 || (o3 = "permission denied"), "config" == i3 && "function not exist" == o3 && (o3 = "ok"), "" == o3 && (o3 = "fail");
+ }
+ return n3 = i3 + ":" + o3;
+ }(e2, t2), n2.errMsg = t2), (i2 = i2 || {})._complete && (i2._complete(n2), delete i2._complete), t2 = n2.errMsg || "", v.debug && !i2.isInnerInvoke && alert(JSON.stringify(n2));
+ var o2 = t2.indexOf(":");
+ switch (t2.substring(o2 + 1)) {
+ case "ok":
+ i2.success && i2.success(n2);
+ break;
+ case "cancel":
+ i2.cancel && i2.cancel(n2);
+ break;
+ default:
+ i2.fail && i2.fail(n2);
+ }
+ i2.complete && i2.complete(n2);
+ }
+ function C(e2) {
+ if (e2) {
+ for (var n2 = 0, i2 = e2.length; n2 < i2; ++n2) {
+ var t2 = e2[n2], o2 = c[t2];
+ o2 && (e2[n2] = o2);
+ }
+ return e2;
+ }
+ }
+ function B(e2, n2) {
+ if (!(!v.debug || n2 && n2.isInnerInvoke)) {
+ var i2 = a[e2];
+ i2 && (e2 = i2), n2 && n2._complete && delete n2._complete, console.log('"' + e2 + '",', n2 || "");
+ }
+ }
+ function L() {
+ return new Date().getTime();
+ }
+ function O(e2) {
+ l && (o.WeixinJSBridge ? e2() : i.addEventListener && i.addEventListener("WeixinJSBridgeReady", e2, false));
+ }
+ });
+ }
+});
+export default require_weixin_js_sdk();
+//# sourceMappingURL=weixin-js-sdk.js.map
diff --git a/.vite/deps/weixin-js-sdk.js.map b/.vite/deps/weixin-js-sdk.js.map
new file mode 100644
index 0000000..c349744
--- /dev/null
+++ b/.vite/deps/weixin-js-sdk.js.map
@@ -0,0 +1,7 @@
+{
+ "version": 3,
+ "sources": ["../../node_modules/weixin-js-sdk/index.js"],
+ "sourcesContent": ["!(function(e, n) {\n module.exports = n(e);\n})(window, function(o, e) {\n if (!o.jWeixin) {\n var n,\n c = {\n config: \"preVerifyJSAPI\",\n onMenuShareTimeline: \"menu:share:timeline\",\n onMenuShareAppMessage: \"menu:share:appmessage\",\n onMenuShareQQ: \"menu:share:qq\",\n onMenuShareWeibo: \"menu:share:weiboApp\",\n onMenuShareQZone: \"menu:share:QZone\",\n previewImage: \"imagePreview\",\n getLocation: \"geoLocation\",\n openProductSpecificView: \"openProductViewWithPid\",\n addCard: \"batchAddCard\",\n openCard: \"batchViewCard\",\n chooseWXPay: \"getBrandWCPayRequest\",\n openEnterpriseRedPacket: \"getRecevieBizHongBaoRequest\",\n startSearchBeacons: \"startMonitoringBeacons\",\n stopSearchBeacons: \"stopMonitoringBeacons\",\n onSearchBeacons: \"onBeaconsInRange\",\n consumeAndShareCard: \"consumedShareCard\",\n openAddress: \"editAddress\"\n },\n a = (function() {\n var e = {};\n for (var n in c) e[c[n]] = n;\n return e;\n })(),\n i = o.document,\n t = i.title,\n r = navigator.userAgent.toLowerCase(),\n s = navigator.platform.toLowerCase(),\n d = !(!s.match(\"mac\") && !s.match(\"win\")),\n u = -1 != r.indexOf(\"wxdebugger\"),\n l = -1 != r.indexOf(\"micromessenger\"),\n p = -1 != r.indexOf(\"android\"),\n f = -1 != r.indexOf(\"iphone\") || -1 != r.indexOf(\"ipad\"),\n m = (n =\n r.match(/micromessenger\\/(\\d+\\.\\d+\\.\\d+)/) ||\n r.match(/micromessenger\\/(\\d+\\.\\d+)/))\n ? n[1]\n : \"\",\n g = {\n initStartTime: L(),\n initEndTime: 0,\n preVerifyStartTime: 0,\n preVerifyEndTime: 0\n },\n h = {\n version: 1,\n appId: \"\",\n initTime: 0,\n preVerifyTime: 0,\n networkType: \"\",\n isPreVerifyOk: 1,\n systemType: f ? 1 : p ? 2 : -1,\n clientVersion: m,\n url: encodeURIComponent(location.href)\n },\n v = {},\n S = { _completes: [] },\n y = { state: 0, data: {} };\n O(function() {\n g.initEndTime = L();\n });\n var I = !1,\n _ = [],\n w = {\n config: function(e) {\n B(\"config\", (v = e));\n var t = !1 !== v.check;\n O(function() {\n if (t)\n M(\n c.config,\n {\n verifyJsApiList: C(v.jsApiList),\n verifyOpenTagList: C(v.openTagList)\n },\n (function() {\n (S._complete = function(e) {\n (g.preVerifyEndTime = L()), (y.state = 1), (y.data = e);\n }),\n (S.success = function(e) {\n h.isPreVerifyOk = 0;\n }),\n (S.fail = function(e) {\n S._fail ? S._fail(e) : (y.state = -1);\n });\n var t = S._completes;\n return (\n t.push(function() {\n !(function() {\n if (\n !(\n d ||\n u ||\n v.debug ||\n m < \"6.0.2\" ||\n h.systemType < 0\n )\n ) {\n var i = new Image();\n (h.appId = v.appId),\n (h.initTime = g.initEndTime - g.initStartTime),\n (h.preVerifyTime =\n g.preVerifyEndTime - g.preVerifyStartTime),\n w.getNetworkType({\n isInnerInvoke: !0,\n success: function(e) {\n h.networkType = e.networkType;\n var n =\n \"https://open.weixin.qq.com/sdk/report?v=\" +\n h.version +\n \"&o=\" +\n h.isPreVerifyOk +\n \"&s=\" +\n h.systemType +\n \"&c=\" +\n h.clientVersion +\n \"&a=\" +\n h.appId +\n \"&n=\" +\n h.networkType +\n \"&i=\" +\n h.initTime +\n \"&p=\" +\n h.preVerifyTime +\n \"&u=\" +\n h.url;\n i.src = n;\n }\n });\n }\n })();\n }),\n (S.complete = function(e) {\n for (var n = 0, i = t.length; n < i; ++n) t[n]();\n S._completes = [];\n }),\n S\n );\n })()\n ),\n (g.preVerifyStartTime = L());\n else {\n y.state = 1;\n for (var e = S._completes, n = 0, i = e.length; n < i; ++n)\n e[n]();\n S._completes = [];\n }\n }),\n w.invoke ||\n ((w.invoke = function(e, n, i) {\n o.WeixinJSBridge && WeixinJSBridge.invoke(e, x(n), i);\n }),\n (w.on = function(e, n) {\n o.WeixinJSBridge && WeixinJSBridge.on(e, n);\n }));\n },\n ready: function(e) {\n 0 != y.state ? e() : (S._completes.push(e), !l && v.debug && e());\n },\n error: function(e) {\n m < \"6.0.2\" || (-1 == y.state ? e(y.data) : (S._fail = e));\n },\n checkJsApi: function(e) {\n M(\n \"checkJsApi\",\n { jsApiList: C(e.jsApiList) },\n ((e._complete = function(e) {\n if (p) {\n var n = e.checkResult;\n n && (e.checkResult = JSON.parse(n));\n }\n e = (function(e) {\n var n = e.checkResult;\n for (var i in n) {\n var t = a[i];\n t && ((n[t] = n[i]), delete n[i]);\n }\n return e;\n })(e);\n }),\n e)\n );\n },\n onMenuShareTimeline: function(e) {\n P(\n c.onMenuShareTimeline,\n {\n complete: function() {\n M(\n \"shareTimeline\",\n {\n title: e.title || t,\n desc: e.title || t,\n img_url: e.imgUrl || \"\",\n link: e.link || location.href,\n type: e.type || \"link\",\n data_url: e.dataUrl || \"\"\n },\n e\n );\n }\n },\n e\n );\n },\n onMenuShareAppMessage: function(n) {\n P(\n c.onMenuShareAppMessage,\n {\n complete: function(e) {\n \"favorite\" === e.scene\n ? M(\"sendAppMessage\", {\n title: n.title || t,\n desc: n.desc || \"\",\n link: n.link || location.href,\n img_url: n.imgUrl || \"\",\n type: n.type || \"link\",\n data_url: n.dataUrl || \"\"\n })\n : M(\n \"sendAppMessage\",\n {\n title: n.title || t,\n desc: n.desc || \"\",\n link: n.link || location.href,\n img_url: n.imgUrl || \"\",\n type: n.type || \"link\",\n data_url: n.dataUrl || \"\"\n },\n n\n );\n }\n },\n n\n );\n },\n onMenuShareQQ: function(e) {\n P(\n c.onMenuShareQQ,\n {\n complete: function() {\n M(\n \"shareQQ\",\n {\n title: e.title || t,\n desc: e.desc || \"\",\n img_url: e.imgUrl || \"\",\n link: e.link || location.href\n },\n e\n );\n }\n },\n e\n );\n },\n onMenuShareWeibo: function(e) {\n P(\n c.onMenuShareWeibo,\n {\n complete: function() {\n M(\n \"shareWeiboApp\",\n {\n title: e.title || t,\n desc: e.desc || \"\",\n img_url: e.imgUrl || \"\",\n link: e.link || location.href\n },\n e\n );\n }\n },\n e\n );\n },\n onMenuShareQZone: function(e) {\n P(\n c.onMenuShareQZone,\n {\n complete: function() {\n M(\n \"shareQZone\",\n {\n title: e.title || t,\n desc: e.desc || \"\",\n img_url: e.imgUrl || \"\",\n link: e.link || location.href\n },\n e\n );\n }\n },\n e\n );\n },\n updateTimelineShareData: function(e) {\n M(\n \"updateTimelineShareData\",\n { title: e.title, link: e.link, imgUrl: e.imgUrl },\n e\n );\n },\n updateAppMessageShareData: function(e) {\n M(\n \"updateAppMessageShareData\",\n { title: e.title, desc: e.desc, link: e.link, imgUrl: e.imgUrl },\n e\n );\n },\n startRecord: function(e) {\n M(\"startRecord\", {}, e);\n },\n stopRecord: function(e) {\n M(\"stopRecord\", {}, e);\n },\n onVoiceRecordEnd: function(e) {\n P(\"onVoiceRecordEnd\", e);\n },\n playVoice: function(e) {\n M(\"playVoice\", { localId: e.localId }, e);\n },\n pauseVoice: function(e) {\n M(\"pauseVoice\", { localId: e.localId }, e);\n },\n stopVoice: function(e) {\n M(\"stopVoice\", { localId: e.localId }, e);\n },\n onVoicePlayEnd: function(e) {\n P(\"onVoicePlayEnd\", e);\n },\n uploadVoice: function(e) {\n M(\n \"uploadVoice\",\n {\n localId: e.localId,\n isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1\n },\n e\n );\n },\n downloadVoice: function(e) {\n M(\n \"downloadVoice\",\n {\n serverId: e.serverId,\n isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1\n },\n e\n );\n },\n translateVoice: function(e) {\n M(\n \"translateVoice\",\n {\n localId: e.localId,\n isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1\n },\n e\n );\n },\n chooseImage: function(e) {\n M(\n \"chooseImage\",\n {\n scene: \"1|2\",\n count: e.count || 9,\n sizeType: e.sizeType || [\"original\", \"compressed\"],\n sourceType: e.sourceType || [\"album\", \"camera\"]\n },\n ((e._complete = function(e) {\n if (p) {\n var n = e.localIds;\n try {\n n && (e.localIds = JSON.parse(n));\n } catch (e) {}\n }\n }),\n e)\n );\n },\n getLocation: function(e) {},\n previewImage: function(e) {\n M(c.previewImage, { current: e.current, urls: e.urls }, e);\n },\n uploadImage: function(e) {\n M(\n \"uploadImage\",\n {\n localId: e.localId,\n isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1\n },\n e\n );\n },\n downloadImage: function(e) {\n M(\n \"downloadImage\",\n {\n serverId: e.serverId,\n isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1\n },\n e\n );\n },\n getLocalImgData: function(e) {\n !1 === I\n ? ((I = !0),\n M(\n \"getLocalImgData\",\n { localId: e.localId },\n ((e._complete = function(e) {\n if (((I = !1), 0 < _.length)) {\n var n = _.shift();\n wx.getLocalImgData(n);\n }\n }),\n e)\n ))\n : _.push(e);\n },\n getNetworkType: function(e) {\n M(\n \"getNetworkType\",\n {},\n ((e._complete = function(e) {\n e = (function(e) {\n var n = e.errMsg;\n e.errMsg = \"getNetworkType:ok\";\n var i = e.subtype;\n if ((delete e.subtype, i)) e.networkType = i;\n else {\n var t = n.indexOf(\":\"),\n o = n.substring(t + 1);\n switch (o) {\n case \"wifi\":\n case \"edge\":\n case \"wwan\":\n e.networkType = o;\n break;\n default:\n e.errMsg = \"getNetworkType:fail\";\n }\n }\n return e;\n })(e);\n }),\n e)\n );\n },\n openLocation: function(e) {\n M(\n \"openLocation\",\n {\n latitude: e.latitude,\n longitude: e.longitude,\n name: e.name || \"\",\n address: e.address || \"\",\n scale: e.scale || 28,\n infoUrl: e.infoUrl || \"\"\n },\n e\n );\n },\n getLocation: function(e) {\n M(\n c.getLocation,\n { type: (e = e || {}).type || \"wgs84\" },\n ((e._complete = function(e) {\n delete e.type;\n }),\n e)\n );\n },\n hideOptionMenu: function(e) {\n M(\"hideOptionMenu\", {}, e);\n },\n showOptionMenu: function(e) {\n M(\"showOptionMenu\", {}, e);\n },\n closeWindow: function(e) {\n M(\"closeWindow\", {}, (e = e || {}));\n },\n hideMenuItems: function(e) {\n M(\"hideMenuItems\", { menuList: e.menuList }, e);\n },\n showMenuItems: function(e) {\n M(\"showMenuItems\", { menuList: e.menuList }, e);\n },\n hideAllNonBaseMenuItem: function(e) {\n M(\"hideAllNonBaseMenuItem\", {}, e);\n },\n showAllNonBaseMenuItem: function(e) {\n M(\"showAllNonBaseMenuItem\", {}, e);\n },\n scanQRCode: function(e) {\n M(\n \"scanQRCode\",\n {\n needResult: (e = e || {}).needResult || 0,\n scanType: e.scanType || [\"qrCode\", \"barCode\"]\n },\n ((e._complete = function(e) {\n if (f) {\n var n = e.resultStr;\n if (n) {\n var i = JSON.parse(n);\n e.resultStr = i && i.scan_code && i.scan_code.scan_result;\n }\n }\n }),\n e)\n );\n },\n openAddress: function(e) {\n M(\n c.openAddress,\n {},\n ((e._complete = function(e) {\n e = (function(e) {\n return (\n (e.postalCode = e.addressPostalCode),\n delete e.addressPostalCode,\n (e.provinceName = e.proviceFirstStageName),\n delete e.proviceFirstStageName,\n (e.cityName = e.addressCitySecondStageName),\n delete e.addressCitySecondStageName,\n (e.countryName = e.addressCountiesThirdStageName),\n delete e.addressCountiesThirdStageName,\n (e.detailInfo = e.addressDetailInfo),\n delete e.addressDetailInfo,\n e\n );\n })(e);\n }),\n e)\n );\n },\n openProductSpecificView: function(e) {\n M(\n c.openProductSpecificView,\n {\n pid: e.productId,\n view_type: e.viewType || 0,\n ext_info: e.extInfo\n },\n e\n );\n },\n addCard: function(e) {\n for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {\n var r = n[t],\n a = { card_id: r.cardId, card_ext: r.cardExt };\n i.push(a);\n }\n M(\n c.addCard,\n { card_list: i },\n ((e._complete = function(e) {\n var n = e.card_list;\n if (n) {\n for (var i = 0, t = (n = JSON.parse(n)).length; i < t; ++i) {\n var o = n[i];\n (o.cardId = o.card_id),\n (o.cardExt = o.card_ext),\n (o.isSuccess = !!o.is_succ),\n delete o.card_id,\n delete o.card_ext,\n delete o.is_succ;\n }\n (e.cardList = n), delete e.card_list;\n }\n }),\n e)\n );\n },\n chooseCard: function(e) {\n M(\n \"chooseCard\",\n {\n app_id: v.appId,\n location_id: e.shopId || \"\",\n sign_type: e.signType || \"SHA1\",\n card_id: e.cardId || \"\",\n card_type: e.cardType || \"\",\n card_sign: e.cardSign,\n time_stamp: e.timestamp + \"\",\n nonce_str: e.nonceStr\n },\n ((e._complete = function(e) {\n (e.cardList = e.choose_card_info), delete e.choose_card_info;\n }),\n e)\n );\n },\n openCard: function(e) {\n for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {\n var r = n[t],\n a = { card_id: r.cardId, code: r.code };\n i.push(a);\n }\n M(c.openCard, { card_list: i }, e);\n },\n consumeAndShareCard: function(e) {\n M(\n c.consumeAndShareCard,\n { consumedCardId: e.cardId, consumedCode: e.code },\n e\n );\n },\n chooseWXPay: function(e) {\n M(c.chooseWXPay, V(e), e);\n },\n openEnterpriseRedPacket: function(e) {\n M(c.openEnterpriseRedPacket, V(e), e);\n },\n startSearchBeacons: function(e) {\n M(c.startSearchBeacons, { ticket: e.ticket }, e);\n },\n stopSearchBeacons: function(e) {\n M(c.stopSearchBeacons, {}, e);\n },\n onSearchBeacons: function(e) {\n P(c.onSearchBeacons, e);\n },\n openEnterpriseChat: function(e) {\n M(\n \"openEnterpriseChat\",\n { useridlist: e.userIds, chatname: e.groupName },\n e\n );\n },\n launchMiniProgram: function(e) {\n M(\n \"launchMiniProgram\",\n {\n targetAppId: e.targetAppId,\n path: (function(e) {\n if (\"string\" == typeof e && 0 < e.length) {\n var n = e.split(\"?\")[0],\n i = e.split(\"?\")[1];\n return (n += \".html\"), void 0 !== i ? n + \"?\" + i : n;\n }\n })(e.path),\n envVersion: e.envVersion\n },\n e\n );\n },\n openBusinessView: function(e) {\n M(\n \"openBusinessView\",\n {\n businessType: e.businessType,\n queryString: e.queryString || \"\",\n envVersion: e.envVersion\n },\n ((e._complete = function(n) {\n if (p) {\n var e = n.extraData;\n if (e)\n try {\n n.extraData = JSON.parse(e);\n } catch (e) {\n n.extraData = {};\n }\n }\n }),\n e)\n );\n },\n miniProgram: {\n navigateBack: function(e) {\n (e = e || {}),\n O(function() {\n M(\n \"invokeMiniProgramAPI\",\n { name: \"navigateBack\", arg: { delta: e.delta || 1 } },\n e\n );\n });\n },\n navigateTo: function(e) {\n O(function() {\n M(\n \"invokeMiniProgramAPI\",\n { name: \"navigateTo\", arg: { url: e.url } },\n e\n );\n });\n },\n redirectTo: function(e) {\n O(function() {\n M(\n \"invokeMiniProgramAPI\",\n { name: \"redirectTo\", arg: { url: e.url } },\n e\n );\n });\n },\n switchTab: function(e) {\n O(function() {\n M(\n \"invokeMiniProgramAPI\",\n { name: \"switchTab\", arg: { url: e.url } },\n e\n );\n });\n },\n reLaunch: function(e) {\n O(function() {\n M(\n \"invokeMiniProgramAPI\",\n { name: \"reLaunch\", arg: { url: e.url } },\n e\n );\n });\n },\n postMessage: function(e) {\n O(function() {\n M(\n \"invokeMiniProgramAPI\",\n { name: \"postMessage\", arg: e.data || {} },\n e\n );\n });\n },\n getEnv: function(e) {\n O(function() {\n e({ miniprogram: \"miniprogram\" === o.__wxjs_environment });\n });\n }\n }\n },\n T = 1,\n k = {};\n return (\n i.addEventListener(\n \"error\",\n function(e) {\n if (!p) {\n var n = e.target,\n i = n.tagName,\n t = n.src;\n if (\"IMG\" == i || \"VIDEO\" == i || \"AUDIO\" == i || \"SOURCE\" == i)\n if (-1 != t.indexOf(\"wxlocalresource://\")) {\n e.preventDefault(), e.stopPropagation();\n var o = n[\"wx-id\"];\n if ((o || ((o = T++), (n[\"wx-id\"] = o)), k[o])) return;\n (k[o] = !0),\n wx.ready(function() {\n wx.getLocalImgData({\n localId: t,\n success: function(e) {\n n.src = e.localData;\n }\n });\n });\n }\n }\n },\n !0\n ),\n i.addEventListener(\n \"load\",\n function(e) {\n if (!p) {\n var n = e.target,\n i = n.tagName;\n n.src;\n if (\"IMG\" == i || \"VIDEO\" == i || \"AUDIO\" == i || \"SOURCE\" == i) {\n var t = n[\"wx-id\"];\n t && (k[t] = !1);\n }\n }\n },\n !0\n ),\n e && (o.wx = o.jWeixin = w),\n w\n );\n }\n function M(n, e, i) {\n o.WeixinJSBridge\n ? WeixinJSBridge.invoke(n, x(e), function(e) {\n A(n, e, i);\n })\n : B(n, i);\n }\n function P(n, i, t) {\n o.WeixinJSBridge\n ? WeixinJSBridge.on(n, function(e) {\n t && t.trigger && t.trigger(e), A(n, e, i);\n })\n : B(n, t || i);\n }\n function x(e) {\n return (\n ((e = e || {}).appId = v.appId),\n (e.verifyAppId = v.appId),\n (e.verifySignType = \"sha1\"),\n (e.verifyTimestamp = v.timestamp + \"\"),\n (e.verifyNonceStr = v.nonceStr),\n (e.verifySignature = v.signature),\n e\n );\n }\n function V(e) {\n return {\n timeStamp: e.timestamp + \"\",\n nonceStr: e.nonceStr,\n package: e.package,\n paySign: e.paySign,\n signType: e.signType || \"SHA1\"\n };\n }\n function A(e, n, i) {\n (\"openEnterpriseChat\" != e && \"openBusinessView\" !== e) ||\n (n.errCode = n.err_code),\n delete n.err_code,\n delete n.err_desc,\n delete n.err_detail;\n var t = n.errMsg;\n t ||\n ((t = n.err_msg),\n delete n.err_msg,\n (t = (function(e, n) {\n var i = e,\n t = a[i];\n t && (i = t);\n var o = \"ok\";\n if (n) {\n var r = n.indexOf(\":\");\n \"confirm\" == (o = n.substring(r + 1)) && (o = \"ok\"),\n \"failed\" == o && (o = \"fail\"),\n -1 != o.indexOf(\"failed_\") && (o = o.substring(7)),\n -1 != o.indexOf(\"fail_\") && (o = o.substring(5)),\n (\"access denied\" !=\n (o = (o = o.replace(/_/g, \" \")).toLowerCase()) &&\n \"no permission to execute\" != o) ||\n (o = \"permission denied\"),\n \"config\" == i && \"function not exist\" == o && (o = \"ok\"),\n \"\" == o && (o = \"fail\");\n }\n return (n = i + \":\" + o);\n })(e, t)),\n (n.errMsg = t)),\n (i = i || {})._complete && (i._complete(n), delete i._complete),\n (t = n.errMsg || \"\"),\n v.debug && !i.isInnerInvoke && alert(JSON.stringify(n));\n var o = t.indexOf(\":\");\n switch (t.substring(o + 1)) {\n case \"ok\":\n i.success && i.success(n);\n break;\n case \"cancel\":\n i.cancel && i.cancel(n);\n break;\n default:\n i.fail && i.fail(n);\n }\n i.complete && i.complete(n);\n }\n function C(e) {\n if (e) {\n for (var n = 0, i = e.length; n < i; ++n) {\n var t = e[n],\n o = c[t];\n o && (e[n] = o);\n }\n return e;\n }\n }\n function B(e, n) {\n if (!(!v.debug || (n && n.isInnerInvoke))) {\n var i = a[e];\n i && (e = i),\n n && n._complete && delete n._complete,\n console.log('\"' + e + '\",', n || \"\");\n }\n }\n function L() {\n return new Date().getTime();\n }\n function O(e) {\n l &&\n (o.WeixinJSBridge\n ? e()\n : i.addEventListener &&\n i.addEventListener(\"WeixinJSBridgeReady\", e, !1));\n }\n});\n"],
+ "mappings": ";;;;;;AAAA;AAAA;AAAA,KAAE,SAAS,GAAG,GAAG;AACf,aAAO,UAAU,EAAE,CAAC;AAAA,IACtB,EAAG,QAAQ,SAAS,GAAG,GAAG;AACxB,UAAI,CAAC,EAAE,SAAS;AACd,YAAI,GACF,IAAI;AAAA,UACF,QAAQ;AAAA,UACR,qBAAqB;AAAA,UACrB,uBAAuB;AAAA,UACvB,eAAe;AAAA,UACf,kBAAkB;AAAA,UAClB,kBAAkB;AAAA,UAClB,cAAc;AAAA,UACd,aAAa;AAAA,UACb,yBAAyB;AAAA,UACzB,SAAS;AAAA,UACT,UAAU;AAAA,UACV,aAAa;AAAA,UACb,yBAAyB;AAAA,UACzB,oBAAoB;AAAA,UACpB,mBAAmB;AAAA,UACnB,iBAAiB;AAAA,UACjB,qBAAqB;AAAA,UACrB,aAAa;AAAA,QACf,GACA,IAAK,WAAW;AACd,cAAIA,KAAI,CAAC;AACT,mBAASC,MAAK;AAAG,YAAAD,GAAE,EAAEC,EAAC,CAAC,IAAIA;AAC3B,iBAAOD;AAAA,QACT,EAAG,GACH,IAAI,EAAE,UACN,IAAI,EAAE,OACN,IAAI,UAAU,UAAU,YAAY,GACpC,IAAI,UAAU,SAAS,YAAY,GACnC,IAAI,EAAE,CAAC,EAAE,MAAM,KAAK,KAAK,CAAC,EAAE,MAAM,KAAK,IACvC,IAAI,MAAM,EAAE,QAAQ,YAAY,GAChC,IAAI,MAAM,EAAE,QAAQ,gBAAgB,GACpC,IAAI,MAAM,EAAE,QAAQ,SAAS,GAC7B,IAAI,MAAM,EAAE,QAAQ,QAAQ,KAAK,MAAM,EAAE,QAAQ,MAAM,GACvD,KAAK,IACH,EAAE,MAAM,iCAAiC,KACzC,EAAE,MAAM,4BAA4B,KAClC,EAAE,CAAC,IACH,IACJ,IAAI;AAAA,UACF,eAAe,EAAE;AAAA,UACjB,aAAa;AAAA,UACb,oBAAoB;AAAA,UACpB,kBAAkB;AAAA,QACpB,GACA,IAAI;AAAA,UACF,SAAS;AAAA,UACT,OAAO;AAAA,UACP,UAAU;AAAA,UACV,eAAe;AAAA,UACf,aAAa;AAAA,UACb,eAAe;AAAA,UACf,YAAY,IAAI,IAAI,IAAI,IAAI;AAAA,UAC5B,eAAe;AAAA,UACf,KAAK,mBAAmB,SAAS,IAAI;AAAA,QACvC,GACA,IAAI,CAAC,GACL,IAAI,EAAE,YAAY,CAAC,EAAE,GACrB,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,EAAE;AAC3B,UAAE,WAAW;AACX,YAAE,cAAc,EAAE;AAAA,QACpB,CAAC;AACD,YAAI,IAAI,OACN,IAAI,CAAC,GACL,IAAI;AAAA,UACF,QAAQ,SAASA,IAAG;AAClB,cAAE,UAAW,IAAIA,EAAE;AACnB,gBAAIE,KAAI,UAAO,EAAE;AACjB,cAAE,WAAW;AACX,kBAAIA;AACF;AAAA,kBACE,EAAE;AAAA,kBACF;AAAA,oBACE,iBAAiB,EAAE,EAAE,SAAS;AAAA,oBAC9B,mBAAmB,EAAE,EAAE,WAAW;AAAA,kBACpC;AAAA,kBACC,WAAW;AACV,oBAAC,EAAE,YAAY,SAASF,IAAG;AACzB,sBAAC,EAAE,mBAAmB,EAAE,GAAK,EAAE,QAAQ,GAAK,EAAE,OAAOA;AAAA,oBACvD,GACG,EAAE,UAAU,SAASA,IAAG;AACvB,wBAAE,gBAAgB;AAAA,oBACpB,GACC,EAAE,OAAO,SAASA,IAAG;AACpB,wBAAE,QAAQ,EAAE,MAAMA,EAAC,IAAK,EAAE,QAAQ;AAAA,oBACpC;AACF,wBAAIE,KAAI,EAAE;AACV,2BACEA,GAAE,KAAK,WAAW;AAChB,uBAAE,WAAW;AACX,4BACE,EACE,KACA,KACA,EAAE,SACF,IAAI,WACJ,EAAE,aAAa,IAEjB;AACA,8BAAIC,KAAI,IAAI,MAAM;AAClB,0BAAC,EAAE,QAAQ,EAAE,OACV,EAAE,WAAW,EAAE,cAAc,EAAE,eAC/B,EAAE,gBACD,EAAE,mBAAmB,EAAE,oBACzB,EAAE,eAAe;AAAA,4BACf,eAAe;AAAA,4BACf,SAAS,SAASH,IAAG;AACnB,gCAAE,cAAcA,GAAE;AAClB,kCAAIC,KACF,6CACA,EAAE,UACF,QACA,EAAE,gBACF,QACA,EAAE,aACF,QACA,EAAE,gBACF,QACA,EAAE,QACF,QACA,EAAE,cACF,QACA,EAAE,WACF,QACA,EAAE,gBACF,QACA,EAAE;AACJ,8BAAAE,GAAE,MAAMF;AAAA,4BACV;AAAA,0BACF,CAAC;AAAA,wBACL;AAAA,sBACF,EAAG;AAAA,oBACL,CAAC,GACA,EAAE,WAAW,SAASD,IAAG;AACxB,+BAASC,KAAI,GAAGE,KAAID,GAAE,QAAQD,KAAIE,IAAG,EAAEF;AAAG,wBAAAC,GAAED,EAAC,EAAE;AAC/C,wBAAE,aAAa,CAAC;AAAA,oBAClB,GACA;AAAA,kBAEJ,EAAG;AAAA,gBACL,GACG,EAAE,qBAAqB,EAAE;AAAA,mBACzB;AACH,kBAAE,QAAQ;AACV,yBAASD,KAAI,EAAE,YAAYC,KAAI,GAAGE,KAAIH,GAAE,QAAQC,KAAIE,IAAG,EAAEF;AACvD,kBAAAD,GAAEC,EAAC,EAAE;AACP,kBAAE,aAAa,CAAC;AAAA,cAClB;AAAA,YACF,CAAC,GACC,EAAE,WACE,EAAE,SAAS,SAASD,IAAGC,IAAGE,IAAG;AAC7B,gBAAE,kBAAkB,eAAe,OAAOH,IAAG,EAAEC,EAAC,GAAGE,EAAC;AAAA,YACtD,GACC,EAAE,KAAK,SAASH,IAAGC,IAAG;AACrB,gBAAE,kBAAkB,eAAe,GAAGD,IAAGC,EAAC;AAAA,YAC5C;AAAA,UACN;AAAA,UACA,OAAO,SAASD,IAAG;AACjB,iBAAK,EAAE,QAAQA,GAAE,KAAK,EAAE,WAAW,KAAKA,EAAC,GAAG,CAAC,KAAK,EAAE,SAASA,GAAE;AAAA,UACjE;AAAA,UACA,OAAO,SAASA,IAAG;AACjB,gBAAI,YAAY,MAAM,EAAE,QAAQA,GAAE,EAAE,IAAI,IAAK,EAAE,QAAQA;AAAA,UACzD;AAAA,UACA,YAAY,SAASA,IAAG;AACtB;AAAA,cACE;AAAA,cACA,EAAE,WAAW,EAAEA,GAAE,SAAS,EAAE;AAAA,eAC1BA,GAAE,YAAY,SAASA,IAAG;AAC1B,oBAAI,GAAG;AACL,sBAAIC,KAAID,GAAE;AACV,kBAAAC,OAAMD,GAAE,cAAc,KAAK,MAAMC,EAAC;AAAA,gBACpC;AACA,gBAAAD,KAAK,SAASA,IAAG;AACf,sBAAIC,KAAID,GAAE;AACV,2BAASG,MAAKF,IAAG;AACf,wBAAIC,KAAI,EAAEC,EAAC;AACX,oBAAAD,OAAOD,GAAEC,EAAC,IAAID,GAAEE,EAAC,GAAI,OAAOF,GAAEE,EAAC;AAAA,kBACjC;AACA,yBAAOH;AAAA,gBACT,EAAGA,EAAC;AAAA,cACN,GACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,qBAAqB,SAASA,IAAG;AAC/B;AAAA,cACE,EAAE;AAAA,cACF;AAAA,gBACE,UAAU,WAAW;AACnB;AAAA,oBACE;AAAA,oBACA;AAAA,sBACE,OAAOA,GAAE,SAAS;AAAA,sBAClB,MAAMA,GAAE,SAAS;AAAA,sBACjB,SAASA,GAAE,UAAU;AAAA,sBACrB,MAAMA,GAAE,QAAQ,SAAS;AAAA,sBACzB,MAAMA,GAAE,QAAQ;AAAA,sBAChB,UAAUA,GAAE,WAAW;AAAA,oBACzB;AAAA,oBACAA;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,uBAAuB,SAASC,IAAG;AACjC;AAAA,cACE,EAAE;AAAA,cACF;AAAA,gBACE,UAAU,SAASD,IAAG;AACpB,iCAAeA,GAAE,QACb,EAAE,kBAAkB;AAAA,oBAClB,OAAOC,GAAE,SAAS;AAAA,oBAClB,MAAMA,GAAE,QAAQ;AAAA,oBAChB,MAAMA,GAAE,QAAQ,SAAS;AAAA,oBACzB,SAASA,GAAE,UAAU;AAAA,oBACrB,MAAMA,GAAE,QAAQ;AAAA,oBAChB,UAAUA,GAAE,WAAW;AAAA,kBACzB,CAAC,IACD;AAAA,oBACE;AAAA,oBACA;AAAA,sBACE,OAAOA,GAAE,SAAS;AAAA,sBAClB,MAAMA,GAAE,QAAQ;AAAA,sBAChB,MAAMA,GAAE,QAAQ,SAAS;AAAA,sBACzB,SAASA,GAAE,UAAU;AAAA,sBACrB,MAAMA,GAAE,QAAQ;AAAA,sBAChB,UAAUA,GAAE,WAAW;AAAA,oBACzB;AAAA,oBACAA;AAAA,kBACF;AAAA,gBACN;AAAA,cACF;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,eAAe,SAASD,IAAG;AACzB;AAAA,cACE,EAAE;AAAA,cACF;AAAA,gBACE,UAAU,WAAW;AACnB;AAAA,oBACE;AAAA,oBACA;AAAA,sBACE,OAAOA,GAAE,SAAS;AAAA,sBAClB,MAAMA,GAAE,QAAQ;AAAA,sBAChB,SAASA,GAAE,UAAU;AAAA,sBACrB,MAAMA,GAAE,QAAQ,SAAS;AAAA,oBAC3B;AAAA,oBACAA;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,kBAAkB,SAASA,IAAG;AAC5B;AAAA,cACE,EAAE;AAAA,cACF;AAAA,gBACE,UAAU,WAAW;AACnB;AAAA,oBACE;AAAA,oBACA;AAAA,sBACE,OAAOA,GAAE,SAAS;AAAA,sBAClB,MAAMA,GAAE,QAAQ;AAAA,sBAChB,SAASA,GAAE,UAAU;AAAA,sBACrB,MAAMA,GAAE,QAAQ,SAAS;AAAA,oBAC3B;AAAA,oBACAA;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,kBAAkB,SAASA,IAAG;AAC5B;AAAA,cACE,EAAE;AAAA,cACF;AAAA,gBACE,UAAU,WAAW;AACnB;AAAA,oBACE;AAAA,oBACA;AAAA,sBACE,OAAOA,GAAE,SAAS;AAAA,sBAClB,MAAMA,GAAE,QAAQ;AAAA,sBAChB,SAASA,GAAE,UAAU;AAAA,sBACrB,MAAMA,GAAE,QAAQ,SAAS;AAAA,oBAC3B;AAAA,oBACAA;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,yBAAyB,SAASA,IAAG;AACnC;AAAA,cACE;AAAA,cACA,EAAE,OAAOA,GAAE,OAAO,MAAMA,GAAE,MAAM,QAAQA,GAAE,OAAO;AAAA,cACjDA;AAAA,YACF;AAAA,UACF;AAAA,UACA,2BAA2B,SAASA,IAAG;AACrC;AAAA,cACE;AAAA,cACA,EAAE,OAAOA,GAAE,OAAO,MAAMA,GAAE,MAAM,MAAMA,GAAE,MAAM,QAAQA,GAAE,OAAO;AAAA,cAC/DA;AAAA,YACF;AAAA,UACF;AAAA,UACA,aAAa,SAASA,IAAG;AACvB,cAAE,eAAe,CAAC,GAAGA,EAAC;AAAA,UACxB;AAAA,UACA,YAAY,SAASA,IAAG;AACtB,cAAE,cAAc,CAAC,GAAGA,EAAC;AAAA,UACvB;AAAA,UACA,kBAAkB,SAASA,IAAG;AAC5B,cAAE,oBAAoBA,EAAC;AAAA,UACzB;AAAA,UACA,WAAW,SAASA,IAAG;AACrB,cAAE,aAAa,EAAE,SAASA,GAAE,QAAQ,GAAGA,EAAC;AAAA,UAC1C;AAAA,UACA,YAAY,SAASA,IAAG;AACtB,cAAE,cAAc,EAAE,SAASA,GAAE,QAAQ,GAAGA,EAAC;AAAA,UAC3C;AAAA,UACA,WAAW,SAASA,IAAG;AACrB,cAAE,aAAa,EAAE,SAASA,GAAE,QAAQ,GAAGA,EAAC;AAAA,UAC1C;AAAA,UACA,gBAAgB,SAASA,IAAG;AAC1B,cAAE,kBAAkBA,EAAC;AAAA,UACvB;AAAA,UACA,aAAa,SAASA,IAAG;AACvB;AAAA,cACE;AAAA,cACA;AAAA,gBACE,SAASA,GAAE;AAAA,gBACX,oBAAoB,KAAKA,GAAE,qBAAqB,IAAI;AAAA,cACtD;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,eAAe,SAASA,IAAG;AACzB;AAAA,cACE;AAAA,cACA;AAAA,gBACE,UAAUA,GAAE;AAAA,gBACZ,oBAAoB,KAAKA,GAAE,qBAAqB,IAAI;AAAA,cACtD;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,gBAAgB,SAASA,IAAG;AAC1B;AAAA,cACE;AAAA,cACA;AAAA,gBACE,SAASA,GAAE;AAAA,gBACX,oBAAoB,KAAKA,GAAE,qBAAqB,IAAI;AAAA,cACtD;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,aAAa,SAASA,IAAG;AACvB;AAAA,cACE;AAAA,cACA;AAAA,gBACE,OAAO;AAAA,gBACP,OAAOA,GAAE,SAAS;AAAA,gBAClB,UAAUA,GAAE,YAAY,CAAC,YAAY,YAAY;AAAA,gBACjD,YAAYA,GAAE,cAAc,CAAC,SAAS,QAAQ;AAAA,cAChD;AAAA,eACEA,GAAE,YAAY,SAASA,IAAG;AAC1B,oBAAI,GAAG;AACL,sBAAIC,KAAID,GAAE;AACV,sBAAI;AACF,oBAAAC,OAAMD,GAAE,WAAW,KAAK,MAAMC,EAAC;AAAA,kBACjC,SAASD,IAAP;AAAA,kBAAW;AAAA,gBACf;AAAA,cACF,GACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,aAAa,SAASA,IAAG;AAAA,UAAC;AAAA,UAC1B,cAAc,SAASA,IAAG;AACxB,cAAE,EAAE,cAAc,EAAE,SAASA,GAAE,SAAS,MAAMA,GAAE,KAAK,GAAGA,EAAC;AAAA,UAC3D;AAAA,UACA,aAAa,SAASA,IAAG;AACvB;AAAA,cACE;AAAA,cACA;AAAA,gBACE,SAASA,GAAE;AAAA,gBACX,oBAAoB,KAAKA,GAAE,qBAAqB,IAAI;AAAA,cACtD;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,eAAe,SAASA,IAAG;AACzB;AAAA,cACE;AAAA,cACA;AAAA,gBACE,UAAUA,GAAE;AAAA,gBACZ,oBAAoB,KAAKA,GAAE,qBAAqB,IAAI;AAAA,cACtD;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,iBAAiB,SAASA,IAAG;AAC3B,sBAAO,KACD,IAAI,MACN;AAAA,cACE;AAAA,cACA,EAAE,SAASA,GAAE,QAAQ;AAAA,eACnBA,GAAE,YAAY,SAASA,IAAG;AAC1B,oBAAM,IAAI,OAAK,IAAI,EAAE,QAAS;AAC5B,sBAAIC,KAAI,EAAE,MAAM;AAChB,qBAAG,gBAAgBA,EAAC;AAAA,gBACtB;AAAA,cACF,GACAD;AAAA,YACF,KACA,EAAE,KAAKA,EAAC;AAAA,UACd;AAAA,UACA,gBAAgB,SAASA,IAAG;AAC1B;AAAA,cACE;AAAA,cACA,CAAC;AAAA,eACCA,GAAE,YAAY,SAASA,IAAG;AAC1B,gBAAAA,KAAK,SAASA,IAAG;AACf,sBAAIC,KAAID,GAAE;AACV,kBAAAA,GAAE,SAAS;AACX,sBAAIG,KAAIH,GAAE;AACV,sBAAK,OAAOA,GAAE,SAASG;AAAI,oBAAAH,GAAE,cAAcG;AAAA,uBACtC;AACH,wBAAID,KAAID,GAAE,QAAQ,GAAG,GACnBG,KAAIH,GAAE,UAAUC,KAAI,CAAC;AACvB,4BAAQE,IAAG;AAAA,sBACT,KAAK;AAAA,sBACL,KAAK;AAAA,sBACL,KAAK;AACH,wBAAAJ,GAAE,cAAcI;AAChB;AAAA,sBACF;AACE,wBAAAJ,GAAE,SAAS;AAAA,oBACf;AAAA,kBACF;AACA,yBAAOA;AAAA,gBACT,EAAGA,EAAC;AAAA,cACN,GACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,cAAc,SAASA,IAAG;AACxB;AAAA,cACE;AAAA,cACA;AAAA,gBACE,UAAUA,GAAE;AAAA,gBACZ,WAAWA,GAAE;AAAA,gBACb,MAAMA,GAAE,QAAQ;AAAA,gBAChB,SAASA,GAAE,WAAW;AAAA,gBACtB,OAAOA,GAAE,SAAS;AAAA,gBAClB,SAASA,GAAE,WAAW;AAAA,cACxB;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,aAAa,SAASA,IAAG;AACvB;AAAA,cACE,EAAE;AAAA,cACF,EAAE,OAAOA,KAAIA,MAAK,CAAC,GAAG,QAAQ,QAAQ;AAAA,eACpCA,GAAE,YAAY,SAASA,IAAG;AAC1B,uBAAOA,GAAE;AAAA,cACX,GACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,gBAAgB,SAASA,IAAG;AAC1B,cAAE,kBAAkB,CAAC,GAAGA,EAAC;AAAA,UAC3B;AAAA,UACA,gBAAgB,SAASA,IAAG;AAC1B,cAAE,kBAAkB,CAAC,GAAGA,EAAC;AAAA,UAC3B;AAAA,UACA,aAAa,SAASA,IAAG;AACvB,cAAE,eAAe,CAAC,GAAIA,KAAIA,MAAK,CAAC,CAAE;AAAA,UACpC;AAAA,UACA,eAAe,SAASA,IAAG;AACzB,cAAE,iBAAiB,EAAE,UAAUA,GAAE,SAAS,GAAGA,EAAC;AAAA,UAChD;AAAA,UACA,eAAe,SAASA,IAAG;AACzB,cAAE,iBAAiB,EAAE,UAAUA,GAAE,SAAS,GAAGA,EAAC;AAAA,UAChD;AAAA,UACA,wBAAwB,SAASA,IAAG;AAClC,cAAE,0BAA0B,CAAC,GAAGA,EAAC;AAAA,UACnC;AAAA,UACA,wBAAwB,SAASA,IAAG;AAClC,cAAE,0BAA0B,CAAC,GAAGA,EAAC;AAAA,UACnC;AAAA,UACA,YAAY,SAASA,IAAG;AACtB;AAAA,cACE;AAAA,cACA;AAAA,gBACE,aAAaA,KAAIA,MAAK,CAAC,GAAG,cAAc;AAAA,gBACxC,UAAUA,GAAE,YAAY,CAAC,UAAU,SAAS;AAAA,cAC9C;AAAA,eACEA,GAAE,YAAY,SAASA,IAAG;AAC1B,oBAAI,GAAG;AACL,sBAAIC,KAAID,GAAE;AACV,sBAAIC,IAAG;AACL,wBAAIE,KAAI,KAAK,MAAMF,EAAC;AACpB,oBAAAD,GAAE,YAAYG,MAAKA,GAAE,aAAaA,GAAE,UAAU;AAAA,kBAChD;AAAA,gBACF;AAAA,cACF,GACAH;AAAA,YACF;AAAA,UACF;AAAA,UACA,aAAa,SAASA,IAAG;AACvB;AAAA,cACE,EAAE;AAAA,cACF,CAAC;AAAA,eACCA,GAAE,YAAY,SAASA,IAAG;AAC1B,gBAAAA,KAAK,SAASA,IAAG;AACf,yBACGA,GAAE,aAAaA,GAAE,mBAClB,OAAOA,GAAE,mBACRA,GAAE,eAAeA,GAAE,uBACpB,OAAOA,GAAE,uBACRA,GAAE,WAAWA,GAAE,4BAChB,OAAOA,GAAE,4BACRA,GAAE,cAAcA,GAAE,+BACnB,OAAOA,GAAE,+BACRA,GAAE,aAAaA,GAAE,mBAClB,OAAOA,GAAE,mBACTA;AAAA,gBAEJ,EAAGA,EAAC;AAAA,cACN,GACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,yBAAyB,SAASA,IAAG;AACnC;AAAA,cACE,EAAE;AAAA,cACF;AAAA,gBACE,KAAKA,GAAE;AAAA,gBACP,WAAWA,GAAE,YAAY;AAAA,gBACzB,UAAUA,GAAE;AAAA,cACd;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,SAAS,SAASA,IAAG;AACnB,qBAASC,KAAID,GAAE,UAAUG,KAAI,CAAC,GAAGD,KAAI,GAAGE,KAAIH,GAAE,QAAQC,KAAIE,IAAG,EAAEF,IAAG;AAChE,kBAAIG,KAAIJ,GAAEC,EAAC,GACTI,KAAI,EAAE,SAASD,GAAE,QAAQ,UAAUA,GAAE,QAAQ;AAC/C,cAAAF,GAAE,KAAKG,EAAC;AAAA,YACV;AACA;AAAA,cACE,EAAE;AAAA,cACF,EAAE,WAAWH,GAAE;AAAA,eACbH,GAAE,YAAY,SAASA,IAAG;AAC1B,oBAAIC,KAAID,GAAE;AACV,oBAAIC,IAAG;AACL,2BAASE,KAAI,GAAGD,MAAKD,KAAI,KAAK,MAAMA,EAAC,GAAG,QAAQE,KAAID,IAAG,EAAEC,IAAG;AAC1D,wBAAIC,KAAIH,GAAEE,EAAC;AACX,oBAACC,GAAE,SAASA,GAAE,SACXA,GAAE,UAAUA,GAAE,UACdA,GAAE,YAAY,CAAC,CAACA,GAAE,SACnB,OAAOA,GAAE,SACT,OAAOA,GAAE,UACT,OAAOA,GAAE;AAAA,kBACb;AACA,kBAACJ,GAAE,WAAWC,IAAI,OAAOD,GAAE;AAAA,gBAC7B;AAAA,cACF,GACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,YAAY,SAASA,IAAG;AACtB;AAAA,cACE;AAAA,cACA;AAAA,gBACE,QAAQ,EAAE;AAAA,gBACV,aAAaA,GAAE,UAAU;AAAA,gBACzB,WAAWA,GAAE,YAAY;AAAA,gBACzB,SAASA,GAAE,UAAU;AAAA,gBACrB,WAAWA,GAAE,YAAY;AAAA,gBACzB,WAAWA,GAAE;AAAA,gBACb,YAAYA,GAAE,YAAY;AAAA,gBAC1B,WAAWA,GAAE;AAAA,cACf;AAAA,eACEA,GAAE,YAAY,SAASA,IAAG;AAC1B,gBAACA,GAAE,WAAWA,GAAE,kBAAmB,OAAOA,GAAE;AAAA,cAC9C,GACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,UAAU,SAASA,IAAG;AACpB,qBAASC,KAAID,GAAE,UAAUG,KAAI,CAAC,GAAGD,KAAI,GAAGE,KAAIH,GAAE,QAAQC,KAAIE,IAAG,EAAEF,IAAG;AAChE,kBAAIG,KAAIJ,GAAEC,EAAC,GACTI,KAAI,EAAE,SAASD,GAAE,QAAQ,MAAMA,GAAE,KAAK;AACxC,cAAAF,GAAE,KAAKG,EAAC;AAAA,YACV;AACA,cAAE,EAAE,UAAU,EAAE,WAAWH,GAAE,GAAGH,EAAC;AAAA,UACnC;AAAA,UACA,qBAAqB,SAASA,IAAG;AAC/B;AAAA,cACE,EAAE;AAAA,cACF,EAAE,gBAAgBA,GAAE,QAAQ,cAAcA,GAAE,KAAK;AAAA,cACjDA;AAAA,YACF;AAAA,UACF;AAAA,UACA,aAAa,SAASA,IAAG;AACvB,cAAE,EAAE,aAAa,EAAEA,EAAC,GAAGA,EAAC;AAAA,UAC1B;AAAA,UACA,yBAAyB,SAASA,IAAG;AACnC,cAAE,EAAE,yBAAyB,EAAEA,EAAC,GAAGA,EAAC;AAAA,UACtC;AAAA,UACA,oBAAoB,SAASA,IAAG;AAC9B,cAAE,EAAE,oBAAoB,EAAE,QAAQA,GAAE,OAAO,GAAGA,EAAC;AAAA,UACjD;AAAA,UACA,mBAAmB,SAASA,IAAG;AAC7B,cAAE,EAAE,mBAAmB,CAAC,GAAGA,EAAC;AAAA,UAC9B;AAAA,UACA,iBAAiB,SAASA,IAAG;AAC3B,cAAE,EAAE,iBAAiBA,EAAC;AAAA,UACxB;AAAA,UACA,oBAAoB,SAASA,IAAG;AAC9B;AAAA,cACE;AAAA,cACA,EAAE,YAAYA,GAAE,SAAS,UAAUA,GAAE,UAAU;AAAA,cAC/CA;AAAA,YACF;AAAA,UACF;AAAA,UACA,mBAAmB,SAASA,IAAG;AAC7B;AAAA,cACE;AAAA,cACA;AAAA,gBACE,aAAaA,GAAE;AAAA,gBACf,MAAO,SAASA,IAAG;AACjB,sBAAI,YAAY,OAAOA,MAAK,IAAIA,GAAE,QAAQ;AACxC,wBAAIC,KAAID,GAAE,MAAM,GAAG,EAAE,CAAC,GACpBG,KAAIH,GAAE,MAAM,GAAG,EAAE,CAAC;AACpB,2BAAQC,MAAK,SAAU,WAAWE,KAAIF,KAAI,MAAME,KAAIF;AAAA,kBACtD;AAAA,gBACF,EAAGD,GAAE,IAAI;AAAA,gBACT,YAAYA,GAAE;AAAA,cAChB;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAAA,UACA,kBAAkB,SAASA,IAAG;AAC5B;AAAA,cACE;AAAA,cACA;AAAA,gBACE,cAAcA,GAAE;AAAA,gBAChB,aAAaA,GAAE,eAAe;AAAA,gBAC9B,YAAYA,GAAE;AAAA,cAChB;AAAA,eACEA,GAAE,YAAY,SAASC,IAAG;AAC1B,oBAAI,GAAG;AACL,sBAAID,KAAIC,GAAE;AACV,sBAAID;AACF,wBAAI;AACF,sBAAAC,GAAE,YAAY,KAAK,MAAMD,EAAC;AAAA,oBAC5B,SAASA,IAAP;AACA,sBAAAC,GAAE,YAAY,CAAC;AAAA,oBACjB;AAAA,gBACJ;AAAA,cACF,GACAD;AAAA,YACF;AAAA,UACF;AAAA,UACA,aAAa;AAAA,YACX,cAAc,SAASA,IAAG;AACxB,cAACA,KAAIA,MAAK,CAAC,GACT,EAAE,WAAW;AACX;AAAA,kBACE;AAAA,kBACA,EAAE,MAAM,gBAAgB,KAAK,EAAE,OAAOA,GAAE,SAAS,EAAE,EAAE;AAAA,kBACrDA;AAAA,gBACF;AAAA,cACF,CAAC;AAAA,YACL;AAAA,YACA,YAAY,SAASA,IAAG;AACtB,gBAAE,WAAW;AACX;AAAA,kBACE;AAAA,kBACA,EAAE,MAAM,cAAc,KAAK,EAAE,KAAKA,GAAE,IAAI,EAAE;AAAA,kBAC1CA;AAAA,gBACF;AAAA,cACF,CAAC;AAAA,YACH;AAAA,YACA,YAAY,SAASA,IAAG;AACtB,gBAAE,WAAW;AACX;AAAA,kBACE;AAAA,kBACA,EAAE,MAAM,cAAc,KAAK,EAAE,KAAKA,GAAE,IAAI,EAAE;AAAA,kBAC1CA;AAAA,gBACF;AAAA,cACF,CAAC;AAAA,YACH;AAAA,YACA,WAAW,SAASA,IAAG;AACrB,gBAAE,WAAW;AACX;AAAA,kBACE;AAAA,kBACA,EAAE,MAAM,aAAa,KAAK,EAAE,KAAKA,GAAE,IAAI,EAAE;AAAA,kBACzCA;AAAA,gBACF;AAAA,cACF,CAAC;AAAA,YACH;AAAA,YACA,UAAU,SAASA,IAAG;AACpB,gBAAE,WAAW;AACX;AAAA,kBACE;AAAA,kBACA,EAAE,MAAM,YAAY,KAAK,EAAE,KAAKA,GAAE,IAAI,EAAE;AAAA,kBACxCA;AAAA,gBACF;AAAA,cACF,CAAC;AAAA,YACH;AAAA,YACA,aAAa,SAASA,IAAG;AACvB,gBAAE,WAAW;AACX;AAAA,kBACE;AAAA,kBACA,EAAE,MAAM,eAAe,KAAKA,GAAE,QAAQ,CAAC,EAAE;AAAA,kBACzCA;AAAA,gBACF;AAAA,cACF,CAAC;AAAA,YACH;AAAA,YACA,QAAQ,SAASA,IAAG;AAClB,gBAAE,WAAW;AACX,gBAAAA,GAAE,EAAE,aAAa,kBAAkB,EAAE,mBAAmB,CAAC;AAAA,cAC3D,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF,GACA,IAAI,GACJ,IAAI,CAAC;AACP,eACE,EAAE;AAAA,UACA;AAAA,UACA,SAASA,IAAG;AACV,gBAAI,CAAC,GAAG;AACN,kBAAIC,KAAID,GAAE,QACRG,KAAIF,GAAE,SACNC,KAAID,GAAE;AACR,kBAAI,SAASE,MAAK,WAAWA,MAAK,WAAWA,MAAK,YAAYA;AAC5D,oBAAI,MAAMD,GAAE,QAAQ,oBAAoB,GAAG;AACzC,kBAAAF,GAAE,eAAe,GAAGA,GAAE,gBAAgB;AACtC,sBAAII,KAAIH,GAAE,OAAO;AACjB,sBAAKG,OAAOA,KAAI,KAAOH,GAAE,OAAO,IAAIG,KAAK,EAAEA,EAAC;AAAI;AAChD,kBAAC,EAAEA,EAAC,IAAI,MACN,GAAG,MAAM,WAAW;AAClB,uBAAG,gBAAgB;AAAA,sBACjB,SAASF;AAAA,sBACT,SAAS,SAASF,IAAG;AACnB,wBAAAC,GAAE,MAAMD,GAAE;AAAA,sBACZ;AAAA,oBACF,CAAC;AAAA,kBACH,CAAC;AAAA,gBACL;AAAA;AAAA,YACJ;AAAA,UACF;AAAA,UACA;AAAA,QACF,GACA,EAAE;AAAA,UACA;AAAA,UACA,SAASA,IAAG;AACV,gBAAI,CAAC,GAAG;AACN,kBAAIC,KAAID,GAAE,QACRG,KAAIF,GAAE;AACR,cAAAA,GAAE;AACF,kBAAI,SAASE,MAAK,WAAWA,MAAK,WAAWA,MAAK,YAAYA,IAAG;AAC/D,oBAAID,KAAID,GAAE,OAAO;AACjB,gBAAAC,OAAM,EAAEA,EAAC,IAAI;AAAA,cACf;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,QACF,GACA,MAAM,EAAE,KAAK,EAAE,UAAU,IACzB;AAAA,MAEJ;AACA,eAAS,EAAED,IAAGD,IAAGG,IAAG;AAClB,UAAE,iBACE,eAAe,OAAOF,IAAG,EAAED,EAAC,GAAG,SAASA,IAAG;AACzC,YAAEC,IAAGD,IAAGG,EAAC;AAAA,QACX,CAAC,IACD,EAAEF,IAAGE,EAAC;AAAA,MACZ;AACA,eAAS,EAAEF,IAAGE,IAAGD,IAAG;AAClB,UAAE,iBACE,eAAe,GAAGD,IAAG,SAASD,IAAG;AAC/B,UAAAE,MAAKA,GAAE,WAAWA,GAAE,QAAQF,EAAC,GAAG,EAAEC,IAAGD,IAAGG,EAAC;AAAA,QAC3C,CAAC,IACD,EAAEF,IAAGC,MAAKC,EAAC;AAAA,MACjB;AACA,eAAS,EAAEH,IAAG;AACZ,gBACIA,KAAIA,MAAK,CAAC,GAAG,QAAQ,EAAE,OACxBA,GAAE,cAAc,EAAE,OAClBA,GAAE,iBAAiB,QACnBA,GAAE,kBAAkB,EAAE,YAAY,IAClCA,GAAE,iBAAiB,EAAE,UACrBA,GAAE,kBAAkB,EAAE,WACvBA;AAAA,MAEJ;AACA,eAAS,EAAEA,IAAG;AACZ,eAAO;AAAA,UACL,WAAWA,GAAE,YAAY;AAAA,UACzB,UAAUA,GAAE;AAAA,UACZ,SAASA,GAAE;AAAA,UACX,SAASA,GAAE;AAAA,UACX,UAAUA,GAAE,YAAY;AAAA,QAC1B;AAAA,MACF;AACA,eAAS,EAAEA,IAAGC,IAAGE,IAAG;AAClB,QAAC,wBAAwBH,MAAK,uBAAuBA,OAClDC,GAAE,UAAUA,GAAE,WACf,OAAOA,GAAE,UACT,OAAOA,GAAE,UACT,OAAOA,GAAE;AACX,YAAIC,KAAID,GAAE;AACV,QAAAC,OACIA,KAAID,GAAE,SACR,OAAOA,GAAE,SACRC,KAAK,SAASF,IAAGC,IAAG;AACnB,cAAIE,KAAIH,IACNE,KAAI,EAAEC,EAAC;AACT,UAAAD,OAAMC,KAAID;AACV,cAAIE,KAAI;AACR,cAAIH,IAAG;AACL,gBAAII,KAAIJ,GAAE,QAAQ,GAAG;AACrB,0BAAcG,KAAIH,GAAE,UAAUI,KAAI,CAAC,OAAOD,KAAI,OAC5C,YAAYA,OAAMA,KAAI,SACtB,MAAMA,GAAE,QAAQ,SAAS,MAAMA,KAAIA,GAAE,UAAU,CAAC,IAChD,MAAMA,GAAE,QAAQ,OAAO,MAAMA,KAAIA,GAAE,UAAU,CAAC,IAC7C,oBACEA,MAAKA,KAAIA,GAAE,QAAQ,MAAM,GAAG,GAAG,YAAY,MAC5C,8BAA8BA,OAC7BA,KAAI,sBACP,YAAYD,MAAK,wBAAwBC,OAAMA,KAAI,OACnD,MAAMA,OAAMA,KAAI;AAAA,UACpB;AACA,iBAAQH,KAAIE,KAAI,MAAMC;AAAA,QACxB,EAAGJ,IAAGE,EAAC,GACND,GAAE,SAASC,MACXC,KAAIA,MAAK,CAAC,GAAG,cAAcA,GAAE,UAAUF,EAAC,GAAG,OAAOE,GAAE,YACpDD,KAAID,GAAE,UAAU,IACjB,EAAE,SAAS,CAACE,GAAE,iBAAiB,MAAM,KAAK,UAAUF,EAAC,CAAC;AACxD,YAAIG,KAAIF,GAAE,QAAQ,GAAG;AACrB,gBAAQA,GAAE,UAAUE,KAAI,CAAC,GAAG;AAAA,UAC1B,KAAK;AACH,YAAAD,GAAE,WAAWA,GAAE,QAAQF,EAAC;AACxB;AAAA,UACF,KAAK;AACH,YAAAE,GAAE,UAAUA,GAAE,OAAOF,EAAC;AACtB;AAAA,UACF;AACE,YAAAE,GAAE,QAAQA,GAAE,KAAKF,EAAC;AAAA,QACtB;AACA,QAAAE,GAAE,YAAYA,GAAE,SAASF,EAAC;AAAA,MAC5B;AACA,eAAS,EAAED,IAAG;AACZ,YAAIA,IAAG;AACL,mBAASC,KAAI,GAAGE,KAAIH,GAAE,QAAQC,KAAIE,IAAG,EAAEF,IAAG;AACxC,gBAAIC,KAAIF,GAAEC,EAAC,GACTG,KAAI,EAAEF,EAAC;AACT,YAAAE,OAAMJ,GAAEC,EAAC,IAAIG;AAAA,UACf;AACA,iBAAOJ;AAAA,QACT;AAAA,MACF;AACA,eAAS,EAAEA,IAAGC,IAAG;AACf,YAAI,EAAE,CAAC,EAAE,SAAUA,MAAKA,GAAE,gBAAiB;AACzC,cAAIE,KAAI,EAAEH,EAAC;AACX,UAAAG,OAAMH,KAAIG,KACRF,MAAKA,GAAE,aAAa,OAAOA,GAAE,WAC7B,QAAQ,IAAI,MAAMD,KAAI,MAAMC,MAAK,EAAE;AAAA,QACvC;AAAA,MACF;AACA,eAAS,IAAI;AACX,eAAO,IAAI,KAAK,EAAE,QAAQ;AAAA,MAC5B;AACA,eAAS,EAAED,IAAG;AACZ,cACG,EAAE,iBACCA,GAAE,IACF,EAAE,oBACF,EAAE,iBAAiB,uBAAuBA,IAAG,KAAE;AAAA,MACvD;AAAA,IACF,CAAC;AAAA;AAAA;",
+ "names": ["e", "n", "t", "i", "o", "r", "a"]
+}
diff --git a/App.vue b/App.vue
new file mode 100644
index 0000000..9e9216e
--- /dev/null
+++ b/App.vue
@@ -0,0 +1,91 @@
+
+
+
\ No newline at end of file
diff --git a/androidPrivacy.json b/androidPrivacy.json
new file mode 100644
index 0000000..4896361
--- /dev/null
+++ b/androidPrivacy.json
@@ -0,0 +1,14 @@
+{
+ "version" : "1",
+ "prompt" : "template",
+ "title" : "服务协议和隐私政策",
+ "message" : " 请你务必审慎阅读、充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。
你可阅读《服务协议》和《隐私政策》了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。",
+ "buttonAccept" : "同意并接受",
+ "buttonRefuse" : "暂不同意",
+ "second" : {
+ "title" : "确认提示",
+ "message" : " 进入应用前,你需先同意《服务协议》和《隐私政策》,否则将退出应用。",
+ "buttonAccept" : "同意并继续",
+ "buttonRefuse" : "退出应用"
+ }
+}
diff --git a/api/address.js b/api/address.js
new file mode 100644
index 0000000..c646854
--- /dev/null
+++ b/api/address.js
@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'address/list',
+ defaultId: 'address/defaultId',
+ detail: 'address/detail',
+ add: 'address/add',
+ edit: 'address/edit',
+ setDefault: 'address/setDefault',
+ remove: 'address/remove',
+ analysis: 'address/analysis'
+}
+
+// 收货地址列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
+
+// 默认收货地址ID
+export const defaultId = (param) => {
+ return request.get(api.defaultId, param)
+}
+
+// 收货地址详情
+export const detail = (addressId) => {
+ return request.get(api.detail, { addressId })
+}
+
+// 新增收货地址
+export const add = (data) => {
+ return request.post(api.add, { form: data })
+}
+
+// 编辑收货地址
+export const edit = (addressId, data) => {
+ return request.post(api.edit, { addressId, form: data })
+}
+
+// 设置默认收货地址
+export const setDefault = (addressId) => {
+ return request.post(api.setDefault, { addressId })
+}
+
+// 删除收货地址
+export const remove = (addressId) => {
+ return request.post(api.remove, { addressId })
+}
+
+// 收货地址智能解析
+export const analysis = (content) => {
+ return request.get(api.analysis, { content })
+}
\ No newline at end of file
diff --git a/api/article/category.js b/api/article/category.js
new file mode 100644
index 0000000..62e0aeb
--- /dev/null
+++ b/api/article/category.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'article.category/list'
+}
+
+// 页面数据
+export function list() {
+ return request.get(api.list)
+}
diff --git a/api/article/index.js b/api/article/index.js
new file mode 100644
index 0000000..a5411f7
--- /dev/null
+++ b/api/article/index.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'article/list',
+ detail: 'article/detail'
+}
+
+// 文章列表
+export function list(param, option) {
+ return request.get(api.list, param, option)
+}
+
+// 文章详情
+export function detail(articleId) {
+ return request.get(api.detail, { articleId })
+}
diff --git a/api/balance.js b/api/balance.js
new file mode 100644
index 0000000..62b0ef1
--- /dev/null
+++ b/api/balance.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'balance.log/list'
+}
+
+// 余额账单明细列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
diff --git a/api/balance/log.js b/api/balance/log.js
new file mode 100644
index 0000000..153fb2a
--- /dev/null
+++ b/api/balance/log.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'balance.log/list'
+}
+
+// 余额账单明细
+export const list = (param) => {
+ return request.get(api.list, param)
+}
diff --git a/api/bargain/active.js b/api/bargain/active.js
new file mode 100644
index 0000000..6cc8d9e
--- /dev/null
+++ b/api/bargain/active.js
@@ -0,0 +1,23 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'bargain.active/list',
+ detail: 'bargain.active/detail',
+ poster: 'bargain.active/poster'
+}
+
+// 砍价活动会场列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
+
+// 砍价活动详情
+export const detail = (activeId, param) => {
+ return request.get(api.detail, { activeId, ...param })
+}
+
+// 生成商品海报
+export const poster = param => {
+ return request.get(api.poster, param)
+}
diff --git a/api/bargain/checkout.js b/api/bargain/checkout.js
new file mode 100644
index 0000000..b6365e5
--- /dev/null
+++ b/api/bargain/checkout.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ order: 'bargain.checkout/order',
+ submit: 'bargain.checkout/submit'
+}
+
+// 结算台订单信息
+export const order = (mode, param) => {
+ return request.get(api.order, { mode, ...param })
+}
+
+// 结算台订单提交
+export const submit = (mode, data) => {
+ return request.post(api.submit, { mode, ...data }, { isPrompt: false })
+}
diff --git a/api/bargain/task.js b/api/bargain/task.js
new file mode 100644
index 0000000..cd860bc
--- /dev/null
+++ b/api/bargain/task.js
@@ -0,0 +1,35 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'bargain.task/list',
+ partake: 'bargain.task/partake',
+ detail: 'bargain.task/detail',
+ helpList: 'bargain.task/helpList',
+ helpCut: 'bargain.task/helpCut'
+}
+
+// 我的砍价列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
+
+// 创建砍价任务
+export const partake = (data) => {
+ return request.post(api.partake, data)
+}
+
+// 获取砍价任务详情
+export const detail = (taskId, param) => {
+ return request.get(api.detail, { taskId, ...param })
+}
+
+// 获取砍价任务好友助力榜
+export const helpList = (taskId, param) => {
+ return request.get(api.helpList, { taskId, ...param })
+}
+
+// 帮砍一刀
+export const helpCut = (taskId, data) => {
+ return request.post(api.helpCut, { taskId, ...data })
+}
diff --git a/api/captcha.js b/api/captcha.js
new file mode 100644
index 0000000..6fff247
--- /dev/null
+++ b/api/captcha.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ image: 'captcha/image',
+ sendSmsCaptcha: 'captcha/sendSmsCaptcha'
+}
+
+// 图形验证码
+export function image() {
+ return request.get(api.image, {}, { load: false })
+}
+
+// 发送短信验证码
+export function sendSmsCaptcha(data) {
+ return request.post(api.sendSmsCaptcha, data, { load: false })
+}
diff --git a/api/cart.js b/api/cart.js
new file mode 100644
index 0000000..cba717e
--- /dev/null
+++ b/api/cart.js
@@ -0,0 +1,35 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'cart/list',
+ total: 'cart/total',
+ add: 'cart/add',
+ update: 'cart/update',
+ clear: 'cart/clear'
+}
+
+// 购物车列表
+export const list = () => {
+ return request.get(api.list, {}, { load: false })
+}
+
+// 购物车商品总数量
+export const total = () => {
+ return request.get(api.total, {}, { load: false })
+}
+
+// 加入购物车
+export const add = (goodsId, goodsSkuId, goodsNum) => {
+ return request.post(api.add, { goodsId, goodsSkuId, goodsNum })
+}
+
+// 更新购物车商品数量
+export const update = (goodsId, goodsSkuId, goodsNum) => {
+ return request.post(api.update, { goodsId, goodsSkuId, goodsNum }, { isPrompt: false })
+}
+
+// 删除购物车中指定记录
+export const clear = (cartIds = []) => {
+ return request.post(api.clear, { cartIds })
+}
diff --git a/api/cashier/index.js b/api/cashier/index.js
new file mode 100644
index 0000000..0710a62
--- /dev/null
+++ b/api/cashier/index.js
@@ -0,0 +1,35 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ orderInfo: 'cashier/orderInfo',
+ orderPay: 'cashier/orderPay',
+ tradeQuery: 'cashier/tradeQuery',
+}
+
+/**
+ * 获取支付订单的信息
+ * @param {Number} orderId
+ * @param {Object} param
+ */
+export function orderInfo(orderId, param) {
+ return request.get(api.orderInfo, { orderId, ...param })
+}
+
+/**
+ * 确认支付
+ * @param {Number} orderId
+ * @param {Object} data
+ */
+export function orderPay(orderId, data) {
+ return request.post(api.orderPay, { orderId, ...data })
+}
+
+/**
+ * 交易查询
+ * 查询第三方支付订单是否付款成功
+ * @param {Object} param
+ */
+export function tradeQuery(param) {
+ return request.get(api.tradeQuery, param)
+}
diff --git a/api/category/index.js b/api/category/index.js
new file mode 100644
index 0000000..7198be0
--- /dev/null
+++ b/api/category/index.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'category/list'
+}
+
+// 页面数据
+export function list() {
+ return request.get(api.list)
+}
diff --git a/api/checkout.js b/api/checkout.js
new file mode 100644
index 0000000..db4a362
--- /dev/null
+++ b/api/checkout.js
@@ -0,0 +1,19 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ order: 'checkout/order',
+ submit: 'checkout/submit',
+}
+
+// mode: 结算模式 (buyNow立即购买 cart购物车)
+
+// 结算台订单信息
+export const order = (mode, param) => {
+ return request.get(api.order, { mode, ...param })
+}
+
+// 结算台订单提交
+export const submit = (mode, data) => {
+ return request.post(api.submit, { mode, ...data }, { isPrompt: false })
+}
diff --git a/api/comment.js b/api/comment.js
new file mode 100644
index 0000000..c751c01
--- /dev/null
+++ b/api/comment.js
@@ -0,0 +1,23 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'comment/list',
+ listRows: 'comment/listRows',
+ total: 'comment/total'
+}
+
+// 商品评价列表
+export const list = (goodsId, param, option) => {
+ return request.get(api.list, { ...param, goodsId }, option)
+}
+
+// 商品评价列表 (限制数量, 用于商品详情页展示)
+export const listRows = (goodsId, limit = 5) => {
+ return request.get(api.listRows, { goodsId, limit })
+}
+
+// 商品评分总数
+export const total = (goodsId) => {
+ return request.get(api.total, { goodsId })
+}
diff --git a/api/coupon.js b/api/coupon.js
new file mode 100644
index 0000000..706149c
--- /dev/null
+++ b/api/coupon.js
@@ -0,0 +1,16 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'coupon/list'
+}
+
+// 优惠券列表
+export const list = (param, option) => {
+ const options = {
+ isPrompt: true, //(默认 true 说明:本接口抛出的错误是否提示)
+ load: true, //(默认 true 说明:本接口是否提示加载动画)
+ ...option
+ }
+ return request.get(api.list, param, options)
+}
diff --git a/api/dealer/apply.js b/api/dealer/apply.js
new file mode 100644
index 0000000..e736e2e
--- /dev/null
+++ b/api/dealer/apply.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ status: 'dealer.apply/status',
+ submit: 'dealer.apply/submit'
+}
+
+// 分销商申请状态
+export const status = (param) => {
+ return request.get(api.status, param)
+}
+
+// 提交分销商申请
+export const submit = (data) => {
+ return request.post(api.submit, data)
+}
diff --git a/api/dealer/index.js b/api/dealer/index.js
new file mode 100644
index 0000000..faab2aa
--- /dev/null
+++ b/api/dealer/index.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ user: 'dealer/user',
+ center: 'dealer/center'
+}
+
+// 分销商用户详情
+export const user = (param) => {
+ return request.get(api.user, param)
+}
+
+// 分销商提现明细
+export const center = (param) => {
+ return request.get(api.center, param)
+}
diff --git a/api/dealer/order.js b/api/dealer/order.js
new file mode 100644
index 0000000..165d3af
--- /dev/null
+++ b/api/dealer/order.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'dealer.order/list'
+}
+
+// 分销商订单列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
diff --git a/api/dealer/poster.js b/api/dealer/poster.js
new file mode 100644
index 0000000..c5a309b
--- /dev/null
+++ b/api/dealer/poster.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ qrcode: 'dealer.poster/qrcode'
+}
+
+// 获取推广二维码
+export const qrcode = (param) => {
+ return request.get(api.qrcode, param)
+}
diff --git a/api/dealer/setting.js b/api/dealer/setting.js
new file mode 100644
index 0000000..e51656b
--- /dev/null
+++ b/api/dealer/setting.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ data: 'dealer.setting/data'
+}
+
+// 获取分销设置 (全部)
+export const data = () => {
+ return request.get(api.data)
+}
diff --git a/api/dealer/team.js b/api/dealer/team.js
new file mode 100644
index 0000000..5e541c2
--- /dev/null
+++ b/api/dealer/team.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'dealer.team/list'
+}
+
+// 我的团队列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
diff --git a/api/dealer/withdraw.js b/api/dealer/withdraw.js
new file mode 100644
index 0000000..f859ca2
--- /dev/null
+++ b/api/dealer/withdraw.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'dealer.withdraw/list',
+ submit: 'dealer.withdraw/submit'
+}
+
+// 分销商提现明细
+export const list = (param) => {
+ return request.get(api.list, param)
+}
+
+// 提交提现申请
+export const submit = (data) => {
+ return request.post(api.submit, data)
+}
diff --git a/api/express.js b/api/express.js
new file mode 100644
index 0000000..b0db530
--- /dev/null
+++ b/api/express.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'express/list'
+}
+
+// 物流公司列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
diff --git a/api/goods/index.js b/api/goods/index.js
new file mode 100644
index 0000000..f00b463
--- /dev/null
+++ b/api/goods/index.js
@@ -0,0 +1,49 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'goods/list',
+ detail: 'goods/detail',
+ basic: 'goods/basic',
+ specData: 'goods/specData',
+ skuInfo: 'goods/skuInfo',
+ recommended: 'goods/recommended',
+ poster: 'goods/poster'
+}
+
+// 商品列表
+export const list = (param, option) => {
+ return request.get(api.list, param, option)
+}
+
+// 商品详情(详细数据)
+export const detail = (goodsId, verifyStatus = true, param = {}) => {
+ verifyStatus = Number(verifyStatus)
+ return request.get(api.detail, { goodsId, verifyStatus, ...param })
+}
+
+// 商品详情(基本数据)
+export const basic = (goodsId, verifyStatus = true, param = {}) => {
+ verifyStatus = Number(verifyStatus)
+ return request.get(api.basic, { goodsId, verifyStatus, ...param })
+}
+
+// 获取商品规格数据
+export const specData = (goodsId) => {
+ return request.get(api.specData, { goodsId })
+}
+
+// 获取推荐的商品列表
+export const recommended = () => {
+ return request.get(api.recommended)
+}
+
+// 获取商品的指定SKU信息
+export const skuInfo = (goodsId, goodsSkuId, param) => {
+ return request.get(api.skuInfo, { goodsId, goodsSkuId, ...param })
+}
+
+// 生成商品海报
+export const poster = param => {
+ return request.get(api.poster, param)
+}
diff --git a/api/goods/service.js b/api/goods/service.js
new file mode 100644
index 0000000..4bc2e43
--- /dev/null
+++ b/api/goods/service.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'goods.service/list'
+}
+
+// 商品评价列表
+export function list(goodsId) {
+ return request.get(api.list, { goodsId })
+}
diff --git a/api/groupon/checkout.js b/api/groupon/checkout.js
new file mode 100644
index 0000000..82dbd2a
--- /dev/null
+++ b/api/groupon/checkout.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ order: 'groupon.checkout/order',
+ submit: 'groupon.checkout/submit'
+}
+
+// 结算台订单信息
+export const order = (mode, param) => {
+ return request.get(api.order, { mode, ...param })
+}
+
+// 结算台订单提交
+export const submit = (mode, data) => {
+ return request.post(api.submit, { mode, ...data }, { isPrompt: false })
+}
diff --git a/api/groupon/goods.js b/api/groupon/goods.js
new file mode 100644
index 0000000..7e3b1d8
--- /dev/null
+++ b/api/groupon/goods.js
@@ -0,0 +1,23 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'groupon.goods/list',
+ detail: 'groupon.goods/detail',
+ poster: 'groupon.goods/poster'
+}
+
+// 拼团商品列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
+
+// 拼团商品详情
+export const detail = (grouponGoodsId, param) => {
+ return request.get(api.detail, { grouponGoodsId, ...param })
+}
+
+// 生成商品海报
+export const poster = param => {
+ return request.get(api.poster, param)
+}
diff --git a/api/groupon/setting.js b/api/groupon/setting.js
new file mode 100644
index 0000000..0314773
--- /dev/null
+++ b/api/groupon/setting.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ data: 'groupon.setting/data'
+}
+
+// 获取拼团设置
+export const data = () => {
+ return request.get(api.data)
+}
diff --git a/api/groupon/task.js b/api/groupon/task.js
new file mode 100644
index 0000000..cbaf4e3
--- /dev/null
+++ b/api/groupon/task.js
@@ -0,0 +1,23 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ myList: 'groupon.task/myList',
+ listByGoods: 'groupon.task/listByGoods',
+ detail: 'groupon.task/detail'
+}
+
+// 我的拼团列表
+export const myList = param => {
+ return request.get(api.myList, param)
+}
+
+// 获取拼单任务详情
+export const detail = (taskId, param) => {
+ return request.get(api.detail, { taskId, ...param })
+}
+
+// 我的拼团列表
+export const listByGoods = (grouponGoodsId, param) => {
+ return request.get(api.listByGoods, { grouponGoodsId, ...param })
+}
diff --git a/api/help.js b/api/help.js
new file mode 100644
index 0000000..150fa07
--- /dev/null
+++ b/api/help.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'help/list'
+}
+
+// 帮助中心列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
diff --git a/api/live/room.js b/api/live/room.js
new file mode 100644
index 0000000..1ab7b04
--- /dev/null
+++ b/api/live/room.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'live.room/list'
+}
+
+// 获取直播间列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
diff --git a/api/login/index.js b/api/login/index.js
new file mode 100644
index 0000000..967f163
--- /dev/null
+++ b/api/login/index.js
@@ -0,0 +1,41 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ login: 'passport/login',
+ loginMpWx: 'passport/loginMpWx',
+ loginWxOfficial: 'passport/loginWxOfficial',
+ loginMpWxMobile: 'passport/loginMpWxMobile',
+ loginMpAlipay: 'passport/loginMpAlipay',
+ isPersonalMpweixin: 'passport/isPersonalMpweixin',
+}
+
+// 用户登录 (手机号+验证码)
+export function login(data) {
+ return request.post(api.login, data)
+}
+
+// 微信小程序快捷登录 (获取微信用户基本信息)
+export function loginMpWx(data, option) {
+ return request.post(api.loginMpWx, data, option)
+}
+
+// 是否需要填写昵称头像 (微信小程序端)
+export function isPersonalMpweixin(data, option) {
+ return request.post(api.isPersonalMpweixin, data, option)
+}
+
+// 微信公众号一键授权登录 (获取微信用户基本信息)
+export function loginWxOfficial(data, option) {
+ return request.post(api.loginWxOfficial, data, option)
+}
+
+// 微信小程序快捷登录 (授权手机号)
+export function loginMpWxMobile(data, option) {
+ return request.post(api.loginMpWxMobile, data, option)
+}
+
+// 支付宝小程序快捷登录 (获取微信用户基本信息)
+export function loginMpAlipay(data, option) {
+ return request.post(api.loginMpAlipay, data, option)
+}
diff --git a/api/myCoupon.js b/api/myCoupon.js
new file mode 100644
index 0000000..d84ea55
--- /dev/null
+++ b/api/myCoupon.js
@@ -0,0 +1,22 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'myCoupon/list',
+ receive: 'myCoupon/receive'
+}
+
+// 我的优惠券列表
+export const list = (param, option) => {
+ const options = {
+ isPrompt: true, //(默认 true 说明:本接口抛出的错误是否提示)
+ load: true, //(默认 true 说明:本接口是否提示加载动画)
+ ...option
+ }
+ return request.get(api.list, param, options)
+}
+
+// 领取优惠券
+export const receive = (couponId, data, option) => {
+ return request.post(api.receive, { couponId, ...data }, option)
+}
diff --git a/api/order.js b/api/order.js
new file mode 100644
index 0000000..1113f06
--- /dev/null
+++ b/api/order.js
@@ -0,0 +1,48 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ todoCounts: 'order/todoCounts',
+ list: 'order/list',
+ detail: 'order/detail',
+ express: 'order/express',
+ cancel: 'order/cancel',
+ extractQrcode: 'order/extractQrcode',
+ receipt: 'order/receipt',
+ pay: 'order/pay'
+}
+
+// 当前用户待处理的订单数量
+export function todoCounts(param, option) {
+ return request.get(api.todoCounts, param, option)
+}
+
+// 我的订单列表
+export function list(param, option) {
+ return request.get(api.list, param, option)
+}
+
+// 订单详情
+export function detail(orderId, param) {
+ return request.get(api.detail, { orderId, ...param })
+}
+
+// 获取物流信息
+export function express(orderId, param) {
+ return request.get(api.express, { orderId, ...param })
+}
+
+// 取消订单
+export function cancel(orderId, data) {
+ return request.post(api.cancel, { orderId, ...data })
+}
+
+// 确认收货
+export function receipt(orderId, data) {
+ return request.post(api.receipt, { orderId, ...data })
+}
+
+// 核销二维码
+export function extractQrcode(orderId, param) {
+ return request.get(api.extractQrcode, { orderId, ...param })
+}
diff --git a/api/order/comment.js b/api/order/comment.js
new file mode 100644
index 0000000..f0d57b8
--- /dev/null
+++ b/api/order/comment.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'order.comment/list',
+ submit: 'order.comment/submit'
+}
+
+// 待评价订单商品列表
+export const list = (orderId, param) => {
+ return request.get(api.list, { orderId, ...param })
+}
+
+// 创建商品评价
+export const submit = (orderId, data) => {
+ return request.post(api.submit, { orderId, form: data })
+}
diff --git a/api/page.js b/api/page.js
new file mode 100644
index 0000000..bc0a519
--- /dev/null
+++ b/api/page.js
@@ -0,0 +1,13 @@
+import request from '@/utils/request'
+
+// api地址
+const apiUri = {
+ detail: 'page/detail'
+}
+
+// 页面数据
+export function detail(pageId) {
+ return request.get(apiUri.detail, {
+ pageId
+ })
+}
diff --git a/api/points/log.js b/api/points/log.js
new file mode 100644
index 0000000..bb7a6e7
--- /dev/null
+++ b/api/points/log.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'points.log/list'
+}
+
+// 积分明细列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
diff --git a/api/recharge.js b/api/recharge.js
new file mode 100644
index 0000000..b6fd546
--- /dev/null
+++ b/api/recharge.js
@@ -0,0 +1,27 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ center: 'recharge/center',
+ submit: 'recharge/submit',
+ tradeQuery: 'recharge/tradeQuery'
+}
+
+// 充值中心页面数据
+export const center = (param) => {
+ return request.get(api.center, param)
+}
+
+// 确认充值订单
+export const submit = (data) => {
+ return request.post(api.submit, { form: data })
+}
+
+/**
+ * 交易查询
+ * 查询第三方支付订单是否付款成功
+ * @param {Object} param
+ */
+export function tradeQuery(param) {
+ return request.get(api.tradeQuery, param)
+}
diff --git a/api/recharge/order.js b/api/recharge/order.js
new file mode 100644
index 0000000..4cab383
--- /dev/null
+++ b/api/recharge/order.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'recharge.order/list'
+}
+
+// 我的充值记录列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
diff --git a/api/refund.js b/api/refund.js
new file mode 100644
index 0000000..d92af6e
--- /dev/null
+++ b/api/refund.js
@@ -0,0 +1,35 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'refund/list',
+ goods: 'refund/goods',
+ apply: 'refund/apply',
+ detail: 'refund/detail',
+ delivery: 'refund/delivery'
+}
+
+// 售后单列表
+export const list = (param, option) => {
+ return request.get(api.list, param, option)
+}
+
+// 订单商品详情
+export const goods = (orderGoodsId, param) => {
+ return request.get(api.goods, { orderGoodsId, ...param })
+}
+
+// 申请售后
+export const apply = (orderGoodsId, data) => {
+ return request.post(api.apply, { orderGoodsId, form: data })
+}
+
+// 售后单详情
+export const detail = (orderRefundId, param) => {
+ return request.get(api.detail, { orderRefundId, ...param })
+}
+
+// 用户发货
+export const delivery = (orderRefundId, data) => {
+ return request.post(api.delivery, { orderRefundId, form: data })
+}
diff --git a/api/region.js b/api/region.js
new file mode 100644
index 0000000..d8ba090
--- /dev/null
+++ b/api/region.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ all: 'region/all',
+ tree: 'region/tree'
+}
+
+// 获取所有地区
+export const all = (param) => {
+ return request.get(api.all, param)
+}
+
+// 获取所有地区(树状)
+export const tree = (param) => {
+ return request.get(api.tree, param)
+}
diff --git a/api/setting.js b/api/setting.js
new file mode 100644
index 0000000..5d3327e
--- /dev/null
+++ b/api/setting.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ data: 'setting/data'
+}
+
+// 设置项详情
+export function data() {
+ return request.get(api.data)
+}
diff --git a/api/sharp/checkout.js b/api/sharp/checkout.js
new file mode 100644
index 0000000..d884183
--- /dev/null
+++ b/api/sharp/checkout.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ order: 'sharp.checkout/order',
+ submit: 'sharp.checkout/submit'
+}
+
+// 结算台订单信息
+export const order = (mode, param) => {
+ return request.get(api.order, { mode, ...param })
+}
+
+// 结算台订单提交
+export const submit = (mode, data) => {
+ return request.post(api.submit, { mode, ...data }, { isPrompt: false })
+}
diff --git a/api/sharp/goods.js b/api/sharp/goods.js
new file mode 100644
index 0000000..b13ea3d
--- /dev/null
+++ b/api/sharp/goods.js
@@ -0,0 +1,23 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'sharp.goods/list',
+ detail: 'sharp.goods/detail',
+ poster: 'sharp.goods/poster'
+}
+
+// 秒杀活动商品列表
+export const list = (activeTimeId, param, option) => {
+ return request.get(api.list, { activeTimeId, ...param }, option)
+}
+
+// 获取活动商品详情
+export const detail = (activeTimeId, sharpGoodsId, param) => {
+ return request.get(api.detail, { activeTimeId, sharpGoodsId, ...param })
+}
+
+// 生成商品海报
+export const poster = param => {
+ return request.get(api.poster, param)
+}
diff --git a/api/sharp/home.js b/api/sharp/home.js
new file mode 100644
index 0000000..0b7b61d
--- /dev/null
+++ b/api/sharp/home.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ data: 'sharp.home/data'
+}
+
+// 秒杀活动首页
+export const data = (param) => {
+ return request.get(api.data, param)
+}
diff --git a/api/shop.js b/api/shop.js
new file mode 100644
index 0000000..17f43e2
--- /dev/null
+++ b/api/shop.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ list: 'shop/list',
+ detail: 'shop/detail'
+}
+
+// 自提门店列表
+export const list = (param) => {
+ return request.get(api.list, param)
+}
+
+// 门店详情
+export const detail = (shopId) => {
+ return request.get(api.detail, { shopId })
+}
diff --git a/api/shop/order.js b/api/shop/order.js
new file mode 100644
index 0000000..be58f9a
--- /dev/null
+++ b/api/shop/order.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ detail: 'shop.order/detail',
+ extract: 'shop.order/extract'
+}
+
+// 核销订单详情 [只有店员才能查看]
+export function detail(orderId, param) {
+ return request.get(api.detail, { orderId, ...param })
+}
+
+// 确认核销 [已取货]
+export function extract(orderId, param) {
+ return request.post(api.extract, { orderId, ...param })
+}
diff --git a/api/store.js b/api/store.js
new file mode 100644
index 0000000..6f248e3
--- /dev/null
+++ b/api/store.js
@@ -0,0 +1,13 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ data: 'store/data'
+}
+
+// 获取商城基础信息
+const data = () => {
+ return request.get(api.data)
+}
+
+export default { data }
diff --git a/api/upload.js b/api/upload.js
new file mode 100644
index 0000000..60aee8d
--- /dev/null
+++ b/api/upload.js
@@ -0,0 +1,18 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ image: 'upload/image'
+}
+
+// 图片上传
+export const image = (files, checkLogin = true) => {
+ // 文件上传大小, 2M
+ const maxSize = 1024 * 1024 * 2
+ // 执行上传
+ return new Promise((resolve, reject) => {
+ request.urlFileUpload({ name: 'file', files, maxSize, data: { test: 123, checkLogin: Number(checkLogin) } })
+ .then(result => resolve(result.map(item => item.data.fileInfo.file_id), result))
+ .catch(reject)
+ })
+}
\ No newline at end of file
diff --git a/api/user.js b/api/user.js
new file mode 100644
index 0000000..6e3c30c
--- /dev/null
+++ b/api/user.js
@@ -0,0 +1,34 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ userInfo: 'user/info',
+ assets: 'user/assets',
+ bindMobile: 'user/bindMobile',
+ personal: 'user/personal'
+}
+
+// 当前登录的用户信息
+export const info = (param, option) => {
+ const options = {
+ isPrompt: true, //(默认 true 说明:本接口抛出的错误是否提示)
+ load: true, //(默认 true 说明:本接口是否提示加载动画)
+ ...option
+ }
+ return request.get(api.userInfo, param, options)
+}
+
+// 账户资产
+export const assets = (param, option) => {
+ return request.get(api.assets, param, option)
+}
+
+// 绑定手机号
+export const bindMobile = (data, option) => {
+ return request.post(api.bindMobile, data, option)
+}
+
+// 修改个人信息(头像昵称)
+export const personal = (data, option) => {
+ return request.post(api.personal, data, option)
+}
diff --git a/api/user/coupon.js b/api/user/coupon.js
new file mode 100644
index 0000000..3412566
--- /dev/null
+++ b/api/user/coupon.js
@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ receive: 'user.coupon/receive'
+}
+
+// 优惠券列表
+export const receive = (data) => {
+ return request.post(api.receive, data)
+}
diff --git a/api/wxofficial.js b/api/wxofficial.js
new file mode 100644
index 0000000..ff4eff1
--- /dev/null
+++ b/api/wxofficial.js
@@ -0,0 +1,25 @@
+import request from '@/utils/request'
+
+// api地址
+const api = {
+ jssdkConfig: 'wxofficial/jssdkConfig',
+ oauthUrl: 'wxofficial/oauthUrl',
+ oauthUserInfo: 'wxofficial/oauthUserInfo'
+}
+
+// 获取微信公众号jssdk配置参数
+const jssdkConfig = url => {
+ return request.get(api.jssdkConfig, { url })
+}
+
+// 获取授权登录地址
+const oauthUrl = callbackUrl => {
+ return request.get(api.oauthUrl, { callbackUrl })
+}
+
+// 获取微信用户信息
+const oauthUserInfo = code => {
+ return request.get(api.oauthUserInfo, { code })
+}
+
+export default { jssdkConfig, oauthUrl, oauthUserInfo }
diff --git a/app.scss b/app.scss
new file mode 100644
index 0000000..3b14f3b
--- /dev/null
+++ b/app.scss
@@ -0,0 +1,43 @@
+/* utils.scss */
+@import "/utils/utils.scss";
+
+page {
+ background: #fafafa;
+}
+
+@keyframes rotate {
+ 0% {
+ transform: rotate(0deg) scale(1);
+ }
+
+ 100% {
+ transform: rotate(360deg) scale(1);
+ }
+}
+
+/* #ifdef H5*/
+
+uni-page {
+ box-shadow: 0 1rpx 44rpx rgba(169, 169, 169, .3);
+}
+
+.uni-app--showlayout+uni-tabbar.uni-tabbar-bottom,
+.uni-app--showlayout+uni-tabbar.uni-tabbar-bottom .uni-tabbar,
+.uni-app--showlayout+uni-tabbar.uni-tabbar-top,
+.uni-app--showlayout+uni-tabbar.uni-tabbar-top .uni-tabbar {
+ left: var(--window-left);
+ right: var(--window-right);
+}
+
+.footer-fixed {
+ left: var(--window-left) !important;
+ right: var(--window-right) !important;
+}
+
+.u-mask,.u-drawer {
+ left: var(--window-left) !important;
+ right: var(--window-right) !important;
+}
+
+/* #endif */
+
diff --git a/common/constant/index.js b/common/constant/index.js
new file mode 100644
index 0000000..282338d
--- /dev/null
+++ b/common/constant/index.js
@@ -0,0 +1,7 @@
+export const paginate = {
+ data: [], // 列表数据
+ current_page: 1, // 当前页码
+ last_page: 1, // 最大页码
+ per_page: 15, // 每页记录数
+ total: 0, // 总记录数
+}
\ No newline at end of file
diff --git a/common/data/region.js b/common/data/region.js
new file mode 100644
index 0000000..417012d
--- /dev/null
+++ b/common/data/region.js
@@ -0,0 +1 @@
+export default{1:{id:1,pid:0,name:"北京市",level:1,city:{2:{id:2,pid:1,name:"北京市",level:2,region:{3:{id:3,pid:2,name:"东城区",level:3},4:{id:4,pid:2,name:"西城区",level:3},5:{id:5,pid:2,name:"朝阳区",level:3},6:{id:6,pid:2,name:"丰台区",level:3},7:{id:7,pid:2,name:"石景山区",level:3},8:{id:8,pid:2,name:"海淀区",level:3},9:{id:9,pid:2,name:"门头沟区",level:3},10:{id:10,pid:2,name:"房山区",level:3},11:{id:11,pid:2,name:"通州区",level:3},12:{id:12,pid:2,name:"顺义区",level:3},13:{id:13,pid:2,name:"昌平区",level:3},14:{id:14,pid:2,name:"大兴区",level:3},15:{id:15,pid:2,name:"怀柔区",level:3},16:{id:16,pid:2,name:"平谷区",level:3},17:{id:17,pid:2,name:"密云区",level:3},18:{id:18,pid:2,name:"延庆区",level:3}}}}},19:{id:19,pid:0,name:"天津市",level:1,city:{20:{id:20,pid:19,name:"天津市",level:2,region:{21:{id:21,pid:20,name:"和平区",level:3},22:{id:22,pid:20,name:"河东区",level:3},23:{id:23,pid:20,name:"河西区",level:3},24:{id:24,pid:20,name:"南开区",level:3},25:{id:25,pid:20,name:"河北区",level:3},26:{id:26,pid:20,name:"红桥区",level:3},27:{id:27,pid:20,name:"东丽区",level:3},28:{id:28,pid:20,name:"西青区",level:3},29:{id:29,pid:20,name:"津南区",level:3},30:{id:30,pid:20,name:"北辰区",level:3},31:{id:31,pid:20,name:"武清区",level:3},32:{id:32,pid:20,name:"宝坻区",level:3},33:{id:33,pid:20,name:"滨海新区",level:3},34:{id:34,pid:20,name:"宁河区",level:3},35:{id:35,pid:20,name:"静海区",level:3},36:{id:36,pid:20,name:"蓟州区",level:3}}}}},37:{id:37,pid:0,name:"河北省",level:1,city:{38:{id:38,pid:37,name:"石家庄市",level:2,region:{39:{id:39,pid:38,name:"长安区",level:3},40:{id:40,pid:38,name:"桥西区",level:3},41:{id:41,pid:38,name:"新华区",level:3},42:{id:42,pid:38,name:"井陉矿区",level:3},43:{id:43,pid:38,name:"裕华区",level:3},44:{id:44,pid:38,name:"藁城区",level:3},45:{id:45,pid:38,name:"鹿泉区",level:3},46:{id:46,pid:38,name:"栾城区",level:3},47:{id:47,pid:38,name:"井陉县",level:3},48:{id:48,pid:38,name:"正定县",level:3},49:{id:49,pid:38,name:"行唐县",level:3},50:{id:50,pid:38,name:"灵寿县",level:3},51:{id:51,pid:38,name:"高邑县",level:3},52:{id:52,pid:38,name:"深泽县",level:3},53:{id:53,pid:38,name:"赞皇县",level:3},54:{id:54,pid:38,name:"无极县",level:3},55:{id:55,pid:38,name:"平山县",level:3},56:{id:56,pid:38,name:"元氏县",level:3},57:{id:57,pid:38,name:"赵县",level:3},58:{id:58,pid:38,name:"辛集市",level:3},59:{id:59,pid:38,name:"晋州市",level:3},60:{id:60,pid:38,name:"新乐市",level:3},3711:{id:3711,pid:38,name:"石家庄高新技术产业开发区",level:3},3712:{id:3712,pid:38,name:"石家庄循环化工园区",level:3}}},61:{id:61,pid:37,name:"唐山市",level:2,region:{62:{id:62,pid:61,name:"路南区",level:3},63:{id:63,pid:61,name:"路北区",level:3},64:{id:64,pid:61,name:"古冶区",level:3},65:{id:65,pid:61,name:"开平区",level:3},66:{id:66,pid:61,name:"丰南区",level:3},67:{id:67,pid:61,name:"丰润区",level:3},68:{id:68,pid:61,name:"曹妃甸区",level:3},69:{id:69,pid:61,name:"滦南县",level:3},70:{id:70,pid:61,name:"乐亭县",level:3},71:{id:71,pid:61,name:"迁西县",level:3},72:{id:72,pid:61,name:"玉田县",level:3},73:{id:73,pid:61,name:"遵化市",level:3},74:{id:74,pid:61,name:"迁安市",level:3},75:{id:75,pid:61,name:"滦州市",level:3},3713:{id:3713,pid:61,name:"河北唐山芦台经济开发区",level:3},3714:{id:3714,pid:61,name:"唐山市汉沽管理区",level:3},3715:{id:3715,pid:61,name:"唐山高新技术产业开发区",level:3},3716:{id:3716,pid:61,name:"河北唐山海港经济开发区",level:3}}},76:{id:76,pid:37,name:"秦皇岛市",level:2,region:{77:{id:77,pid:76,name:"海港区",level:3},78:{id:78,pid:76,name:"山海关区",level:3},79:{id:79,pid:76,name:"北戴河区",level:3},80:{id:80,pid:76,name:"抚宁区",level:3},81:{id:81,pid:76,name:"青龙满族自治县",level:3},82:{id:82,pid:76,name:"昌黎县",level:3},83:{id:83,pid:76,name:"卢龙县",level:3},3717:{id:3717,pid:76,name:"秦皇岛市经济技术开发区",level:3},3718:{id:3718,pid:76,name:"北戴河新区",level:3}}},84:{id:84,pid:37,name:"邯郸市",level:2,region:{85:{id:85,pid:84,name:"邯山区",level:3},86:{id:86,pid:84,name:"丛台区",level:3},87:{id:87,pid:84,name:"复兴区",level:3},88:{id:88,pid:84,name:"峰峰矿区",level:3},89:{id:89,pid:84,name:"肥乡区",level:3},90:{id:90,pid:84,name:"永年区",level:3},91:{id:91,pid:84,name:"临漳县",level:3},92:{id:92,pid:84,name:"成安县",level:3},93:{id:93,pid:84,name:"大名县",level:3},94:{id:94,pid:84,name:"涉县",level:3},95:{id:95,pid:84,name:"磁县",level:3},96:{id:96,pid:84,name:"邱县",level:3},97:{id:97,pid:84,name:"鸡泽县",level:3},98:{id:98,pid:84,name:"广平县",level:3},99:{id:99,pid:84,name:"馆陶县",level:3},100:{id:100,pid:84,name:"魏县",level:3},101:{id:101,pid:84,name:"曲周县",level:3},102:{id:102,pid:84,name:"武安市",level:3},3719:{id:3719,pid:84,name:"邯郸经济技术开发区",level:3},3720:{id:3720,pid:84,name:"邯郸冀南新区",level:3}}},103:{id:103,pid:37,name:"邢台市",level:2,region:{107:{id:107,pid:103,name:"临城县",level:3},108:{id:108,pid:103,name:"内丘县",level:3},109:{id:109,pid:103,name:"柏乡县",level:3},110:{id:110,pid:103,name:"隆尧县",level:3},113:{id:113,pid:103,name:"宁晋县",level:3},114:{id:114,pid:103,name:"巨鹿县",level:3},115:{id:115,pid:103,name:"新河县",level:3},116:{id:116,pid:103,name:"广宗县",level:3},117:{id:117,pid:103,name:"平乡县",level:3},118:{id:118,pid:103,name:"威县",level:3},119:{id:119,pid:103,name:"清河县",level:3},120:{id:120,pid:103,name:"临西县",level:3},121:{id:121,pid:103,name:"南宫市",level:3},122:{id:122,pid:103,name:"沙河市",level:3},3721:{id:3721,pid:103,name:"襄都区",level:3},3722:{id:3722,pid:103,name:"信都区",level:3},3723:{id:3723,pid:103,name:"任泽区",level:3},3724:{id:3724,pid:103,name:"南和区",level:3},3725:{id:3725,pid:103,name:"河北邢台经济开发区",level:3}}},123:{id:123,pid:37,name:"保定市",level:2,region:{124:{id:124,pid:123,name:"竞秀区",level:3},125:{id:125,pid:123,name:"莲池区",level:3},126:{id:126,pid:123,name:"满城区",level:3},127:{id:127,pid:123,name:"清苑区",level:3},128:{id:128,pid:123,name:"徐水区",level:3},129:{id:129,pid:123,name:"涞水县",level:3},130:{id:130,pid:123,name:"阜平县",level:3},131:{id:131,pid:123,name:"定兴县",level:3},132:{id:132,pid:123,name:"唐县",level:3},133:{id:133,pid:123,name:"高阳县",level:3},134:{id:134,pid:123,name:"容城县",level:3},135:{id:135,pid:123,name:"涞源县",level:3},136:{id:136,pid:123,name:"望都县",level:3},137:{id:137,pid:123,name:"安新县",level:3},138:{id:138,pid:123,name:"易县",level:3},139:{id:139,pid:123,name:"曲阳县",level:3},140:{id:140,pid:123,name:"蠡县",level:3},141:{id:141,pid:123,name:"顺平县",level:3},142:{id:142,pid:123,name:"博野县",level:3},143:{id:143,pid:123,name:"雄县",level:3},144:{id:144,pid:123,name:"涿州市",level:3},145:{id:145,pid:123,name:"定州市",level:3},146:{id:146,pid:123,name:"安国市",level:3},147:{id:147,pid:123,name:"高碑店市",level:3},3726:{id:3726,pid:123,name:"保定高新技术产业开发区",level:3},3727:{id:3727,pid:123,name:"保定白沟新城",level:3}}},148:{id:148,pid:37,name:"张家口市",level:2,region:{149:{id:149,pid:148,name:"桥东区",level:3},150:{id:150,pid:148,name:"桥西区",level:3},151:{id:151,pid:148,name:"宣化区",level:3},152:{id:152,pid:148,name:"下花园区",level:3},153:{id:153,pid:148,name:"万全区",level:3},154:{id:154,pid:148,name:"崇礼区",level:3},155:{id:155,pid:148,name:"张北县",level:3},156:{id:156,pid:148,name:"康保县",level:3},157:{id:157,pid:148,name:"沽源县",level:3},158:{id:158,pid:148,name:"尚义县",level:3},159:{id:159,pid:148,name:"蔚县",level:3},160:{id:160,pid:148,name:"阳原县",level:3},161:{id:161,pid:148,name:"怀安县",level:3},162:{id:162,pid:148,name:"怀来县",level:3},163:{id:163,pid:148,name:"涿鹿县",level:3},164:{id:164,pid:148,name:"赤城县",level:3},3728:{id:3728,pid:148,name:"张家口经济开发区",level:3},3729:{id:3729,pid:148,name:"张家口市察北管理区",level:3},3730:{id:3730,pid:148,name:"张家口市塞北管理区",level:3}}},165:{id:165,pid:37,name:"承德市",level:2,region:{166:{id:166,pid:165,name:"双桥区",level:3},167:{id:167,pid:165,name:"双滦区",level:3},168:{id:168,pid:165,name:"鹰手营子矿区",level:3},169:{id:169,pid:165,name:"承德县",level:3},170:{id:170,pid:165,name:"兴隆县",level:3},171:{id:171,pid:165,name:"滦平县",level:3},172:{id:172,pid:165,name:"隆化县",level:3},173:{id:173,pid:165,name:"丰宁满族自治县",level:3},174:{id:174,pid:165,name:"宽城满族自治县",level:3},175:{id:175,pid:165,name:"围场满族蒙古族自治县",level:3},176:{id:176,pid:165,name:"平泉市",level:3},3731:{id:3731,pid:165,name:"承德高新技术产业开发区",level:3}}},177:{id:177,pid:37,name:"沧州市",level:2,region:{178:{id:178,pid:177,name:"新华区",level:3},179:{id:179,pid:177,name:"运河区",level:3},180:{id:180,pid:177,name:"沧县",level:3},181:{id:181,pid:177,name:"青县",level:3},182:{id:182,pid:177,name:"东光县",level:3},183:{id:183,pid:177,name:"海兴县",level:3},184:{id:184,pid:177,name:"盐山县",level:3},185:{id:185,pid:177,name:"肃宁县",level:3},186:{id:186,pid:177,name:"南皮县",level:3},187:{id:187,pid:177,name:"吴桥县",level:3},188:{id:188,pid:177,name:"献县",level:3},189:{id:189,pid:177,name:"孟村回族自治县",level:3},190:{id:190,pid:177,name:"泊头市",level:3},191:{id:191,pid:177,name:"任丘市",level:3},192:{id:192,pid:177,name:"黄骅市",level:3},193:{id:193,pid:177,name:"河间市",level:3},3732:{id:3732,pid:177,name:"河北沧州经济开发区",level:3},3733:{id:3733,pid:177,name:"沧州高新技术产业开发区",level:3},3734:{id:3734,pid:177,name:"沧州渤海新区",level:3}}},194:{id:194,pid:37,name:"廊坊市",level:2,region:{195:{id:195,pid:194,name:"安次区",level:3},196:{id:196,pid:194,name:"广阳区",level:3},197:{id:197,pid:194,name:"固安县",level:3},198:{id:198,pid:194,name:"永清县",level:3},199:{id:199,pid:194,name:"香河县",level:3},200:{id:200,pid:194,name:"大城县",level:3},201:{id:201,pid:194,name:"文安县",level:3},202:{id:202,pid:194,name:"大厂回族自治县",level:3},203:{id:203,pid:194,name:"霸州市",level:3},204:{id:204,pid:194,name:"三河市",level:3},3735:{id:3735,pid:194,name:"廊坊经济技术开发区",level:3}}},205:{id:205,pid:37,name:"衡水市",level:2,region:{206:{id:206,pid:205,name:"桃城区",level:3},207:{id:207,pid:205,name:"冀州区",level:3},208:{id:208,pid:205,name:"枣强县",level:3},209:{id:209,pid:205,name:"武邑县",level:3},210:{id:210,pid:205,name:"武强县",level:3},211:{id:211,pid:205,name:"饶阳县",level:3},212:{id:212,pid:205,name:"安平县",level:3},213:{id:213,pid:205,name:"故城县",level:3},214:{id:214,pid:205,name:"景县",level:3},215:{id:215,pid:205,name:"阜城县",level:3},216:{id:216,pid:205,name:"深州市",level:3},3736:{id:3736,pid:205,name:"河北衡水高新技术产业开发区",level:3},3737:{id:3737,pid:205,name:"衡水滨湖新区",level:3}}}}},217:{id:217,pid:0,name:"山西省",level:1,city:{218:{id:218,pid:217,name:"太原市",level:2,region:{219:{id:219,pid:218,name:"小店区",level:3},220:{id:220,pid:218,name:"迎泽区",level:3},221:{id:221,pid:218,name:"杏花岭区",level:3},222:{id:222,pid:218,name:"尖草坪区",level:3},223:{id:223,pid:218,name:"万柏林区",level:3},224:{id:224,pid:218,name:"晋源区",level:3},225:{id:225,pid:218,name:"清徐县",level:3},226:{id:226,pid:218,name:"阳曲县",level:3},227:{id:227,pid:218,name:"娄烦县",level:3},228:{id:228,pid:218,name:"古交市",level:3},3738:{id:3738,pid:218,name:"山西转型综合改革示范区",level:3}}},229:{id:229,pid:217,name:"大同市",level:2,region:{230:{id:230,pid:229,name:"新荣区",level:3},231:{id:231,pid:229,name:"平城区",level:3},232:{id:232,pid:229,name:"云冈区",level:3},233:{id:233,pid:229,name:"云州区",level:3},234:{id:234,pid:229,name:"阳高县",level:3},235:{id:235,pid:229,name:"天镇县",level:3},236:{id:236,pid:229,name:"广灵县",level:3},237:{id:237,pid:229,name:"灵丘县",level:3},238:{id:238,pid:229,name:"浑源县",level:3},239:{id:239,pid:229,name:"左云县",level:3},3739:{id:3739,pid:229,name:"山西大同经济开发区",level:3}}},240:{id:240,pid:217,name:"阳泉市",level:2,region:{241:{id:241,pid:240,name:"城区",level:3},242:{id:242,pid:240,name:"矿区",level:3},243:{id:243,pid:240,name:"郊区",level:3},244:{id:244,pid:240,name:"平定县",level:3},245:{id:245,pid:240,name:"盂县",level:3}}},246:{id:246,pid:217,name:"长治市",level:2,region:{247:{id:247,pid:246,name:"潞州区",level:3},248:{id:248,pid:246,name:"上党区",level:3},249:{id:249,pid:246,name:"屯留区",level:3},250:{id:250,pid:246,name:"潞城区",level:3},251:{id:251,pid:246,name:"襄垣县",level:3},252:{id:252,pid:246,name:"平顺县",level:3},253:{id:253,pid:246,name:"黎城县",level:3},254:{id:254,pid:246,name:"壶关县",level:3},255:{id:255,pid:246,name:"长子县",level:3},256:{id:256,pid:246,name:"武乡县",level:3},257:{id:257,pid:246,name:"沁县",level:3},258:{id:258,pid:246,name:"沁源县",level:3},3740:{id:3740,pid:246,name:"山西长治高新技术产业园区",level:3}}},259:{id:259,pid:217,name:"晋城市",level:2,region:{260:{id:260,pid:259,name:"城区",level:3},261:{id:261,pid:259,name:"沁水县",level:3},262:{id:262,pid:259,name:"阳城县",level:3},263:{id:263,pid:259,name:"陵川县",level:3},264:{id:264,pid:259,name:"泽州县",level:3},265:{id:265,pid:259,name:"高平市",level:3}}},266:{id:266,pid:217,name:"朔州市",level:2,region:{267:{id:267,pid:266,name:"朔城区",level:3},268:{id:268,pid:266,name:"平鲁区",level:3},269:{id:269,pid:266,name:"山阴县",level:3},270:{id:270,pid:266,name:"应县",level:3},271:{id:271,pid:266,name:"右玉县",level:3},272:{id:272,pid:266,name:"怀仁市",level:3},3741:{id:3741,pid:266,name:"山西朔州经济开发区",level:3}}},273:{id:273,pid:217,name:"晋中市",level:2,region:{274:{id:274,pid:273,name:"榆次区",level:3},275:{id:275,pid:273,name:"太谷区",level:3},276:{id:276,pid:273,name:"榆社县",level:3},277:{id:277,pid:273,name:"左权县",level:3},278:{id:278,pid:273,name:"和顺县",level:3},279:{id:279,pid:273,name:"昔阳县",level:3},280:{id:280,pid:273,name:"寿阳县",level:3},281:{id:281,pid:273,name:"祁县",level:3},282:{id:282,pid:273,name:"平遥县",level:3},283:{id:283,pid:273,name:"灵石县",level:3},284:{id:284,pid:273,name:"介休市",level:3}}},285:{id:285,pid:217,name:"运城市",level:2,region:{286:{id:286,pid:285,name:"盐湖区",level:3},287:{id:287,pid:285,name:"临猗县",level:3},288:{id:288,pid:285,name:"万荣县",level:3},289:{id:289,pid:285,name:"闻喜县",level:3},290:{id:290,pid:285,name:"稷山县",level:3},291:{id:291,pid:285,name:"新绛县",level:3},292:{id:292,pid:285,name:"绛县",level:3},293:{id:293,pid:285,name:"垣曲县",level:3},294:{id:294,pid:285,name:"夏县",level:3},295:{id:295,pid:285,name:"平陆县",level:3},296:{id:296,pid:285,name:"芮城县",level:3},297:{id:297,pid:285,name:"永济市",level:3},298:{id:298,pid:285,name:"河津市",level:3}}},299:{id:299,pid:217,name:"忻州市",level:2,region:{300:{id:300,pid:299,name:"忻府区",level:3},301:{id:301,pid:299,name:"定襄县",level:3},302:{id:302,pid:299,name:"五台县",level:3},303:{id:303,pid:299,name:"代县",level:3},304:{id:304,pid:299,name:"繁峙县",level:3},305:{id:305,pid:299,name:"宁武县",level:3},306:{id:306,pid:299,name:"静乐县",level:3},307:{id:307,pid:299,name:"神池县",level:3},308:{id:308,pid:299,name:"五寨县",level:3},309:{id:309,pid:299,name:"岢岚县",level:3},310:{id:310,pid:299,name:"河曲县",level:3},311:{id:311,pid:299,name:"保德县",level:3},312:{id:312,pid:299,name:"偏关县",level:3},313:{id:313,pid:299,name:"原平市",level:3},3742:{id:3742,pid:299,name:"五台山风景名胜区",level:3}}},314:{id:314,pid:217,name:"临汾市",level:2,region:{315:{id:315,pid:314,name:"尧都区",level:3},316:{id:316,pid:314,name:"曲沃县",level:3},317:{id:317,pid:314,name:"翼城县",level:3},318:{id:318,pid:314,name:"襄汾县",level:3},319:{id:319,pid:314,name:"洪洞县",level:3},320:{id:320,pid:314,name:"古县",level:3},321:{id:321,pid:314,name:"安泽县",level:3},322:{id:322,pid:314,name:"浮山县",level:3},323:{id:323,pid:314,name:"吉县",level:3},324:{id:324,pid:314,name:"乡宁县",level:3},325:{id:325,pid:314,name:"大宁县",level:3},326:{id:326,pid:314,name:"隰县",level:3},327:{id:327,pid:314,name:"永和县",level:3},328:{id:328,pid:314,name:"蒲县",level:3},329:{id:329,pid:314,name:"汾西县",level:3},330:{id:330,pid:314,name:"侯马市",level:3},331:{id:331,pid:314,name:"霍州市",level:3}}},332:{id:332,pid:217,name:"吕梁市",level:2,region:{333:{id:333,pid:332,name:"离石区",level:3},334:{id:334,pid:332,name:"文水县",level:3},335:{id:335,pid:332,name:"交城县",level:3},336:{id:336,pid:332,name:"兴县",level:3},337:{id:337,pid:332,name:"临县",level:3},338:{id:338,pid:332,name:"柳林县",level:3},339:{id:339,pid:332,name:"石楼县",level:3},340:{id:340,pid:332,name:"岚县",level:3},341:{id:341,pid:332,name:"方山县",level:3},342:{id:342,pid:332,name:"中阳县",level:3},343:{id:343,pid:332,name:"交口县",level:3},344:{id:344,pid:332,name:"孝义市",level:3},345:{id:345,pid:332,name:"汾阳市",level:3}}}}},346:{id:346,pid:0,name:"内蒙古自治区",level:1,city:{347:{id:347,pid:346,name:"呼和浩特市",level:2,region:{348:{id:348,pid:347,name:"新城区",level:3},349:{id:349,pid:347,name:"回民区",level:3},350:{id:350,pid:347,name:"玉泉区",level:3},351:{id:351,pid:347,name:"赛罕区",level:3},352:{id:352,pid:347,name:"土默特左旗",level:3},353:{id:353,pid:347,name:"托克托县",level:3},354:{id:354,pid:347,name:"和林格尔县",level:3},355:{id:355,pid:347,name:"清水河县",level:3},356:{id:356,pid:347,name:"武川县",level:3},3743:{id:3743,pid:347,name:"呼和浩特经济技术开发区",level:3}}},357:{id:357,pid:346,name:"包头市",level:2,region:{358:{id:358,pid:357,name:"东河区",level:3},359:{id:359,pid:357,name:"昆都仑区",level:3},360:{id:360,pid:357,name:"青山区",level:3},361:{id:361,pid:357,name:"石拐区",level:3},362:{id:362,pid:357,name:"白云鄂博矿区",level:3},363:{id:363,pid:357,name:"九原区",level:3},364:{id:364,pid:357,name:"土默特右旗",level:3},365:{id:365,pid:357,name:"固阳县",level:3},366:{id:366,pid:357,name:"达尔罕茂明安联合旗",level:3},3744:{id:3744,pid:357,name:"包头稀土高新技术产业开发区",level:3}}},367:{id:367,pid:346,name:"乌海市",level:2,region:{368:{id:368,pid:367,name:"海勃湾区",level:3},369:{id:369,pid:367,name:"海南区",level:3},370:{id:370,pid:367,name:"乌达区",level:3}}},371:{id:371,pid:346,name:"赤峰市",level:2,region:{372:{id:372,pid:371,name:"红山区",level:3},373:{id:373,pid:371,name:"元宝山区",level:3},374:{id:374,pid:371,name:"松山区",level:3},375:{id:375,pid:371,name:"阿鲁科尔沁旗",level:3},376:{id:376,pid:371,name:"巴林左旗",level:3},377:{id:377,pid:371,name:"巴林右旗",level:3},378:{id:378,pid:371,name:"林西县",level:3},379:{id:379,pid:371,name:"克什克腾旗",level:3},380:{id:380,pid:371,name:"翁牛特旗",level:3},381:{id:381,pid:371,name:"喀喇沁旗",level:3},382:{id:382,pid:371,name:"宁城县",level:3},383:{id:383,pid:371,name:"敖汉旗",level:3}}},384:{id:384,pid:346,name:"通辽市",level:2,region:{385:{id:385,pid:384,name:"科尔沁区",level:3},386:{id:386,pid:384,name:"科尔沁左翼中旗",level:3},387:{id:387,pid:384,name:"科尔沁左翼后旗",level:3},388:{id:388,pid:384,name:"开鲁县",level:3},389:{id:389,pid:384,name:"库伦旗",level:3},390:{id:390,pid:384,name:"奈曼旗",level:3},391:{id:391,pid:384,name:"扎鲁特旗",level:3},392:{id:392,pid:384,name:"霍林郭勒市",level:3},3745:{id:3745,pid:384,name:"通辽经济技术开发区",level:3}}},393:{id:393,pid:346,name:"鄂尔多斯市",level:2,region:{394:{id:394,pid:393,name:"东胜区",level:3},395:{id:395,pid:393,name:"康巴什区",level:3},396:{id:396,pid:393,name:"达拉特旗",level:3},397:{id:397,pid:393,name:"准格尔旗",level:3},398:{id:398,pid:393,name:"鄂托克前旗",level:3},399:{id:399,pid:393,name:"鄂托克旗",level:3},400:{id:400,pid:393,name:"杭锦旗",level:3},401:{id:401,pid:393,name:"乌审旗",level:3},402:{id:402,pid:393,name:"伊金霍洛旗",level:3}}},403:{id:403,pid:346,name:"呼伦贝尔市",level:2,region:{404:{id:404,pid:403,name:"海拉尔区",level:3},405:{id:405,pid:403,name:"扎赉诺尔区",level:3},406:{id:406,pid:403,name:"阿荣旗",level:3},407:{id:407,pid:403,name:"莫力达瓦达斡尔族自治旗",level:3},408:{id:408,pid:403,name:"鄂伦春自治旗",level:3},409:{id:409,pid:403,name:"鄂温克族自治旗",level:3},410:{id:410,pid:403,name:"陈巴尔虎旗",level:3},411:{id:411,pid:403,name:"新巴尔虎左旗",level:3},412:{id:412,pid:403,name:"新巴尔虎右旗",level:3},413:{id:413,pid:403,name:"满洲里市",level:3},414:{id:414,pid:403,name:"牙克石市",level:3},415:{id:415,pid:403,name:"扎兰屯市",level:3},416:{id:416,pid:403,name:"额尔古纳市",level:3},417:{id:417,pid:403,name:"根河市",level:3}}},418:{id:418,pid:346,name:"巴彦淖尔市",level:2,region:{419:{id:419,pid:418,name:"临河区",level:3},420:{id:420,pid:418,name:"五原县",level:3},421:{id:421,pid:418,name:"磴口县",level:3},422:{id:422,pid:418,name:"乌拉特前旗",level:3},423:{id:423,pid:418,name:"乌拉特中旗",level:3},424:{id:424,pid:418,name:"乌拉特后旗",level:3},425:{id:425,pid:418,name:"杭锦后旗",level:3}}},426:{id:426,pid:346,name:"乌兰察布市",level:2,region:{427:{id:427,pid:426,name:"集宁区",level:3},428:{id:428,pid:426,name:"卓资县",level:3},429:{id:429,pid:426,name:"化德县",level:3},430:{id:430,pid:426,name:"商都县",level:3},431:{id:431,pid:426,name:"兴和县",level:3},432:{id:432,pid:426,name:"凉城县",level:3},433:{id:433,pid:426,name:"察哈尔右翼前旗",level:3},434:{id:434,pid:426,name:"察哈尔右翼中旗",level:3},435:{id:435,pid:426,name:"察哈尔右翼后旗",level:3},436:{id:436,pid:426,name:"四子王旗",level:3},437:{id:437,pid:426,name:"丰镇市",level:3}}},438:{id:438,pid:346,name:"兴安盟",level:2,region:{439:{id:439,pid:438,name:"乌兰浩特市",level:3},440:{id:440,pid:438,name:"阿尔山市",level:3},441:{id:441,pid:438,name:"科尔沁右翼前旗",level:3},442:{id:442,pid:438,name:"科尔沁右翼中旗",level:3},443:{id:443,pid:438,name:"扎赉特旗",level:3},444:{id:444,pid:438,name:"突泉县",level:3}}},445:{id:445,pid:346,name:"锡林郭勒盟",level:2,region:{446:{id:446,pid:445,name:"二连浩特市",level:3},447:{id:447,pid:445,name:"锡林浩特市",level:3},448:{id:448,pid:445,name:"阿巴嘎旗",level:3},449:{id:449,pid:445,name:"苏尼特左旗",level:3},450:{id:450,pid:445,name:"苏尼特右旗",level:3},451:{id:451,pid:445,name:"东乌珠穆沁旗",level:3},452:{id:452,pid:445,name:"西乌珠穆沁旗",level:3},453:{id:453,pid:445,name:"太仆寺旗",level:3},454:{id:454,pid:445,name:"镶黄旗",level:3},455:{id:455,pid:445,name:"正镶白旗",level:3},456:{id:456,pid:445,name:"正蓝旗",level:3},457:{id:457,pid:445,name:"多伦县",level:3},3746:{id:3746,pid:445,name:"乌拉盖管委会",level:3}}},458:{id:458,pid:346,name:"阿拉善盟",level:2,region:{459:{id:459,pid:458,name:"阿拉善左旗",level:3},460:{id:460,pid:458,name:"阿拉善右旗",level:3},461:{id:461,pid:458,name:"额济纳旗",level:3},3747:{id:3747,pid:458,name:"内蒙古阿拉善高新技术产业开发区",level:3}}}}},462:{id:462,pid:0,name:"辽宁省",level:1,city:{463:{id:463,pid:462,name:"沈阳市",level:2,region:{464:{id:464,pid:463,name:"和平区",level:3},465:{id:465,pid:463,name:"沈河区",level:3},466:{id:466,pid:463,name:"大东区",level:3},467:{id:467,pid:463,name:"皇姑区",level:3},468:{id:468,pid:463,name:"铁西区",level:3},469:{id:469,pid:463,name:"苏家屯区",level:3},470:{id:470,pid:463,name:"浑南区",level:3},471:{id:471,pid:463,name:"沈北新区",level:3},472:{id:472,pid:463,name:"于洪区",level:3},473:{id:473,pid:463,name:"辽中区",level:3},474:{id:474,pid:463,name:"康平县",level:3},475:{id:475,pid:463,name:"法库县",level:3},476:{id:476,pid:463,name:"新民市",level:3}}},477:{id:477,pid:462,name:"大连市",level:2,region:{478:{id:478,pid:477,name:"中山区",level:3},479:{id:479,pid:477,name:"西岗区",level:3},480:{id:480,pid:477,name:"沙河口区",level:3},481:{id:481,pid:477,name:"甘井子区",level:3},482:{id:482,pid:477,name:"旅顺口区",level:3},483:{id:483,pid:477,name:"金州区",level:3},484:{id:484,pid:477,name:"普兰店区",level:3},485:{id:485,pid:477,name:"长海县",level:3},486:{id:486,pid:477,name:"瓦房店市",level:3},487:{id:487,pid:477,name:"庄河市",level:3}}},488:{id:488,pid:462,name:"鞍山市",level:2,region:{489:{id:489,pid:488,name:"铁东区",level:3},490:{id:490,pid:488,name:"铁西区",level:3},491:{id:491,pid:488,name:"立山区",level:3},492:{id:492,pid:488,name:"千山区",level:3},493:{id:493,pid:488,name:"台安县",level:3},494:{id:494,pid:488,name:"岫岩满族自治县",level:3},495:{id:495,pid:488,name:"海城市",level:3}}},496:{id:496,pid:462,name:"抚顺市",level:2,region:{497:{id:497,pid:496,name:"新抚区",level:3},498:{id:498,pid:496,name:"东洲区",level:3},499:{id:499,pid:496,name:"望花区",level:3},500:{id:500,pid:496,name:"顺城区",level:3},501:{id:501,pid:496,name:"抚顺县",level:3},502:{id:502,pid:496,name:"新宾满族自治县",level:3},503:{id:503,pid:496,name:"清原满族自治县",level:3}}},504:{id:504,pid:462,name:"本溪市",level:2,region:{505:{id:505,pid:504,name:"平山区",level:3},506:{id:506,pid:504,name:"溪湖区",level:3},507:{id:507,pid:504,name:"明山区",level:3},508:{id:508,pid:504,name:"南芬区",level:3},509:{id:509,pid:504,name:"本溪满族自治县",level:3},510:{id:510,pid:504,name:"桓仁满族自治县",level:3}}},511:{id:511,pid:462,name:"丹东市",level:2,region:{512:{id:512,pid:511,name:"元宝区",level:3},513:{id:513,pid:511,name:"振兴区",level:3},514:{id:514,pid:511,name:"振安区",level:3},515:{id:515,pid:511,name:"宽甸满族自治县",level:3},516:{id:516,pid:511,name:"东港市",level:3},517:{id:517,pid:511,name:"凤城市",level:3}}},518:{id:518,pid:462,name:"锦州市",level:2,region:{519:{id:519,pid:518,name:"古塔区",level:3},520:{id:520,pid:518,name:"凌河区",level:3},521:{id:521,pid:518,name:"太和区",level:3},522:{id:522,pid:518,name:"黑山县",level:3},523:{id:523,pid:518,name:"义县",level:3},524:{id:524,pid:518,name:"凌海市",level:3},525:{id:525,pid:518,name:"北镇市",level:3}}},526:{id:526,pid:462,name:"营口市",level:2,region:{527:{id:527,pid:526,name:"站前区",level:3},528:{id:528,pid:526,name:"西市区",level:3},529:{id:529,pid:526,name:"鲅鱼圈区",level:3},530:{id:530,pid:526,name:"老边区",level:3},531:{id:531,pid:526,name:"盖州市",level:3},532:{id:532,pid:526,name:"大石桥市",level:3}}},533:{id:533,pid:462,name:"阜新市",level:2,region:{534:{id:534,pid:533,name:"海州区",level:3},535:{id:535,pid:533,name:"新邱区",level:3},536:{id:536,pid:533,name:"太平区",level:3},537:{id:537,pid:533,name:"清河门区",level:3},538:{id:538,pid:533,name:"细河区",level:3},539:{id:539,pid:533,name:"阜新蒙古族自治县",level:3},540:{id:540,pid:533,name:"彰武县",level:3}}},541:{id:541,pid:462,name:"辽阳市",level:2,region:{542:{id:542,pid:541,name:"白塔区",level:3},543:{id:543,pid:541,name:"文圣区",level:3},544:{id:544,pid:541,name:"宏伟区",level:3},545:{id:545,pid:541,name:"弓长岭区",level:3},546:{id:546,pid:541,name:"太子河区",level:3},547:{id:547,pid:541,name:"辽阳县",level:3},548:{id:548,pid:541,name:"灯塔市",level:3}}},549:{id:549,pid:462,name:"盘锦市",level:2,region:{550:{id:550,pid:549,name:"双台子区",level:3},551:{id:551,pid:549,name:"兴隆台区",level:3},552:{id:552,pid:549,name:"大洼区",level:3},553:{id:553,pid:549,name:"盘山县",level:3}}},554:{id:554,pid:462,name:"铁岭市",level:2,region:{555:{id:555,pid:554,name:"银州区",level:3},556:{id:556,pid:554,name:"清河区",level:3},557:{id:557,pid:554,name:"铁岭县",level:3},558:{id:558,pid:554,name:"西丰县",level:3},559:{id:559,pid:554,name:"昌图县",level:3},560:{id:560,pid:554,name:"调兵山市",level:3},561:{id:561,pid:554,name:"开原市",level:3}}},562:{id:562,pid:462,name:"朝阳市",level:2,region:{563:{id:563,pid:562,name:"双塔区",level:3},564:{id:564,pid:562,name:"龙城区",level:3},565:{id:565,pid:562,name:"朝阳县",level:3},566:{id:566,pid:562,name:"建平县",level:3},567:{id:567,pid:562,name:"喀喇沁左翼蒙古族自治县",level:3},568:{id:568,pid:562,name:"北票市",level:3},569:{id:569,pid:562,name:"凌源市",level:3}}},570:{id:570,pid:462,name:"葫芦岛市",level:2,region:{571:{id:571,pid:570,name:"连山区",level:3},572:{id:572,pid:570,name:"龙港区",level:3},573:{id:573,pid:570,name:"南票区",level:3},574:{id:574,pid:570,name:"绥中县",level:3},575:{id:575,pid:570,name:"建昌县",level:3},576:{id:576,pid:570,name:"兴城市",level:3}}}}},577:{id:577,pid:0,name:"吉林省",level:1,city:{578:{id:578,pid:577,name:"长春市",level:2,region:{579:{id:579,pid:578,name:"南关区",level:3},580:{id:580,pid:578,name:"宽城区",level:3},581:{id:581,pid:578,name:"朝阳区",level:3},582:{id:582,pid:578,name:"二道区",level:3},583:{id:583,pid:578,name:"绿园区",level:3},584:{id:584,pid:578,name:"双阳区",level:3},585:{id:585,pid:578,name:"九台区",level:3},586:{id:586,pid:578,name:"农安县",level:3},587:{id:587,pid:578,name:"榆树市",level:3},588:{id:588,pid:578,name:"德惠市",level:3},3748:{id:3748,pid:578,name:"长春经济技术开发区",level:3},3749:{id:3749,pid:578,name:"长春净月高新技术产业开发区",level:3},3750:{id:3750,pid:578,name:"长春高新技术产业开发区",level:3},3751:{id:3751,pid:578,name:"长春汽车经济技术开发区",level:3},3752:{id:3752,pid:578,name:"公主岭市",level:3}}},589:{id:589,pid:577,name:"吉林市",level:2,region:{590:{id:590,pid:589,name:"昌邑区",level:3},591:{id:591,pid:589,name:"龙潭区",level:3},592:{id:592,pid:589,name:"船营区",level:3},593:{id:593,pid:589,name:"丰满区",level:3},594:{id:594,pid:589,name:"永吉县",level:3},595:{id:595,pid:589,name:"蛟河市",level:3},596:{id:596,pid:589,name:"桦甸市",level:3},597:{id:597,pid:589,name:"舒兰市",level:3},598:{id:598,pid:589,name:"磐石市",level:3},3753:{id:3753,pid:589,name:"吉林经济开发区",level:3},3754:{id:3754,pid:589,name:"吉林高新技术产业开发区",level:3},3755:{id:3755,pid:589,name:"吉林中国新加坡食品区",level:3}}},599:{id:599,pid:577,name:"四平市",level:2,region:{600:{id:600,pid:599,name:"铁西区",level:3},601:{id:601,pid:599,name:"铁东区",level:3},602:{id:602,pid:599,name:"梨树县",level:3},603:{id:603,pid:599,name:"伊通满族自治县",level:3},605:{id:605,pid:599,name:"双辽市",level:3}}},606:{id:606,pid:577,name:"辽源市",level:2,region:{607:{id:607,pid:606,name:"龙山区",level:3},608:{id:608,pid:606,name:"西安区",level:3},609:{id:609,pid:606,name:"东丰县",level:3},610:{id:610,pid:606,name:"东辽县",level:3}}},611:{id:611,pid:577,name:"通化市",level:2,region:{612:{id:612,pid:611,name:"东昌区",level:3},613:{id:613,pid:611,name:"二道江区",level:3},614:{id:614,pid:611,name:"通化县",level:3},615:{id:615,pid:611,name:"辉南县",level:3},616:{id:616,pid:611,name:"柳河县",level:3},617:{id:617,pid:611,name:"梅河口市",level:3},618:{id:618,pid:611,name:"集安市",level:3}}},619:{id:619,pid:577,name:"白山市",level:2,region:{620:{id:620,pid:619,name:"浑江区",level:3},621:{id:621,pid:619,name:"江源区",level:3},622:{id:622,pid:619,name:"抚松县",level:3},623:{id:623,pid:619,name:"靖宇县",level:3},624:{id:624,pid:619,name:"长白朝鲜族自治县",level:3},625:{id:625,pid:619,name:"临江市",level:3}}},626:{id:626,pid:577,name:"松原市",level:2,region:{627:{id:627,pid:626,name:"宁江区",level:3},628:{id:628,pid:626,name:"前郭尔罗斯蒙古族自治县",level:3},629:{id:629,pid:626,name:"长岭县",level:3},630:{id:630,pid:626,name:"乾安县",level:3},631:{id:631,pid:626,name:"扶余市",level:3},3756:{id:3756,pid:626,name:"吉林松原经济开发区",level:3}}},632:{id:632,pid:577,name:"白城市",level:2,region:{633:{id:633,pid:632,name:"洮北区",level:3},634:{id:634,pid:632,name:"镇赉县",level:3},635:{id:635,pid:632,name:"通榆县",level:3},636:{id:636,pid:632,name:"洮南市",level:3},637:{id:637,pid:632,name:"大安市",level:3},3757:{id:3757,pid:632,name:"吉林白城经济开发区",level:3}}},638:{id:638,pid:577,name:"延边朝鲜族自治州",level:2,region:{639:{id:639,pid:638,name:"延吉市",level:3},640:{id:640,pid:638,name:"图们市",level:3},641:{id:641,pid:638,name:"敦化市",level:3},642:{id:642,pid:638,name:"珲春市",level:3},643:{id:643,pid:638,name:"龙井市",level:3},644:{id:644,pid:638,name:"和龙市",level:3},645:{id:645,pid:638,name:"汪清县",level:3},646:{id:646,pid:638,name:"安图县",level:3}}}}},647:{id:647,pid:0,name:"黑龙江省",level:1,city:{648:{id:648,pid:647,name:"哈尔滨市",level:2,region:{649:{id:649,pid:648,name:"道里区",level:3},650:{id:650,pid:648,name:"南岗区",level:3},651:{id:651,pid:648,name:"道外区",level:3},652:{id:652,pid:648,name:"平房区",level:3},653:{id:653,pid:648,name:"松北区",level:3},654:{id:654,pid:648,name:"香坊区",level:3},655:{id:655,pid:648,name:"呼兰区",level:3},656:{id:656,pid:648,name:"阿城区",level:3},657:{id:657,pid:648,name:"双城区",level:3},658:{id:658,pid:648,name:"依兰县",level:3},659:{id:659,pid:648,name:"方正县",level:3},660:{id:660,pid:648,name:"宾县",level:3},661:{id:661,pid:648,name:"巴彦县",level:3},662:{id:662,pid:648,name:"木兰县",level:3},663:{id:663,pid:648,name:"通河县",level:3},664:{id:664,pid:648,name:"延寿县",level:3},665:{id:665,pid:648,name:"尚志市",level:3},666:{id:666,pid:648,name:"五常市",level:3}}},667:{id:667,pid:647,name:"齐齐哈尔市",level:2,region:{668:{id:668,pid:667,name:"龙沙区",level:3},669:{id:669,pid:667,name:"建华区",level:3},670:{id:670,pid:667,name:"铁锋区",level:3},671:{id:671,pid:667,name:"昂昂溪区",level:3},672:{id:672,pid:667,name:"富拉尔基区",level:3},673:{id:673,pid:667,name:"碾子山区",level:3},674:{id:674,pid:667,name:"梅里斯达斡尔族区",level:3},675:{id:675,pid:667,name:"龙江县",level:3},676:{id:676,pid:667,name:"依安县",level:3},677:{id:677,pid:667,name:"泰来县",level:3},678:{id:678,pid:667,name:"甘南县",level:3},679:{id:679,pid:667,name:"富裕县",level:3},680:{id:680,pid:667,name:"克山县",level:3},681:{id:681,pid:667,name:"克东县",level:3},682:{id:682,pid:667,name:"拜泉县",level:3},683:{id:683,pid:667,name:"讷河市",level:3}}},684:{id:684,pid:647,name:"鸡西市",level:2,region:{685:{id:685,pid:684,name:"鸡冠区",level:3},686:{id:686,pid:684,name:"恒山区",level:3},687:{id:687,pid:684,name:"滴道区",level:3},688:{id:688,pid:684,name:"梨树区",level:3},689:{id:689,pid:684,name:"城子河区",level:3},690:{id:690,pid:684,name:"麻山区",level:3},691:{id:691,pid:684,name:"鸡东县",level:3},692:{id:692,pid:684,name:"虎林市",level:3},693:{id:693,pid:684,name:"密山市",level:3}}},694:{id:694,pid:647,name:"鹤岗市",level:2,region:{695:{id:695,pid:694,name:"向阳区",level:3},696:{id:696,pid:694,name:"工农区",level:3},697:{id:697,pid:694,name:"南山区",level:3},698:{id:698,pid:694,name:"兴安区",level:3},699:{id:699,pid:694,name:"东山区",level:3},700:{id:700,pid:694,name:"兴山区",level:3},701:{id:701,pid:694,name:"萝北县",level:3},702:{id:702,pid:694,name:"绥滨县",level:3}}},703:{id:703,pid:647,name:"双鸭山市",level:2,region:{704:{id:704,pid:703,name:"尖山区",level:3},705:{id:705,pid:703,name:"岭东区",level:3},706:{id:706,pid:703,name:"四方台区",level:3},707:{id:707,pid:703,name:"宝山区",level:3},708:{id:708,pid:703,name:"集贤县",level:3},709:{id:709,pid:703,name:"友谊县",level:3},710:{id:710,pid:703,name:"宝清县",level:3},711:{id:711,pid:703,name:"饶河县",level:3}}},712:{id:712,pid:647,name:"大庆市",level:2,region:{713:{id:713,pid:712,name:"萨尔图区",level:3},714:{id:714,pid:712,name:"龙凤区",level:3},715:{id:715,pid:712,name:"让胡路区",level:3},716:{id:716,pid:712,name:"红岗区",level:3},717:{id:717,pid:712,name:"大同区",level:3},718:{id:718,pid:712,name:"肇州县",level:3},719:{id:719,pid:712,name:"肇源县",level:3},720:{id:720,pid:712,name:"林甸县",level:3},721:{id:721,pid:712,name:"杜尔伯特蒙古族自治县",level:3},3758:{id:3758,pid:712,name:"大庆高新技术产业开发区",level:3}}},722:{id:722,pid:647,name:"伊春市",level:2,region:{723:{id:723,pid:722,name:"伊美区",level:3},724:{id:724,pid:722,name:"乌翠区",level:3},725:{id:725,pid:722,name:"友好区",level:3},726:{id:726,pid:722,name:"嘉荫县",level:3},727:{id:727,pid:722,name:"汤旺县",level:3},728:{id:728,pid:722,name:"丰林县",level:3},729:{id:729,pid:722,name:"大箐山县",level:3},730:{id:730,pid:722,name:"南岔县",level:3},731:{id:731,pid:722,name:"金林区",level:3},732:{id:732,pid:722,name:"铁力市",level:3}}},733:{id:733,pid:647,name:"佳木斯市",level:2,region:{734:{id:734,pid:733,name:"向阳区",level:3},735:{id:735,pid:733,name:"前进区",level:3},736:{id:736,pid:733,name:"东风区",level:3},737:{id:737,pid:733,name:"郊区",level:3},738:{id:738,pid:733,name:"桦南县",level:3},739:{id:739,pid:733,name:"桦川县",level:3},740:{id:740,pid:733,name:"汤原县",level:3},741:{id:741,pid:733,name:"同江市",level:3},742:{id:742,pid:733,name:"富锦市",level:3},743:{id:743,pid:733,name:"抚远市",level:3}}},744:{id:744,pid:647,name:"七台河市",level:2,region:{745:{id:745,pid:744,name:"新兴区",level:3},746:{id:746,pid:744,name:"桃山区",level:3},747:{id:747,pid:744,name:"茄子河区",level:3},748:{id:748,pid:744,name:"勃利县",level:3}}},749:{id:749,pid:647,name:"牡丹江市",level:2,region:{750:{id:750,pid:749,name:"东安区",level:3},751:{id:751,pid:749,name:"阳明区",level:3},752:{id:752,pid:749,name:"爱民区",level:3},753:{id:753,pid:749,name:"西安区",level:3},754:{id:754,pid:749,name:"林口县",level:3},755:{id:755,pid:749,name:"绥芬河市",level:3},756:{id:756,pid:749,name:"海林市",level:3},757:{id:757,pid:749,name:"宁安市",level:3},758:{id:758,pid:749,name:"穆棱市",level:3},759:{id:759,pid:749,name:"东宁市",level:3},3759:{id:3759,pid:749,name:"牡丹江经济技术开发区",level:3}}},760:{id:760,pid:647,name:"黑河市",level:2,region:{761:{id:761,pid:760,name:"爱辉区",level:3},762:{id:762,pid:760,name:"逊克县",level:3},763:{id:763,pid:760,name:"孙吴县",level:3},764:{id:764,pid:760,name:"北安市",level:3},765:{id:765,pid:760,name:"五大连池市",level:3},766:{id:766,pid:760,name:"嫩江市",level:3}}},767:{id:767,pid:647,name:"绥化市",level:2,region:{768:{id:768,pid:767,name:"北林区",level:3},769:{id:769,pid:767,name:"望奎县",level:3},770:{id:770,pid:767,name:"兰西县",level:3},771:{id:771,pid:767,name:"青冈县",level:3},772:{id:772,pid:767,name:"庆安县",level:3},773:{id:773,pid:767,name:"明水县",level:3},774:{id:774,pid:767,name:"绥棱县",level:3},775:{id:775,pid:767,name:"安达市",level:3},776:{id:776,pid:767,name:"肇东市",level:3},777:{id:777,pid:767,name:"海伦市",level:3}}},778:{id:778,pid:647,name:"大兴安岭地区",level:2,region:{779:{id:779,pid:778,name:"漠河市",level:3},780:{id:780,pid:778,name:"呼玛县",level:3},781:{id:781,pid:778,name:"塔河县",level:3},3760:{id:3760,pid:778,name:"加格达奇区",level:3},3761:{id:3761,pid:778,name:"松岭区",level:3},3762:{id:3762,pid:778,name:"新林区",level:3},3763:{id:3763,pid:778,name:"呼中区",level:3}}}}},782:{id:782,pid:0,name:"上海市",level:1,city:{783:{id:783,pid:782,name:"上海市",level:2,region:{784:{id:784,pid:783,name:"黄浦区",level:3},785:{id:785,pid:783,name:"徐汇区",level:3},786:{id:786,pid:783,name:"长宁区",level:3},787:{id:787,pid:783,name:"静安区",level:3},788:{id:788,pid:783,name:"普陀区",level:3},789:{id:789,pid:783,name:"虹口区",level:3},790:{id:790,pid:783,name:"杨浦区",level:3},791:{id:791,pid:783,name:"闵行区",level:3},792:{id:792,pid:783,name:"宝山区",level:3},793:{id:793,pid:783,name:"嘉定区",level:3},794:{id:794,pid:783,name:"浦东新区",level:3},795:{id:795,pid:783,name:"金山区",level:3},796:{id:796,pid:783,name:"松江区",level:3},797:{id:797,pid:783,name:"青浦区",level:3},798:{id:798,pid:783,name:"奉贤区",level:3},799:{id:799,pid:783,name:"崇明区",level:3}}}}},800:{id:800,pid:0,name:"江苏省",level:1,city:{801:{id:801,pid:800,name:"南京市",level:2,region:{802:{id:802,pid:801,name:"玄武区",level:3},803:{id:803,pid:801,name:"秦淮区",level:3},804:{id:804,pid:801,name:"建邺区",level:3},805:{id:805,pid:801,name:"鼓楼区",level:3},806:{id:806,pid:801,name:"浦口区",level:3},807:{id:807,pid:801,name:"栖霞区",level:3},808:{id:808,pid:801,name:"雨花台区",level:3},809:{id:809,pid:801,name:"江宁区",level:3},810:{id:810,pid:801,name:"六合区",level:3},811:{id:811,pid:801,name:"溧水区",level:3},812:{id:812,pid:801,name:"高淳区",level:3}}},813:{id:813,pid:800,name:"无锡市",level:2,region:{814:{id:814,pid:813,name:"锡山区",level:3},815:{id:815,pid:813,name:"惠山区",level:3},816:{id:816,pid:813,name:"滨湖区",level:3},817:{id:817,pid:813,name:"梁溪区",level:3},818:{id:818,pid:813,name:"新吴区",level:3},819:{id:819,pid:813,name:"江阴市",level:3},820:{id:820,pid:813,name:"宜兴市",level:3}}},821:{id:821,pid:800,name:"徐州市",level:2,region:{822:{id:822,pid:821,name:"鼓楼区",level:3},823:{id:823,pid:821,name:"云龙区",level:3},824:{id:824,pid:821,name:"贾汪区",level:3},825:{id:825,pid:821,name:"泉山区",level:3},826:{id:826,pid:821,name:"铜山区",level:3},827:{id:827,pid:821,name:"丰县",level:3},828:{id:828,pid:821,name:"沛县",level:3},829:{id:829,pid:821,name:"睢宁县",level:3},830:{id:830,pid:821,name:"新沂市",level:3},831:{id:831,pid:821,name:"邳州市",level:3},3764:{id:3764,pid:821,name:"徐州经济技术开发区",level:3}}},832:{id:832,pid:800,name:"常州市",level:2,region:{833:{id:833,pid:832,name:"天宁区",level:3},834:{id:834,pid:832,name:"钟楼区",level:3},835:{id:835,pid:832,name:"新北区",level:3},836:{id:836,pid:832,name:"武进区",level:3},837:{id:837,pid:832,name:"金坛区",level:3},838:{id:838,pid:832,name:"溧阳市",level:3}}},839:{id:839,pid:800,name:"苏州市",level:2,region:{840:{id:840,pid:839,name:"虎丘区",level:3},841:{id:841,pid:839,name:"吴中区",level:3},842:{id:842,pid:839,name:"相城区",level:3},843:{id:843,pid:839,name:"姑苏区",level:3},844:{id:844,pid:839,name:"吴江区",level:3},845:{id:845,pid:839,name:"常熟市",level:3},846:{id:846,pid:839,name:"张家港市",level:3},847:{id:847,pid:839,name:"昆山市",level:3},848:{id:848,pid:839,name:"太仓市",level:3},3765:{id:3765,pid:839,name:"苏州工业园区",level:3}}},849:{id:849,pid:800,name:"南通市",level:2,region:{852:{id:852,pid:849,name:"通州区",level:3},853:{id:853,pid:849,name:"如东县",level:3},854:{id:854,pid:849,name:"启东市",level:3},855:{id:855,pid:849,name:"如皋市",level:3},857:{id:857,pid:849,name:"海安市",level:3},3766:{id:3766,pid:849,name:"崇川区",level:3},3767:{id:3767,pid:849,name:"海门区",level:3},3768:{id:3768,pid:849,name:"南通经济技术开发区",level:3}}},858:{id:858,pid:800,name:"连云港市",level:2,region:{859:{id:859,pid:858,name:"连云区",level:3},860:{id:860,pid:858,name:"海州区",level:3},861:{id:861,pid:858,name:"赣榆区",level:3},862:{id:862,pid:858,name:"东海县",level:3},863:{id:863,pid:858,name:"灌云县",level:3},864:{id:864,pid:858,name:"灌南县",level:3},3769:{id:3769,pid:858,name:"连云港经济技术开发区",level:3},3770:{id:3770,pid:858,name:"连云港高新技术产业开发区",level:3}}},865:{id:865,pid:800,name:"淮安市",level:2,region:{866:{id:866,pid:865,name:"淮安区",level:3},867:{id:867,pid:865,name:"淮阴区",level:3},868:{id:868,pid:865,name:"清江浦区",level:3},869:{id:869,pid:865,name:"洪泽区",level:3},870:{id:870,pid:865,name:"涟水县",level:3},871:{id:871,pid:865,name:"盱眙县",level:3},872:{id:872,pid:865,name:"金湖县",level:3},3771:{id:3771,pid:865,name:"淮安经济技术开发区",level:3}}},873:{id:873,pid:800,name:"盐城市",level:2,region:{874:{id:874,pid:873,name:"亭湖区",level:3},875:{id:875,pid:873,name:"盐都区",level:3},876:{id:876,pid:873,name:"大丰区",level:3},877:{id:877,pid:873,name:"响水县",level:3},878:{id:878,pid:873,name:"滨海县",level:3},879:{id:879,pid:873,name:"阜宁县",level:3},880:{id:880,pid:873,name:"射阳县",level:3},881:{id:881,pid:873,name:"建湖县",level:3},882:{id:882,pid:873,name:"东台市",level:3},3772:{id:3772,pid:873,name:"盐城经济技术开发区",level:3}}},883:{id:883,pid:800,name:"扬州市",level:2,region:{884:{id:884,pid:883,name:"广陵区",level:3},885:{id:885,pid:883,name:"邗江区",level:3},886:{id:886,pid:883,name:"江都区",level:3},887:{id:887,pid:883,name:"宝应县",level:3},888:{id:888,pid:883,name:"仪征市",level:3},889:{id:889,pid:883,name:"高邮市",level:3},3773:{id:3773,pid:883,name:"扬州经济技术开发区",level:3}}},890:{id:890,pid:800,name:"镇江市",level:2,region:{891:{id:891,pid:890,name:"京口区",level:3},892:{id:892,pid:890,name:"润州区",level:3},893:{id:893,pid:890,name:"丹徒区",level:3},894:{id:894,pid:890,name:"丹阳市",level:3},895:{id:895,pid:890,name:"扬中市",level:3},896:{id:896,pid:890,name:"句容市",level:3},3774:{id:3774,pid:890,name:"镇江新区",level:3}}},897:{id:897,pid:800,name:"泰州市",level:2,region:{898:{id:898,pid:897,name:"海陵区",level:3},899:{id:899,pid:897,name:"高港区",level:3},900:{id:900,pid:897,name:"姜堰区",level:3},901:{id:901,pid:897,name:"兴化市",level:3},902:{id:902,pid:897,name:"靖江市",level:3},903:{id:903,pid:897,name:"泰兴市",level:3},3775:{id:3775,pid:897,name:"泰州医药高新技术产业开发区",level:3}}},904:{id:904,pid:800,name:"宿迁市",level:2,region:{905:{id:905,pid:904,name:"宿城区",level:3},906:{id:906,pid:904,name:"宿豫区",level:3},907:{id:907,pid:904,name:"沭阳县",level:3},908:{id:908,pid:904,name:"泗阳县",level:3},909:{id:909,pid:904,name:"泗洪县",level:3},3776:{id:3776,pid:904,name:"宿迁经济技术开发区",level:3}}}}},910:{id:910,pid:0,name:"浙江省",level:1,city:{911:{id:911,pid:910,name:"杭州市",level:2,region:{912:{id:912,pid:911,name:"上城区",level:3},915:{id:915,pid:911,name:"拱墅区",level:3},916:{id:916,pid:911,name:"西湖区",level:3},917:{id:917,pid:911,name:"滨江区",level:3},918:{id:918,pid:911,name:"萧山区",level:3},919:{id:919,pid:911,name:"余杭区",level:3},920:{id:920,pid:911,name:"富阳区",level:3},921:{id:921,pid:911,name:"临安区",level:3},922:{id:922,pid:911,name:"桐庐县",level:3},923:{id:923,pid:911,name:"淳安县",level:3},924:{id:924,pid:911,name:"建德市",level:3},3777:{id:3777,pid:911,name:"临平区",level:3},3778:{id:3778,pid:911,name:"钱塘区",level:3}}},925:{id:925,pid:910,name:"宁波市",level:2,region:{926:{id:926,pid:925,name:"海曙区",level:3},927:{id:927,pid:925,name:"江北区",level:3},928:{id:928,pid:925,name:"北仑区",level:3},929:{id:929,pid:925,name:"镇海区",level:3},930:{id:930,pid:925,name:"鄞州区",level:3},931:{id:931,pid:925,name:"奉化区",level:3},932:{id:932,pid:925,name:"象山县",level:3},933:{id:933,pid:925,name:"宁海县",level:3},934:{id:934,pid:925,name:"余姚市",level:3},935:{id:935,pid:925,name:"慈溪市",level:3}}},936:{id:936,pid:910,name:"温州市",level:2,region:{937:{id:937,pid:936,name:"鹿城区",level:3},938:{id:938,pid:936,name:"龙湾区",level:3},939:{id:939,pid:936,name:"瓯海区",level:3},940:{id:940,pid:936,name:"洞头区",level:3},941:{id:941,pid:936,name:"永嘉县",level:3},942:{id:942,pid:936,name:"平阳县",level:3},943:{id:943,pid:936,name:"苍南县",level:3},944:{id:944,pid:936,name:"文成县",level:3},945:{id:945,pid:936,name:"泰顺县",level:3},946:{id:946,pid:936,name:"瑞安市",level:3},947:{id:947,pid:936,name:"乐清市",level:3},948:{id:948,pid:936,name:"龙港市",level:3}}},949:{id:949,pid:910,name:"嘉兴市",level:2,region:{950:{id:950,pid:949,name:"南湖区",level:3},951:{id:951,pid:949,name:"秀洲区",level:3},952:{id:952,pid:949,name:"嘉善县",level:3},953:{id:953,pid:949,name:"海盐县",level:3},954:{id:954,pid:949,name:"海宁市",level:3},955:{id:955,pid:949,name:"平湖市",level:3},956:{id:956,pid:949,name:"桐乡市",level:3}}},957:{id:957,pid:910,name:"湖州市",level:2,region:{958:{id:958,pid:957,name:"吴兴区",level:3},959:{id:959,pid:957,name:"南浔区",level:3},960:{id:960,pid:957,name:"德清县",level:3},961:{id:961,pid:957,name:"长兴县",level:3},962:{id:962,pid:957,name:"安吉县",level:3}}},963:{id:963,pid:910,name:"绍兴市",level:2,region:{964:{id:964,pid:963,name:"越城区",level:3},965:{id:965,pid:963,name:"柯桥区",level:3},966:{id:966,pid:963,name:"上虞区",level:3},967:{id:967,pid:963,name:"新昌县",level:3},968:{id:968,pid:963,name:"诸暨市",level:3},969:{id:969,pid:963,name:"嵊州市",level:3}}},970:{id:970,pid:910,name:"金华市",level:2,region:{971:{id:971,pid:970,name:"婺城区",level:3},972:{id:972,pid:970,name:"金东区",level:3},973:{id:973,pid:970,name:"武义县",level:3},974:{id:974,pid:970,name:"浦江县",level:3},975:{id:975,pid:970,name:"磐安县",level:3},976:{id:976,pid:970,name:"兰溪市",level:3},977:{id:977,pid:970,name:"义乌市",level:3},978:{id:978,pid:970,name:"东阳市",level:3},979:{id:979,pid:970,name:"永康市",level:3}}},980:{id:980,pid:910,name:"衢州市",level:2,region:{981:{id:981,pid:980,name:"柯城区",level:3},982:{id:982,pid:980,name:"衢江区",level:3},983:{id:983,pid:980,name:"常山县",level:3},984:{id:984,pid:980,name:"开化县",level:3},985:{id:985,pid:980,name:"龙游县",level:3},986:{id:986,pid:980,name:"江山市",level:3}}},987:{id:987,pid:910,name:"舟山市",level:2,region:{988:{id:988,pid:987,name:"定海区",level:3},989:{id:989,pid:987,name:"普陀区",level:3},990:{id:990,pid:987,name:"岱山县",level:3},991:{id:991,pid:987,name:"嵊泗县",level:3}}},992:{id:992,pid:910,name:"台州市",level:2,region:{993:{id:993,pid:992,name:"椒江区",level:3},994:{id:994,pid:992,name:"黄岩区",level:3},995:{id:995,pid:992,name:"路桥区",level:3},996:{id:996,pid:992,name:"三门县",level:3},997:{id:997,pid:992,name:"天台县",level:3},998:{id:998,pid:992,name:"仙居县",level:3},999:{id:999,pid:992,name:"温岭市",level:3},1e3:{id:1e3,pid:992,name:"临海市",level:3},1001:{id:1001,pid:992,name:"玉环市",level:3}}},1002:{id:1002,pid:910,name:"丽水市",level:2,region:{1003:{id:1003,pid:1002,name:"莲都区",level:3},1004:{id:1004,pid:1002,name:"青田县",level:3},1005:{id:1005,pid:1002,name:"缙云县",level:3},1006:{id:1006,pid:1002,name:"遂昌县",level:3},1007:{id:1007,pid:1002,name:"松阳县",level:3},1008:{id:1008,pid:1002,name:"云和县",level:3},1009:{id:1009,pid:1002,name:"庆元县",level:3},1010:{id:1010,pid:1002,name:"景宁畲族自治县",level:3},1011:{id:1011,pid:1002,name:"龙泉市",level:3}}}}},1012:{id:1012,pid:0,name:"安徽省",level:1,city:{1013:{id:1013,pid:1012,name:"合肥市",level:2,region:{1014:{id:1014,pid:1013,name:"瑶海区",level:3},1015:{id:1015,pid:1013,name:"庐阳区",level:3},1016:{id:1016,pid:1013,name:"蜀山区",level:3},1017:{id:1017,pid:1013,name:"包河区",level:3},1018:{id:1018,pid:1013,name:"长丰县",level:3},1019:{id:1019,pid:1013,name:"肥东县",level:3},1020:{id:1020,pid:1013,name:"肥西县",level:3},1021:{id:1021,pid:1013,name:"庐江县",level:3},1022:{id:1022,pid:1013,name:"巢湖市",level:3},3779:{id:3779,pid:1013,name:"合肥高新技术产业开发区",level:3},3780:{id:3780,pid:1013,name:"合肥经济技术开发区",level:3},3781:{id:3781,pid:1013,name:"合肥新站高新技术产业开发区",level:3}}},1023:{id:1023,pid:1012,name:"芜湖市",level:2,region:{1024:{id:1024,pid:1023,name:"镜湖区",level:3},1026:{id:1026,pid:1023,name:"鸠江区",level:3},1030:{id:1030,pid:1023,name:"南陵县",level:3},1031:{id:1031,pid:1023,name:"无为市",level:3},3782:{id:3782,pid:1023,name:"弋江区",level:3},3783:{id:3783,pid:1023,name:"湾沚区",level:3},3784:{id:3784,pid:1023,name:"繁昌区",level:3},3785:{id:3785,pid:1023,name:"芜湖经济技术开发区",level:3},3786:{id:3786,pid:1023,name:"安徽芜湖三山经济开发区",level:3}}},1032:{id:1032,pid:1012,name:"蚌埠市",level:2,region:{1033:{id:1033,pid:1032,name:"龙子湖区",level:3},1034:{id:1034,pid:1032,name:"蚌山区",level:3},1035:{id:1035,pid:1032,name:"禹会区",level:3},1036:{id:1036,pid:1032,name:"淮上区",level:3},1037:{id:1037,pid:1032,name:"怀远县",level:3},1038:{id:1038,pid:1032,name:"五河县",level:3},1039:{id:1039,pid:1032,name:"固镇县",level:3},3787:{id:3787,pid:1032,name:"蚌埠市高新技术开发区",level:3},3788:{id:3788,pid:1032,name:"蚌埠市经济开发区",level:3}}},1040:{id:1040,pid:1012,name:"淮南市",level:2,region:{1041:{id:1041,pid:1040,name:"大通区",level:3},1042:{id:1042,pid:1040,name:"田家庵区",level:3},1043:{id:1043,pid:1040,name:"谢家集区",level:3},1044:{id:1044,pid:1040,name:"八公山区",level:3},1045:{id:1045,pid:1040,name:"潘集区",level:3},1046:{id:1046,pid:1040,name:"凤台县",level:3},1047:{id:1047,pid:1040,name:"寿县",level:3}}},1048:{id:1048,pid:1012,name:"马鞍山市",level:2,region:{1049:{id:1049,pid:1048,name:"花山区",level:3},1050:{id:1050,pid:1048,name:"雨山区",level:3},1051:{id:1051,pid:1048,name:"博望区",level:3},1052:{id:1052,pid:1048,name:"当涂县",level:3},1053:{id:1053,pid:1048,name:"含山县",level:3},1054:{id:1054,pid:1048,name:"和县",level:3}}},1055:{id:1055,pid:1012,name:"淮北市",level:2,region:{1056:{id:1056,pid:1055,name:"杜集区",level:3},1057:{id:1057,pid:1055,name:"相山区",level:3},1058:{id:1058,pid:1055,name:"烈山区",level:3},1059:{id:1059,pid:1055,name:"濉溪县",level:3}}},1060:{id:1060,pid:1012,name:"铜陵市",level:2,region:{1061:{id:1061,pid:1060,name:"铜官区",level:3},1062:{id:1062,pid:1060,name:"义安区",level:3},1063:{id:1063,pid:1060,name:"郊区",level:3},1064:{id:1064,pid:1060,name:"枞阳县",level:3}}},1065:{id:1065,pid:1012,name:"安庆市",level:2,region:{1066:{id:1066,pid:1065,name:"迎江区",level:3},1067:{id:1067,pid:1065,name:"大观区",level:3},1068:{id:1068,pid:1065,name:"宜秀区",level:3},1069:{id:1069,pid:1065,name:"怀宁县",level:3},1070:{id:1070,pid:1065,name:"太湖县",level:3},1071:{id:1071,pid:1065,name:"宿松县",level:3},1072:{id:1072,pid:1065,name:"望江县",level:3},1073:{id:1073,pid:1065,name:"岳西县",level:3},1074:{id:1074,pid:1065,name:"桐城市",level:3},1075:{id:1075,pid:1065,name:"潜山市",level:3},3789:{id:3789,pid:1065,name:"安徽安庆经济开发区",level:3}}},1076:{id:1076,pid:1012,name:"黄山市",level:2,region:{1077:{id:1077,pid:1076,name:"屯溪区",level:3},1078:{id:1078,pid:1076,name:"黄山区",level:3},1079:{id:1079,pid:1076,name:"徽州区",level:3},1080:{id:1080,pid:1076,name:"歙县",level:3},1081:{id:1081,pid:1076,name:"休宁县",level:3},1082:{id:1082,pid:1076,name:"黟县",level:3},1083:{id:1083,pid:1076,name:"祁门县",level:3}}},1084:{id:1084,pid:1012,name:"滁州市",level:2,region:{1085:{id:1085,pid:1084,name:"琅琊区",level:3},1086:{id:1086,pid:1084,name:"南谯区",level:3},1087:{id:1087,pid:1084,name:"来安县",level:3},1088:{id:1088,pid:1084,name:"全椒县",level:3},1089:{id:1089,pid:1084,name:"定远县",level:3},1090:{id:1090,pid:1084,name:"凤阳县",level:3},1091:{id:1091,pid:1084,name:"天长市",level:3},1092:{id:1092,pid:1084,name:"明光市",level:3},3790:{id:3790,pid:1084,name:"中新苏滁高新技术产业开发区",level:3},3791:{id:3791,pid:1084,name:"滁州经济技术开发区",level:3}}},1093:{id:1093,pid:1012,name:"阜阳市",level:2,region:{1094:{id:1094,pid:1093,name:"颍州区",level:3},1095:{id:1095,pid:1093,name:"颍东区",level:3},1096:{id:1096,pid:1093,name:"颍泉区",level:3},1097:{id:1097,pid:1093,name:"临泉县",level:3},1098:{id:1098,pid:1093,name:"太和县",level:3},1099:{id:1099,pid:1093,name:"阜南县",level:3},1100:{id:1100,pid:1093,name:"颍上县",level:3},1101:{id:1101,pid:1093,name:"界首市",level:3},3792:{id:3792,pid:1093,name:"阜阳合肥现代产业园区",level:3},3793:{id:3793,pid:1093,name:"阜阳经济技术开发区",level:3}}},1102:{id:1102,pid:1012,name:"宿州市",level:2,region:{1103:{id:1103,pid:1102,name:"埇桥区",level:3},1104:{id:1104,pid:1102,name:"砀山县",level:3},1105:{id:1105,pid:1102,name:"萧县",level:3},1106:{id:1106,pid:1102,name:"灵璧县",level:3},1107:{id:1107,pid:1102,name:"泗县",level:3},3794:{id:3794,pid:1102,name:"宿州马鞍山现代产业园区",level:3},3795:{id:3795,pid:1102,name:"宿州经济技术开发区",level:3}}},1108:{id:1108,pid:1012,name:"六安市",level:2,region:{1109:{id:1109,pid:1108,name:"金安区",level:3},1110:{id:1110,pid:1108,name:"裕安区",level:3},1111:{id:1111,pid:1108,name:"叶集区",level:3},1112:{id:1112,pid:1108,name:"霍邱县",level:3},1113:{id:1113,pid:1108,name:"舒城县",level:3},1114:{id:1114,pid:1108,name:"金寨县",level:3},1115:{id:1115,pid:1108,name:"霍山县",level:3}}},1116:{id:1116,pid:1012,name:"亳州市",level:2,region:{1117:{id:1117,pid:1116,name:"谯城区",level:3},1118:{id:1118,pid:1116,name:"涡阳县",level:3},1119:{id:1119,pid:1116,name:"蒙城县",level:3},1120:{id:1120,pid:1116,name:"利辛县",level:3}}},1121:{id:1121,pid:1012,name:"池州市",level:2,region:{1122:{id:1122,pid:1121,name:"贵池区",level:3},1123:{id:1123,pid:1121,name:"东至县",level:3},1124:{id:1124,pid:1121,name:"石台县",level:3},1125:{id:1125,pid:1121,name:"青阳县",level:3}}},1126:{id:1126,pid:1012,name:"宣城市",level:2,region:{1127:{id:1127,pid:1126,name:"宣州区",level:3},1128:{id:1128,pid:1126,name:"郎溪县",level:3},1129:{id:1129,pid:1126,name:"泾县",level:3},1130:{id:1130,pid:1126,name:"绩溪县",level:3},1131:{id:1131,pid:1126,name:"旌德县",level:3},1132:{id:1132,pid:1126,name:"宁国市",level:3},1133:{id:1133,pid:1126,name:"广德市",level:3},3796:{id:3796,pid:1126,name:"宣城市经济开发区",level:3}}}}},1134:{id:1134,pid:0,name:"福建省",level:1,city:{1135:{id:1135,pid:1134,name:"福州市",level:2,region:{1136:{id:1136,pid:1135,name:"鼓楼区",level:3},1137:{id:1137,pid:1135,name:"台江区",level:3},1138:{id:1138,pid:1135,name:"仓山区",level:3},1139:{id:1139,pid:1135,name:"马尾区",level:3},1140:{id:1140,pid:1135,name:"晋安区",level:3},1141:{id:1141,pid:1135,name:"长乐区",level:3},1142:{id:1142,pid:1135,name:"闽侯县",level:3},1143:{id:1143,pid:1135,name:"连江县",level:3},1144:{id:1144,pid:1135,name:"罗源县",level:3},1145:{id:1145,pid:1135,name:"闽清县",level:3},1146:{id:1146,pid:1135,name:"永泰县",level:3},1147:{id:1147,pid:1135,name:"平潭县",level:3},1148:{id:1148,pid:1135,name:"福清市",level:3}}},1149:{id:1149,pid:1134,name:"厦门市",level:2,region:{1150:{id:1150,pid:1149,name:"思明区",level:3},1151:{id:1151,pid:1149,name:"海沧区",level:3},1152:{id:1152,pid:1149,name:"湖里区",level:3},1153:{id:1153,pid:1149,name:"集美区",level:3},1154:{id:1154,pid:1149,name:"同安区",level:3},1155:{id:1155,pid:1149,name:"翔安区",level:3}}},1156:{id:1156,pid:1134,name:"莆田市",level:2,region:{1157:{id:1157,pid:1156,name:"城厢区",level:3},1158:{id:1158,pid:1156,name:"涵江区",level:3},1159:{id:1159,pid:1156,name:"荔城区",level:3},1160:{id:1160,pid:1156,name:"秀屿区",level:3},1161:{id:1161,pid:1156,name:"仙游县",level:3}}},1162:{id:1162,pid:1134,name:"三明市",level:2,region:{1165:{id:1165,pid:1162,name:"明溪县",level:3},1166:{id:1166,pid:1162,name:"清流县",level:3},1167:{id:1167,pid:1162,name:"宁化县",level:3},1168:{id:1168,pid:1162,name:"大田县",level:3},1169:{id:1169,pid:1162,name:"尤溪县",level:3},1171:{id:1171,pid:1162,name:"将乐县",level:3},1172:{id:1172,pid:1162,name:"泰宁县",level:3},1173:{id:1173,pid:1162,name:"建宁县",level:3},1174:{id:1174,pid:1162,name:"永安市",level:3},3797:{id:3797,pid:1162,name:"三元区",level:3},3798:{id:3798,pid:1162,name:"沙县区",level:3}}},1175:{id:1175,pid:1134,name:"泉州市",level:2,region:{1176:{id:1176,pid:1175,name:"鲤城区",level:3},1177:{id:1177,pid:1175,name:"丰泽区",level:3},1178:{id:1178,pid:1175,name:"洛江区",level:3},1179:{id:1179,pid:1175,name:"泉港区",level:3},1180:{id:1180,pid:1175,name:"惠安县",level:3},1181:{id:1181,pid:1175,name:"安溪县",level:3},1182:{id:1182,pid:1175,name:"永春县",level:3},1183:{id:1183,pid:1175,name:"德化县",level:3},1185:{id:1185,pid:1175,name:"石狮市",level:3},1186:{id:1186,pid:1175,name:"晋江市",level:3},1187:{id:1187,pid:1175,name:"南安市",level:3}}},1188:{id:1188,pid:1134,name:"漳州市",level:2,region:{1189:{id:1189,pid:1188,name:"芗城区",level:3},1190:{id:1190,pid:1188,name:"龙文区",level:3},1191:{id:1191,pid:1188,name:"云霄县",level:3},1192:{id:1192,pid:1188,name:"漳浦县",level:3},1193:{id:1193,pid:1188,name:"诏安县",level:3},1195:{id:1195,pid:1188,name:"东山县",level:3},1196:{id:1196,pid:1188,name:"南靖县",level:3},1197:{id:1197,pid:1188,name:"平和县",level:3},1198:{id:1198,pid:1188,name:"华安县",level:3},3799:{id:3799,pid:1188,name:"龙海区",level:3},3800:{id:3800,pid:1188,name:"长泰区",level:3}}},1200:{id:1200,pid:1134,name:"南平市",level:2,region:{1201:{id:1201,pid:1200,name:"延平区",level:3},1202:{id:1202,pid:1200,name:"建阳区",level:3},1203:{id:1203,pid:1200,name:"顺昌县",level:3},1204:{id:1204,pid:1200,name:"浦城县",level:3},1205:{id:1205,pid:1200,name:"光泽县",level:3},1206:{id:1206,pid:1200,name:"松溪县",level:3},1207:{id:1207,pid:1200,name:"政和县",level:3},1208:{id:1208,pid:1200,name:"邵武市",level:3},1209:{id:1209,pid:1200,name:"武夷山市",level:3},1210:{id:1210,pid:1200,name:"建瓯市",level:3}}},1211:{id:1211,pid:1134,name:"龙岩市",level:2,region:{1212:{id:1212,pid:1211,name:"新罗区",level:3},1213:{id:1213,pid:1211,name:"永定区",level:3},1214:{id:1214,pid:1211,name:"长汀县",level:3},1215:{id:1215,pid:1211,name:"上杭县",level:3},1216:{id:1216,pid:1211,name:"武平县",level:3},1217:{id:1217,pid:1211,name:"连城县",level:3},1218:{id:1218,pid:1211,name:"漳平市",level:3}}},1219:{id:1219,pid:1134,name:"宁德市",level:2,region:{1220:{id:1220,pid:1219,name:"蕉城区",level:3},1221:{id:1221,pid:1219,name:"霞浦县",level:3},1222:{id:1222,pid:1219,name:"古田县",level:3},1223:{id:1223,pid:1219,name:"屏南县",level:3},1224:{id:1224,pid:1219,name:"寿宁县",level:3},1225:{id:1225,pid:1219,name:"周宁县",level:3},1226:{id:1226,pid:1219,name:"柘荣县",level:3},1227:{id:1227,pid:1219,name:"福安市",level:3},1228:{id:1228,pid:1219,name:"福鼎市",level:3}}}}},1229:{id:1229,pid:0,name:"江西省",level:1,city:{1230:{id:1230,pid:1229,name:"南昌市",level:2,region:{1231:{id:1231,pid:1230,name:"东湖区",level:3},1232:{id:1232,pid:1230,name:"西湖区",level:3},1233:{id:1233,pid:1230,name:"青云谱区",level:3},1234:{id:1234,pid:1230,name:"青山湖区",level:3},1235:{id:1235,pid:1230,name:"新建区",level:3},1236:{id:1236,pid:1230,name:"红谷滩区",level:3},1237:{id:1237,pid:1230,name:"南昌县",level:3},1238:{id:1238,pid:1230,name:"安义县",level:3},1239:{id:1239,pid:1230,name:"进贤县",level:3}}},1240:{id:1240,pid:1229,name:"景德镇市",level:2,region:{1241:{id:1241,pid:1240,name:"昌江区",level:3},1242:{id:1242,pid:1240,name:"珠山区",level:3},1243:{id:1243,pid:1240,name:"浮梁县",level:3},1244:{id:1244,pid:1240,name:"乐平市",level:3}}},1245:{id:1245,pid:1229,name:"萍乡市",level:2,region:{1246:{id:1246,pid:1245,name:"安源区",level:3},1247:{id:1247,pid:1245,name:"湘东区",level:3},1248:{id:1248,pid:1245,name:"莲花县",level:3},1249:{id:1249,pid:1245,name:"上栗县",level:3},1250:{id:1250,pid:1245,name:"芦溪县",level:3}}},1251:{id:1251,pid:1229,name:"九江市",level:2,region:{1252:{id:1252,pid:1251,name:"濂溪区",level:3},1253:{id:1253,pid:1251,name:"浔阳区",level:3},1254:{id:1254,pid:1251,name:"柴桑区",level:3},1255:{id:1255,pid:1251,name:"武宁县",level:3},1256:{id:1256,pid:1251,name:"修水县",level:3},1257:{id:1257,pid:1251,name:"永修县",level:3},1258:{id:1258,pid:1251,name:"德安县",level:3},1259:{id:1259,pid:1251,name:"都昌县",level:3},1260:{id:1260,pid:1251,name:"湖口县",level:3},1261:{id:1261,pid:1251,name:"彭泽县",level:3},1262:{id:1262,pid:1251,name:"瑞昌市",level:3},1263:{id:1263,pid:1251,name:"共青城市",level:3},1264:{id:1264,pid:1251,name:"庐山市",level:3}}},1265:{id:1265,pid:1229,name:"新余市",level:2,region:{1266:{id:1266,pid:1265,name:"渝水区",level:3},1267:{id:1267,pid:1265,name:"分宜县",level:3}}},1268:{id:1268,pid:1229,name:"鹰潭市",level:2,region:{1269:{id:1269,pid:1268,name:"月湖区",level:3},1270:{id:1270,pid:1268,name:"余江区",level:3},1271:{id:1271,pid:1268,name:"贵溪市",level:3}}},1272:{id:1272,pid:1229,name:"赣州市",level:2,region:{1273:{id:1273,pid:1272,name:"章贡区",level:3},1274:{id:1274,pid:1272,name:"南康区",level:3},1275:{id:1275,pid:1272,name:"赣县区",level:3},1276:{id:1276,pid:1272,name:"信丰县",level:3},1277:{id:1277,pid:1272,name:"大余县",level:3},1278:{id:1278,pid:1272,name:"上犹县",level:3},1279:{id:1279,pid:1272,name:"崇义县",level:3},1280:{id:1280,pid:1272,name:"安远县",level:3},1282:{id:1282,pid:1272,name:"定南县",level:3},1283:{id:1283,pid:1272,name:"全南县",level:3},1284:{id:1284,pid:1272,name:"宁都县",level:3},1285:{id:1285,pid:1272,name:"于都县",level:3},1286:{id:1286,pid:1272,name:"兴国县",level:3},1287:{id:1287,pid:1272,name:"会昌县",level:3},1288:{id:1288,pid:1272,name:"寻乌县",level:3},1289:{id:1289,pid:1272,name:"石城县",level:3},1290:{id:1290,pid:1272,name:"瑞金市",level:3},3801:{id:3801,pid:1272,name:"龙南市",level:3}}},1291:{id:1291,pid:1229,name:"吉安市",level:2,region:{1292:{id:1292,pid:1291,name:"吉州区",level:3},1293:{id:1293,pid:1291,name:"青原区",level:3},1294:{id:1294,pid:1291,name:"吉安县",level:3},1295:{id:1295,pid:1291,name:"吉水县",level:3},1296:{id:1296,pid:1291,name:"峡江县",level:3},1297:{id:1297,pid:1291,name:"新干县",level:3},1298:{id:1298,pid:1291,name:"永丰县",level:3},1299:{id:1299,pid:1291,name:"泰和县",level:3},1300:{id:1300,pid:1291,name:"遂川县",level:3},1301:{id:1301,pid:1291,name:"万安县",level:3},1302:{id:1302,pid:1291,name:"安福县",level:3},1303:{id:1303,pid:1291,name:"永新县",level:3},1304:{id:1304,pid:1291,name:"井冈山市",level:3}}},1305:{id:1305,pid:1229,name:"宜春市",level:2,region:{1306:{id:1306,pid:1305,name:"袁州区",level:3},1307:{id:1307,pid:1305,name:"奉新县",level:3},1308:{id:1308,pid:1305,name:"万载县",level:3},1309:{id:1309,pid:1305,name:"上高县",level:3},1310:{id:1310,pid:1305,name:"宜丰县",level:3},1311:{id:1311,pid:1305,name:"靖安县",level:3},1312:{id:1312,pid:1305,name:"铜鼓县",level:3},1313:{id:1313,pid:1305,name:"丰城市",level:3},1314:{id:1314,pid:1305,name:"樟树市",level:3},1315:{id:1315,pid:1305,name:"高安市",level:3}}},1316:{id:1316,pid:1229,name:"抚州市",level:2,region:{1317:{id:1317,pid:1316,name:"临川区",level:3},1318:{id:1318,pid:1316,name:"东乡区",level:3},1319:{id:1319,pid:1316,name:"南城县",level:3},1320:{id:1320,pid:1316,name:"黎川县",level:3},1321:{id:1321,pid:1316,name:"南丰县",level:3},1322:{id:1322,pid:1316,name:"崇仁县",level:3},1323:{id:1323,pid:1316,name:"乐安县",level:3},1324:{id:1324,pid:1316,name:"宜黄县",level:3},1325:{id:1325,pid:1316,name:"金溪县",level:3},1326:{id:1326,pid:1316,name:"资溪县",level:3},1327:{id:1327,pid:1316,name:"广昌县",level:3}}},1328:{id:1328,pid:1229,name:"上饶市",level:2,region:{1329:{id:1329,pid:1328,name:"信州区",level:3},1330:{id:1330,pid:1328,name:"广丰区",level:3},1331:{id:1331,pid:1328,name:"广信区",level:3},1332:{id:1332,pid:1328,name:"玉山县",level:3},1333:{id:1333,pid:1328,name:"铅山县",level:3},1334:{id:1334,pid:1328,name:"横峰县",level:3},1335:{id:1335,pid:1328,name:"弋阳县",level:3},1336:{id:1336,pid:1328,name:"余干县",level:3},1337:{id:1337,pid:1328,name:"鄱阳县",level:3},1338:{id:1338,pid:1328,name:"万年县",level:3},1339:{id:1339,pid:1328,name:"婺源县",level:3},1340:{id:1340,pid:1328,name:"德兴市",level:3}}}}},1341:{id:1341,pid:0,name:"山东省",level:1,city:{1342:{id:1342,pid:1341,name:"济南市",level:2,region:{1343:{id:1343,pid:1342,name:"历下区",level:3},1344:{id:1344,pid:1342,name:"市中区",level:3},1345:{id:1345,pid:1342,name:"槐荫区",level:3},1346:{id:1346,pid:1342,name:"天桥区",level:3},1347:{id:1347,pid:1342,name:"历城区",level:3},1348:{id:1348,pid:1342,name:"长清区",level:3},1349:{id:1349,pid:1342,name:"章丘区",level:3},1350:{id:1350,pid:1342,name:"济阳区",level:3},1351:{id:1351,pid:1342,name:"莱芜区",level:3},1352:{id:1352,pid:1342,name:"钢城区",level:3},1353:{id:1353,pid:1342,name:"平阴县",level:3},1354:{id:1354,pid:1342,name:"商河县",level:3},3802:{id:3802,pid:1342,name:"济南高新技术产业开发区",level:3}}},1355:{id:1355,pid:1341,name:"青岛市",level:2,region:{1356:{id:1356,pid:1355,name:"市南区",level:3},1357:{id:1357,pid:1355,name:"市北区",level:3},1358:{id:1358,pid:1355,name:"黄岛区",level:3},1359:{id:1359,pid:1355,name:"崂山区",level:3},1360:{id:1360,pid:1355,name:"李沧区",level:3},1361:{id:1361,pid:1355,name:"城阳区",level:3},1362:{id:1362,pid:1355,name:"即墨区",level:3},1363:{id:1363,pid:1355,name:"胶州市",level:3},1364:{id:1364,pid:1355,name:"平度市",level:3},1365:{id:1365,pid:1355,name:"莱西市",level:3},3803:{id:3803,pid:1355,name:"青岛高新技术产业开发区",level:3}}},1366:{id:1366,pid:1341,name:"淄博市",level:2,region:{1367:{id:1367,pid:1366,name:"淄川区",level:3},1368:{id:1368,pid:1366,name:"张店区",level:3},1369:{id:1369,pid:1366,name:"博山区",level:3},1370:{id:1370,pid:1366,name:"临淄区",level:3},1371:{id:1371,pid:1366,name:"周村区",level:3},1372:{id:1372,pid:1366,name:"桓台县",level:3},1373:{id:1373,pid:1366,name:"高青县",level:3},1374:{id:1374,pid:1366,name:"沂源县",level:3}}},1375:{id:1375,pid:1341,name:"枣庄市",level:2,region:{1376:{id:1376,pid:1375,name:"市中区",level:3},1377:{id:1377,pid:1375,name:"薛城区",level:3},1378:{id:1378,pid:1375,name:"峄城区",level:3},1379:{id:1379,pid:1375,name:"台儿庄区",level:3},1380:{id:1380,pid:1375,name:"山亭区",level:3},1381:{id:1381,pid:1375,name:"滕州市",level:3}}},1382:{id:1382,pid:1341,name:"东营市",level:2,region:{1383:{id:1383,pid:1382,name:"东营区",level:3},1384:{id:1384,pid:1382,name:"河口区",level:3},1385:{id:1385,pid:1382,name:"垦利区",level:3},1386:{id:1386,pid:1382,name:"利津县",level:3},1387:{id:1387,pid:1382,name:"广饶县",level:3},3804:{id:3804,pid:1382,name:"东营经济技术开发区",level:3},3805:{id:3805,pid:1382,name:"东营港经济开发区",level:3}}},1388:{id:1388,pid:1341,name:"烟台市",level:2,region:{1389:{id:1389,pid:1388,name:"芝罘区",level:3},1390:{id:1390,pid:1388,name:"福山区",level:3},1391:{id:1391,pid:1388,name:"牟平区",level:3},1392:{id:1392,pid:1388,name:"莱山区",level:3},1394:{id:1394,pid:1388,name:"龙口市",level:3},1395:{id:1395,pid:1388,name:"莱阳市",level:3},1396:{id:1396,pid:1388,name:"莱州市",level:3},1398:{id:1398,pid:1388,name:"招远市",level:3},1399:{id:1399,pid:1388,name:"栖霞市",level:3},1400:{id:1400,pid:1388,name:"海阳市",level:3},3806:{id:3806,pid:1388,name:"蓬莱区",level:3},3807:{id:3807,pid:1388,name:"烟台高新技术产业开发区",level:3},3808:{id:3808,pid:1388,name:"烟台经济技术开发区",level:3}}},1401:{id:1401,pid:1341,name:"潍坊市",level:2,region:{1402:{id:1402,pid:1401,name:"潍城区",level:3},1403:{id:1403,pid:1401,name:"寒亭区",level:3},1404:{id:1404,pid:1401,name:"坊子区",level:3},1405:{id:1405,pid:1401,name:"奎文区",level:3},1406:{id:1406,pid:1401,name:"临朐县",level:3},1407:{id:1407,pid:1401,name:"昌乐县",level:3},1408:{id:1408,pid:1401,name:"青州市",level:3},1409:{id:1409,pid:1401,name:"诸城市",level:3},1410:{id:1410,pid:1401,name:"寿光市",level:3},1411:{id:1411,pid:1401,name:"安丘市",level:3},1412:{id:1412,pid:1401,name:"高密市",level:3},1413:{id:1413,pid:1401,name:"昌邑市",level:3},3809:{id:3809,pid:1401,name:"潍坊滨海经济技术开发区",level:3}}},1414:{id:1414,pid:1341,name:"济宁市",level:2,region:{1415:{id:1415,pid:1414,name:"任城区",level:3},1416:{id:1416,pid:1414,name:"兖州区",level:3},1417:{id:1417,pid:1414,name:"微山县",level:3},1418:{id:1418,pid:1414,name:"鱼台县",level:3},1419:{id:1419,pid:1414,name:"金乡县",level:3},1420:{id:1420,pid:1414,name:"嘉祥县",level:3},1421:{id:1421,pid:1414,name:"汶上县",level:3},1422:{id:1422,pid:1414,name:"泗水县",level:3},1423:{id:1423,pid:1414,name:"梁山县",level:3},1424:{id:1424,pid:1414,name:"曲阜市",level:3},1425:{id:1425,pid:1414,name:"邹城市",level:3},3810:{id:3810,pid:1414,name:"济宁高新技术产业开发区",level:3}}},1426:{id:1426,pid:1341,name:"泰安市",level:2,region:{1427:{id:1427,pid:1426,name:"泰山区",level:3},1428:{id:1428,pid:1426,name:"岱岳区",level:3},1429:{id:1429,pid:1426,name:"宁阳县",level:3},1430:{id:1430,pid:1426,name:"东平县",level:3},1431:{id:1431,pid:1426,name:"新泰市",level:3},1432:{id:1432,pid:1426,name:"肥城市",level:3}}},1433:{id:1433,pid:1341,name:"威海市",level:2,region:{1434:{id:1434,pid:1433,name:"环翠区",level:3},1435:{id:1435,pid:1433,name:"文登区",level:3},1436:{id:1436,pid:1433,name:"荣成市",level:3},1437:{id:1437,pid:1433,name:"乳山市",level:3},3811:{id:3811,pid:1433,name:"威海火炬高技术产业开发区",level:3},3812:{id:3812,pid:1433,name:"威海经济技术开发区",level:3},3813:{id:3813,pid:1433,name:"威海临港经济技术开发区",level:3}}},1438:{id:1438,pid:1341,name:"日照市",level:2,region:{1439:{id:1439,pid:1438,name:"东港区",level:3},1440:{id:1440,pid:1438,name:"岚山区",level:3},1441:{id:1441,pid:1438,name:"五莲县",level:3},1442:{id:1442,pid:1438,name:"莒县",level:3},3814:{id:3814,pid:1438,name:"日照经济技术开发区",level:3}}},1443:{id:1443,pid:1341,name:"临沂市",level:2,region:{1444:{id:1444,pid:1443,name:"兰山区",level:3},1445:{id:1445,pid:1443,name:"罗庄区",level:3},1446:{id:1446,pid:1443,name:"河东区",level:3},1447:{id:1447,pid:1443,name:"沂南县",level:3},1448:{id:1448,pid:1443,name:"郯城县",level:3},1449:{id:1449,pid:1443,name:"沂水县",level:3},1450:{id:1450,pid:1443,name:"兰陵县",level:3},1451:{id:1451,pid:1443,name:"费县",level:3},1452:{id:1452,pid:1443,name:"平邑县",level:3},1453:{id:1453,pid:1443,name:"莒南县",level:3},1454:{id:1454,pid:1443,name:"蒙阴县",level:3},1455:{id:1455,pid:1443,name:"临沭县",level:3},3815:{id:3815,pid:1443,name:"临沂高新技术产业开发区",level:3}}},1456:{id:1456,pid:1341,name:"德州市",level:2,region:{1457:{id:1457,pid:1456,name:"德城区",level:3},1458:{id:1458,pid:1456,name:"陵城区",level:3},1459:{id:1459,pid:1456,name:"宁津县",level:3},1460:{id:1460,pid:1456,name:"庆云县",level:3},1461:{id:1461,pid:1456,name:"临邑县",level:3},1462:{id:1462,pid:1456,name:"齐河县",level:3},1463:{id:1463,pid:1456,name:"平原县",level:3},1464:{id:1464,pid:1456,name:"夏津县",level:3},1465:{id:1465,pid:1456,name:"武城县",level:3},1466:{id:1466,pid:1456,name:"乐陵市",level:3},1467:{id:1467,pid:1456,name:"禹城市",level:3},3816:{id:3816,pid:1456,name:"德州天衢新区",level:3}}},1468:{id:1468,pid:1341,name:"聊城市",level:2,region:{1469:{id:1469,pid:1468,name:"东昌府区",level:3},1470:{id:1470,pid:1468,name:"茌平区",level:3},1471:{id:1471,pid:1468,name:"阳谷县",level:3},1472:{id:1472,pid:1468,name:"莘县",level:3},1473:{id:1473,pid:1468,name:"东阿县",level:3},1474:{id:1474,pid:1468,name:"冠县",level:3},1475:{id:1475,pid:1468,name:"高唐县",level:3},1476:{id:1476,pid:1468,name:"临清市",level:3}}},1477:{id:1477,pid:1341,name:"滨州市",level:2,region:{1478:{id:1478,pid:1477,name:"滨城区",level:3},1479:{id:1479,pid:1477,name:"沾化区",level:3},1480:{id:1480,pid:1477,name:"惠民县",level:3},1481:{id:1481,pid:1477,name:"阳信县",level:3},1482:{id:1482,pid:1477,name:"无棣县",level:3},1483:{id:1483,pid:1477,name:"博兴县",level:3},1484:{id:1484,pid:1477,name:"邹平市",level:3}}},1485:{id:1485,pid:1341,name:"菏泽市",level:2,region:{1486:{id:1486,pid:1485,name:"牡丹区",level:3},1487:{id:1487,pid:1485,name:"定陶区",level:3},1488:{id:1488,pid:1485,name:"曹县",level:3},1489:{id:1489,pid:1485,name:"单县",level:3},1490:{id:1490,pid:1485,name:"成武县",level:3},1491:{id:1491,pid:1485,name:"巨野县",level:3},1492:{id:1492,pid:1485,name:"郓城县",level:3},1493:{id:1493,pid:1485,name:"鄄城县",level:3},1494:{id:1494,pid:1485,name:"东明县",level:3},3817:{id:3817,pid:1485,name:"菏泽经济技术开发区",level:3},3818:{id:3818,pid:1485,name:"菏泽高新技术开发区",level:3}}}}},1495:{id:1495,pid:0,name:"河南省",level:1,city:{1496:{id:1496,pid:1495,name:"郑州市",level:2,region:{1497:{id:1497,pid:1496,name:"中原区",level:3},1498:{id:1498,pid:1496,name:"二七区",level:3},1499:{id:1499,pid:1496,name:"管城回族区",level:3},1500:{id:1500,pid:1496,name:"金水区",level:3},1501:{id:1501,pid:1496,name:"上街区",level:3},1502:{id:1502,pid:1496,name:"惠济区",level:3},1503:{id:1503,pid:1496,name:"中牟县",level:3},1504:{id:1504,pid:1496,name:"巩义市",level:3},1505:{id:1505,pid:1496,name:"荥阳市",level:3},1506:{id:1506,pid:1496,name:"新密市",level:3},1507:{id:1507,pid:1496,name:"新郑市",level:3},1508:{id:1508,pid:1496,name:"登封市",level:3},3819:{id:3819,pid:1496,name:"郑州经济技术开发区",level:3},3820:{id:3820,pid:1496,name:"郑州高新技术产业开发区",level:3},3821:{id:3821,pid:1496,name:"郑州航空港经济综合实验区",level:3}}},1509:{id:1509,pid:1495,name:"开封市",level:2,region:{1510:{id:1510,pid:1509,name:"龙亭区",level:3},1511:{id:1511,pid:1509,name:"顺河回族区",level:3},1512:{id:1512,pid:1509,name:"鼓楼区",level:3},1513:{id:1513,pid:1509,name:"禹王台区",level:3},1514:{id:1514,pid:1509,name:"祥符区",level:3},1515:{id:1515,pid:1509,name:"杞县",level:3},1516:{id:1516,pid:1509,name:"通许县",level:3},1517:{id:1517,pid:1509,name:"尉氏县",level:3},1518:{id:1518,pid:1509,name:"兰考县",level:3}}},1519:{id:1519,pid:1495,name:"洛阳市",level:2,region:{1520:{id:1520,pid:1519,name:"老城区",level:3},1521:{id:1521,pid:1519,name:"西工区",level:3},1522:{id:1522,pid:1519,name:"瀍河回族区",level:3},1523:{id:1523,pid:1519,name:"涧西区",level:3},1525:{id:1525,pid:1519,name:"洛龙区",level:3},1527:{id:1527,pid:1519,name:"新安县",level:3},1528:{id:1528,pid:1519,name:"栾川县",level:3},1529:{id:1529,pid:1519,name:"嵩县",level:3},1530:{id:1530,pid:1519,name:"汝阳县",level:3},1531:{id:1531,pid:1519,name:"宜阳县",level:3},1532:{id:1532,pid:1519,name:"洛宁县",level:3},1533:{id:1533,pid:1519,name:"伊川县",level:3},3822:{id:3822,pid:1519,name:"偃师区",level:3},3823:{id:3823,pid:1519,name:"孟津区",level:3},3824:{id:3824,pid:1519,name:"洛阳高新技术产业开发区",level:3}}},1535:{id:1535,pid:1495,name:"平顶山市",level:2,region:{1536:{id:1536,pid:1535,name:"新华区",level:3},1537:{id:1537,pid:1535,name:"卫东区",level:3},1538:{id:1538,pid:1535,name:"石龙区",level:3},1539:{id:1539,pid:1535,name:"湛河区",level:3},1540:{id:1540,pid:1535,name:"宝丰县",level:3},1541:{id:1541,pid:1535,name:"叶县",level:3},1542:{id:1542,pid:1535,name:"鲁山县",level:3},1543:{id:1543,pid:1535,name:"郏县",level:3},1544:{id:1544,pid:1535,name:"舞钢市",level:3},1545:{id:1545,pid:1535,name:"汝州市",level:3},3825:{id:3825,pid:1535,name:"平顶山高新技术产业开发区",level:3},3826:{id:3826,pid:1535,name:"平顶山市城乡一体化示范区",level:3}}},1546:{id:1546,pid:1495,name:"安阳市",level:2,region:{1547:{id:1547,pid:1546,name:"文峰区",level:3},1548:{id:1548,pid:1546,name:"北关区",level:3},1549:{id:1549,pid:1546,name:"殷都区",level:3},1550:{id:1550,pid:1546,name:"龙安区",level:3},1551:{id:1551,pid:1546,name:"安阳县",level:3},1552:{id:1552,pid:1546,name:"汤阴县",level:3},1553:{id:1553,pid:1546,name:"滑县",level:3},1554:{id:1554,pid:1546,name:"内黄县",level:3},1555:{id:1555,pid:1546,name:"林州市",level:3},3827:{id:3827,pid:1546,name:"安阳高新技术产业开发区",level:3}}},1556:{id:1556,pid:1495,name:"鹤壁市",level:2,region:{1557:{id:1557,pid:1556,name:"鹤山区",level:3},1558:{id:1558,pid:1556,name:"山城区",level:3},1559:{id:1559,pid:1556,name:"淇滨区",level:3},1560:{id:1560,pid:1556,name:"浚县",level:3},1561:{id:1561,pid:1556,name:"淇县",level:3},3828:{id:3828,pid:1556,name:"鹤壁经济技术开发区",level:3}}},1562:{id:1562,pid:1495,name:"新乡市",level:2,region:{1563:{id:1563,pid:1562,name:"红旗区",level:3},1564:{id:1564,pid:1562,name:"卫滨区",level:3},1565:{id:1565,pid:1562,name:"凤泉区",level:3},1566:{id:1566,pid:1562,name:"牧野区",level:3},1567:{id:1567,pid:1562,name:"新乡县",level:3},1568:{id:1568,pid:1562,name:"获嘉县",level:3},1569:{id:1569,pid:1562,name:"原阳县",level:3},1570:{id:1570,pid:1562,name:"延津县",level:3},1571:{id:1571,pid:1562,name:"封丘县",level:3},1572:{id:1572,pid:1562,name:"卫辉市",level:3},1573:{id:1573,pid:1562,name:"辉县市",level:3},1574:{id:1574,pid:1562,name:"长垣市",level:3},3829:{id:3829,pid:1562,name:"新乡高新技术产业开发区",level:3},3830:{id:3830,pid:1562,name:"新乡经济技术开发区",level:3},3831:{id:3831,pid:1562,name:"新乡市平原城乡一体化示范区",level:3}}},1575:{id:1575,pid:1495,name:"焦作市",level:2,region:{1576:{id:1576,pid:1575,name:"解放区",level:3},1577:{id:1577,pid:1575,name:"中站区",level:3},1578:{id:1578,pid:1575,name:"马村区",level:3},1579:{id:1579,pid:1575,name:"山阳区",level:3},1580:{id:1580,pid:1575,name:"修武县",level:3},1581:{id:1581,pid:1575,name:"博爱县",level:3},1582:{id:1582,pid:1575,name:"武陟县",level:3},1583:{id:1583,pid:1575,name:"温县",level:3},1584:{id:1584,pid:1575,name:"沁阳市",level:3},1585:{id:1585,pid:1575,name:"孟州市",level:3},3832:{id:3832,pid:1575,name:"焦作城乡一体化示范区",level:3}}},1586:{id:1586,pid:1495,name:"濮阳市",level:2,region:{1587:{id:1587,pid:1586,name:"华龙区",level:3},1588:{id:1588,pid:1586,name:"清丰县",level:3},1589:{id:1589,pid:1586,name:"南乐县",level:3},1590:{id:1590,pid:1586,name:"范县",level:3},1591:{id:1591,pid:1586,name:"台前县",level:3},1592:{id:1592,pid:1586,name:"濮阳县",level:3},3833:{id:3833,pid:1586,name:"河南濮阳工业园区",level:3},3834:{id:3834,pid:1586,name:"濮阳经济技术开发区",level:3}}},1593:{id:1593,pid:1495,name:"许昌市",level:2,region:{1594:{id:1594,pid:1593,name:"魏都区",level:3},1595:{id:1595,pid:1593,name:"建安区",level:3},1596:{id:1596,pid:1593,name:"鄢陵县",level:3},1597:{id:1597,pid:1593,name:"襄城县",level:3},1598:{id:1598,pid:1593,name:"禹州市",level:3},1599:{id:1599,pid:1593,name:"长葛市",level:3},3835:{id:3835,pid:1593,name:"许昌经济技术开发区",level:3}}},1600:{id:1600,pid:1495,name:"漯河市",level:2,region:{1601:{id:1601,pid:1600,name:"源汇区",level:3},1602:{id:1602,pid:1600,name:"郾城区",level:3},1603:{id:1603,pid:1600,name:"召陵区",level:3},1604:{id:1604,pid:1600,name:"舞阳县",level:3},1605:{id:1605,pid:1600,name:"临颍县",level:3},3836:{id:3836,pid:1600,name:"漯河经济技术开发区",level:3}}},1606:{id:1606,pid:1495,name:"三门峡市",level:2,region:{1607:{id:1607,pid:1606,name:"湖滨区",level:3},1608:{id:1608,pid:1606,name:"陕州区",level:3},1609:{id:1609,pid:1606,name:"渑池县",level:3},1610:{id:1610,pid:1606,name:"卢氏县",level:3},1611:{id:1611,pid:1606,name:"义马市",level:3},1612:{id:1612,pid:1606,name:"灵宝市",level:3},3837:{id:3837,pid:1606,name:"河南三门峡经济开发区",level:3}}},1613:{id:1613,pid:1495,name:"南阳市",level:2,region:{1614:{id:1614,pid:1613,name:"宛城区",level:3},1615:{id:1615,pid:1613,name:"卧龙区",level:3},1616:{id:1616,pid:1613,name:"南召县",level:3},1617:{id:1617,pid:1613,name:"方城县",level:3},1618:{id:1618,pid:1613,name:"西峡县",level:3},1619:{id:1619,pid:1613,name:"镇平县",level:3},1620:{id:1620,pid:1613,name:"内乡县",level:3},1621:{id:1621,pid:1613,name:"淅川县",level:3},1622:{id:1622,pid:1613,name:"社旗县",level:3},1623:{id:1623,pid:1613,name:"唐河县",level:3},1624:{id:1624,pid:1613,name:"新野县",level:3},1625:{id:1625,pid:1613,name:"桐柏县",level:3},1626:{id:1626,pid:1613,name:"邓州市",level:3},3838:{id:3838,pid:1613,name:"南阳高新技术产业开发区",level:3},3839:{id:3839,pid:1613,name:"南阳市城乡一体化示范区",level:3}}},1627:{id:1627,pid:1495,name:"商丘市",level:2,region:{1628:{id:1628,pid:1627,name:"梁园区",level:3},1629:{id:1629,pid:1627,name:"睢阳区",level:3},1630:{id:1630,pid:1627,name:"民权县",level:3},1631:{id:1631,pid:1627,name:"睢县",level:3},1632:{id:1632,pid:1627,name:"宁陵县",level:3},1633:{id:1633,pid:1627,name:"柘城县",level:3},1634:{id:1634,pid:1627,name:"虞城县",level:3},1635:{id:1635,pid:1627,name:"夏邑县",level:3},1636:{id:1636,pid:1627,name:"永城市",level:3},3840:{id:3840,pid:1627,name:"豫东综合物流产业聚集区",level:3},3841:{id:3841,pid:1627,name:"河南商丘经济开发区",level:3}}},1637:{id:1637,pid:1495,name:"信阳市",level:2,region:{1638:{id:1638,pid:1637,name:"浉河区",level:3},1639:{id:1639,pid:1637,name:"平桥区",level:3},1640:{id:1640,pid:1637,name:"罗山县",level:3},1641:{id:1641,pid:1637,name:"光山县",level:3},1642:{id:1642,pid:1637,name:"新县",level:3},1643:{id:1643,pid:1637,name:"商城县",level:3},1644:{id:1644,pid:1637,name:"固始县",level:3},1645:{id:1645,pid:1637,name:"潢川县",level:3},1646:{id:1646,pid:1637,name:"淮滨县",level:3},1647:{id:1647,pid:1637,name:"息县",level:3},3842:{id:3842,pid:1637,name:"信阳高新技术产业开发区",level:3}}},1648:{id:1648,pid:1495,name:"周口市",level:2,region:{1649:{id:1649,pid:1648,name:"川汇区",level:3},1650:{id:1650,pid:1648,name:"淮阳区",level:3},1651:{id:1651,pid:1648,name:"扶沟县",level:3},1652:{id:1652,pid:1648,name:"西华县",level:3},1653:{id:1653,pid:1648,name:"商水县",level:3},1654:{id:1654,pid:1648,name:"沈丘县",level:3},1655:{id:1655,pid:1648,name:"郸城县",level:3},1656:{id:1656,pid:1648,name:"太康县",level:3},1657:{id:1657,pid:1648,name:"鹿邑县",level:3},1658:{id:1658,pid:1648,name:"项城市",level:3},3843:{id:3843,pid:1648,name:"河南周口经济开发区",level:3}}},1659:{id:1659,pid:1495,name:"驻马店市",level:2,region:{1660:{id:1660,pid:1659,name:"驿城区",level:3},1661:{id:1661,pid:1659,name:"西平县",level:3},1662:{id:1662,pid:1659,name:"上蔡县",level:3},1663:{id:1663,pid:1659,name:"平舆县",level:3},1664:{id:1664,pid:1659,name:"正阳县",level:3},1665:{id:1665,pid:1659,name:"确山县",level:3},1666:{id:1666,pid:1659,name:"泌阳县",level:3},1667:{id:1667,pid:1659,name:"汝南县",level:3},1668:{id:1668,pid:1659,name:"遂平县",level:3},1669:{id:1669,pid:1659,name:"新蔡县",level:3},3844:{id:3844,pid:1659,name:"河南驻马店经济开发区",level:3}}},3706:{id:3706,pid:1495,name:"省直辖县级行政区划",level:2,region:{3845:{id:3845,pid:3706,name:"济源市",level:3}}}}},1671:{id:1671,pid:0,name:"湖北省",level:1,city:{1672:{id:1672,pid:1671,name:"武汉市",level:2,region:{1673:{id:1673,pid:1672,name:"江岸区",level:3},1674:{id:1674,pid:1672,name:"江汉区",level:3},1675:{id:1675,pid:1672,name:"硚口区",level:3},1676:{id:1676,pid:1672,name:"汉阳区",level:3},1677:{id:1677,pid:1672,name:"武昌区",level:3},1678:{id:1678,pid:1672,name:"青山区",level:3},1679:{id:1679,pid:1672,name:"洪山区",level:3},1680:{id:1680,pid:1672,name:"东西湖区",level:3},1681:{id:1681,pid:1672,name:"汉南区",level:3},1682:{id:1682,pid:1672,name:"蔡甸区",level:3},1683:{id:1683,pid:1672,name:"江夏区",level:3},1684:{id:1684,pid:1672,name:"黄陂区",level:3},1685:{id:1685,pid:1672,name:"新洲区",level:3}}},1686:{id:1686,pid:1671,name:"黄石市",level:2,region:{1687:{id:1687,pid:1686,name:"黄石港区",level:3},1688:{id:1688,pid:1686,name:"西塞山区",level:3},1689:{id:1689,pid:1686,name:"下陆区",level:3},1690:{id:1690,pid:1686,name:"铁山区",level:3},1691:{id:1691,pid:1686,name:"阳新县",level:3},1692:{id:1692,pid:1686,name:"大冶市",level:3}}},1693:{id:1693,pid:1671,name:"十堰市",level:2,region:{1694:{id:1694,pid:1693,name:"茅箭区",level:3},1695:{id:1695,pid:1693,name:"张湾区",level:3},1696:{id:1696,pid:1693,name:"郧阳区",level:3},1697:{id:1697,pid:1693,name:"郧西县",level:3},1698:{id:1698,pid:1693,name:"竹山县",level:3},1699:{id:1699,pid:1693,name:"竹溪县",level:3},1700:{id:1700,pid:1693,name:"房县",level:3},1701:{id:1701,pid:1693,name:"丹江口市",level:3}}},1702:{id:1702,pid:1671,name:"宜昌市",level:2,region:{1703:{id:1703,pid:1702,name:"西陵区",level:3},1704:{id:1704,pid:1702,name:"伍家岗区",level:3},1705:{id:1705,pid:1702,name:"点军区",level:3},1706:{id:1706,pid:1702,name:"猇亭区",level:3},1707:{id:1707,pid:1702,name:"夷陵区",level:3},1708:{id:1708,pid:1702,name:"远安县",level:3},1709:{id:1709,pid:1702,name:"兴山县",level:3},1710:{id:1710,pid:1702,name:"秭归县",level:3},1711:{id:1711,pid:1702,name:"长阳土家族自治县",level:3},1712:{id:1712,pid:1702,name:"五峰土家族自治县",level:3},1713:{id:1713,pid:1702,name:"宜都市",level:3},1714:{id:1714,pid:1702,name:"当阳市",level:3},1715:{id:1715,pid:1702,name:"枝江市",level:3}}},1716:{id:1716,pid:1671,name:"襄阳市",level:2,region:{1717:{id:1717,pid:1716,name:"襄城区",level:3},1718:{id:1718,pid:1716,name:"樊城区",level:3},1719:{id:1719,pid:1716,name:"襄州区",level:3},1720:{id:1720,pid:1716,name:"南漳县",level:3},1721:{id:1721,pid:1716,name:"谷城县",level:3},1722:{id:1722,pid:1716,name:"保康县",level:3},1723:{id:1723,pid:1716,name:"老河口市",level:3},1724:{id:1724,pid:1716,name:"枣阳市",level:3},1725:{id:1725,pid:1716,name:"宜城市",level:3}}},1726:{id:1726,pid:1671,name:"鄂州市",level:2,region:{1727:{id:1727,pid:1726,name:"梁子湖区",level:3},1728:{id:1728,pid:1726,name:"华容区",level:3},1729:{id:1729,pid:1726,name:"鄂城区",level:3}}},1730:{id:1730,pid:1671,name:"荆门市",level:2,region:{1731:{id:1731,pid:1730,name:"东宝区",level:3},1732:{id:1732,pid:1730,name:"掇刀区",level:3},1733:{id:1733,pid:1730,name:"沙洋县",level:3},1734:{id:1734,pid:1730,name:"钟祥市",level:3},1735:{id:1735,pid:1730,name:"京山市",level:3}}},1736:{id:1736,pid:1671,name:"孝感市",level:2,region:{1737:{id:1737,pid:1736,name:"孝南区",level:3},1738:{id:1738,pid:1736,name:"孝昌县",level:3},1739:{id:1739,pid:1736,name:"大悟县",level:3},1740:{id:1740,pid:1736,name:"云梦县",level:3},1741:{id:1741,pid:1736,name:"应城市",level:3},1742:{id:1742,pid:1736,name:"安陆市",level:3},1743:{id:1743,pid:1736,name:"汉川市",level:3}}},1744:{id:1744,pid:1671,name:"荆州市",level:2,region:{1745:{id:1745,pid:1744,name:"沙市区",level:3},1746:{id:1746,pid:1744,name:"荆州区",level:3},1747:{id:1747,pid:1744,name:"公安县",level:3},1749:{id:1749,pid:1744,name:"江陵县",level:3},1750:{id:1750,pid:1744,name:"石首市",level:3},1751:{id:1751,pid:1744,name:"洪湖市",level:3},1752:{id:1752,pid:1744,name:"松滋市",level:3},3846:{id:3846,pid:1744,name:"荆州经济技术开发区",level:3},3847:{id:3847,pid:1744,name:"监利市",level:3}}},1753:{id:1753,pid:1671,name:"黄冈市",level:2,region:{1754:{id:1754,pid:1753,name:"黄州区",level:3},1755:{id:1755,pid:1753,name:"团风县",level:3},1756:{id:1756,pid:1753,name:"红安县",level:3},1757:{id:1757,pid:1753,name:"罗田县",level:3},1758:{id:1758,pid:1753,name:"英山县",level:3},1759:{id:1759,pid:1753,name:"浠水县",level:3},1760:{id:1760,pid:1753,name:"蕲春县",level:3},1761:{id:1761,pid:1753,name:"黄梅县",level:3},1762:{id:1762,pid:1753,name:"麻城市",level:3},1763:{id:1763,pid:1753,name:"武穴市",level:3},3848:{id:3848,pid:1753,name:"龙感湖管理区",level:3}}},1764:{id:1764,pid:1671,name:"咸宁市",level:2,region:{1765:{id:1765,pid:1764,name:"咸安区",level:3},1766:{id:1766,pid:1764,name:"嘉鱼县",level:3},1767:{id:1767,pid:1764,name:"通城县",level:3},1768:{id:1768,pid:1764,name:"崇阳县",level:3},1769:{id:1769,pid:1764,name:"通山县",level:3},1770:{id:1770,pid:1764,name:"赤壁市",level:3}}},1771:{id:1771,pid:1671,name:"随州市",level:2,region:{1772:{id:1772,pid:1771,name:"曾都区",level:3},1773:{id:1773,pid:1771,name:"随县",level:3},1774:{id:1774,pid:1771,name:"广水市",level:3}}},1775:{id:1775,pid:1671,name:"恩施土家族苗族自治州",level:2,region:{1776:{id:1776,pid:1775,name:"恩施市",level:3},1777:{id:1777,pid:1775,name:"利川市",level:3},1778:{id:1778,pid:1775,name:"建始县",level:3},1779:{id:1779,pid:1775,name:"巴东县",level:3},1780:{id:1780,pid:1775,name:"宣恩县",level:3},1781:{id:1781,pid:1775,name:"咸丰县",level:3},1782:{id:1782,pid:1775,name:"来凤县",level:3},1783:{id:1783,pid:1775,name:"鹤峰县",level:3}}},3707:{id:3707,pid:1671,name:"省直辖县级行政区划",level:2,region:{3849:{id:3849,pid:3707,name:"仙桃市",level:3},3850:{id:3850,pid:3707,name:"潜江市",level:3},3851:{id:3851,pid:3707,name:"天门市",level:3},3852:{id:3852,pid:3707,name:"神农架林区",level:3}}}}},1788:{id:1788,pid:0,name:"湖南省",level:1,city:{1789:{id:1789,pid:1788,name:"长沙市",level:2,region:{1790:{id:1790,pid:1789,name:"芙蓉区",level:3},1791:{id:1791,pid:1789,name:"天心区",level:3},1792:{id:1792,pid:1789,name:"岳麓区",level:3},1793:{id:1793,pid:1789,name:"开福区",level:3},1794:{id:1794,pid:1789,name:"雨花区",level:3},1795:{id:1795,pid:1789,name:"望城区",level:3},1796:{id:1796,pid:1789,name:"长沙县",level:3},1797:{id:1797,pid:1789,name:"浏阳市",level:3},1798:{id:1798,pid:1789,name:"宁乡市",level:3}}},1799:{id:1799,pid:1788,name:"株洲市",level:2,region:{1800:{id:1800,pid:1799,name:"荷塘区",level:3},1801:{id:1801,pid:1799,name:"芦淞区",level:3},1802:{id:1802,pid:1799,name:"石峰区",level:3},1803:{id:1803,pid:1799,name:"天元区",level:3},1804:{id:1804,pid:1799,name:"渌口区",level:3},1805:{id:1805,pid:1799,name:"攸县",level:3},1806:{id:1806,pid:1799,name:"茶陵县",level:3},1807:{id:1807,pid:1799,name:"炎陵县",level:3},1808:{id:1808,pid:1799,name:"醴陵市",level:3}}},1809:{id:1809,pid:1788,name:"湘潭市",level:2,region:{1810:{id:1810,pid:1809,name:"雨湖区",level:3},1811:{id:1811,pid:1809,name:"岳塘区",level:3},1812:{id:1812,pid:1809,name:"湘潭县",level:3},1813:{id:1813,pid:1809,name:"湘乡市",level:3},1814:{id:1814,pid:1809,name:"韶山市",level:3},3853:{id:3853,pid:1809,name:"湖南湘潭高新技术产业园区",level:3},3854:{id:3854,pid:1809,name:"湘潭昭山示范区",level:3},3855:{id:3855,pid:1809,name:"湘潭九华示范区",level:3}}},1815:{id:1815,pid:1788,name:"衡阳市",level:2,region:{1816:{id:1816,pid:1815,name:"珠晖区",level:3},1817:{id:1817,pid:1815,name:"雁峰区",level:3},1818:{id:1818,pid:1815,name:"石鼓区",level:3},1819:{id:1819,pid:1815,name:"蒸湘区",level:3},1820:{id:1820,pid:1815,name:"南岳区",level:3},1821:{id:1821,pid:1815,name:"衡阳县",level:3},1822:{id:1822,pid:1815,name:"衡南县",level:3},1823:{id:1823,pid:1815,name:"衡山县",level:3},1824:{id:1824,pid:1815,name:"衡东县",level:3},1825:{id:1825,pid:1815,name:"祁东县",level:3},1826:{id:1826,pid:1815,name:"耒阳市",level:3},1827:{id:1827,pid:1815,name:"常宁市",level:3},3856:{id:3856,pid:1815,name:"衡阳综合保税区",level:3},3857:{id:3857,pid:1815,name:"湖南衡阳高新技术产业园区",level:3},3858:{id:3858,pid:1815,name:"湖南衡阳松木经济开发区",level:3}}},1828:{id:1828,pid:1788,name:"邵阳市",level:2,region:{1829:{id:1829,pid:1828,name:"双清区",level:3},1830:{id:1830,pid:1828,name:"大祥区",level:3},1831:{id:1831,pid:1828,name:"北塔区",level:3},1832:{id:1832,pid:1828,name:"新邵县",level:3},1833:{id:1833,pid:1828,name:"邵阳县",level:3},1834:{id:1834,pid:1828,name:"隆回县",level:3},1835:{id:1835,pid:1828,name:"洞口县",level:3},1836:{id:1836,pid:1828,name:"绥宁县",level:3},1837:{id:1837,pid:1828,name:"新宁县",level:3},1838:{id:1838,pid:1828,name:"城步苗族自治县",level:3},1839:{id:1839,pid:1828,name:"武冈市",level:3},1840:{id:1840,pid:1828,name:"邵东市",level:3}}},1841:{id:1841,pid:1788,name:"岳阳市",level:2,region:{1842:{id:1842,pid:1841,name:"岳阳楼区",level:3},1843:{id:1843,pid:1841,name:"云溪区",level:3},1844:{id:1844,pid:1841,name:"君山区",level:3},1845:{id:1845,pid:1841,name:"岳阳县",level:3},1846:{id:1846,pid:1841,name:"华容县",level:3},1847:{id:1847,pid:1841,name:"湘阴县",level:3},1848:{id:1848,pid:1841,name:"平江县",level:3},1849:{id:1849,pid:1841,name:"汨罗市",level:3},1850:{id:1850,pid:1841,name:"临湘市",level:3},3859:{id:3859,pid:1841,name:"岳阳市屈原管理区",level:3}}},1851:{id:1851,pid:1788,name:"常德市",level:2,region:{1852:{id:1852,pid:1851,name:"武陵区",level:3},1853:{id:1853,pid:1851,name:"鼎城区",level:3},1854:{id:1854,pid:1851,name:"安乡县",level:3},1855:{id:1855,pid:1851,name:"汉寿县",level:3},1856:{id:1856,pid:1851,name:"澧县",level:3},1857:{id:1857,pid:1851,name:"临澧县",level:3},1858:{id:1858,pid:1851,name:"桃源县",level:3},1859:{id:1859,pid:1851,name:"石门县",level:3},1860:{id:1860,pid:1851,name:"津市市",level:3},3860:{id:3860,pid:1851,name:"常德市西洞庭管理区",level:3}}},1861:{id:1861,pid:1788,name:"张家界市",level:2,region:{1862:{id:1862,pid:1861,name:"永定区",level:3},1863:{id:1863,pid:1861,name:"武陵源区",level:3},1864:{id:1864,pid:1861,name:"慈利县",level:3},1865:{id:1865,pid:1861,name:"桑植县",level:3}}},1866:{id:1866,pid:1788,name:"益阳市",level:2,region:{1867:{id:1867,pid:1866,name:"资阳区",level:3},1868:{id:1868,pid:1866,name:"赫山区",level:3},1869:{id:1869,pid:1866,name:"南县",level:3},1870:{id:1870,pid:1866,name:"桃江县",level:3},1871:{id:1871,pid:1866,name:"安化县",level:3},1872:{id:1872,pid:1866,name:"沅江市",level:3},3861:{id:3861,pid:1866,name:"益阳市大通湖管理区",level:3},3862:{id:3862,pid:1866,name:"湖南益阳高新技术产业园区",level:3}}},1873:{id:1873,pid:1788,name:"郴州市",level:2,region:{1874:{id:1874,pid:1873,name:"北湖区",level:3},1875:{id:1875,pid:1873,name:"苏仙区",level:3},1876:{id:1876,pid:1873,name:"桂阳县",level:3},1877:{id:1877,pid:1873,name:"宜章县",level:3},1878:{id:1878,pid:1873,name:"永兴县",level:3},1879:{id:1879,pid:1873,name:"嘉禾县",level:3},1880:{id:1880,pid:1873,name:"临武县",level:3},1881:{id:1881,pid:1873,name:"汝城县",level:3},1882:{id:1882,pid:1873,name:"桂东县",level:3},1883:{id:1883,pid:1873,name:"安仁县",level:3},1884:{id:1884,pid:1873,name:"资兴市",level:3}}},1885:{id:1885,pid:1788,name:"永州市",level:2,region:{1886:{id:1886,pid:1885,name:"零陵区",level:3},1887:{id:1887,pid:1885,name:"冷水滩区",level:3},1889:{id:1889,pid:1885,name:"东安县",level:3},1890:{id:1890,pid:1885,name:"双牌县",level:3},1891:{id:1891,pid:1885,name:"道县",level:3},1892:{id:1892,pid:1885,name:"江永县",level:3},1893:{id:1893,pid:1885,name:"宁远县",level:3},1894:{id:1894,pid:1885,name:"蓝山县",level:3},1895:{id:1895,pid:1885,name:"新田县",level:3},1896:{id:1896,pid:1885,name:"江华瑶族自治县",level:3},3863:{id:3863,pid:1885,name:"永州经济技术开发区",level:3},3864:{id:3864,pid:1885,name:"永州市回龙圩管理区",level:3},3865:{id:3865,pid:1885,name:"祁阳市",level:3}}},1897:{id:1897,pid:1788,name:"怀化市",level:2,region:{1898:{id:1898,pid:1897,name:"鹤城区",level:3},1899:{id:1899,pid:1897,name:"中方县",level:3},1900:{id:1900,pid:1897,name:"沅陵县",level:3},1901:{id:1901,pid:1897,name:"辰溪县",level:3},1902:{id:1902,pid:1897,name:"溆浦县",level:3},1903:{id:1903,pid:1897,name:"会同县",level:3},1904:{id:1904,pid:1897,name:"麻阳苗族自治县",level:3},1905:{id:1905,pid:1897,name:"新晃侗族自治县",level:3},1906:{id:1906,pid:1897,name:"芷江侗族自治县",level:3},1907:{id:1907,pid:1897,name:"靖州苗族侗族自治县",level:3},1908:{id:1908,pid:1897,name:"通道侗族自治县",level:3},1909:{id:1909,pid:1897,name:"洪江市",level:3},3866:{id:3866,pid:1897,name:"怀化市洪江管理区",level:3}}},1910:{id:1910,pid:1788,name:"娄底市",level:2,region:{1911:{id:1911,pid:1910,name:"娄星区",level:3},1912:{id:1912,pid:1910,name:"双峰县",level:3},1913:{id:1913,pid:1910,name:"新化县",level:3},1914:{id:1914,pid:1910,name:"冷水江市",level:3},1915:{id:1915,pid:1910,name:"涟源市",level:3}}},1916:{id:1916,pid:1788,name:"湘西土家族苗族自治州",level:2,region:{1917:{id:1917,pid:1916,name:"吉首市",level:3},1918:{id:1918,pid:1916,name:"泸溪县",level:3},1919:{id:1919,pid:1916,name:"凤凰县",level:3},1920:{id:1920,pid:1916,name:"花垣县",level:3},1921:{id:1921,pid:1916,name:"保靖县",level:3},1922:{id:1922,pid:1916,name:"古丈县",level:3},1923:{id:1923,pid:1916,name:"永顺县",level:3},1924:{id:1924,pid:1916,name:"龙山县",level:3}}}}},1925:{id:1925,pid:0,name:"广东省",level:1,city:{1926:{id:1926,pid:1925,name:"广州市",level:2,region:{1927:{id:1927,pid:1926,name:"荔湾区",level:3},1928:{id:1928,pid:1926,name:"越秀区",level:3},1929:{id:1929,pid:1926,name:"海珠区",level:3},1930:{id:1930,pid:1926,name:"天河区",level:3},1931:{id:1931,pid:1926,name:"白云区",level:3},1932:{id:1932,pid:1926,name:"黄埔区",level:3},1933:{id:1933,pid:1926,name:"番禺区",level:3},1934:{id:1934,pid:1926,name:"花都区",level:3},1935:{id:1935,pid:1926,name:"南沙区",level:3},1936:{id:1936,pid:1926,name:"从化区",level:3},1937:{id:1937,pid:1926,name:"增城区",level:3}}},1938:{id:1938,pid:1925,name:"韶关市",level:2,region:{1939:{id:1939,pid:1938,name:"武江区",level:3},1940:{id:1940,pid:1938,name:"浈江区",level:3},1941:{id:1941,pid:1938,name:"曲江区",level:3},1942:{id:1942,pid:1938,name:"始兴县",level:3},1943:{id:1943,pid:1938,name:"仁化县",level:3},1944:{id:1944,pid:1938,name:"翁源县",level:3},1945:{id:1945,pid:1938,name:"乳源瑶族自治县",level:3},1946:{id:1946,pid:1938,name:"新丰县",level:3},1947:{id:1947,pid:1938,name:"乐昌市",level:3},1948:{id:1948,pid:1938,name:"南雄市",level:3}}},1949:{id:1949,pid:1925,name:"深圳市",level:2,region:{1950:{id:1950,pid:1949,name:"罗湖区",level:3},1951:{id:1951,pid:1949,name:"福田区",level:3},1952:{id:1952,pid:1949,name:"南山区",level:3},1953:{id:1953,pid:1949,name:"宝安区",level:3},1954:{id:1954,pid:1949,name:"龙岗区",level:3},1955:{id:1955,pid:1949,name:"盐田区",level:3},1956:{id:1956,pid:1949,name:"龙华区",level:3},1957:{id:1957,pid:1949,name:"坪山区",level:3},1958:{id:1958,pid:1949,name:"光明区",level:3}}},1959:{id:1959,pid:1925,name:"珠海市",level:2,region:{1960:{id:1960,pid:1959,name:"香洲区",level:3},1961:{id:1961,pid:1959,name:"斗门区",level:3},1962:{id:1962,pid:1959,name:"金湾区",level:3}}},1963:{id:1963,pid:1925,name:"汕头市",level:2,region:{1964:{id:1964,pid:1963,name:"龙湖区",level:3},1965:{id:1965,pid:1963,name:"金平区",level:3},1966:{id:1966,pid:1963,name:"濠江区",level:3},1967:{id:1967,pid:1963,name:"潮阳区",level:3},1968:{id:1968,pid:1963,name:"潮南区",level:3},1969:{id:1969,pid:1963,name:"澄海区",level:3},1970:{id:1970,pid:1963,name:"南澳县",level:3}}},1971:{id:1971,pid:1925,name:"佛山市",level:2,region:{1972:{id:1972,pid:1971,name:"禅城区",level:3},1973:{id:1973,pid:1971,name:"南海区",level:3},1974:{id:1974,pid:1971,name:"顺德区",level:3},1975:{id:1975,pid:1971,name:"三水区",level:3},1976:{id:1976,pid:1971,name:"高明区",level:3}}},1977:{id:1977,pid:1925,name:"江门市",level:2,region:{1978:{id:1978,pid:1977,name:"蓬江区",level:3},1979:{id:1979,pid:1977,name:"江海区",level:3},1980:{id:1980,pid:1977,name:"新会区",level:3},1981:{id:1981,pid:1977,name:"台山市",level:3},1982:{id:1982,pid:1977,name:"开平市",level:3},1983:{id:1983,pid:1977,name:"鹤山市",level:3},1984:{id:1984,pid:1977,name:"恩平市",level:3}}},1985:{id:1985,pid:1925,name:"湛江市",level:2,region:{1986:{id:1986,pid:1985,name:"赤坎区",level:3},1987:{id:1987,pid:1985,name:"霞山区",level:3},1988:{id:1988,pid:1985,name:"坡头区",level:3},1989:{id:1989,pid:1985,name:"麻章区",level:3},1990:{id:1990,pid:1985,name:"遂溪县",level:3},1991:{id:1991,pid:1985,name:"徐闻县",level:3},1992:{id:1992,pid:1985,name:"廉江市",level:3},1993:{id:1993,pid:1985,name:"雷州市",level:3},1994:{id:1994,pid:1985,name:"吴川市",level:3}}},1995:{id:1995,pid:1925,name:"茂名市",level:2,region:{1996:{id:1996,pid:1995,name:"茂南区",level:3},1997:{id:1997,pid:1995,name:"电白区",level:3},1998:{id:1998,pid:1995,name:"高州市",level:3},1999:{id:1999,pid:1995,name:"化州市",level:3},2e3:{id:2e3,pid:1995,name:"信宜市",level:3}}},2001:{id:2001,pid:1925,name:"肇庆市",level:2,region:{2002:{id:2002,pid:2001,name:"端州区",level:3},2003:{id:2003,pid:2001,name:"鼎湖区",level:3},2004:{id:2004,pid:2001,name:"高要区",level:3},2005:{id:2005,pid:2001,name:"广宁县",level:3},2006:{id:2006,pid:2001,name:"怀集县",level:3},2007:{id:2007,pid:2001,name:"封开县",level:3},2008:{id:2008,pid:2001,name:"德庆县",level:3},2009:{id:2009,pid:2001,name:"四会市",level:3}}},2010:{id:2010,pid:1925,name:"惠州市",level:2,region:{2011:{id:2011,pid:2010,name:"惠城区",level:3},2012:{id:2012,pid:2010,name:"惠阳区",level:3},2013:{id:2013,pid:2010,name:"博罗县",level:3},2014:{id:2014,pid:2010,name:"惠东县",level:3},2015:{id:2015,pid:2010,name:"龙门县",level:3}}},2016:{id:2016,pid:1925,name:"梅州市",level:2,region:{2017:{id:2017,pid:2016,name:"梅江区",level:3},2018:{id:2018,pid:2016,name:"梅县区",level:3},2019:{id:2019,pid:2016,name:"大埔县",level:3},2020:{id:2020,pid:2016,name:"丰顺县",level:3},2021:{id:2021,pid:2016,name:"五华县",level:3},2022:{id:2022,pid:2016,name:"平远县",level:3},2023:{id:2023,pid:2016,name:"蕉岭县",level:3},2024:{id:2024,pid:2016,name:"兴宁市",level:3}}},2025:{id:2025,pid:1925,name:"汕尾市",level:2,region:{2026:{id:2026,pid:2025,name:"城区",level:3},2027:{id:2027,pid:2025,name:"海丰县",level:3},2028:{id:2028,pid:2025,name:"陆河县",level:3},2029:{id:2029,pid:2025,name:"陆丰市",level:3}}},2030:{id:2030,pid:1925,name:"河源市",level:2,region:{2031:{id:2031,pid:2030,name:"源城区",level:3},2032:{id:2032,pid:2030,name:"紫金县",level:3},2033:{id:2033,pid:2030,name:"龙川县",level:3},2034:{id:2034,pid:2030,name:"连平县",level:3},2035:{id:2035,pid:2030,name:"和平县",level:3},2036:{id:2036,pid:2030,name:"东源县",level:3}}},2037:{id:2037,pid:1925,name:"阳江市",level:2,region:{2038:{id:2038,pid:2037,name:"江城区",level:3},2039:{id:2039,pid:2037,name:"阳东区",level:3},2040:{id:2040,pid:2037,name:"阳西县",level:3},2041:{id:2041,pid:2037,name:"阳春市",level:3}}},2042:{id:2042,pid:1925,name:"清远市",level:2,region:{2043:{id:2043,pid:2042,name:"清城区",level:3},2044:{id:2044,pid:2042,name:"清新区",level:3},2045:{id:2045,pid:2042,name:"佛冈县",level:3},2046:{id:2046,pid:2042,name:"阳山县",level:3},2047:{id:2047,pid:2042,name:"连山壮族瑶族自治县",level:3},2048:{id:2048,pid:2042,name:"连南瑶族自治县",level:3},2049:{id:2049,pid:2042,name:"英德市",level:3},2050:{id:2050,pid:2042,name:"连州市",level:3}}},2051:{id:2051,pid:1925,name:"东莞市",level:2,region:{3621:{id:3621,pid:2051,name:"南城街道",level:3},3622:{id:3622,pid:2051,name:"万江街道",level:3},3623:{id:3623,pid:2051,name:"莞城街道",level:3},3624:{id:3624,pid:2051,name:"石碣镇",level:3},3625:{id:3625,pid:2051,name:"石龙镇",level:3},3626:{id:3626,pid:2051,name:"茶山镇",level:3},3627:{id:3627,pid:2051,name:"石排镇",level:3},3628:{id:3628,pid:2051,name:"企石镇",level:3},3629:{id:3629,pid:2051,name:"横沥镇",level:3},3630:{id:3630,pid:2051,name:"桥头镇",level:3},3631:{id:3631,pid:2051,name:"谢岗镇",level:3},3632:{id:3632,pid:2051,name:"东坑镇",level:3},3633:{id:3633,pid:2051,name:"常平镇",level:3},3634:{id:3634,pid:2051,name:"寮步镇",level:3},3635:{id:3635,pid:2051,name:"樟木头镇",level:3},3636:{id:3636,pid:2051,name:"大朗镇",level:3},3637:{id:3637,pid:2051,name:"黄江镇",level:3},3638:{id:3638,pid:2051,name:"清溪镇",level:3},3639:{id:3639,pid:2051,name:"塘厦镇",level:3},3640:{id:3640,pid:2051,name:"凤岗镇",level:3},3641:{id:3641,pid:2051,name:"大岭山镇",level:3},3642:{id:3642,pid:2051,name:"长安镇",level:3},3643:{id:3643,pid:2051,name:"虎门镇",level:3},3644:{id:3644,pid:2051,name:"厚街镇",level:3},3645:{id:3645,pid:2051,name:"沙田镇",level:3},3646:{id:3646,pid:2051,name:"道滘镇",level:3},3647:{id:3647,pid:2051,name:"洪梅镇",level:3},3648:{id:3648,pid:2051,name:"麻涌镇",level:3},3649:{id:3649,pid:2051,name:"望牛墩镇",level:3},3650:{id:3650,pid:2051,name:"中堂镇",level:3},3651:{id:3651,pid:2051,name:"高埗镇",level:3},3652:{id:3652,pid:2051,name:"松山湖",level:3},3653:{id:3653,pid:2051,name:"东莞港",level:3},3654:{id:3654,pid:2051,name:"东莞生态园",level:3},3867:{id:3867,pid:2051,name:"东城街道",level:3},3868:{id:3868,pid:2051,name:"东莞滨海湾新区",level:3}}},2052:{id:2052,pid:1925,name:"中山市",level:2,region:{3656:{id:3656,pid:2052,name:"东区街道",level:3},3657:{id:3657,pid:2052,name:"中山港街道",level:3},3658:{id:3658,pid:2052,name:"西区街道",level:3},3659:{id:3659,pid:2052,name:"南区街道",level:3},3660:{id:3660,pid:2052,name:"五桂山街道",level:3},3661:{id:3661,pid:2052,name:"小榄镇",level:3},3662:{id:3662,pid:2052,name:"黄圃镇",level:3},3664:{id:3664,pid:2052,name:"东凤镇",level:3},3666:{id:3666,pid:2052,name:"古镇镇",level:3},3667:{id:3667,pid:2052,name:"沙溪镇",level:3},3668:{id:3668,pid:2052,name:"坦洲镇",level:3},3669:{id:3669,pid:2052,name:"港口镇",level:3},3670:{id:3670,pid:2052,name:"三角镇",level:3},3671:{id:3671,pid:2052,name:"横栏镇",level:3},3672:{id:3672,pid:2052,name:"南头镇",level:3},3673:{id:3673,pid:2052,name:"阜沙镇",level:3},3675:{id:3675,pid:2052,name:"三乡镇",level:3},3676:{id:3676,pid:2052,name:"板芙镇",level:3},3677:{id:3677,pid:2052,name:"大涌镇",level:3},3678:{id:3678,pid:2052,name:"神湾镇",level:3},3869:{id:3869,pid:2052,name:"石岐街道",level:3},3870:{id:3870,pid:2052,name:"民众街道",level:3},3871:{id:3871,pid:2052,name:"南朗街道",level:3}}},2053:{id:2053,pid:1925,name:"潮州市",level:2,region:{2054:{id:2054,pid:2053,name:"湘桥区",level:3},2055:{id:2055,pid:2053,name:"潮安区",level:3},2056:{id:2056,pid:2053,name:"饶平县",level:3}}},2057:{id:2057,pid:1925,name:"揭阳市",level:2,region:{2058:{id:2058,pid:2057,name:"榕城区",level:3},2059:{id:2059,pid:2057,name:"揭东区",level:3},2060:{id:2060,pid:2057,name:"揭西县",level:3},2061:{id:2061,pid:2057,name:"惠来县",level:3},2062:{id:2062,pid:2057,name:"普宁市",level:3}}},2063:{id:2063,pid:1925,name:"云浮市",level:2,region:{2064:{id:2064,pid:2063,name:"云城区",level:3},2065:{id:2065,pid:2063,name:"云安区",level:3},2066:{id:2066,pid:2063,name:"新兴县",level:3},2067:{id:2067,pid:2063,name:"郁南县",level:3},2068:{id:2068,pid:2063,name:"罗定市",level:3}}}}},2069:{id:2069,pid:0,name:"广西壮族自治区",level:1,city:{2070:{id:2070,pid:2069,name:"南宁市",level:2,region:{2071:{id:2071,pid:2070,name:"兴宁区",level:3},2072:{id:2072,pid:2070,name:"青秀区",level:3},2073:{id:2073,pid:2070,name:"江南区",level:3},2074:{id:2074,pid:2070,name:"西乡塘区",level:3},2075:{id:2075,pid:2070,name:"良庆区",level:3},2076:{id:2076,pid:2070,name:"邕宁区",level:3},2077:{id:2077,pid:2070,name:"武鸣区",level:3},2078:{id:2078,pid:2070,name:"隆安县",level:3},2079:{id:2079,pid:2070,name:"马山县",level:3},2080:{id:2080,pid:2070,name:"上林县",level:3},2081:{id:2081,pid:2070,name:"宾阳县",level:3},3872:{id:3872,pid:2070,name:"横州市",level:3}}},2083:{id:2083,pid:2069,name:"柳州市",level:2,region:{2084:{id:2084,pid:2083,name:"城中区",level:3},2085:{id:2085,pid:2083,name:"鱼峰区",level:3},2086:{id:2086,pid:2083,name:"柳南区",level:3},2087:{id:2087,pid:2083,name:"柳北区",level:3},2088:{id:2088,pid:2083,name:"柳江区",level:3},2089:{id:2089,pid:2083,name:"柳城县",level:3},2090:{id:2090,pid:2083,name:"鹿寨县",level:3},2091:{id:2091,pid:2083,name:"融安县",level:3},2092:{id:2092,pid:2083,name:"融水苗族自治县",level:3},2093:{id:2093,pid:2083,name:"三江侗族自治县",level:3}}},2094:{id:2094,pid:2069,name:"桂林市",level:2,region:{2095:{id:2095,pid:2094,name:"秀峰区",level:3},2096:{id:2096,pid:2094,name:"叠彩区",level:3},2097:{id:2097,pid:2094,name:"象山区",level:3},2098:{id:2098,pid:2094,name:"七星区",level:3},2099:{id:2099,pid:2094,name:"雁山区",level:3},2100:{id:2100,pid:2094,name:"临桂区",level:3},2101:{id:2101,pid:2094,name:"阳朔县",level:3},2102:{id:2102,pid:2094,name:"灵川县",level:3},2103:{id:2103,pid:2094,name:"全州县",level:3},2104:{id:2104,pid:2094,name:"兴安县",level:3},2105:{id:2105,pid:2094,name:"永福县",level:3},2106:{id:2106,pid:2094,name:"灌阳县",level:3},2107:{id:2107,pid:2094,name:"龙胜各族自治县",level:3},2108:{id:2108,pid:2094,name:"资源县",level:3},2109:{id:2109,pid:2094,name:"平乐县",level:3},2110:{id:2110,pid:2094,name:"荔浦市",level:3},2111:{id:2111,pid:2094,name:"恭城瑶族自治县",level:3}}},2112:{id:2112,pid:2069,name:"梧州市",level:2,region:{2113:{id:2113,pid:2112,name:"万秀区",level:3},2114:{id:2114,pid:2112,name:"长洲区",level:3},2115:{id:2115,pid:2112,name:"龙圩区",level:3},2116:{id:2116,pid:2112,name:"苍梧县",level:3},2117:{id:2117,pid:2112,name:"藤县",level:3},2118:{id:2118,pid:2112,name:"蒙山县",level:3},2119:{id:2119,pid:2112,name:"岑溪市",level:3}}},2120:{id:2120,pid:2069,name:"北海市",level:2,region:{2121:{id:2121,pid:2120,name:"海城区",level:3},2122:{id:2122,pid:2120,name:"银海区",level:3},2123:{id:2123,pid:2120,name:"铁山港区",level:3},2124:{id:2124,pid:2120,name:"合浦县",level:3}}},2125:{id:2125,pid:2069,name:"防城港市",level:2,region:{2126:{id:2126,pid:2125,name:"港口区",level:3},2127:{id:2127,pid:2125,name:"防城区",level:3},2128:{id:2128,pid:2125,name:"上思县",level:3},2129:{id:2129,pid:2125,name:"东兴市",level:3}}},2130:{id:2130,pid:2069,name:"钦州市",level:2,region:{2131:{id:2131,pid:2130,name:"钦南区",level:3},2132:{id:2132,pid:2130,name:"钦北区",level:3},2133:{id:2133,pid:2130,name:"灵山县",level:3},2134:{id:2134,pid:2130,name:"浦北县",level:3}}},2135:{id:2135,pid:2069,name:"贵港市",level:2,region:{2136:{id:2136,pid:2135,name:"港北区",level:3},2137:{id:2137,pid:2135,name:"港南区",level:3},2138:{id:2138,pid:2135,name:"覃塘区",level:3},2139:{id:2139,pid:2135,name:"平南县",level:3},2140:{id:2140,pid:2135,name:"桂平市",level:3}}},2141:{id:2141,pid:2069,name:"玉林市",level:2,region:{2142:{id:2142,pid:2141,name:"玉州区",level:3},2143:{id:2143,pid:2141,name:"福绵区",level:3},2144:{id:2144,pid:2141,name:"容县",level:3},2145:{id:2145,pid:2141,name:"陆川县",level:3},2146:{id:2146,pid:2141,name:"博白县",level:3},2147:{id:2147,pid:2141,name:"兴业县",level:3},2148:{id:2148,pid:2141,name:"北流市",level:3}}},2149:{id:2149,pid:2069,name:"百色市",level:2,region:{2150:{id:2150,pid:2149,name:"右江区",level:3},2151:{id:2151,pid:2149,name:"田阳区",level:3},2152:{id:2152,pid:2149,name:"田东县",level:3},2153:{id:2153,pid:2149,name:"德保县",level:3},2154:{id:2154,pid:2149,name:"那坡县",level:3},2155:{id:2155,pid:2149,name:"凌云县",level:3},2156:{id:2156,pid:2149,name:"乐业县",level:3},2157:{id:2157,pid:2149,name:"田林县",level:3},2158:{id:2158,pid:2149,name:"西林县",level:3},2159:{id:2159,pid:2149,name:"隆林各族自治县",level:3},2160:{id:2160,pid:2149,name:"靖西市",level:3},2161:{id:2161,pid:2149,name:"平果市",level:3}}},2162:{id:2162,pid:2069,name:"贺州市",level:2,region:{2163:{id:2163,pid:2162,name:"八步区",level:3},2164:{id:2164,pid:2162,name:"平桂区",level:3},2165:{id:2165,pid:2162,name:"昭平县",level:3},2166:{id:2166,pid:2162,name:"钟山县",level:3},2167:{id:2167,pid:2162,name:"富川瑶族自治县",level:3}}},2168:{id:2168,pid:2069,name:"河池市",level:2,region:{2169:{id:2169,pid:2168,name:"金城江区",level:3},2170:{id:2170,pid:2168,name:"宜州区",level:3},2171:{id:2171,pid:2168,name:"南丹县",level:3},2172:{id:2172,pid:2168,name:"天峨县",level:3},2173:{id:2173,pid:2168,name:"凤山县",level:3},2174:{id:2174,pid:2168,name:"东兰县",level:3},2175:{id:2175,pid:2168,name:"罗城仫佬族自治县",level:3},2176:{id:2176,pid:2168,name:"环江毛南族自治县",level:3},2177:{id:2177,pid:2168,name:"巴马瑶族自治县",level:3},2178:{id:2178,pid:2168,name:"都安瑶族自治县",level:3},2179:{id:2179,pid:2168,name:"大化瑶族自治县",level:3}}},2180:{id:2180,pid:2069,name:"来宾市",level:2,region:{2181:{id:2181,pid:2180,name:"兴宾区",level:3},2182:{id:2182,pid:2180,name:"忻城县",level:3},2183:{id:2183,pid:2180,name:"象州县",level:3},2184:{id:2184,pid:2180,name:"武宣县",level:3},2185:{id:2185,pid:2180,name:"金秀瑶族自治县",level:3},2186:{id:2186,pid:2180,name:"合山市",level:3}}},2187:{id:2187,pid:2069,name:"崇左市",level:2,region:{2188:{id:2188,pid:2187,name:"江州区",level:3},2189:{id:2189,pid:2187,name:"扶绥县",level:3},2190:{id:2190,pid:2187,name:"宁明县",level:3},2191:{id:2191,pid:2187,name:"龙州县",level:3},2192:{id:2192,pid:2187,name:"大新县",level:3},2193:{id:2193,pid:2187,name:"天等县",level:3},2194:{id:2194,pid:2187,name:"凭祥市",level:3}}}}},2195:{id:2195,pid:0,name:"海南省",level:1,city:{2196:{id:2196,pid:2195,name:"海口市",level:2,region:{2197:{id:2197,pid:2196,name:"秀英区",level:3},2198:{id:2198,pid:2196,name:"龙华区",level:3},2199:{id:2199,pid:2196,name:"琼山区",level:3},2200:{id:2200,pid:2196,name:"美兰区",level:3}}},2201:{id:2201,pid:2195,name:"三亚市",level:2,region:{2202:{id:2202,pid:2201,name:"海棠区",level:3},2203:{id:2203,pid:2201,name:"吉阳区",level:3},2204:{id:2204,pid:2201,name:"天涯区",level:3},2205:{id:2205,pid:2201,name:"崖州区",level:3}}},2206:{id:2206,pid:2195,name:"三沙市",level:2,region:{3680:{id:3680,pid:2206,name:"南沙群岛",level:3},3681:{id:3681,pid:2206,name:"中沙群岛的岛礁及其海域",level:3},3873:{id:3873,pid:2206,name:"西沙群岛",level:3}}},2207:{id:2207,pid:2195,name:"儋州市",level:2,region:{3683:{id:3683,pid:2207,name:"和庆镇",level:3},3684:{id:3684,pid:2207,name:"南丰镇",level:3},3685:{id:3685,pid:2207,name:"大成镇",level:3},3686:{id:3686,pid:2207,name:"雅星镇",level:3},3687:{id:3687,pid:2207,name:"兰洋镇",level:3},3688:{id:3688,pid:2207,name:"光村镇",level:3},3689:{id:3689,pid:2207,name:"木棠镇",level:3},3690:{id:3690,pid:2207,name:"海头镇",level:3},3691:{id:3691,pid:2207,name:"峨蔓镇",level:3},3692:{id:3692,pid:2207,name:"王五镇",level:3},3693:{id:3693,pid:2207,name:"白马井镇",level:3},3694:{id:3694,pid:2207,name:"中和镇",level:3},3695:{id:3695,pid:2207,name:"排浦镇",level:3},3696:{id:3696,pid:2207,name:"东成镇",level:3},3697:{id:3697,pid:2207,name:"新州镇",level:3},3698:{id:3698,pid:2207,name:"洋浦经济开发区",level:3},3699:{id:3699,pid:2207,name:"华南热作学院",level:3},3874:{id:3874,pid:2207,name:"那大镇",level:3}}},3708:{id:3708,pid:2195,name:"省直辖县级行政区划",level:2,region:{3875:{id:3875,pid:3708,name:"五指山市",level:3},3876:{id:3876,pid:3708,name:"琼海市",level:3},3877:{id:3877,pid:3708,name:"文昌市",level:3},3878:{id:3878,pid:3708,name:"万宁市",level:3},3879:{id:3879,pid:3708,name:"东方市",level:3},3880:{id:3880,pid:3708,name:"定安县",level:3},3881:{id:3881,pid:3708,name:"屯昌县",level:3},3882:{id:3882,pid:3708,name:"澄迈县",level:3},3883:{id:3883,pid:3708,name:"临高县",level:3},3884:{id:3884,pid:3708,name:"白沙黎族自治县",level:3},3885:{id:3885,pid:3708,name:"昌江黎族自治县",level:3},3886:{id:3886,pid:3708,name:"乐东黎族自治县",level:3},3887:{id:3887,pid:3708,name:"陵水黎族自治县",level:3},3888:{id:3888,pid:3708,name:"保亭黎族苗族自治县",level:3},3889:{id:3889,pid:3708,name:"琼中黎族苗族自治县",level:3}}}}},2223:{id:2223,pid:0,name:"重庆市",level:1,city:{2224:{id:2224,pid:2223,name:"重庆市",level:2,region:{2225:{id:2225,pid:2224,name:"万州区",level:3},2226:{id:2226,pid:2224,name:"涪陵区",level:3},2227:{id:2227,pid:2224,name:"渝中区",level:3},2228:{id:2228,pid:2224,name:"大渡口区",level:3},2229:{id:2229,pid:2224,name:"江北区",level:3},2230:{id:2230,pid:2224,name:"沙坪坝区",level:3},2231:{id:2231,pid:2224,name:"九龙坡区",level:3},2232:{id:2232,pid:2224,name:"南岸区",level:3},2233:{id:2233,pid:2224,name:"北碚区",level:3},2234:{id:2234,pid:2224,name:"綦江区",level:3},2235:{id:2235,pid:2224,name:"大足区",level:3},2236:{id:2236,pid:2224,name:"渝北区",level:3},2237:{id:2237,pid:2224,name:"巴南区",level:3},2238:{id:2238,pid:2224,name:"黔江区",level:3},2239:{id:2239,pid:2224,name:"长寿区",level:3},2240:{id:2240,pid:2224,name:"江津区",level:3},2241:{id:2241,pid:2224,name:"合川区",level:3},2242:{id:2242,pid:2224,name:"永川区",level:3},2243:{id:2243,pid:2224,name:"南川区",level:3},2244:{id:2244,pid:2224,name:"璧山区",level:3},2245:{id:2245,pid:2224,name:"铜梁区",level:3},2246:{id:2246,pid:2224,name:"潼南区",level:3},2247:{id:2247,pid:2224,name:"荣昌区",level:3},2248:{id:2248,pid:2224,name:"开州区",level:3},2249:{id:2249,pid:2224,name:"梁平区",level:3},2250:{id:2250,pid:2224,name:"武隆区",level:3}}},3709:{id:3709,pid:2223,name:"县",level:2,region:{3890:{id:3890,pid:3709,name:"城口县",level:3},3891:{id:3891,pid:3709,name:"丰都县",level:3},3892:{id:3892,pid:3709,name:"垫江县",level:3},3893:{id:3893,pid:3709,name:"忠县",level:3},3894:{id:3894,pid:3709,name:"云阳县",level:3},3895:{id:3895,pid:3709,name:"奉节县",level:3},3896:{id:3896,pid:3709,name:"巫山县",level:3},3897:{id:3897,pid:3709,name:"巫溪县",level:3},3898:{id:3898,pid:3709,name:"石柱土家族自治县",level:3},3899:{id:3899,pid:3709,name:"秀山土家族苗族自治县",level:3},3900:{id:3900,pid:3709,name:"酉阳土家族苗族自治县",level:3},3901:{id:3901,pid:3709,name:"彭水苗族土家族自治县",level:3}}}}},2263:{id:2263,pid:0,name:"四川省",level:1,city:{2264:{id:2264,pid:2263,name:"成都市",level:2,region:{2265:{id:2265,pid:2264,name:"锦江区",level:3},2266:{id:2266,pid:2264,name:"青羊区",level:3},2267:{id:2267,pid:2264,name:"金牛区",level:3},2268:{id:2268,pid:2264,name:"武侯区",level:3},2269:{id:2269,pid:2264,name:"成华区",level:3},2270:{id:2270,pid:2264,name:"龙泉驿区",level:3},2271:{id:2271,pid:2264,name:"青白江区",level:3},2272:{id:2272,pid:2264,name:"新都区",level:3},2273:{id:2273,pid:2264,name:"温江区",level:3},2274:{id:2274,pid:2264,name:"双流区",level:3},2275:{id:2275,pid:2264,name:"郫都区",level:3},2276:{id:2276,pid:2264,name:"金堂县",level:3},2277:{id:2277,pid:2264,name:"大邑县",level:3},2278:{id:2278,pid:2264,name:"蒲江县",level:3},2280:{id:2280,pid:2264,name:"都江堰市",level:3},2281:{id:2281,pid:2264,name:"彭州市",level:3},2282:{id:2282,pid:2264,name:"邛崃市",level:3},2283:{id:2283,pid:2264,name:"崇州市",level:3},2284:{id:2284,pid:2264,name:"简阳市",level:3},3902:{id:3902,pid:2264,name:"新津区",level:3}}},2285:{id:2285,pid:2263,name:"自贡市",level:2,region:{2286:{id:2286,pid:2285,name:"自流井区",level:3},2287:{id:2287,pid:2285,name:"贡井区",level:3},2288:{id:2288,pid:2285,name:"大安区",level:3},2289:{id:2289,pid:2285,name:"沿滩区",level:3},2290:{id:2290,pid:2285,name:"荣县",level:3},2291:{id:2291,pid:2285,name:"富顺县",level:3}}},2292:{id:2292,pid:2263,name:"攀枝花市",level:2,region:{2293:{id:2293,pid:2292,name:"东区",level:3},2294:{id:2294,pid:2292,name:"西区",level:3},2295:{id:2295,pid:2292,name:"仁和区",level:3},2296:{id:2296,pid:2292,name:"米易县",level:3},2297:{id:2297,pid:2292,name:"盐边县",level:3}}},2298:{id:2298,pid:2263,name:"泸州市",level:2,region:{2299:{id:2299,pid:2298,name:"江阳区",level:3},2300:{id:2300,pid:2298,name:"纳溪区",level:3},2301:{id:2301,pid:2298,name:"龙马潭区",level:3},2302:{id:2302,pid:2298,name:"泸县",level:3},2303:{id:2303,pid:2298,name:"合江县",level:3},2304:{id:2304,pid:2298,name:"叙永县",level:3},2305:{id:2305,pid:2298,name:"古蔺县",level:3}}},2306:{id:2306,pid:2263,name:"德阳市",level:2,region:{2307:{id:2307,pid:2306,name:"旌阳区",level:3},2308:{id:2308,pid:2306,name:"罗江区",level:3},2309:{id:2309,pid:2306,name:"中江县",level:3},2310:{id:2310,pid:2306,name:"广汉市",level:3},2311:{id:2311,pid:2306,name:"什邡市",level:3},2312:{id:2312,pid:2306,name:"绵竹市",level:3}}},2313:{id:2313,pid:2263,name:"绵阳市",level:2,region:{2314:{id:2314,pid:2313,name:"涪城区",level:3},2315:{id:2315,pid:2313,name:"游仙区",level:3},2316:{id:2316,pid:2313,name:"安州区",level:3},2317:{id:2317,pid:2313,name:"三台县",level:3},2318:{id:2318,pid:2313,name:"盐亭县",level:3},2319:{id:2319,pid:2313,name:"梓潼县",level:3},2320:{id:2320,pid:2313,name:"北川羌族自治县",level:3},2321:{id:2321,pid:2313,name:"平武县",level:3},2322:{id:2322,pid:2313,name:"江油市",level:3}}},2323:{id:2323,pid:2263,name:"广元市",level:2,region:{2324:{id:2324,pid:2323,name:"利州区",level:3},2325:{id:2325,pid:2323,name:"昭化区",level:3},2326:{id:2326,pid:2323,name:"朝天区",level:3},2327:{id:2327,pid:2323,name:"旺苍县",level:3},2328:{id:2328,pid:2323,name:"青川县",level:3},2329:{id:2329,pid:2323,name:"剑阁县",level:3},2330:{id:2330,pid:2323,name:"苍溪县",level:3}}},2331:{id:2331,pid:2263,name:"遂宁市",level:2,region:{2332:{id:2332,pid:2331,name:"船山区",level:3},2333:{id:2333,pid:2331,name:"安居区",level:3},2334:{id:2334,pid:2331,name:"蓬溪县",level:3},2335:{id:2335,pid:2331,name:"大英县",level:3},2336:{id:2336,pid:2331,name:"射洪市",level:3}}},2337:{id:2337,pid:2263,name:"内江市",level:2,region:{2338:{id:2338,pid:2337,name:"市中区",level:3},2339:{id:2339,pid:2337,name:"东兴区",level:3},2340:{id:2340,pid:2337,name:"威远县",level:3},2341:{id:2341,pid:2337,name:"资中县",level:3},2342:{id:2342,pid:2337,name:"隆昌市",level:3}}},2343:{id:2343,pid:2263,name:"乐山市",level:2,region:{2344:{id:2344,pid:2343,name:"市中区",level:3},2345:{id:2345,pid:2343,name:"沙湾区",level:3},2346:{id:2346,pid:2343,name:"五通桥区",level:3},2347:{id:2347,pid:2343,name:"金口河区",level:3},2348:{id:2348,pid:2343,name:"犍为县",level:3},2349:{id:2349,pid:2343,name:"井研县",level:3},2350:{id:2350,pid:2343,name:"夹江县",level:3},2351:{id:2351,pid:2343,name:"沐川县",level:3},2352:{id:2352,pid:2343,name:"峨边彝族自治县",level:3},2353:{id:2353,pid:2343,name:"马边彝族自治县",level:3},2354:{id:2354,pid:2343,name:"峨眉山市",level:3}}},2355:{id:2355,pid:2263,name:"南充市",level:2,region:{2356:{id:2356,pid:2355,name:"顺庆区",level:3},2357:{id:2357,pid:2355,name:"高坪区",level:3},2358:{id:2358,pid:2355,name:"嘉陵区",level:3},2359:{id:2359,pid:2355,name:"南部县",level:3},2360:{id:2360,pid:2355,name:"营山县",level:3},2361:{id:2361,pid:2355,name:"蓬安县",level:3},2362:{id:2362,pid:2355,name:"仪陇县",level:3},2363:{id:2363,pid:2355,name:"西充县",level:3},2364:{id:2364,pid:2355,name:"阆中市",level:3}}},2365:{id:2365,pid:2263,name:"眉山市",level:2,region:{2366:{id:2366,pid:2365,name:"东坡区",level:3},2367:{id:2367,pid:2365,name:"彭山区",level:3},2368:{id:2368,pid:2365,name:"仁寿县",level:3},2369:{id:2369,pid:2365,name:"洪雅县",level:3},2370:{id:2370,pid:2365,name:"丹棱县",level:3},2371:{id:2371,pid:2365,name:"青神县",level:3}}},2372:{id:2372,pid:2263,name:"宜宾市",level:2,region:{2373:{id:2373,pid:2372,name:"翠屏区",level:3},2374:{id:2374,pid:2372,name:"南溪区",level:3},2375:{id:2375,pid:2372,name:"叙州区",level:3},2376:{id:2376,pid:2372,name:"江安县",level:3},2377:{id:2377,pid:2372,name:"长宁县",level:3},2378:{id:2378,pid:2372,name:"高县",level:3},2379:{id:2379,pid:2372,name:"珙县",level:3},2380:{id:2380,pid:2372,name:"筠连县",level:3},2381:{id:2381,pid:2372,name:"兴文县",level:3},2382:{id:2382,pid:2372,name:"屏山县",level:3}}},2383:{id:2383,pid:2263,name:"广安市",level:2,region:{2384:{id:2384,pid:2383,name:"广安区",level:3},2385:{id:2385,pid:2383,name:"前锋区",level:3},2386:{id:2386,pid:2383,name:"岳池县",level:3},2387:{id:2387,pid:2383,name:"武胜县",level:3},2388:{id:2388,pid:2383,name:"邻水县",level:3},2389:{id:2389,pid:2383,name:"华蓥市",level:3}}},2390:{id:2390,pid:2263,name:"达州市",level:2,region:{2391:{id:2391,pid:2390,name:"通川区",level:3},2392:{id:2392,pid:2390,name:"达川区",level:3},2393:{id:2393,pid:2390,name:"宣汉县",level:3},2394:{id:2394,pid:2390,name:"开江县",level:3},2395:{id:2395,pid:2390,name:"大竹县",level:3},2396:{id:2396,pid:2390,name:"渠县",level:3},2397:{id:2397,pid:2390,name:"万源市",level:3}}},2398:{id:2398,pid:2263,name:"雅安市",level:2,region:{2399:{id:2399,pid:2398,name:"雨城区",level:3},2400:{id:2400,pid:2398,name:"名山区",level:3},2401:{id:2401,pid:2398,name:"荥经县",level:3},2402:{id:2402,pid:2398,name:"汉源县",level:3},2403:{id:2403,pid:2398,name:"石棉县",level:3},2404:{id:2404,pid:2398,name:"天全县",level:3},2405:{id:2405,pid:2398,name:"芦山县",level:3},2406:{id:2406,pid:2398,name:"宝兴县",level:3}}},2407:{id:2407,pid:2263,name:"巴中市",level:2,region:{2408:{id:2408,pid:2407,name:"巴州区",level:3},2409:{id:2409,pid:2407,name:"恩阳区",level:3},2410:{id:2410,pid:2407,name:"通江县",level:3},2411:{id:2411,pid:2407,name:"南江县",level:3},2412:{id:2412,pid:2407,name:"平昌县",level:3}}},2413:{id:2413,pid:2263,name:"资阳市",level:2,region:{2414:{id:2414,pid:2413,name:"雁江区",level:3},2415:{id:2415,pid:2413,name:"安岳县",level:3},2416:{id:2416,pid:2413,name:"乐至县",level:3}}},2417:{id:2417,pid:2263,name:"阿坝藏族羌族自治州",level:2,region:{2418:{id:2418,pid:2417,name:"马尔康市",level:3},2419:{id:2419,pid:2417,name:"汶川县",level:3},2420:{id:2420,pid:2417,name:"理县",level:3},2421:{id:2421,pid:2417,name:"茂县",level:3},2422:{id:2422,pid:2417,name:"松潘县",level:3},2423:{id:2423,pid:2417,name:"九寨沟县",level:3},2424:{id:2424,pid:2417,name:"金川县",level:3},2425:{id:2425,pid:2417,name:"小金县",level:3},2426:{id:2426,pid:2417,name:"黑水县",level:3},2427:{id:2427,pid:2417,name:"壤塘县",level:3},2428:{id:2428,pid:2417,name:"阿坝县",level:3},2429:{id:2429,pid:2417,name:"若尔盖县",level:3},2430:{id:2430,pid:2417,name:"红原县",level:3}}},2431:{id:2431,pid:2263,name:"甘孜藏族自治州",level:2,region:{2432:{id:2432,pid:2431,name:"康定市",level:3},2433:{id:2433,pid:2431,name:"泸定县",level:3},2434:{id:2434,pid:2431,name:"丹巴县",level:3},2435:{id:2435,pid:2431,name:"九龙县",level:3},2436:{id:2436,pid:2431,name:"雅江县",level:3},2437:{id:2437,pid:2431,name:"道孚县",level:3},2438:{id:2438,pid:2431,name:"炉霍县",level:3},2439:{id:2439,pid:2431,name:"甘孜县",level:3},2440:{id:2440,pid:2431,name:"新龙县",level:3},2441:{id:2441,pid:2431,name:"德格县",level:3},2442:{id:2442,pid:2431,name:"白玉县",level:3},2443:{id:2443,pid:2431,name:"石渠县",level:3},2444:{id:2444,pid:2431,name:"色达县",level:3},2445:{id:2445,pid:2431,name:"理塘县",level:3},2446:{id:2446,pid:2431,name:"巴塘县",level:3},2447:{id:2447,pid:2431,name:"乡城县",level:3},2448:{id:2448,pid:2431,name:"稻城县",level:3},2449:{id:2449,pid:2431,name:"得荣县",level:3}}},2450:{id:2450,pid:2263,name:"凉山彝族自治州",level:2,region:{2451:{id:2451,pid:2450,name:"西昌市",level:3},2452:{id:2452,pid:2450,name:"木里藏族自治县",level:3},2453:{id:2453,pid:2450,name:"盐源县",level:3},2454:{id:2454,pid:2450,name:"德昌县",level:3},2456:{id:2456,pid:2450,name:"会东县",level:3},2457:{id:2457,pid:2450,name:"宁南县",level:3},2458:{id:2458,pid:2450,name:"普格县",level:3},2459:{id:2459,pid:2450,name:"布拖县",level:3},2460:{id:2460,pid:2450,name:"金阳县",level:3},2461:{id:2461,pid:2450,name:"昭觉县",level:3},2462:{id:2462,pid:2450,name:"喜德县",level:3},2463:{id:2463,pid:2450,name:"冕宁县",level:3},2464:{id:2464,pid:2450,name:"越西县",level:3},2465:{id:2465,pid:2450,name:"甘洛县",level:3},2466:{id:2466,pid:2450,name:"美姑县",level:3},2467:{id:2467,pid:2450,name:"雷波县",level:3},3903:{id:3903,pid:2450,name:"会理市",level:3}}}}},2468:{id:2468,pid:0,name:"贵州省",level:1,city:{2469:{id:2469,pid:2468,name:"贵阳市",level:2,region:{2470:{id:2470,pid:2469,name:"南明区",level:3},2471:{id:2471,pid:2469,name:"云岩区",level:3},2472:{id:2472,pid:2469,name:"花溪区",level:3},2473:{id:2473,pid:2469,name:"乌当区",level:3},2474:{id:2474,pid:2469,name:"白云区",level:3},2475:{id:2475,pid:2469,name:"观山湖区",level:3},2476:{id:2476,pid:2469,name:"开阳县",level:3},2477:{id:2477,pid:2469,name:"息烽县",level:3},2478:{id:2478,pid:2469,name:"修文县",level:3},2479:{id:2479,pid:2469,name:"清镇市",level:3}}},2480:{id:2480,pid:2468,name:"六盘水市",level:2,region:{2481:{id:2481,pid:2480,name:"钟山区",level:3},2482:{id:2482,pid:2480,name:"六枝特区",level:3},2484:{id:2484,pid:2480,name:"盘州市",level:3},3904:{id:3904,pid:2480,name:"水城区",level:3}}},2485:{id:2485,pid:2468,name:"遵义市",level:2,region:{2486:{id:2486,pid:2485,name:"红花岗区",level:3},2487:{id:2487,pid:2485,name:"汇川区",level:3},2488:{id:2488,pid:2485,name:"播州区",level:3},2489:{id:2489,pid:2485,name:"桐梓县",level:3},2490:{id:2490,pid:2485,name:"绥阳县",level:3},2491:{id:2491,pid:2485,name:"正安县",level:3},2492:{id:2492,pid:2485,name:"道真仡佬族苗族自治县",level:3},2493:{id:2493,pid:2485,name:"务川仡佬族苗族自治县",level:3},2494:{id:2494,pid:2485,name:"凤冈县",level:3},2495:{id:2495,pid:2485,name:"湄潭县",level:3},2496:{id:2496,pid:2485,name:"余庆县",level:3},2497:{id:2497,pid:2485,name:"习水县",level:3},2498:{id:2498,pid:2485,name:"赤水市",level:3},2499:{id:2499,pid:2485,name:"仁怀市",level:3}}},2500:{id:2500,pid:2468,name:"安顺市",level:2,region:{2501:{id:2501,pid:2500,name:"西秀区",level:3},2502:{id:2502,pid:2500,name:"平坝区",level:3},2503:{id:2503,pid:2500,name:"普定县",level:3},2504:{id:2504,pid:2500,name:"镇宁布依族苗族自治县",level:3},2505:{id:2505,pid:2500,name:"关岭布依族苗族自治县",level:3},2506:{id:2506,pid:2500,name:"紫云苗族布依族自治县",level:3}}},2507:{id:2507,pid:2468,name:"毕节市",level:2,region:{2508:{id:2508,pid:2507,name:"七星关区",level:3},2509:{id:2509,pid:2507,name:"大方县",level:3},2511:{id:2511,pid:2507,name:"金沙县",level:3},2512:{id:2512,pid:2507,name:"织金县",level:3},2513:{id:2513,pid:2507,name:"纳雍县",level:3},2514:{id:2514,pid:2507,name:"威宁彝族回族苗族自治县",level:3},2515:{id:2515,pid:2507,name:"赫章县",level:3},3905:{id:3905,pid:2507,name:"黔西市",level:3}}},2516:{id:2516,pid:2468,name:"铜仁市",level:2,region:{2517:{id:2517,pid:2516,name:"碧江区",level:3},2518:{id:2518,pid:2516,name:"万山区",level:3},2519:{id:2519,pid:2516,name:"江口县",level:3},2520:{id:2520,pid:2516,name:"玉屏侗族自治县",level:3},2521:{id:2521,pid:2516,name:"石阡县",level:3},2522:{id:2522,pid:2516,name:"思南县",level:3},2523:{id:2523,pid:2516,name:"印江土家族苗族自治县",level:3},2524:{id:2524,pid:2516,name:"德江县",level:3},2525:{id:2525,pid:2516,name:"沿河土家族自治县",level:3},2526:{id:2526,pid:2516,name:"松桃苗族自治县",level:3}}},2527:{id:2527,pid:2468,name:"黔西南布依族苗族自治州",level:2,region:{2528:{id:2528,pid:2527,name:"兴义市",level:3},2529:{id:2529,pid:2527,name:"兴仁市",level:3},2530:{id:2530,pid:2527,name:"普安县",level:3},2531:{id:2531,pid:2527,name:"晴隆县",level:3},2532:{id:2532,pid:2527,name:"贞丰县",level:3},2533:{id:2533,pid:2527,name:"望谟县",level:3},2534:{id:2534,pid:2527,name:"册亨县",level:3},2535:{id:2535,pid:2527,name:"安龙县",level:3}}},2536:{id:2536,pid:2468,name:"黔东南苗族侗族自治州",level:2,region:{2537:{id:2537,pid:2536,name:"凯里市",level:3},2538:{id:2538,pid:2536,name:"黄平县",level:3},2539:{id:2539,pid:2536,name:"施秉县",level:3},2540:{id:2540,pid:2536,name:"三穗县",level:3},2541:{id:2541,pid:2536,name:"镇远县",level:3},2542:{id:2542,pid:2536,name:"岑巩县",level:3},2543:{id:2543,pid:2536,name:"天柱县",level:3},2544:{id:2544,pid:2536,name:"锦屏县",level:3},2545:{id:2545,pid:2536,name:"剑河县",level:3},2546:{id:2546,pid:2536,name:"台江县",level:3},2547:{id:2547,pid:2536,name:"黎平县",level:3},2548:{id:2548,pid:2536,name:"榕江县",level:3},2549:{id:2549,pid:2536,name:"从江县",level:3},2550:{id:2550,pid:2536,name:"雷山县",level:3},2551:{id:2551,pid:2536,name:"麻江县",level:3},2552:{id:2552,pid:2536,name:"丹寨县",level:3}}},2553:{id:2553,pid:2468,name:"黔南布依族苗族自治州",level:2,region:{2554:{id:2554,pid:2553,name:"都匀市",level:3},2555:{id:2555,pid:2553,name:"福泉市",level:3},2556:{id:2556,pid:2553,name:"荔波县",level:3},2557:{id:2557,pid:2553,name:"贵定县",level:3},2558:{id:2558,pid:2553,name:"瓮安县",level:3},2559:{id:2559,pid:2553,name:"独山县",level:3},2560:{id:2560,pid:2553,name:"平塘县",level:3},2561:{id:2561,pid:2553,name:"罗甸县",level:3},2562:{id:2562,pid:2553,name:"长顺县",level:3},2563:{id:2563,pid:2553,name:"龙里县",level:3},2564:{id:2564,pid:2553,name:"惠水县",level:3},2565:{id:2565,pid:2553,name:"三都水族自治县",level:3}}}}},2566:{id:2566,pid:0,name:"云南省",level:1,city:{2567:{id:2567,pid:2566,name:"昆明市",level:2,region:{2568:{id:2568,pid:2567,name:"五华区",level:3},2569:{id:2569,pid:2567,name:"盘龙区",level:3},2570:{id:2570,pid:2567,name:"官渡区",level:3},2571:{id:2571,pid:2567,name:"西山区",level:3},2572:{id:2572,pid:2567,name:"东川区",level:3},2573:{id:2573,pid:2567,name:"呈贡区",level:3},2574:{id:2574,pid:2567,name:"晋宁区",level:3},2575:{id:2575,pid:2567,name:"富民县",level:3},2576:{id:2576,pid:2567,name:"宜良县",level:3},2577:{id:2577,pid:2567,name:"石林彝族自治县",level:3},2578:{id:2578,pid:2567,name:"嵩明县",level:3},2579:{id:2579,pid:2567,name:"禄劝彝族苗族自治县",level:3},2580:{id:2580,pid:2567,name:"寻甸回族彝族自治县",level:3},2581:{id:2581,pid:2567,name:"安宁市",level:3}}},2582:{id:2582,pid:2566,name:"曲靖市",level:2,region:{2583:{id:2583,pid:2582,name:"麒麟区",level:3},2584:{id:2584,pid:2582,name:"沾益区",level:3},2585:{id:2585,pid:2582,name:"马龙区",level:3},2586:{id:2586,pid:2582,name:"陆良县",level:3},2587:{id:2587,pid:2582,name:"师宗县",level:3},2588:{id:2588,pid:2582,name:"罗平县",level:3},2589:{id:2589,pid:2582,name:"富源县",level:3},2590:{id:2590,pid:2582,name:"会泽县",level:3},2591:{id:2591,pid:2582,name:"宣威市",level:3}}},2592:{id:2592,pid:2566,name:"玉溪市",level:2,region:{2593:{id:2593,pid:2592,name:"红塔区",level:3},2594:{id:2594,pid:2592,name:"江川区",level:3},2595:{id:2595,pid:2592,name:"通海县",level:3},2596:{id:2596,pid:2592,name:"华宁县",level:3},2597:{id:2597,pid:2592,name:"易门县",level:3},2598:{id:2598,pid:2592,name:"峨山彝族自治县",level:3},2599:{id:2599,pid:2592,name:"新平彝族傣族自治县",level:3},2600:{id:2600,pid:2592,name:"元江哈尼族彝族傣族自治县",level:3},2601:{id:2601,pid:2592,name:"澄江市",level:3}}},2602:{id:2602,pid:2566,name:"保山市",level:2,region:{2603:{id:2603,pid:2602,name:"隆阳区",level:3},2604:{id:2604,pid:2602,name:"施甸县",level:3},2605:{id:2605,pid:2602,name:"龙陵县",level:3},2606:{id:2606,pid:2602,name:"昌宁县",level:3},2607:{id:2607,pid:2602,name:"腾冲市",level:3}}},2608:{id:2608,pid:2566,name:"昭通市",level:2,region:{2609:{id:2609,pid:2608,name:"昭阳区",level:3},2610:{id:2610,pid:2608,name:"鲁甸县",level:3},2611:{id:2611,pid:2608,name:"巧家县",level:3},2612:{id:2612,pid:2608,name:"盐津县",level:3},2613:{id:2613,pid:2608,name:"大关县",level:3},2614:{id:2614,pid:2608,name:"永善县",level:3},2615:{id:2615,pid:2608,name:"绥江县",level:3},2616:{id:2616,pid:2608,name:"镇雄县",level:3},2617:{id:2617,pid:2608,name:"彝良县",level:3},2618:{id:2618,pid:2608,name:"威信县",level:3},2619:{id:2619,pid:2608,name:"水富市",level:3}}},2620:{id:2620,pid:2566,name:"丽江市",level:2,region:{2621:{id:2621,pid:2620,name:"古城区",level:3},2622:{id:2622,pid:2620,name:"玉龙纳西族自治县",level:3},2623:{id:2623,pid:2620,name:"永胜县",level:3},2624:{id:2624,pid:2620,name:"华坪县",level:3},2625:{id:2625,pid:2620,name:"宁蒗彝族自治县",level:3}}},2626:{id:2626,pid:2566,name:"普洱市",level:2,region:{2627:{id:2627,pid:2626,name:"思茅区",level:3},2628:{id:2628,pid:2626,name:"宁洱哈尼族彝族自治县",level:3},2629:{id:2629,pid:2626,name:"墨江哈尼族自治县",level:3},2630:{id:2630,pid:2626,name:"景东彝族自治县",level:3},2631:{id:2631,pid:2626,name:"景谷傣族彝族自治县",level:3},2632:{id:2632,pid:2626,name:"镇沅彝族哈尼族拉祜族自治县",level:3},2633:{id:2633,pid:2626,name:"江城哈尼族彝族自治县",level:3},2634:{id:2634,pid:2626,name:"孟连傣族拉祜族佤族自治县",level:3},2635:{id:2635,pid:2626,name:"澜沧拉祜族自治县",level:3},2636:{id:2636,pid:2626,name:"西盟佤族自治县",level:3}}},2637:{id:2637,pid:2566,name:"临沧市",level:2,region:{2638:{id:2638,pid:2637,name:"临翔区",level:3},2639:{id:2639,pid:2637,name:"凤庆县",level:3},2640:{id:2640,pid:2637,name:"云县",level:3},2641:{id:2641,pid:2637,name:"永德县",level:3},2642:{id:2642,pid:2637,name:"镇康县",level:3},2643:{id:2643,pid:2637,name:"双江拉祜族佤族布朗族傣族自治县",level:3},2644:{id:2644,pid:2637,name:"耿马傣族佤族自治县",level:3},2645:{id:2645,pid:2637,name:"沧源佤族自治县",level:3}}},2646:{id:2646,pid:2566,name:"楚雄彝族自治州",level:2,region:{2647:{id:2647,pid:2646,name:"楚雄市",level:3},2648:{id:2648,pid:2646,name:"双柏县",level:3},2649:{id:2649,pid:2646,name:"牟定县",level:3},2650:{id:2650,pid:2646,name:"南华县",level:3},2651:{id:2651,pid:2646,name:"姚安县",level:3},2652:{id:2652,pid:2646,name:"大姚县",level:3},2653:{id:2653,pid:2646,name:"永仁县",level:3},2654:{id:2654,pid:2646,name:"元谋县",level:3},2655:{id:2655,pid:2646,name:"武定县",level:3},3906:{id:3906,pid:2646,name:"禄丰市",level:3}}},2657:{id:2657,pid:2566,name:"红河哈尼族彝族自治州",level:2,region:{2658:{id:2658,pid:2657,name:"个旧市",level:3},2659:{id:2659,pid:2657,name:"开远市",level:3},2660:{id:2660,pid:2657,name:"蒙自市",level:3},2661:{id:2661,pid:2657,name:"弥勒市",level:3},2662:{id:2662,pid:2657,name:"屏边苗族自治县",level:3},2663:{id:2663,pid:2657,name:"建水县",level:3},2664:{id:2664,pid:2657,name:"石屏县",level:3},2665:{id:2665,pid:2657,name:"泸西县",level:3},2666:{id:2666,pid:2657,name:"元阳县",level:3},2667:{id:2667,pid:2657,name:"红河县",level:3},2668:{id:2668,pid:2657,name:"金平苗族瑶族傣族自治县",level:3},2669:{id:2669,pid:2657,name:"绿春县",level:3},2670:{id:2670,pid:2657,name:"河口瑶族自治县",level:3}}},2671:{id:2671,pid:2566,name:"文山壮族苗族自治州",level:2,region:{2672:{id:2672,pid:2671,name:"文山市",level:3},2673:{id:2673,pid:2671,name:"砚山县",level:3},2674:{id:2674,pid:2671,name:"西畴县",level:3},2675:{id:2675,pid:2671,name:"麻栗坡县",level:3},2676:{id:2676,pid:2671,name:"马关县",level:3},2677:{id:2677,pid:2671,name:"丘北县",level:3},2678:{id:2678,pid:2671,name:"广南县",level:3},2679:{id:2679,pid:2671,name:"富宁县",level:3}}},2680:{id:2680,pid:2566,name:"西双版纳傣族自治州",level:2,region:{2681:{id:2681,pid:2680,name:"景洪市",level:3},2682:{id:2682,pid:2680,name:"勐海县",level:3},2683:{id:2683,pid:2680,name:"勐腊县",level:3}}},2684:{id:2684,pid:2566,name:"大理白族自治州",level:2,region:{2685:{id:2685,pid:2684,name:"大理市",level:3},2686:{id:2686,pid:2684,name:"漾濞彝族自治县",level:3},2687:{id:2687,pid:2684,name:"祥云县",level:3},2688:{id:2688,pid:2684,name:"宾川县",level:3},2689:{id:2689,pid:2684,name:"弥渡县",level:3},2690:{id:2690,pid:2684,name:"南涧彝族自治县",level:3},2691:{id:2691,pid:2684,name:"巍山彝族回族自治县",level:3},2692:{id:2692,pid:2684,name:"永平县",level:3},2693:{id:2693,pid:2684,name:"云龙县",level:3},2694:{id:2694,pid:2684,name:"洱源县",level:3},2695:{id:2695,pid:2684,name:"剑川县",level:3},2696:{id:2696,pid:2684,name:"鹤庆县",level:3}}},2697:{id:2697,pid:2566,name:"德宏傣族景颇族自治州",level:2,region:{2698:{id:2698,pid:2697,name:"瑞丽市",level:3},2699:{id:2699,pid:2697,name:"芒市",level:3},2700:{id:2700,pid:2697,name:"梁河县",level:3},2701:{id:2701,pid:2697,name:"盈江县",level:3},2702:{id:2702,pid:2697,name:"陇川县",level:3}}},2703:{id:2703,pid:2566,name:"怒江傈僳族自治州",level:2,region:{2704:{id:2704,pid:2703,name:"泸水市",level:3},2705:{id:2705,pid:2703,name:"福贡县",level:3},2706:{id:2706,pid:2703,name:"贡山独龙族怒族自治县",level:3},2707:{id:2707,pid:2703,name:"兰坪白族普米族自治县",level:3}}},2708:{id:2708,pid:2566,name:"迪庆藏族自治州",level:2,region:{2709:{id:2709,pid:2708,name:"香格里拉市",level:3},2710:{id:2710,pid:2708,name:"德钦县",level:3},2711:{id:2711,pid:2708,name:"维西傈僳族自治县",level:3}}}}},2712:{id:2712,pid:0,name:"西藏自治区",level:1,city:{2713:{id:2713,pid:2712,name:"拉萨市",level:2,region:{2714:{id:2714,pid:2713,name:"城关区",level:3},2715:{id:2715,pid:2713,name:"堆龙德庆区",level:3},2716:{id:2716,pid:2713,name:"达孜区",level:3},2717:{id:2717,pid:2713,name:"林周县",level:3},2718:{id:2718,pid:2713,name:"当雄县",level:3},2719:{id:2719,pid:2713,name:"尼木县",level:3},2720:{id:2720,pid:2713,name:"曲水县",level:3},2721:{id:2721,pid:2713,name:"墨竹工卡县",level:3},3907:{id:3907,pid:2713,name:"格尔木藏青工业园区",level:3},3908:{id:3908,pid:2713,name:"拉萨经济技术开发区",level:3},3909:{id:3909,pid:2713,name:"西藏文化旅游创意园区",level:3},3910:{id:3910,pid:2713,name:"达孜工业园区",level:3}}},2722:{id:2722,pid:2712,name:"日喀则市",level:2,region:{2723:{id:2723,pid:2722,name:"桑珠孜区",level:3},2724:{id:2724,pid:2722,name:"南木林县",level:3},2725:{id:2725,pid:2722,name:"江孜县",level:3},2726:{id:2726,pid:2722,name:"定日县",level:3},2727:{id:2727,pid:2722,name:"萨迦县",level:3},2728:{id:2728,pid:2722,name:"拉孜县",level:3},2729:{id:2729,pid:2722,name:"昂仁县",level:3},2730:{id:2730,pid:2722,name:"谢通门县",level:3},2731:{id:2731,pid:2722,name:"白朗县",level:3},2732:{id:2732,pid:2722,name:"仁布县",level:3},2733:{id:2733,pid:2722,name:"康马县",level:3},2734:{id:2734,pid:2722,name:"定结县",level:3},2735:{id:2735,pid:2722,name:"仲巴县",level:3},2736:{id:2736,pid:2722,name:"亚东县",level:3},2737:{id:2737,pid:2722,name:"吉隆县",level:3},2738:{id:2738,pid:2722,name:"聂拉木县",level:3},2739:{id:2739,pid:2722,name:"萨嘎县",level:3},2740:{id:2740,pid:2722,name:"岗巴县",level:3}}},2741:{id:2741,pid:2712,name:"昌都市",level:2,region:{2742:{id:2742,pid:2741,name:"卡若区",level:3},2743:{id:2743,pid:2741,name:"江达县",level:3},2744:{id:2744,pid:2741,name:"贡觉县",level:3},2745:{id:2745,pid:2741,name:"类乌齐县",level:3},2746:{id:2746,pid:2741,name:"丁青县",level:3},2747:{id:2747,pid:2741,name:"察雅县",level:3},2748:{id:2748,pid:2741,name:"八宿县",level:3},2749:{id:2749,pid:2741,name:"左贡县",level:3},2750:{id:2750,pid:2741,name:"芒康县",level:3},2751:{id:2751,pid:2741,name:"洛隆县",level:3},2752:{id:2752,pid:2741,name:"边坝县",level:3}}},2753:{id:2753,pid:2712,name:"林芝市",level:2,region:{2754:{id:2754,pid:2753,name:"巴宜区",level:3},2755:{id:2755,pid:2753,name:"工布江达县",level:3},2756:{id:2756,pid:2753,name:"米林县",level:3},2757:{id:2757,pid:2753,name:"墨脱县",level:3},2758:{id:2758,pid:2753,name:"波密县",level:3},2759:{id:2759,pid:2753,name:"察隅县",level:3},2760:{id:2760,pid:2753,name:"朗县",level:3}}},2761:{id:2761,pid:2712,name:"山南市",level:2,region:{2762:{id:2762,pid:2761,name:"乃东区",level:3},2763:{id:2763,pid:2761,name:"扎囊县",level:3},2764:{id:2764,pid:2761,name:"贡嘎县",level:3},2765:{id:2765,pid:2761,name:"桑日县",level:3},2766:{id:2766,pid:2761,name:"琼结县",level:3},2767:{id:2767,pid:2761,name:"曲松县",level:3},2768:{id:2768,pid:2761,name:"措美县",level:3},2769:{id:2769,pid:2761,name:"洛扎县",level:3},2770:{id:2770,pid:2761,name:"加查县",level:3},2771:{id:2771,pid:2761,name:"隆子县",level:3},2772:{id:2772,pid:2761,name:"错那县",level:3},2773:{id:2773,pid:2761,name:"浪卡子县",level:3}}},2774:{id:2774,pid:2712,name:"那曲市",level:2,region:{2775:{id:2775,pid:2774,name:"色尼区",level:3},2776:{id:2776,pid:2774,name:"嘉黎县",level:3},2777:{id:2777,pid:2774,name:"比如县",level:3},2778:{id:2778,pid:2774,name:"聂荣县",level:3},2779:{id:2779,pid:2774,name:"安多县",level:3},2780:{id:2780,pid:2774,name:"申扎县",level:3},2781:{id:2781,pid:2774,name:"索县",level:3},2782:{id:2782,pid:2774,name:"班戈县",level:3},2783:{id:2783,pid:2774,name:"巴青县",level:3},2784:{id:2784,pid:2774,name:"尼玛县",level:3},2785:{id:2785,pid:2774,name:"双湖县",level:3}}},2786:{id:2786,pid:2712,name:"阿里地区",level:2,region:{2787:{id:2787,pid:2786,name:"普兰县",level:3},2788:{id:2788,pid:2786,name:"札达县",level:3},2789:{id:2789,pid:2786,name:"噶尔县",level:3},2790:{id:2790,pid:2786,name:"日土县",level:3},2791:{id:2791,pid:2786,name:"革吉县",level:3},2792:{id:2792,pid:2786,name:"改则县",level:3},2793:{id:2793,pid:2786,name:"措勤县",level:3}}}}},2794:{id:2794,pid:0,name:"陕西省",level:1,city:{2795:{id:2795,pid:2794,name:"西安市",level:2,region:{2796:{id:2796,pid:2795,name:"新城区",level:3},2797:{id:2797,pid:2795,name:"碑林区",level:3},2798:{id:2798,pid:2795,name:"莲湖区",level:3},2799:{id:2799,pid:2795,name:"灞桥区",level:3},2800:{id:2800,pid:2795,name:"未央区",level:3},2801:{id:2801,pid:2795,name:"雁塔区",level:3},2802:{id:2802,pid:2795,name:"阎良区",level:3},2803:{id:2803,pid:2795,name:"临潼区",level:3},2804:{id:2804,pid:2795,name:"长安区",level:3},2805:{id:2805,pid:2795,name:"高陵区",level:3},2806:{id:2806,pid:2795,name:"鄠邑区",level:3},2807:{id:2807,pid:2795,name:"蓝田县",level:3},2808:{id:2808,pid:2795,name:"周至县",level:3}}},2809:{id:2809,pid:2794,name:"铜川市",level:2,region:{2810:{id:2810,pid:2809,name:"王益区",level:3},2811:{id:2811,pid:2809,name:"印台区",level:3},2812:{id:2812,pid:2809,name:"耀州区",level:3},2813:{id:2813,pid:2809,name:"宜君县",level:3}}},2814:{id:2814,pid:2794,name:"宝鸡市",level:2,region:{2815:{id:2815,pid:2814,name:"渭滨区",level:3},2816:{id:2816,pid:2814,name:"金台区",level:3},2817:{id:2817,pid:2814,name:"陈仓区",level:3},2819:{id:2819,pid:2814,name:"岐山县",level:3},2820:{id:2820,pid:2814,name:"扶风县",level:3},2821:{id:2821,pid:2814,name:"眉县",level:3},2822:{id:2822,pid:2814,name:"陇县",level:3},2823:{id:2823,pid:2814,name:"千阳县",level:3},2824:{id:2824,pid:2814,name:"麟游县",level:3},2825:{id:2825,pid:2814,name:"凤县",level:3},2826:{id:2826,pid:2814,name:"太白县",level:3},3911:{id:3911,pid:2814,name:"凤翔区",level:3}}},2827:{id:2827,pid:2794,name:"咸阳市",level:2,region:{2828:{id:2828,pid:2827,name:"秦都区",level:3},2829:{id:2829,pid:2827,name:"杨陵区",level:3},2830:{id:2830,pid:2827,name:"渭城区",level:3},2831:{id:2831,pid:2827,name:"三原县",level:3},2832:{id:2832,pid:2827,name:"泾阳县",level:3},2833:{id:2833,pid:2827,name:"乾县",level:3},2834:{id:2834,pid:2827,name:"礼泉县",level:3},2835:{id:2835,pid:2827,name:"永寿县",level:3},2836:{id:2836,pid:2827,name:"长武县",level:3},2837:{id:2837,pid:2827,name:"旬邑县",level:3},2838:{id:2838,pid:2827,name:"淳化县",level:3},2839:{id:2839,pid:2827,name:"武功县",level:3},2840:{id:2840,pid:2827,name:"兴平市",level:3},2841:{id:2841,pid:2827,name:"彬州市",level:3}}},2842:{id:2842,pid:2794,name:"渭南市",level:2,region:{2843:{id:2843,pid:2842,name:"临渭区",level:3},2844:{id:2844,pid:2842,name:"华州区",level:3},2845:{id:2845,pid:2842,name:"潼关县",level:3},2846:{id:2846,pid:2842,name:"大荔县",level:3},2847:{id:2847,pid:2842,name:"合阳县",level:3},2848:{id:2848,pid:2842,name:"澄城县",level:3},2849:{id:2849,pid:2842,name:"蒲城县",level:3},2850:{id:2850,pid:2842,name:"白水县",level:3},2851:{id:2851,pid:2842,name:"富平县",level:3},2852:{id:2852,pid:2842,name:"韩城市",level:3},2853:{id:2853,pid:2842,name:"华阴市",level:3}}},2854:{id:2854,pid:2794,name:"延安市",level:2,region:{2855:{id:2855,pid:2854,name:"宝塔区",level:3},2856:{id:2856,pid:2854,name:"安塞区",level:3},2857:{id:2857,pid:2854,name:"延长县",level:3},2858:{id:2858,pid:2854,name:"延川县",level:3},2859:{id:2859,pid:2854,name:"志丹县",level:3},2860:{id:2860,pid:2854,name:"吴起县",level:3},2861:{id:2861,pid:2854,name:"甘泉县",level:3},2862:{id:2862,pid:2854,name:"富县",level:3},2863:{id:2863,pid:2854,name:"洛川县",level:3},2864:{id:2864,pid:2854,name:"宜川县",level:3},2865:{id:2865,pid:2854,name:"黄龙县",level:3},2866:{id:2866,pid:2854,name:"黄陵县",level:3},2867:{id:2867,pid:2854,name:"子长市",level:3}}},2868:{id:2868,pid:2794,name:"汉中市",level:2,region:{2869:{id:2869,pid:2868,name:"汉台区",level:3},2870:{id:2870,pid:2868,name:"南郑区",level:3},2871:{id:2871,pid:2868,name:"城固县",level:3},2872:{id:2872,pid:2868,name:"洋县",level:3},2873:{id:2873,pid:2868,name:"西乡县",level:3},2874:{id:2874,pid:2868,name:"勉县",level:3},2875:{id:2875,pid:2868,name:"宁强县",level:3},2876:{id:2876,pid:2868,name:"略阳县",level:3},2877:{id:2877,pid:2868,name:"镇巴县",level:3},2878:{id:2878,pid:2868,name:"留坝县",level:3},2879:{id:2879,pid:2868,name:"佛坪县",level:3}}},2880:{id:2880,pid:2794,name:"榆林市",level:2,region:{2881:{id:2881,pid:2880,name:"榆阳区",level:3},2882:{id:2882,pid:2880,name:"横山区",level:3},2883:{id:2883,pid:2880,name:"府谷县",level:3},2884:{id:2884,pid:2880,name:"靖边县",level:3},2885:{id:2885,pid:2880,name:"定边县",level:3},2886:{id:2886,pid:2880,name:"绥德县",level:3},2887:{id:2887,pid:2880,name:"米脂县",level:3},2888:{id:2888,pid:2880,name:"佳县",level:3},2889:{id:2889,pid:2880,name:"吴堡县",level:3},2890:{id:2890,pid:2880,name:"清涧县",level:3},2891:{id:2891,pid:2880,name:"子洲县",level:3},2892:{id:2892,pid:2880,name:"神木市",level:3}}},2893:{id:2893,pid:2794,name:"安康市",level:2,region:{2894:{id:2894,pid:2893,name:"汉滨区",level:3},2895:{id:2895,pid:2893,name:"汉阴县",level:3},2896:{id:2896,pid:2893,name:"石泉县",level:3},2897:{id:2897,pid:2893,name:"宁陕县",level:3},2898:{id:2898,pid:2893,name:"紫阳县",level:3},2899:{id:2899,pid:2893,name:"岚皋县",level:3},2900:{id:2900,pid:2893,name:"平利县",level:3},2901:{id:2901,pid:2893,name:"镇坪县",level:3},2903:{id:2903,pid:2893,name:"白河县",level:3},3912:{id:3912,pid:2893,name:"旬阳市",level:3}}},2904:{id:2904,pid:2794,name:"商洛市",level:2,region:{2905:{id:2905,pid:2904,name:"商州区",level:3},2906:{id:2906,pid:2904,name:"洛南县",level:3},2907:{id:2907,pid:2904,name:"丹凤县",level:3},2908:{id:2908,pid:2904,name:"商南县",level:3},2909:{id:2909,pid:2904,name:"山阳县",level:3},2910:{id:2910,pid:2904,name:"镇安县",level:3},2911:{id:2911,pid:2904,name:"柞水县",level:3}}}}},2912:{id:2912,pid:0,name:"甘肃省",level:1,city:{2913:{id:2913,pid:2912,name:"兰州市",level:2,region:{2914:{id:2914,pid:2913,name:"城关区",level:3},2915:{id:2915,pid:2913,name:"七里河区",level:3},2916:{id:2916,pid:2913,name:"西固区",level:3},2917:{id:2917,pid:2913,name:"安宁区",level:3},2918:{id:2918,pid:2913,name:"红古区",level:3},2919:{id:2919,pid:2913,name:"永登县",level:3},2920:{id:2920,pid:2913,name:"皋兰县",level:3},2921:{id:2921,pid:2913,name:"榆中县",level:3},3913:{id:3913,pid:2913,name:"兰州新区",level:3}}},2922:{id:2922,pid:2912,name:"嘉峪关市",level:2,region:{3914:{id:3914,pid:2922,name:"市辖区",level:3}}},2923:{id:2923,pid:2912,name:"金昌市",level:2,region:{2924:{id:2924,pid:2923,name:"金川区",level:3},2925:{id:2925,pid:2923,name:"永昌县",level:3}}},2926:{id:2926,pid:2912,name:"白银市",level:2,region:{2927:{id:2927,pid:2926,name:"白银区",level:3},2928:{id:2928,pid:2926,name:"平川区",level:3},2929:{id:2929,pid:2926,name:"靖远县",level:3},2930:{id:2930,pid:2926,name:"会宁县",level:3},2931:{id:2931,pid:2926,name:"景泰县",level:3}}},2932:{id:2932,pid:2912,name:"天水市",level:2,region:{2933:{id:2933,pid:2932,name:"秦州区",level:3},2934:{id:2934,pid:2932,name:"麦积区",level:3},2935:{id:2935,pid:2932,name:"清水县",level:3},2936:{id:2936,pid:2932,name:"秦安县",level:3},2937:{id:2937,pid:2932,name:"甘谷县",level:3},2938:{id:2938,pid:2932,name:"武山县",level:3},2939:{id:2939,pid:2932,name:"张家川回族自治县",level:3}}},2940:{id:2940,pid:2912,name:"武威市",level:2,region:{2941:{id:2941,pid:2940,name:"凉州区",level:3},2942:{id:2942,pid:2940,name:"民勤县",level:3},2943:{id:2943,pid:2940,name:"古浪县",level:3},2944:{id:2944,pid:2940,name:"天祝藏族自治县",level:3}}},2945:{id:2945,pid:2912,name:"张掖市",level:2,region:{2946:{id:2946,pid:2945,name:"甘州区",level:3},2947:{id:2947,pid:2945,name:"肃南裕固族自治县",level:3},2948:{id:2948,pid:2945,name:"民乐县",level:3},2949:{id:2949,pid:2945,name:"临泽县",level:3},2950:{id:2950,pid:2945,name:"高台县",level:3},2951:{id:2951,pid:2945,name:"山丹县",level:3}}},2952:{id:2952,pid:2912,name:"平凉市",level:2,region:{2953:{id:2953,pid:2952,name:"崆峒区",level:3},2954:{id:2954,pid:2952,name:"泾川县",level:3},2955:{id:2955,pid:2952,name:"灵台县",level:3},2956:{id:2956,pid:2952,name:"崇信县",level:3},2957:{id:2957,pid:2952,name:"庄浪县",level:3},2958:{id:2958,pid:2952,name:"静宁县",level:3},2959:{id:2959,pid:2952,name:"华亭市",level:3}}},2960:{id:2960,pid:2912,name:"酒泉市",level:2,region:{2961:{id:2961,pid:2960,name:"肃州区",level:3},2962:{id:2962,pid:2960,name:"金塔县",level:3},2963:{id:2963,pid:2960,name:"瓜州县",level:3},2964:{id:2964,pid:2960,name:"肃北蒙古族自治县",level:3},2965:{id:2965,pid:2960,name:"阿克塞哈萨克族自治县",level:3},2966:{id:2966,pid:2960,name:"玉门市",level:3},2967:{id:2967,pid:2960,name:"敦煌市",level:3}}},2968:{id:2968,pid:2912,name:"庆阳市",level:2,region:{2969:{id:2969,pid:2968,name:"西峰区",level:3},2970:{id:2970,pid:2968,name:"庆城县",level:3},2971:{id:2971,pid:2968,name:"环县",level:3},2972:{id:2972,pid:2968,name:"华池县",level:3},2973:{id:2973,pid:2968,name:"合水县",level:3},2974:{id:2974,pid:2968,name:"正宁县",level:3},2975:{id:2975,pid:2968,name:"宁县",level:3},2976:{id:2976,pid:2968,name:"镇原县",level:3}}},2977:{id:2977,pid:2912,name:"定西市",level:2,region:{2978:{id:2978,pid:2977,name:"安定区",level:3},2979:{id:2979,pid:2977,name:"通渭县",level:3},2980:{id:2980,pid:2977,name:"陇西县",level:3},2981:{id:2981,pid:2977,name:"渭源县",level:3},2982:{id:2982,pid:2977,name:"临洮县",level:3},2983:{id:2983,pid:2977,name:"漳县",level:3},2984:{id:2984,pid:2977,name:"岷县",level:3}}},2985:{id:2985,pid:2912,name:"陇南市",level:2,region:{2986:{id:2986,pid:2985,name:"武都区",level:3},2987:{id:2987,pid:2985,name:"成县",level:3},2988:{id:2988,pid:2985,name:"文县",level:3},2989:{id:2989,pid:2985,name:"宕昌县",level:3},2990:{id:2990,pid:2985,name:"康县",level:3},2991:{id:2991,pid:2985,name:"西和县",level:3},2992:{id:2992,pid:2985,name:"礼县",level:3},2993:{id:2993,pid:2985,name:"徽县",level:3},2994:{id:2994,pid:2985,name:"两当县",level:3}}},2995:{id:2995,pid:2912,name:"临夏回族自治州",level:2,region:{2996:{id:2996,pid:2995,name:"临夏市",level:3},2997:{id:2997,pid:2995,name:"临夏县",level:3},2998:{id:2998,pid:2995,name:"康乐县",level:3},2999:{id:2999,pid:2995,name:"永靖县",level:3},3e3:{id:3e3,pid:2995,name:"广河县",level:3},3001:{id:3001,pid:2995,name:"和政县",level:3},3002:{id:3002,pid:2995,name:"东乡族自治县",level:3},3003:{id:3003,pid:2995,name:"积石山保安族东乡族撒拉族自治县",level:3}}},3004:{id:3004,pid:2912,name:"甘南藏族自治州",level:2,region:{3005:{id:3005,pid:3004,name:"合作市",level:3},3006:{id:3006,pid:3004,name:"临潭县",level:3},3007:{id:3007,pid:3004,name:"卓尼县",level:3},3008:{id:3008,pid:3004,name:"舟曲县",level:3},3009:{id:3009,pid:3004,name:"迭部县",level:3},3010:{id:3010,pid:3004,name:"玛曲县",level:3},3011:{id:3011,pid:3004,name:"碌曲县",level:3},3012:{id:3012,pid:3004,name:"夏河县",level:3}}}}},3013:{id:3013,pid:0,name:"青海省",level:1,city:{3014:{id:3014,pid:3013,name:"西宁市",level:2,region:{3015:{id:3015,pid:3014,name:"城东区",level:3},3016:{id:3016,pid:3014,name:"城中区",level:3},3017:{id:3017,pid:3014,name:"城西区",level:3},3018:{id:3018,pid:3014,name:"城北区",level:3},3019:{id:3019,pid:3014,name:"湟中区",level:3},3020:{id:3020,pid:3014,name:"大通回族土族自治县",level:3},3021:{id:3021,pid:3014,name:"湟源县",level:3}}},3022:{id:3022,pid:3013,name:"海东市",level:2,region:{3023:{id:3023,pid:3022,name:"乐都区",level:3},3024:{id:3024,pid:3022,name:"平安区",level:3},3025:{id:3025,pid:3022,name:"民和回族土族自治县",level:3},3026:{id:3026,pid:3022,name:"互助土族自治县",level:3},3027:{id:3027,pid:3022,name:"化隆回族自治县",level:3},3028:{id:3028,pid:3022,name:"循化撒拉族自治县",level:3}}},3029:{id:3029,pid:3013,name:"海北藏族自治州",level:2,region:{3030:{id:3030,pid:3029,name:"门源回族自治县",level:3},3031:{id:3031,pid:3029,name:"祁连县",level:3},3032:{id:3032,pid:3029,name:"海晏县",level:3},3033:{id:3033,pid:3029,name:"刚察县",level:3}}},3034:{id:3034,pid:3013,name:"黄南藏族自治州",level:2,region:{3036:{id:3036,pid:3034,name:"尖扎县",level:3},3037:{id:3037,pid:3034,name:"泽库县",level:3},3038:{id:3038,pid:3034,name:"河南蒙古族自治县",level:3},3915:{id:3915,pid:3034,name:"同仁市",level:3}}},3039:{id:3039,pid:3013,name:"海南藏族自治州",level:2,region:{3040:{id:3040,pid:3039,name:"共和县",level:3},3041:{id:3041,pid:3039,name:"同德县",level:3},3042:{id:3042,pid:3039,name:"贵德县",level:3},3043:{id:3043,pid:3039,name:"兴海县",level:3},3044:{id:3044,pid:3039,name:"贵南县",level:3}}},3045:{id:3045,pid:3013,name:"果洛藏族自治州",level:2,region:{3046:{id:3046,pid:3045,name:"玛沁县",level:3},3047:{id:3047,pid:3045,name:"班玛县",level:3},3048:{id:3048,pid:3045,name:"甘德县",level:3},3049:{id:3049,pid:3045,name:"达日县",level:3},3050:{id:3050,pid:3045,name:"久治县",level:3},3051:{id:3051,pid:3045,name:"玛多县",level:3}}},3052:{id:3052,pid:3013,name:"玉树藏族自治州",level:2,region:{3053:{id:3053,pid:3052,name:"玉树市",level:3},3054:{id:3054,pid:3052,name:"杂多县",level:3},3055:{id:3055,pid:3052,name:"称多县",level:3},3056:{id:3056,pid:3052,name:"治多县",level:3},3057:{id:3057,pid:3052,name:"囊谦县",level:3},3058:{id:3058,pid:3052,name:"曲麻莱县",level:3}}},3059:{id:3059,pid:3013,name:"海西蒙古族藏族自治州",level:2,region:{3060:{id:3060,pid:3059,name:"格尔木市",level:3},3061:{id:3061,pid:3059,name:"德令哈市",level:3},3062:{id:3062,pid:3059,name:"茫崖市",level:3},3063:{id:3063,pid:3059,name:"乌兰县",level:3},3064:{id:3064,pid:3059,name:"都兰县",level:3},3065:{id:3065,pid:3059,name:"天峻县",level:3},3916:{id:3916,pid:3059,name:"大柴旦行政委员会",level:3}}}}},3066:{id:3066,pid:0,name:"宁夏回族自治区",level:1,city:{3067:{id:3067,pid:3066,name:"银川市",level:2,region:{3068:{id:3068,pid:3067,name:"兴庆区",level:3},3069:{id:3069,pid:3067,name:"西夏区",level:3},3070:{id:3070,pid:3067,name:"金凤区",level:3},3071:{id:3071,pid:3067,name:"永宁县",level:3},3072:{id:3072,pid:3067,name:"贺兰县",level:3},3073:{id:3073,pid:3067,name:"灵武市",level:3}}},3074:{id:3074,pid:3066,name:"石嘴山市",level:2,region:{3075:{id:3075,pid:3074,name:"大武口区",level:3},3076:{id:3076,pid:3074,name:"惠农区",level:3},3077:{id:3077,pid:3074,name:"平罗县",level:3}}},3078:{id:3078,pid:3066,name:"吴忠市",level:2,region:{3079:{id:3079,pid:3078,name:"利通区",level:3},3080:{id:3080,pid:3078,name:"红寺堡区",level:3},3081:{id:3081,pid:3078,name:"盐池县",level:3},3082:{id:3082,pid:3078,name:"同心县",level:3},3083:{id:3083,pid:3078,name:"青铜峡市",level:3}}},3084:{id:3084,pid:3066,name:"固原市",level:2,region:{3085:{id:3085,pid:3084,name:"原州区",level:3},3086:{id:3086,pid:3084,name:"西吉县",level:3},3087:{id:3087,pid:3084,name:"隆德县",level:3},3088:{id:3088,pid:3084,name:"泾源县",level:3},3089:{id:3089,pid:3084,name:"彭阳县",level:3}}},3090:{id:3090,pid:3066,name:"中卫市",level:2,region:{3091:{id:3091,pid:3090,name:"沙坡头区",level:3},3092:{id:3092,pid:3090,name:"中宁县",level:3},3093:{id:3093,pid:3090,name:"海原县",level:3}}}}},3094:{id:3094,pid:0,name:"新疆维吾尔自治区",level:1,city:{3095:{id:3095,pid:3094,name:"乌鲁木齐市",level:2,region:{3096:{id:3096,pid:3095,name:"天山区",level:3},3097:{id:3097,pid:3095,name:"沙依巴克区",level:3},3098:{id:3098,pid:3095,name:"新市区",level:3},3099:{id:3099,pid:3095,name:"水磨沟区",level:3},3100:{id:3100,pid:3095,name:"头屯河区",level:3},3101:{id:3101,pid:3095,name:"达坂城区",level:3},3102:{id:3102,pid:3095,name:"米东区",level:3},3103:{id:3103,pid:3095,name:"乌鲁木齐县",level:3}}},3104:{id:3104,pid:3094,name:"克拉玛依市",level:2,region:{3105:{id:3105,pid:3104,name:"独山子区",level:3},3106:{id:3106,pid:3104,name:"克拉玛依区",level:3},3107:{id:3107,pid:3104,name:"白碱滩区",level:3},3108:{id:3108,pid:3104,name:"乌尔禾区",level:3}}},3109:{id:3109,pid:3094,name:"吐鲁番市",level:2,region:{3110:{id:3110,pid:3109,name:"高昌区",level:3},3111:{id:3111,pid:3109,name:"鄯善县",level:3},3112:{id:3112,pid:3109,name:"托克逊县",level:3}}},3113:{id:3113,pid:3094,name:"哈密市",level:2,region:{3114:{id:3114,pid:3113,name:"伊州区",level:3},3115:{id:3115,pid:3113,name:"巴里坤哈萨克自治县",level:3},3116:{id:3116,pid:3113,name:"伊吾县",level:3}}},3117:{id:3117,pid:3094,name:"昌吉回族自治州",level:2,region:{3118:{id:3118,pid:3117,name:"昌吉市",level:3},3119:{id:3119,pid:3117,name:"阜康市",level:3},3120:{id:3120,pid:3117,name:"呼图壁县",level:3},3121:{id:3121,pid:3117,name:"玛纳斯县",level:3},3122:{id:3122,pid:3117,name:"奇台县",level:3},3123:{id:3123,pid:3117,name:"吉木萨尔县",level:3},3124:{id:3124,pid:3117,name:"木垒哈萨克自治县",level:3}}},3125:{id:3125,pid:3094,name:"博尔塔拉蒙古自治州",level:2,region:{3126:{id:3126,pid:3125,name:"博乐市",level:3},3127:{id:3127,pid:3125,name:"阿拉山口市",level:3},3128:{id:3128,pid:3125,name:"精河县",level:3},3129:{id:3129,pid:3125,name:"温泉县",level:3}}},3130:{id:3130,pid:3094,name:"巴音郭楞蒙古自治州",level:2,region:{3131:{id:3131,pid:3130,name:"库尔勒市",level:3},3132:{id:3132,pid:3130,name:"轮台县",level:3},3133:{id:3133,pid:3130,name:"尉犁县",level:3},3134:{id:3134,pid:3130,name:"若羌县",level:3},3135:{id:3135,pid:3130,name:"且末县",level:3},3136:{id:3136,pid:3130,name:"焉耆回族自治县",level:3},3137:{id:3137,pid:3130,name:"和静县",level:3},3138:{id:3138,pid:3130,name:"和硕县",level:3},3139:{id:3139,pid:3130,name:"博湖县",level:3},3917:{id:3917,pid:3130,name:"库尔勒经济技术开发区",level:3}}},3140:{id:3140,pid:3094,name:"阿克苏地区",level:2,region:{3141:{id:3141,pid:3140,name:"阿克苏市",level:3},3142:{id:3142,pid:3140,name:"库车市",level:3},3143:{id:3143,pid:3140,name:"温宿县",level:3},3144:{id:3144,pid:3140,name:"沙雅县",level:3},3145:{id:3145,pid:3140,name:"新和县",level:3},3146:{id:3146,pid:3140,name:"拜城县",level:3},3147:{id:3147,pid:3140,name:"乌什县",level:3},3148:{id:3148,pid:3140,name:"阿瓦提县",level:3},3149:{id:3149,pid:3140,name:"柯坪县",level:3}}},3150:{id:3150,pid:3094,name:"克孜勒苏柯尔克孜自治州",level:2,region:{3151:{id:3151,pid:3150,name:"阿图什市",level:3},3152:{id:3152,pid:3150,name:"阿克陶县",level:3},3153:{id:3153,pid:3150,name:"阿合奇县",level:3},3154:{id:3154,pid:3150,name:"乌恰县",level:3}}},3155:{id:3155,pid:3094,name:"喀什地区",level:2,region:{3156:{id:3156,pid:3155,name:"喀什市",level:3},3157:{id:3157,pid:3155,name:"疏附县",level:3},3158:{id:3158,pid:3155,name:"疏勒县",level:3},3159:{id:3159,pid:3155,name:"英吉沙县",level:3},3160:{id:3160,pid:3155,name:"泽普县",level:3},3161:{id:3161,pid:3155,name:"莎车县",level:3},3162:{id:3162,pid:3155,name:"叶城县",level:3},3163:{id:3163,pid:3155,name:"麦盖提县",level:3},3164:{id:3164,pid:3155,name:"岳普湖县",level:3},3165:{id:3165,pid:3155,name:"伽师县",level:3},3166:{id:3166,pid:3155,name:"巴楚县",level:3},3167:{id:3167,pid:3155,name:"塔什库尔干塔吉克自治县",level:3}}},3168:{id:3168,pid:3094,name:"和田地区",level:2,region:{3169:{id:3169,pid:3168,name:"和田市",level:3},3170:{id:3170,pid:3168,name:"和田县",level:3},3171:{id:3171,pid:3168,name:"墨玉县",level:3},3172:{id:3172,pid:3168,name:"皮山县",level:3},3173:{id:3173,pid:3168,name:"洛浦县",level:3},3174:{id:3174,pid:3168,name:"策勒县",level:3},3175:{id:3175,pid:3168,name:"于田县",level:3},3176:{id:3176,pid:3168,name:"民丰县",level:3}}},3177:{id:3177,pid:3094,name:"伊犁哈萨克自治州",level:2,region:{3178:{id:3178,pid:3177,name:"伊宁市",level:3},3179:{id:3179,pid:3177,name:"奎屯市",level:3},3180:{id:3180,pid:3177,name:"霍尔果斯市",level:3},3181:{id:3181,pid:3177,name:"伊宁县",level:3},3182:{id:3182,pid:3177,name:"察布查尔锡伯自治县",level:3},3183:{id:3183,pid:3177,name:"霍城县",level:3},3184:{id:3184,pid:3177,name:"巩留县",level:3},3185:{id:3185,pid:3177,name:"新源县",level:3},3186:{id:3186,pid:3177,name:"昭苏县",level:3},3187:{id:3187,pid:3177,name:"特克斯县",level:3},3188:{id:3188,pid:3177,name:"尼勒克县",level:3}}},3189:{id:3189,pid:3094,name:"塔城地区",level:2,region:{3190:{id:3190,pid:3189,name:"塔城市",level:3},3191:{id:3191,pid:3189,name:"乌苏市",level:3},3192:{id:3192,pid:3189,name:"额敏县",level:3},3194:{id:3194,pid:3189,name:"托里县",level:3},3195:{id:3195,pid:3189,name:"裕民县",level:3},3196:{id:3196,pid:3189,name:"和布克赛尔蒙古自治县",level:3},3918:{id:3918,pid:3189,name:"沙湾市",level:3}}},3197:{id:3197,pid:3094,name:"阿勒泰地区",level:2,region:{3198:{id:3198,pid:3197,name:"阿勒泰市",level:3},3199:{id:3199,pid:3197,name:"布尔津县",level:3},3200:{id:3200,pid:3197,name:"富蕴县",level:3},3201:{id:3201,pid:3197,name:"福海县",level:3},3202:{id:3202,pid:3197,name:"哈巴河县",level:3},3203:{id:3203,pid:3197,name:"青河县",level:3},3204:{id:3204,pid:3197,name:"吉木乃县",level:3}}},3710:{id:3710,pid:3094,name:"自治区直辖县级行政区划",level:2,region:{3919:{id:3919,pid:3710,name:"石河子市",level:3},3920:{id:3920,pid:3710,name:"阿拉尔市",level:3},3921:{id:3921,pid:3710,name:"图木舒克市",level:3},3922:{id:3922,pid:3710,name:"五家渠市",level:3},3923:{id:3923,pid:3710,name:"北屯市",level:3},3924:{id:3924,pid:3710,name:"铁门关市",level:3},3925:{id:3925,pid:3710,name:"双河市",level:3},3926:{id:3926,pid:3710,name:"可克达拉市",level:3},3927:{id:3927,pid:3710,name:"昆玉市",level:3},3928:{id:3928,pid:3710,name:"胡杨河市",level:3},3929:{id:3929,pid:3710,name:"新星市",level:3}}}}},3215:{id:3215,pid:0,name:"台湾省",level:1,city:{3216:{id:3216,pid:3215,name:"台北市",level:2,region:{3217:{id:3217,pid:3216,name:"中正区",level:3},3218:{id:3218,pid:3216,name:"大同区",level:3},3219:{id:3219,pid:3216,name:"中山区",level:3},3220:{id:3220,pid:3216,name:"松山区",level:3},3221:{id:3221,pid:3216,name:"大安区",level:3},3222:{id:3222,pid:3216,name:"万华区",level:3},3223:{id:3223,pid:3216,name:"信义区",level:3},3224:{id:3224,pid:3216,name:"士林区",level:3},3225:{id:3225,pid:3216,name:"北投区",level:3},3226:{id:3226,pid:3216,name:"内湖区",level:3},3227:{id:3227,pid:3216,name:"南港区",level:3},3228:{id:3228,pid:3216,name:"文山区",level:3}}},3229:{id:3229,pid:3215,name:"高雄市",level:2,region:{3230:{id:3230,pid:3229,name:"新兴区",level:3},3231:{id:3231,pid:3229,name:"前金区",level:3},3232:{id:3232,pid:3229,name:"苓雅区",level:3},3233:{id:3233,pid:3229,name:"盐埕区",level:3},3234:{id:3234,pid:3229,name:"鼓山区",level:3},3235:{id:3235,pid:3229,name:"旗津区",level:3},3236:{id:3236,pid:3229,name:"前镇区",level:3},3237:{id:3237,pid:3229,name:"三民区",level:3},3238:{id:3238,pid:3229,name:"左营区",level:3},3239:{id:3239,pid:3229,name:"楠梓区",level:3},3240:{id:3240,pid:3229,name:"小港区",level:3},3241:{id:3241,pid:3229,name:"仁武区",level:3},3242:{id:3242,pid:3229,name:"大社区",level:3},3243:{id:3243,pid:3229,name:"冈山区",level:3},3244:{id:3244,pid:3229,name:"路竹区",level:3},3245:{id:3245,pid:3229,name:"阿莲区",level:3},3246:{id:3246,pid:3229,name:"田寮区",level:3},3247:{id:3247,pid:3229,name:"燕巢区",level:3},3248:{id:3248,pid:3229,name:"桥头区",level:3},3249:{id:3249,pid:3229,name:"梓官区",level:3},3250:{id:3250,pid:3229,name:"弥陀区",level:3},3251:{id:3251,pid:3229,name:"永安区",level:3},3252:{id:3252,pid:3229,name:"湖内区",level:3},3253:{id:3253,pid:3229,name:"凤山区",level:3},3254:{id:3254,pid:3229,name:"大寮区",level:3},3255:{id:3255,pid:3229,name:"林园区",level:3},3256:{id:3256,pid:3229,name:"鸟松区",level:3},3257:{id:3257,pid:3229,name:"大树区",level:3},3258:{id:3258,pid:3229,name:"旗山区",level:3},3259:{id:3259,pid:3229,name:"美浓区",level:3},3260:{id:3260,pid:3229,name:"六龟区",level:3},3261:{id:3261,pid:3229,name:"内门区",level:3},3262:{id:3262,pid:3229,name:"杉林区",level:3},3263:{id:3263,pid:3229,name:"甲仙区",level:3},3264:{id:3264,pid:3229,name:"桃源区",level:3},3265:{id:3265,pid:3229,name:"那玛夏区",level:3},3266:{id:3266,pid:3229,name:"茂林区",level:3},3267:{id:3267,pid:3229,name:"茄萣区",level:3}}},3268:{id:3268,pid:3215,name:"台南市",level:2,region:{3269:{id:3269,pid:3268,name:"中西区",level:3},3270:{id:3270,pid:3268,name:"东区",level:3},3271:{id:3271,pid:3268,name:"南区",level:3},3272:{id:3272,pid:3268,name:"北区",level:3},3273:{id:3273,pid:3268,name:"安平区",level:3},3274:{id:3274,pid:3268,name:"安南区",level:3},3275:{id:3275,pid:3268,name:"永康区",level:3},3276:{id:3276,pid:3268,name:"归仁区",level:3},3277:{id:3277,pid:3268,name:"新化区",level:3},3278:{id:3278,pid:3268,name:"左镇区",level:3},3279:{id:3279,pid:3268,name:"玉井区",level:3},3280:{id:3280,pid:3268,name:"楠西区",level:3},3281:{id:3281,pid:3268,name:"南化区",level:3},3282:{id:3282,pid:3268,name:"仁德区",level:3},3283:{id:3283,pid:3268,name:"关庙区",level:3},3284:{id:3284,pid:3268,name:"龙崎区",level:3},3285:{id:3285,pid:3268,name:"官田区",level:3},3286:{id:3286,pid:3268,name:"麻豆区",level:3},3287:{id:3287,pid:3268,name:"佳里区",level:3},3288:{id:3288,pid:3268,name:"西港区",level:3},3289:{id:3289,pid:3268,name:"七股区",level:3},3290:{id:3290,pid:3268,name:"将军区",level:3},3291:{id:3291,pid:3268,name:"学甲区",level:3},3292:{id:3292,pid:3268,name:"北门区",level:3},3293:{id:3293,pid:3268,name:"新营区",level:3},3294:{id:3294,pid:3268,name:"后壁区",level:3},3295:{id:3295,pid:3268,name:"白河区",level:3},3296:{id:3296,pid:3268,name:"东山区",level:3},3297:{id:3297,pid:3268,name:"六甲区",level:3},3298:{id:3298,pid:3268,name:"下营区",level:3},3299:{id:3299,pid:3268,name:"柳营区",level:3},3300:{id:3300,pid:3268,name:"盐水区",level:3},3301:{id:3301,pid:3268,name:"善化区",level:3},3302:{id:3302,pid:3268,name:"大内区",level:3},3303:{id:3303,pid:3268,name:"山上区",level:3},3304:{id:3304,pid:3268,name:"新市区",level:3},3305:{id:3305,pid:3268,name:"安定区",level:3}}},3306:{id:3306,pid:3215,name:"台中市",level:2,region:{3307:{id:3307,pid:3306,name:"中区",level:3},3308:{id:3308,pid:3306,name:"东区",level:3},3309:{id:3309,pid:3306,name:"南区",level:3},3310:{id:3310,pid:3306,name:"西区",level:3},3311:{id:3311,pid:3306,name:"北区",level:3},3312:{id:3312,pid:3306,name:"北屯区",level:3},3313:{id:3313,pid:3306,name:"西屯区",level:3},3314:{id:3314,pid:3306,name:"南屯区",level:3},3315:{id:3315,pid:3306,name:"太平区",level:3},3316:{id:3316,pid:3306,name:"大里区",level:3},3317:{id:3317,pid:3306,name:"雾峰区",level:3},3318:{id:3318,pid:3306,name:"乌日区",level:3},3319:{id:3319,pid:3306,name:"丰原区",level:3},3320:{id:3320,pid:3306,name:"后里区",level:3},3321:{id:3321,pid:3306,name:"石冈区",level:3},3322:{id:3322,pid:3306,name:"东势区",level:3},3323:{id:3323,pid:3306,name:"和平区",level:3},3324:{id:3324,pid:3306,name:"新社区",level:3},3325:{id:3325,pid:3306,name:"潭子区",level:3},3326:{id:3326,pid:3306,name:"大雅区",level:3},3327:{id:3327,pid:3306,name:"神冈区",level:3},3328:{id:3328,pid:3306,name:"大肚区",level:3},3329:{id:3329,pid:3306,name:"沙鹿区",level:3},3330:{id:3330,pid:3306,name:"龙井区",level:3},3331:{id:3331,pid:3306,name:"梧栖区",level:3},3332:{id:3332,pid:3306,name:"清水区",level:3},3333:{id:3333,pid:3306,name:"大甲区",level:3},3334:{id:3334,pid:3306,name:"外埔区",level:3},3335:{id:3335,pid:3306,name:"大安区",level:3}}},3336:{id:3336,pid:3215,name:"南投县",level:2,region:{3337:{id:3337,pid:3336,name:"南投市",level:3},3338:{id:3338,pid:3336,name:"中寮乡",level:3},3339:{id:3339,pid:3336,name:"草屯镇",level:3},3340:{id:3340,pid:3336,name:"国姓乡",level:3},3341:{id:3341,pid:3336,name:"埔里镇",level:3},3342:{id:3342,pid:3336,name:"仁爱乡",level:3},3343:{id:3343,pid:3336,name:"名间乡",level:3},3344:{id:3344,pid:3336,name:"集集镇",level:3},3345:{id:3345,pid:3336,name:"水里乡",level:3},3346:{id:3346,pid:3336,name:"鱼池乡",level:3},3347:{id:3347,pid:3336,name:"信义乡",level:3},3348:{id:3348,pid:3336,name:"竹山镇",level:3},3349:{id:3349,pid:3336,name:"鹿谷乡",level:3}}},3350:{id:3350,pid:3215,name:"基隆市",level:2,region:{3351:{id:3351,pid:3350,name:"仁爱区",level:3},3352:{id:3352,pid:3350,name:"信义区",level:3},3353:{id:3353,pid:3350,name:"中正区",level:3},3354:{id:3354,pid:3350,name:"中山区",level:3},3355:{id:3355,pid:3350,name:"安乐区",level:3},3356:{id:3356,pid:3350,name:"暖暖区",level:3},3357:{id:3357,pid:3350,name:"七堵区",level:3}}},3358:{id:3358,pid:3215,name:"新竹市",level:2,region:{3359:{id:3359,pid:3358,name:"东区",level:3},3360:{id:3360,pid:3358,name:"北区",level:3},3361:{id:3361,pid:3358,name:"香山区",level:3}}},3362:{id:3362,pid:3215,name:"嘉义市",level:2,region:{3363:{id:3363,pid:3362,name:"东区",level:3},3364:{id:3364,pid:3362,name:"西区",level:3}}},3365:{id:3365,pid:3215,name:"新北市",level:2,region:{3366:{id:3366,pid:3365,name:"万里区",level:3},3367:{id:3367,pid:3365,name:"金山区",level:3},3368:{id:3368,pid:3365,name:"板桥区",level:3},3369:{id:3369,pid:3365,name:"汐止区",level:3},3370:{id:3370,pid:3365,name:"深坑区",level:3},3371:{id:3371,pid:3365,name:"石碇区",level:3},3372:{id:3372,pid:3365,name:"瑞芳区",level:3},3373:{id:3373,pid:3365,name:"平溪区",level:3},3374:{id:3374,pid:3365,name:"双溪区",level:3},3375:{id:3375,pid:3365,name:"贡寮区",level:3},3376:{id:3376,pid:3365,name:"新店区",level:3},3377:{id:3377,pid:3365,name:"坪林区",level:3},3378:{id:3378,pid:3365,name:"乌来区",level:3},3379:{id:3379,pid:3365,name:"永和区",level:3},3380:{id:3380,pid:3365,name:"中和区",level:3},3381:{id:3381,pid:3365,name:"土城区",level:3},3382:{id:3382,pid:3365,name:"三峡区",level:3},3383:{id:3383,pid:3365,name:"树林区",level:3},3384:{id:3384,pid:3365,name:"莺歌区",level:3},3385:{id:3385,pid:3365,name:"三重区",level:3},3386:{id:3386,pid:3365,name:"新庄区",level:3},3387:{id:3387,pid:3365,name:"泰山区",level:3},3388:{id:3388,pid:3365,name:"林口区",level:3},3389:{id:3389,pid:3365,name:"芦洲区",level:3},3390:{id:3390,pid:3365,name:"五股区",level:3},3391:{id:3391,pid:3365,name:"八里区",level:3},3392:{id:3392,pid:3365,name:"淡水区",level:3},3393:{id:3393,pid:3365,name:"三芝区",level:3},3394:{id:3394,pid:3365,name:"石门区",level:3}}},3395:{id:3395,pid:3215,name:"宜兰县",level:2,region:{3396:{id:3396,pid:3395,name:"宜兰市",level:3},3397:{id:3397,pid:3395,name:"头城镇",level:3},3398:{id:3398,pid:3395,name:"礁溪乡",level:3},3399:{id:3399,pid:3395,name:"壮围乡",level:3},3400:{id:3400,pid:3395,name:"员山乡",level:3},3401:{id:3401,pid:3395,name:"罗东镇",level:3},3402:{id:3402,pid:3395,name:"三星乡",level:3},3403:{id:3403,pid:3395,name:"大同乡",level:3},3404:{id:3404,pid:3395,name:"五结乡",level:3},3405:{id:3405,pid:3395,name:"冬山乡",level:3},3406:{id:3406,pid:3395,name:"苏澳镇",level:3},3407:{id:3407,pid:3395,name:"南澳乡",level:3}}},3408:{id:3408,pid:3215,name:"新竹县",level:2,region:{3409:{id:3409,pid:3408,name:"竹北市",level:3},3410:{id:3410,pid:3408,name:"湖口乡",level:3},3411:{id:3411,pid:3408,name:"新丰乡",level:3},3412:{id:3412,pid:3408,name:"新埔镇",level:3},3413:{id:3413,pid:3408,name:"关西镇",level:3},3414:{id:3414,pid:3408,name:"芎林乡",level:3},3415:{id:3415,pid:3408,name:"宝山乡",level:3},3416:{id:3416,pid:3408,name:"竹东镇",level:3},3417:{id:3417,pid:3408,name:"五峰乡",level:3},3418:{id:3418,pid:3408,name:"横山乡",level:3},3419:{id:3419,pid:3408,name:"尖石乡",level:3},3420:{id:3420,pid:3408,name:"北埔乡",level:3},3421:{id:3421,pid:3408,name:"峨眉乡",level:3}}},3422:{id:3422,pid:3215,name:"桃园市",level:2,region:{3423:{id:3423,pid:3422,name:"中坜区",level:3},3424:{id:3424,pid:3422,name:"平镇区",level:3},3425:{id:3425,pid:3422,name:"龙潭区",level:3},3426:{id:3426,pid:3422,name:"杨梅区",level:3},3427:{id:3427,pid:3422,name:"新屋区",level:3},3428:{id:3428,pid:3422,name:"观音区",level:3},3429:{id:3429,pid:3422,name:"桃园区",level:3},3430:{id:3430,pid:3422,name:"龟山区",level:3},3431:{id:3431,pid:3422,name:"八德区",level:3},3432:{id:3432,pid:3422,name:"大溪区",level:3},3433:{id:3433,pid:3422,name:"复兴区",level:3},3434:{id:3434,pid:3422,name:"大园区",level:3},3435:{id:3435,pid:3422,name:"芦竹区",level:3}}},3436:{id:3436,pid:3215,name:"苗栗县",level:2,region:{3437:{id:3437,pid:3436,name:"竹南镇",level:3},3438:{id:3438,pid:3436,name:"头份市",level:3},3439:{id:3439,pid:3436,name:"三湾乡",level:3},3440:{id:3440,pid:3436,name:"南庄乡",level:3},3441:{id:3441,pid:3436,name:"狮潭乡",level:3},3442:{id:3442,pid:3436,name:"后龙镇",level:3},3443:{id:3443,pid:3436,name:"通霄镇",level:3},3444:{id:3444,pid:3436,name:"苑里镇",level:3},3445:{id:3445,pid:3436,name:"苗栗市",level:3},3446:{id:3446,pid:3436,name:"造桥乡",level:3},3447:{id:3447,pid:3436,name:"头屋乡",level:3},3448:{id:3448,pid:3436,name:"公馆乡",level:3},3449:{id:3449,pid:3436,name:"大湖乡",level:3},3450:{id:3450,pid:3436,name:"泰安乡",level:3},3451:{id:3451,pid:3436,name:"铜锣乡",level:3},3452:{id:3452,pid:3436,name:"三义乡",level:3},3453:{id:3453,pid:3436,name:"西湖乡",level:3},3454:{id:3454,pid:3436,name:"卓兰镇",level:3}}},3455:{id:3455,pid:3215,name:"彰化县",level:2,region:{3456:{id:3456,pid:3455,name:"彰化市",level:3},3457:{id:3457,pid:3455,name:"芬园乡",level:3},3458:{id:3458,pid:3455,name:"花坛乡",level:3},3459:{id:3459,pid:3455,name:"秀水乡",level:3},3460:{id:3460,pid:3455,name:"鹿港镇",level:3},3461:{id:3461,pid:3455,name:"福兴乡",level:3},3462:{id:3462,pid:3455,name:"线西乡",level:3},3463:{id:3463,pid:3455,name:"和美镇",level:3},3464:{id:3464,pid:3455,name:"伸港乡",level:3},3465:{id:3465,pid:3455,name:"员林市",level:3},3466:{id:3466,pid:3455,name:"社头乡",level:3},3467:{id:3467,pid:3455,name:"永靖乡",level:3},3468:{id:3468,pid:3455,name:"埔心乡",level:3},3469:{id:3469,pid:3455,name:"溪湖镇",level:3},3470:{id:3470,pid:3455,name:"大村乡",level:3},3471:{id:3471,pid:3455,name:"埔盐乡",level:3},3472:{id:3472,pid:3455,name:"田中镇",level:3},3473:{id:3473,pid:3455,name:"北斗镇",level:3},3474:{id:3474,pid:3455,name:"田尾乡",level:3},3475:{id:3475,pid:3455,name:"埤头乡",level:3},3476:{id:3476,pid:3455,name:"溪州乡",level:3},3477:{id:3477,pid:3455,name:"竹塘乡",level:3},3478:{id:3478,pid:3455,name:"二林镇",level:3},3479:{id:3479,pid:3455,name:"大城乡",level:3},3480:{id:3480,pid:3455,name:"芳苑乡",level:3},3481:{id:3481,pid:3455,name:"二水乡",level:3}}},3482:{id:3482,pid:3215,name:"嘉义县",level:2,region:{3483:{id:3483,pid:3482,name:"番路乡",level:3},3484:{id:3484,pid:3482,name:"梅山乡",level:3},3485:{id:3485,pid:3482,name:"竹崎乡",level:3},3486:{id:3486,pid:3482,name:"阿里山乡",level:3},3487:{id:3487,pid:3482,name:"中埔乡",level:3},3488:{id:3488,pid:3482,name:"大埔乡",level:3},3489:{id:3489,pid:3482,name:"水上乡",level:3},3490:{id:3490,pid:3482,name:"鹿草乡",level:3},3491:{id:3491,pid:3482,name:"太保市",level:3},3492:{id:3492,pid:3482,name:"朴子市",level:3},3493:{id:3493,pid:3482,name:"东石乡",level:3},3494:{id:3494,pid:3482,name:"六脚乡",level:3},3495:{id:3495,pid:3482,name:"新港乡",level:3},3496:{id:3496,pid:3482,name:"民雄乡",level:3},3497:{id:3497,pid:3482,name:"大林镇",level:3},3498:{id:3498,pid:3482,name:"溪口乡",level:3},3499:{id:3499,pid:3482,name:"义竹乡",level:3},3500:{id:3500,pid:3482,name:"布袋镇",level:3}}},3501:{id:3501,pid:3215,name:"云林县",level:2,region:{3502:{id:3502,pid:3501,name:"斗南镇",level:3},3503:{id:3503,pid:3501,name:"大埤乡",level:3},3504:{id:3504,pid:3501,name:"虎尾镇",level:3},3505:{id:3505,pid:3501,name:"土库镇",level:3},3506:{id:3506,pid:3501,name:"褒忠乡",level:3},3507:{id:3507,pid:3501,name:"东势乡",level:3},3508:{id:3508,pid:3501,name:"台西乡",level:3},3509:{id:3509,pid:3501,name:"仑背乡",level:3},3510:{id:3510,pid:3501,name:"麦寮乡",level:3},3511:{id:3511,pid:3501,name:"斗六市",level:3},3512:{id:3512,pid:3501,name:"林内乡",level:3},3513:{id:3513,pid:3501,name:"古坑乡",level:3},3514:{id:3514,pid:3501,name:"莿桐乡",level:3},3515:{id:3515,pid:3501,name:"西螺镇",level:3},3516:{id:3516,pid:3501,name:"二仑乡",level:3},3517:{id:3517,pid:3501,name:"北港镇",level:3},3518:{id:3518,pid:3501,name:"水林乡",level:3},3519:{id:3519,pid:3501,name:"口湖乡",level:3},3520:{id:3520,pid:3501,name:"四湖乡",level:3},3521:{id:3521,pid:3501,name:"元长乡",level:3}}},3522:{id:3522,pid:3215,name:"屏东县",level:2,region:{3523:{id:3523,pid:3522,name:"屏东市",level:3},3524:{id:3524,pid:3522,name:"三地门乡",level:3},3525:{id:3525,pid:3522,name:"雾台乡",level:3},3526:{id:3526,pid:3522,name:"玛家乡",level:3},3527:{id:3527,pid:3522,name:"九如乡",level:3},3528:{id:3528,pid:3522,name:"里港乡",level:3},3529:{id:3529,pid:3522,name:"高树乡",level:3},3530:{id:3530,pid:3522,name:"盐埔乡",level:3},3531:{id:3531,pid:3522,name:"长治乡",level:3},3532:{id:3532,pid:3522,name:"麟洛乡",level:3},3533:{id:3533,pid:3522,name:"竹田乡",level:3},3534:{id:3534,pid:3522,name:"内埔乡",level:3},3535:{id:3535,pid:3522,name:"万丹乡",level:3},3536:{id:3536,pid:3522,name:"潮州镇",level:3},3537:{id:3537,pid:3522,name:"泰武乡",level:3},3538:{id:3538,pid:3522,name:"来义乡",level:3},3539:{id:3539,pid:3522,name:"万峦乡",level:3},3540:{id:3540,pid:3522,name:"崁顶乡",level:3},3541:{id:3541,pid:3522,name:"新埤乡",level:3},3542:{id:3542,pid:3522,name:"南州乡",level:3},3543:{id:3543,pid:3522,name:"林边乡",level:3},3544:{id:3544,pid:3522,name:"东港镇",level:3},3545:{id:3545,pid:3522,name:"琉球乡",level:3},3546:{id:3546,pid:3522,name:"佳冬乡",level:3},3547:{id:3547,pid:3522,name:"新园乡",level:3},3548:{id:3548,pid:3522,name:"枋寮乡",level:3},3549:{id:3549,pid:3522,name:"枋山乡",level:3},3550:{id:3550,pid:3522,name:"春日乡",level:3},3551:{id:3551,pid:3522,name:"狮子乡",level:3},3552:{id:3552,pid:3522,name:"车城乡",level:3},3553:{id:3553,pid:3522,name:"牡丹乡",level:3},3554:{id:3554,pid:3522,name:"恒春镇",level:3},3555:{id:3555,pid:3522,name:"满州乡",level:3}}},3556:{id:3556,pid:3215,name:"台东县",level:2,region:{3557:{id:3557,pid:3556,name:"台东市",level:3},3558:{id:3558,pid:3556,name:"绿岛乡",level:3},3559:{id:3559,pid:3556,name:"兰屿乡",level:3},3560:{id:3560,pid:3556,name:"延平乡",level:3},3561:{id:3561,pid:3556,name:"卑南乡",level:3},3562:{id:3562,pid:3556,name:"鹿野乡",level:3},3563:{id:3563,pid:3556,name:"关山镇",level:3},3564:{id:3564,pid:3556,name:"海端乡",level:3},3565:{id:3565,pid:3556,name:"池上乡",level:3},3566:{id:3566,pid:3556,name:"东河乡",level:3},3567:{id:3567,pid:3556,name:"成功镇",level:3},3568:{id:3568,pid:3556,name:"长滨乡",level:3},3569:{id:3569,pid:3556,name:"金峰乡",level:3},3570:{id:3570,pid:3556,name:"大武乡",level:3},3571:{id:3571,pid:3556,name:"达仁乡",level:3},3572:{id:3572,pid:3556,name:"太麻里乡",level:3}}},3573:{id:3573,pid:3215,name:"花莲县",level:2,region:{3574:{id:3574,pid:3573,name:"花莲市",level:3},3575:{id:3575,pid:3573,name:"新城乡",level:3},3576:{id:3576,pid:3573,name:"秀林乡",level:3},3577:{id:3577,pid:3573,name:"吉安乡",level:3},3578:{id:3578,pid:3573,name:"寿丰乡",level:3},3579:{id:3579,pid:3573,name:"凤林镇",level:3},3580:{id:3580,pid:3573,name:"光复乡",level:3},3581:{id:3581,pid:3573,name:"丰滨乡",level:3},3582:{id:3582,pid:3573,name:"瑞穗乡",level:3},3583:{id:3583,pid:3573,name:"万荣乡",level:3},3584:{id:3584,pid:3573,name:"玉里镇",level:3},3585:{id:3585,pid:3573,name:"卓溪乡",level:3},3586:{id:3586,pid:3573,name:"富里乡",level:3}}},3587:{id:3587,pid:3215,name:"澎湖县",level:2,region:{3588:{id:3588,pid:3587,name:"马公市",level:3},3589:{id:3589,pid:3587,name:"西屿乡",level:3},3590:{id:3590,pid:3587,name:"望安乡",level:3},3591:{id:3591,pid:3587,name:"七美乡",level:3},3592:{id:3592,pid:3587,name:"白沙乡",level:3},3593:{id:3593,pid:3587,name:"湖西乡",level:3}}}}},3594:{id:3594,pid:0,name:"香港特别行政区",level:1,city:{3595:{id:3595,pid:3594,name:"香港特别行政区",level:2,region:{3596:{id:3596,pid:3595,name:"中西区",level:3},3597:{id:3597,pid:3595,name:"东区",level:3},3598:{id:3598,pid:3595,name:"九龙城区",level:3},3599:{id:3599,pid:3595,name:"观塘区",level:3},3600:{id:3600,pid:3595,name:"南区",level:3},3601:{id:3601,pid:3595,name:"深水埗区",level:3},3602:{id:3602,pid:3595,name:"湾仔区",level:3},3603:{id:3603,pid:3595,name:"黄大仙区",level:3},3604:{id:3604,pid:3595,name:"油尖旺区",level:3},3605:{id:3605,pid:3595,name:"离岛区",level:3},3606:{id:3606,pid:3595,name:"葵青区",level:3},3607:{id:3607,pid:3595,name:"北区",level:3},3608:{id:3608,pid:3595,name:"西贡区",level:3},3609:{id:3609,pid:3595,name:"沙田区",level:3},3610:{id:3610,pid:3595,name:"屯门区",level:3},3611:{id:3611,pid:3595,name:"大埔区",level:3},3612:{id:3612,pid:3595,name:"荃湾区",level:3},3613:{id:3613,pid:3595,name:"元朗区",level:3}}}}},3614:{id:3614,pid:0,name:"澳门特别行政区",level:1,city:{3615:{id:3615,pid:3614,name:"澳门特别行政区",level:2,region:{3616:{id:3616,pid:3615,name:"澳门半岛",level:3},3617:{id:3617,pid:3615,name:"凼仔",level:3},3618:{id:3618,pid:3615,name:"路凼城",level:3},3619:{id:3619,pid:3615,name:"路环",level:3}}}}}};
\ No newline at end of file
diff --git a/common/enum/Client.js b/common/enum/Client.js
new file mode 100644
index 0000000..a4afcbe
--- /dev/null
+++ b/common/enum/Client.js
@@ -0,0 +1,13 @@
+import Enum from './enum'
+
+/**
+ * 枚举类:客户端类型
+ * ClientEnum
+ */
+export default new Enum([
+ { key: 'APP', name: 'APP端', value: 'APP' },
+ { key: 'H5', name: 'H5端', value: 'H5' },
+ { key: 'WXOFFICIAL', name: '微信公众号端', value: 'WXOFFICIAL' },
+ { key: 'MP_WEIXIN', name: '微信小程序端', value: 'MP-WEIXIN' },
+ { key: 'MP_ALIPAY', name: '支付宝小程序端', value: 'MP-ALIPAY' },
+])
diff --git a/common/enum/coupon/ApplyRange.js b/common/enum/coupon/ApplyRange.js
new file mode 100644
index 0000000..7422e62
--- /dev/null
+++ b/common/enum/coupon/ApplyRange.js
@@ -0,0 +1,10 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:优惠券适用范围
+ * ApplyRangeEnum
+ */
+export default new Enum([
+ { key: 'ALL', name: '全部商品', value: 10 },
+ { key: 'SOME_GOODS', name: '指定商品', value: 20 }
+])
diff --git a/common/enum/coupon/CouponType.js b/common/enum/coupon/CouponType.js
new file mode 100644
index 0000000..5f56fda
--- /dev/null
+++ b/common/enum/coupon/CouponType.js
@@ -0,0 +1,10 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:优惠券类型
+ * CouponTypeEnum
+ */
+export default new Enum([
+ { key: 'FULL_DISCOUNT', name: '满减券', value: 10 },
+ { key: 'DISCOUNT', name: '折扣券', value: 20 }
+])
diff --git a/common/enum/coupon/ExpireType.js b/common/enum/coupon/ExpireType.js
new file mode 100644
index 0000000..269b36c
--- /dev/null
+++ b/common/enum/coupon/ExpireType.js
@@ -0,0 +1,10 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:优惠券到期类型
+ * ExpireTypeEnum
+ */
+export default new Enum([
+ { key: 'RECEIVE', name: '领取后', value: 10 },
+ { key: 'FIXED_TIME', name: '固定时间', value: 20 }
+])
diff --git a/common/enum/coupon/index.js b/common/enum/coupon/index.js
new file mode 100644
index 0000000..be1bdc8
--- /dev/null
+++ b/common/enum/coupon/index.js
@@ -0,0 +1,5 @@
+import ApplyRangeEnum from './ApplyRange'
+import ExpireTypeEnum from './ExpireType'
+import CouponTypeEnum from './CouponType'
+
+export { ApplyRangeEnum, CouponTypeEnum, ExpireTypeEnum }
diff --git a/common/enum/dealer/apply/ApplyStatus.js b/common/enum/dealer/apply/ApplyStatus.js
new file mode 100644
index 0000000..4808d4c
--- /dev/null
+++ b/common/enum/dealer/apply/ApplyStatus.js
@@ -0,0 +1,11 @@
+import Enum from '../../enum'
+
+/**
+ * 枚举类:分销商审核状态
+ * ApplyStatusEnum
+ */
+export default new Enum([
+ { key: 'WAIT', name: '待审核', value: 10 },
+ { key: 'PASSED', name: '审核通过', value: 20 },
+ { key: 'REJECT', name: '驳回', value: 30 }
+])
diff --git a/common/enum/dealer/apply/ApplyType.js b/common/enum/dealer/apply/ApplyType.js
new file mode 100644
index 0000000..31b80a1
--- /dev/null
+++ b/common/enum/dealer/apply/ApplyType.js
@@ -0,0 +1,10 @@
+import Enum from '../../enum'
+
+/**
+ * 枚举类:分销商申请方式
+ * ApplyTypeEnum
+ */
+export default new Enum([
+ { key: 'AUDIT', name: '需后台审核', value: 10 },
+ { key: 'PASS', name: '无需审核', value: 20 }
+])
diff --git a/common/enum/dealer/apply/index.js b/common/enum/dealer/apply/index.js
new file mode 100644
index 0000000..63844d6
--- /dev/null
+++ b/common/enum/dealer/apply/index.js
@@ -0,0 +1,4 @@
+import ApplyStatusEnum from './ApplyStatus'
+import ApplyTypeEnum from './ApplyType'
+
+export { ApplyStatusEnum, ApplyTypeEnum }
diff --git a/common/enum/dealer/withdraw/ApplyStatus.js b/common/enum/dealer/withdraw/ApplyStatus.js
new file mode 100644
index 0000000..2297ebe
--- /dev/null
+++ b/common/enum/dealer/withdraw/ApplyStatus.js
@@ -0,0 +1,12 @@
+import Enum from '../../enum'
+
+/**
+ * 枚举类:分销商提现申请状态
+ * ApplyStatusEnum
+ */
+export default new Enum([
+ { key: 'WAIT', name: '待审核', value: 10 },
+ { key: 'PASSED', name: '审核通过', value: 20 },
+ { key: 'REJECT', name: '驳回', value: 30 },
+ { key: 'PAYMENT', name: '已打款', value: 40 }
+])
diff --git a/common/enum/dealer/withdraw/PayType.js b/common/enum/dealer/withdraw/PayType.js
new file mode 100644
index 0000000..2b0c23d
--- /dev/null
+++ b/common/enum/dealer/withdraw/PayType.js
@@ -0,0 +1,11 @@
+import Enum from '../../enum'
+
+/**
+ * 枚举类:分销商体现打款方式
+ * PayTypeEnum
+ */
+export default new Enum([
+ { key: 'WECHAT', name: '微信零钱', value: 10 },
+ { key: 'ALIPAY', name: '支付宝', value: 20 },
+ { key: 'BANK_CARD', name: '银行卡', value: 30 }
+])
diff --git a/common/enum/dealer/withdraw/index.js b/common/enum/dealer/withdraw/index.js
new file mode 100644
index 0000000..9e8210c
--- /dev/null
+++ b/common/enum/dealer/withdraw/index.js
@@ -0,0 +1,4 @@
+import PayTypeEnum from './PayType'
+import ApplyStatusEnum from './ApplyStatus'
+
+export { PayTypeEnum, ApplyStatusEnum }
diff --git a/common/enum/enum.js b/common/enum/enum.js
new file mode 100644
index 0000000..0894708
--- /dev/null
+++ b/common/enum/enum.js
@@ -0,0 +1,85 @@
+/**
+ * 枚举类
+ * Enum.IMAGE.name => "图片"
+ * Enum.getNameByKey('IMAGE') => "图片"
+ * Enum.getValueByKey('IMAGE') => 10
+ * Enum.getNameByValue(10) => "图片"
+ * Enum.getData() => [{key: "IMAGE", name: "图片", value: 10}]
+ */
+class Enum {
+ constructor (param) {
+ const keyArr = []
+ const valueArr = []
+
+ if (!Array.isArray(param)) {
+ throw new Error('param is not an array!')
+ }
+
+ param.map(element => {
+ if (!element.key || !element.name) {
+ return
+ }
+ // 保存key值组成的数组,方便A.getName(name)类型的调用
+ keyArr.push(element.key)
+ valueArr.push(element.value)
+ // 根据key生成不同属性值,以便A.B.name类型的调用
+ this[element.key] = element
+ if (element.key !== element.value) {
+ this[element.value] = element
+ }
+ })
+
+
+ // 保存源数组
+ this.data = param
+ this.keyArr = keyArr
+ this.valueArr = valueArr
+
+ // 防止被修改
+ // Object.freeze(this)
+ }
+
+ // 根据key得到对象
+ keyOf (key) {
+ return this.data[this.keyArr.indexOf(key)]
+ }
+
+ // 根据key得到对象
+ valueOf (key) {
+ return this.data[this.valueArr.indexOf(key)]
+ }
+
+ // 根据key获取name值
+ getNameByKey (key) {
+ const prop = this.keyOf(key)
+ if (!prop) {
+ throw new Error('No enum constant' + key)
+ }
+ return prop.name
+ }
+
+ // 根据value获取name值
+ getNameByValue (value) {
+ const prop = this.valueOf(value)
+ if (!prop) {
+ throw new Error('No enum constant' + value)
+ }
+ return prop.name
+ }
+
+ // 根据key获取value值
+ getValueByKey (key) {
+ const prop = this.keyOf(key)
+ if (!prop) {
+ throw new Error('No enum constant' + key)
+ }
+ return prop.key
+ }
+
+ // 返回源数组
+ getData () {
+ return this.data
+ }
+}
+
+export default Enum
diff --git a/common/enum/goods/GoodsType.js b/common/enum/goods/GoodsType.js
new file mode 100644
index 0000000..235af2a
--- /dev/null
+++ b/common/enum/goods/GoodsType.js
@@ -0,0 +1,10 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:商品类型
+ * GoodsTypeEnum
+ */
+export default new Enum([
+ { key: 'PHYSICAL', name: '实物商品', value: 10 },
+ { key: 'VIRTUAL', name: '虚拟商品', value: 20 }
+])
diff --git a/common/enum/goods/SpecType.js b/common/enum/goods/SpecType.js
new file mode 100644
index 0000000..ec7832e
--- /dev/null
+++ b/common/enum/goods/SpecType.js
@@ -0,0 +1,10 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:商品规格类型
+ * SpecTypeEnum
+ */
+export default new Enum([
+ { key: 'SINGLE', name: '单规格', value: 10 },
+ { key: 'MULTI', name: '多规格', value: 20 }
+])
diff --git a/common/enum/goods/index.js b/common/enum/goods/index.js
new file mode 100644
index 0000000..b057a95
--- /dev/null
+++ b/common/enum/goods/index.js
@@ -0,0 +1,4 @@
+import GoodsTypeEnum from './GoodsType'
+import SpecTypeEnum from './SpecType'
+
+export { GoodsTypeEnum, SpecTypeEnum }
diff --git a/common/enum/groupon/ActiveStatus.js b/common/enum/groupon/ActiveStatus.js
new file mode 100644
index 0000000..77c0350
--- /dev/null
+++ b/common/enum/groupon/ActiveStatus.js
@@ -0,0 +1,11 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:拼团活动状态
+ * GoodsStatusEnum
+ */
+export default new Enum([
+ { key: 'STATE_BEGIN', name: '已开始', value: 10 },
+ { key: 'STATE_SOON', name: '未开始', value: 20 },
+ { key: 'STATE_END', name: '已结束', value: 30 }
+])
diff --git a/common/enum/groupon/ActiveType.js b/common/enum/groupon/ActiveType.js
new file mode 100644
index 0000000..0a89d33
--- /dev/null
+++ b/common/enum/groupon/ActiveType.js
@@ -0,0 +1,11 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:拼团类型
+ * ActiveTypeEnum
+ */
+export default new Enum([
+ { key: 'NORMAL', name: '普通拼团', value: 10, name2: '多人拼团' },
+ { key: 'PULL_NEW', name: '老带新拼团', value: 20, name2: '新人团' },
+ { key: 'STEPS', name: '阶梯拼团', value: 30, name2: '阶梯团' }
+])
diff --git a/common/enum/groupon/GoodsStatus.js b/common/enum/groupon/GoodsStatus.js
new file mode 100644
index 0000000..039a02c
--- /dev/null
+++ b/common/enum/groupon/GoodsStatus.js
@@ -0,0 +1,10 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:拼团商品状态
+ * GoodsStatusEnum
+ */
+export default new Enum([
+ { key: 'NORMAL', name: '进行中', value: 10 },
+ { key: 'FINISH', name: '已结束', value: 20 }
+])
diff --git a/common/enum/groupon/TaskStatus.js b/common/enum/groupon/TaskStatus.js
new file mode 100644
index 0000000..6299cfd
--- /dev/null
+++ b/common/enum/groupon/TaskStatus.js
@@ -0,0 +1,11 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:拼单状态
+ * TaskStatusEnum
+ */
+export default new Enum([
+ { key: 'NORMAL', name: '进行中', value: 10 },
+ { key: 'SUCCESS', name: '拼单成功', value: 20 },
+ { key: 'FAIL', name: '拼单失败', value: 30 }
+])
diff --git a/common/enum/groupon/index.js b/common/enum/groupon/index.js
new file mode 100644
index 0000000..316d18e
--- /dev/null
+++ b/common/enum/groupon/index.js
@@ -0,0 +1,6 @@
+import GoodsStatusEnum from './GoodsStatus'
+import TaskStatusEnum from './TaskStatus'
+import ActiveTypeEnum from './ActiveType'
+import ActiveStatusEnum from './ActiveStatus'
+
+export { GoodsStatusEnum, TaskStatusEnum, ActiveTypeEnum, ActiveStatusEnum }
diff --git a/common/enum/live/LiveStatus.js b/common/enum/live/LiveStatus.js
new file mode 100644
index 0000000..cbb683e
--- /dev/null
+++ b/common/enum/live/LiveStatus.js
@@ -0,0 +1,15 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:微信小程序直播间状态
+ * LiveStatusEnum
+ */
+export default new Enum([
+ { key: 101, name: '直播中', value: 101 },
+ { key: 102, name: '未开始', value: 102 },
+ { key: 103, name: '已结束', value: 103 },
+ { key: 104, name: '禁播', value: 104 },
+ { key: 105, name: '暂停中', value: 105 },
+ { key: 106, name: '异常', value: 106 },
+ { key: 107, name: '已过期', value: 107 }
+])
diff --git a/common/enum/live/index.js b/common/enum/live/index.js
new file mode 100644
index 0000000..d8a53cc
--- /dev/null
+++ b/common/enum/live/index.js
@@ -0,0 +1,3 @@
+import LiveStatusEnum from './LiveStatus'
+
+export { LiveStatusEnum }
diff --git a/common/enum/order/DeliveryStatus.js b/common/enum/order/DeliveryStatus.js
new file mode 100644
index 0000000..ed55f95
--- /dev/null
+++ b/common/enum/order/DeliveryStatus.js
@@ -0,0 +1,10 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:订单发货状态
+ * DeliveryStatusEnum
+ */
+export default new Enum([
+ { key: 'NOT_DELIVERED', name: '未发货', value: 10 },
+ { key: 'DELIVERED', name: '已发货', value: 20 }
+])
diff --git a/common/enum/order/DeliveryType.js b/common/enum/order/DeliveryType.js
new file mode 100644
index 0000000..230eb18
--- /dev/null
+++ b/common/enum/order/DeliveryType.js
@@ -0,0 +1,11 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:配送方式
+ * DeliveryTypeEnum
+ */
+export default new Enum([
+ { key: 'EXPRESS', name: '快递配送', value: 10 },
+ { key: 'EXTRACT', name: '上门自提', value: 20 },
+ { key: 'NOTHING', name: '无需配送', value: 30 }
+])
diff --git a/common/enum/order/OrderSource.js b/common/enum/order/OrderSource.js
new file mode 100644
index 0000000..e46062c
--- /dev/null
+++ b/common/enum/order/OrderSource.js
@@ -0,0 +1,11 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:订单来源
+ * OrderSourceEnum
+ */
+export default new Enum([
+ { key: 'MASTER', name: '普通订单', value: 10 },
+ { key: 'BARGAIN', name: '砍价订单', value: 20 },
+ { key: 'SHARP', name: '秒杀订单', value: 30 }
+])
diff --git a/common/enum/order/OrderStatus.js b/common/enum/order/OrderStatus.js
new file mode 100644
index 0000000..f706e43
--- /dev/null
+++ b/common/enum/order/OrderStatus.js
@@ -0,0 +1,12 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:订单状态
+ * OrderStatusEnum
+ */
+export default new Enum([
+ { key: 'NORMAL', name: '进行中', value: 10 },
+ { key: 'CANCELLED', name: '已取消', value: 20 },
+ { key: 'APPLY_CANCEL', name: '待取消', value: 21 },
+ { key: 'COMPLETED', name: '已完成', value: 30 }
+])
diff --git a/common/enum/order/OrderType.js b/common/enum/order/OrderType.js
new file mode 100644
index 0000000..de77681
--- /dev/null
+++ b/common/enum/order/OrderType.js
@@ -0,0 +1,10 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:订单类型
+ * OrderTypeEnum
+ */
+export default new Enum([
+ { key: 'PHYSICAL', name: '实物订单', value: 10 },
+ { key: 'VIRTUAL', name: '虚拟订单', value: 20 }
+])
diff --git a/common/enum/order/PayStatus.js b/common/enum/order/PayStatus.js
new file mode 100644
index 0000000..f0e4b1d
--- /dev/null
+++ b/common/enum/order/PayStatus.js
@@ -0,0 +1,10 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:订单支付状态
+ * PayStatusEnum
+ */
+export default new Enum([
+ { key: 'PENDING', name: '待支付', value: 10 },
+ { key: 'SUCCESS', name: '已支付', value: 20 }
+])
diff --git a/common/enum/order/ReceiptStatus.js b/common/enum/order/ReceiptStatus.js
new file mode 100644
index 0000000..34916a0
--- /dev/null
+++ b/common/enum/order/ReceiptStatus.js
@@ -0,0 +1,10 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:订单收货状态
+ * ReceiptStatusEnum
+ */
+export default new Enum([
+ { key: 'NOT_RECEIVED', name: '未收货', value: 10 },
+ { key: 'RECEIVED', name: '已收货', value: 20 }
+])
diff --git a/common/enum/order/delivery/DeliveryMethod.js b/common/enum/order/delivery/DeliveryMethod.js
new file mode 100644
index 0000000..7d06cb1
--- /dev/null
+++ b/common/enum/order/delivery/DeliveryMethod.js
@@ -0,0 +1,11 @@
+import Enum from '../../enum'
+
+/**
+ * 枚举类:发货方式
+ * DeliveryMethodEnum
+ */
+export default new Enum([
+ { key: 'MANUAL', name: '手动发货', value: 10 },
+ { key: 'UNWANTED', name: '无需物流', value: 20 },
+ { key: 'EORDER', name: '电子面单', value: 30 }
+])
diff --git a/common/enum/order/delivery/index.js b/common/enum/order/delivery/index.js
new file mode 100644
index 0000000..171a078
--- /dev/null
+++ b/common/enum/order/delivery/index.js
@@ -0,0 +1,3 @@
+import DeliveryMethodEnum from './DeliveryMethod'
+
+export { DeliveryMethodEnum }
diff --git a/common/enum/order/index.js b/common/enum/order/index.js
new file mode 100644
index 0000000..56f507b
--- /dev/null
+++ b/common/enum/order/index.js
@@ -0,0 +1,17 @@
+import DeliveryStatusEnum from './DeliveryStatus'
+import DeliveryTypeEnum from './DeliveryType'
+import OrderSourceEnum from './OrderSource'
+import OrderStatusEnum from './OrderStatus'
+import PayStatusEnum from './PayStatus'
+import ReceiptStatusEnum from './ReceiptStatus'
+import OrderTypeEnum from './OrderType'
+
+export {
+ DeliveryStatusEnum,
+ DeliveryTypeEnum,
+ OrderSourceEnum,
+ OrderStatusEnum,
+ PayStatusEnum,
+ ReceiptStatusEnum,
+ OrderTypeEnum
+}
diff --git a/common/enum/order/refund/AuditStatus.js b/common/enum/order/refund/AuditStatus.js
new file mode 100644
index 0000000..2d9f5f0
--- /dev/null
+++ b/common/enum/order/refund/AuditStatus.js
@@ -0,0 +1,11 @@
+import Enum from '../../enum'
+
+/**
+ * 枚举类:商家审核状态
+ * AuditStatusEnum
+ */
+export default new Enum([
+ { key: 'WAIT', name: '待审核', value: 0 },
+ { key: 'REVIEWED', name: '已同意', value: 10 },
+ { key: 'REJECTED', name: '已拒绝', value: 20 }
+])
diff --git a/common/enum/order/refund/RefundStatus.js b/common/enum/order/refund/RefundStatus.js
new file mode 100644
index 0000000..78331b2
--- /dev/null
+++ b/common/enum/order/refund/RefundStatus.js
@@ -0,0 +1,12 @@
+import Enum from '../../enum'
+
+/**
+ * 枚举类:售后单状态
+ * RefundStatusEnum
+ */
+export default new Enum([
+ { key: 'NORMAL', name: '进行中', value: 0 },
+ { key: 'REJECTED', name: '已拒绝', value: 10 },
+ { key: 'COMPLETED', name: '已完成', value: 20 },
+ { key: 'CANCELLED', name: '已取消', value: 30 }
+])
diff --git a/common/enum/order/refund/RefundType.js b/common/enum/order/refund/RefundType.js
new file mode 100644
index 0000000..63999cd
--- /dev/null
+++ b/common/enum/order/refund/RefundType.js
@@ -0,0 +1,10 @@
+import Enum from '../../enum'
+
+/**
+ * 枚举类:售后类型
+ * RefundTypeEnum
+ */
+export default new Enum([
+ { key: 'RETURN', name: '退货退款', value: 10 },
+ { key: 'EXCHANGE', name: '换货', value: 20 }
+])
diff --git a/common/enum/order/refund/index.js b/common/enum/order/refund/index.js
new file mode 100644
index 0000000..803b268
--- /dev/null
+++ b/common/enum/order/refund/index.js
@@ -0,0 +1,9 @@
+import AuditStatusEnum from './AuditStatus'
+import RefundStatusEnum from './RefundStatus'
+import RefundTypeEnum from './RefundType'
+
+export {
+ AuditStatusEnum,
+ RefundStatusEnum,
+ RefundTypeEnum
+}
diff --git a/common/enum/payment/Method.js b/common/enum/payment/Method.js
new file mode 100644
index 0000000..e9213e4
--- /dev/null
+++ b/common/enum/payment/Method.js
@@ -0,0 +1,11 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:支付方式类型
+ * PayMethodEnum
+ */
+export default new Enum([
+ { key: 'WECHAT', name: '微信支付', value: 'wechat' },
+ { key: 'ALIPAY', name: '支付宝支付', value: 'alipay' },
+ { key: 'BALANCE', name: '余额支付', value: 'balance' }
+])
diff --git a/common/enum/payment/index.js b/common/enum/payment/index.js
new file mode 100644
index 0000000..030b061
--- /dev/null
+++ b/common/enum/payment/index.js
@@ -0,0 +1,3 @@
+import PayMethodEnum from './Method'
+
+export { PayMethodEnum }
diff --git a/common/enum/setting/Key.js b/common/enum/setting/Key.js
new file mode 100644
index 0000000..8bf7582
--- /dev/null
+++ b/common/enum/setting/Key.js
@@ -0,0 +1,42 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:设置项索引
+ * SettingKeyEnum
+ */
+export default new Enum([{
+ key: 'REGISTER',
+ name: '账户注册设置',
+ value: 'register'
+ },
+ {
+ key: 'APP_THEME',
+ name: '店铺页面风格',
+ value: 'app_theme'
+ },
+ {
+ key: 'PAGE_CATEGORY_TEMPLATE',
+ name: '分类页模板',
+ value: 'page_category_template'
+ },
+ {
+ key: 'POINTS',
+ name: '积分设置',
+ value: 'points'
+ },
+ {
+ key: 'RECHARGE',
+ name: '充值设置',
+ value: 'recharge'
+ },
+ {
+ key: 'RECOMMENDED',
+ name: '商品推荐设置',
+ value: 'recommended'
+ },
+ {
+ key: 'CUSTOMER',
+ name: '商城客服设置',
+ value: 'customer'
+ }
+])
diff --git a/common/enum/sharp/ActiveStatus.js b/common/enum/sharp/ActiveStatus.js
new file mode 100644
index 0000000..de89022
--- /dev/null
+++ b/common/enum/sharp/ActiveStatus.js
@@ -0,0 +1,11 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:整点秒杀-活动会场状态
+ * ActiveStatusEnum
+ */
+export default new Enum([
+ { key: 'STATE_BEGIN', name: '已开始', value: 10 },
+ { key: 'STATE_SOON', name: '即将开始', value: 20 },
+ { key: 'STATE_NOTICE', name: '预告', value: 30 }
+])
diff --git a/common/enum/sharp/GoodsStatus.js b/common/enum/sharp/GoodsStatus.js
new file mode 100644
index 0000000..f5eac32
--- /dev/null
+++ b/common/enum/sharp/GoodsStatus.js
@@ -0,0 +1,11 @@
+import Enum from '../enum'
+
+/**
+ * 枚举类:整点秒杀-活动商品状态
+ * GoodsStatusEnum
+ */
+export default new Enum([
+ { key: 'STATE_BEGIN', name: '已开始', value: 10 },
+ { key: 'STATE_SOON', name: '未开始', value: 20 },
+ { key: 'STATE_END', name: '已结束', value: 30 }
+])
diff --git a/common/enum/sharp/index.js b/common/enum/sharp/index.js
new file mode 100644
index 0000000..9a98bdb
--- /dev/null
+++ b/common/enum/sharp/index.js
@@ -0,0 +1,4 @@
+import ActiveStatusEnum from './ActiveStatus'
+import GoodsStatusEnum from './GoodsStatus'
+
+export { ActiveStatusEnum, GoodsStatusEnum }
diff --git a/common/enum/store/page/category/Style.js b/common/enum/store/page/category/Style.js
new file mode 100644
index 0000000..c33c486
--- /dev/null
+++ b/common/enum/store/page/category/Style.js
@@ -0,0 +1,12 @@
+import Enum from '../../../enum'
+
+/**
+ * 枚举类:地址类型
+ * PageCategoryStyleEnum
+ */
+export default new Enum([
+ { key: 'ONE_LEVEL_BIG', name: '一级分类[大图]', value: 10 },
+ { key: 'ONE_LEVEL_SMALL', name: '一级分类[小图]', value: 11 },
+ { key: 'TWO_LEVEL', name: '二级分类', value: 20 },
+ { key: 'COMMODITY', name: '一级分类+商品', value: 30 }
+])
diff --git a/common/enum/store/page/category/index.js b/common/enum/store/page/category/index.js
new file mode 100644
index 0000000..bf350e1
--- /dev/null
+++ b/common/enum/store/page/category/index.js
@@ -0,0 +1,3 @@
+import PageCategoryStyleEnum from './Style'
+
+export { PageCategoryStyleEnum }
diff --git a/common/model/Region.js b/common/model/Region.js
new file mode 100644
index 0000000..56a06ba
--- /dev/null
+++ b/common/model/Region.js
@@ -0,0 +1,77 @@
+import * as Api from '@/api/region'
+import storage from '@/utils/storage'
+import regionData from '../data/region'
+
+const REGION_TREE = 'region_tree'
+
+/**
+ * 商品分类 model类
+ * RegionModel
+ */
+export default {
+
+ // 从服务端获取全部地区数据(树状)
+ getTreeDataFromApi() {
+ return new Promise((resolve, reject) => {
+ Api.tree().then(result => resolve(result.data.list))
+ })
+ },
+
+ // 获取所有地区(树状) 从storage中获取
+ getTreeData() {
+ return new Promise((resolve, reject) => {
+ // 判断缓存中是否存在
+ const data = storage.get(REGION_TREE)
+ // 从服务端获取全部地区数据
+ if (data) {
+ resolve(data)
+ } else {
+ this.getTreeDataFromApi().then(list => {
+ // 缓存24小时
+ storage.set(REGION_TREE, list, 24 * 60 * 60)
+ resolve(list)
+ })
+ }
+ })
+ },
+
+ // 同步获取所有地区(树状)
+ getTreeDataSync() {
+ return regionData
+ },
+
+ // 获取所有地区的总数
+ getCitysCount() {
+ return new Promise((resolve, reject) => {
+ // 获取所有地区(树状)
+ this.getTreeData().then(data => {
+ const cityIds = []
+ // 遍历省份
+ for (const pidx in data) {
+ const province = data[pidx]
+ // 遍历城市
+ for (const cidx in province.city) {
+ const cityItem = province.city[cidx]
+ cityIds.push(cityItem.id)
+ }
+ }
+ resolve(cityIds.length)
+ })
+ })
+ },
+
+ // 同步获取所有地区的总数
+ getCitysCountSync() {
+ const regionData = this.getTreeDataSync()
+ const cityIds = []
+ for (const pidx in regionData) {
+ const province = regionData[pidx]
+ for (const cidx in province.city) {
+ const cityItem = province.city[cidx]
+ cityIds.push(cityItem.id)
+ }
+ }
+ return cityIds.length
+ }
+
+}
\ No newline at end of file
diff --git a/common/model/Setting.js b/common/model/Setting.js
new file mode 100644
index 0000000..4ab679f
--- /dev/null
+++ b/common/model/Setting.js
@@ -0,0 +1,91 @@
+import store from '@/store'
+import Config from '@/core/config'
+import storage from '@/utils/storage'
+import * as SettingApi from '@/api/setting'
+import SettingKeyEnum from '@/common/enum/setting/Key'
+import MpAlipaySettingModel from '@/common/model/mp/alipay/Setting'
+import platform from '@/core/platform'
+
+const CACHE_KEY = 'Setting'
+
+// 写入缓存, 到期时间10分钟
+const setStorage = data => {
+ const expireTime = 10 * 60
+ storage.set(CACHE_KEY, data, expireTime)
+}
+
+// 获取缓存中的数据
+const getStorage = () => {
+ return storage.get(CACHE_KEY)
+}
+
+// 获取后端接口商城设置 (最新)
+const getApiData = () => {
+ return new Promise((resolve, reject) => {
+ SettingApi.data()
+ .then(result => {
+ resolve(result.data.setting)
+ })
+ })
+}
+
+/**
+ * 获取商城设置
+ * 有缓存的情况下返回缓存, 没有缓存从后端api获取
+ * @param {bool} isCache 是否从缓存中获取 [优点不用每次请求后端api 缺点后台更新设置后需等待时效性]
+ */
+const data = (isCache = undefined) => {
+ if (isCache == undefined) {
+ isCache = Config.get('enabledSettingCache')
+ }
+ return new Promise((resolve, reject) => {
+ const cacheData = getStorage()
+ if (isCache && cacheData) {
+ resolve(cacheData)
+ } else {
+ getApiData().then(data => {
+ setStorage(data)
+ resolve(data)
+ })
+ }
+ })
+}
+
+// 获取商城设置(指定项)
+const item = (key, isCache = undefined) => {
+ return new Promise((resolve, reject) => {
+ data(isCache).then(setting => resolve(setting[key]))
+ })
+}
+
+// 设置全局自定义主题
+const setAppTheme = () => {
+ return new Promise((resolve, reject) => {
+ item(SettingKeyEnum.APP_THEME.value).then(appTheme => {
+ store.dispatch('SetAppTheme', appTheme)
+ resolve()
+ })
+ })
+}
+
+// 是否显示客服按钮 (微信小程序客服只有在微信小程序端显示)
+const isShowCustomerBtn = async () => {
+ // #ifdef MP-ALIPAY
+ return await MpAlipaySettingModel.isShowCustomerBtn()
+ // #endif
+ // #ifndef MP-ALIPAY
+ const setting = await item(SettingKeyEnum.CUSTOMER.value, true)
+ if (!setting.enabled) {
+ return false
+ }
+ return setting.provider === 'wxqykf' || (setting.provider === 'mpwxkf' && platform === 'MP-WEIXIN')
+ // #endif
+}
+
+export default {
+ setStorage,
+ data,
+ item,
+ setAppTheme,
+ isShowCustomerBtn
+}
\ No newline at end of file
diff --git a/common/model/Store.js b/common/model/Store.js
new file mode 100644
index 0000000..25771c8
--- /dev/null
+++ b/common/model/Store.js
@@ -0,0 +1,97 @@
+import store from '@/store'
+import StoreApi from '@/api/store'
+import storage from '@/utils/storage'
+import { isWeixinOfficial } from '@/core/platform'
+import SettingModel from '@/common/model/Setting'
+import WxofficialSettingModel from '@/common/model/wxofficial/Setting'
+
+const CACHE_KEY = 'Store'
+
+// 写入缓存, 到期时间10分钟
+const setStorage = data => {
+ const expireTime = 10 * 60
+ storage.set(CACHE_KEY, data, expireTime)
+}
+
+// 获取缓存中的数据
+const getStorage = () => {
+ return storage.get(CACHE_KEY)
+}
+
+// 获取后端接口商城设置 (最新)
+const getApiData = () => {
+ return new Promise((resolve, reject) => {
+ StoreApi.data().then(result => {
+ // 初始化商城数据
+ initStoreData(result.data)
+ resolve(result.data)
+ })
+ })
+}
+
+// 初始化商城数据
+const initStoreData = data => {
+ // 将商城基本信息写入缓存
+ setStorage(data)
+ // 设置商城设置缓存
+ SettingModel.setStorage(data.setting)
+ // 设置全局自定义主题
+ SettingModel.setAppTheme()
+ // 设置微信公众号链接分享卡片内容(全局)
+ if (isWeixinOfficial) {
+ WxofficialSettingModel.setGlobalShareCard(false)
+ }
+ // 设置开启的功能模块
+ store.dispatch('SetModules', data.modules)
+}
+
+/**
+ * 获取商城基础信息
+ * 有缓存的情况下返回缓存, 没有缓存从后端api获取
+ */
+const data = (isCache = true) => {
+ return new Promise((resolve, reject) => {
+ const cacheData = getStorage()
+ if (isCache && cacheData) {
+ resolve(cacheData)
+ } else {
+ getApiData().then(data => {
+ resolve(data)
+ })
+ }
+ })
+}
+
+// 获取商城基本信息
+const storeInfo = () => {
+ return new Promise((resolve, reject) => {
+ data().then(data => resolve(data.storeInfo))
+ })
+}
+
+// 获取H5端访问地址
+const h5Url = () => {
+ return new Promise((resolve, reject) => {
+ data().then(data => {
+ const h5Url = data.clientData.h5.setting.baseUrl
+ resolve(h5Url)
+ })
+ })
+}
+
+// 是否开启分销中心
+const isEnabledDealer = () => {
+ return new Promise((resolve, reject) => {
+ data().then(data => {
+ const isEnabledDealer = Boolean(data.dealer.setting.is_open)
+ resolve(isEnabledDealer)
+ })
+ })
+}
+
+export default {
+ data,
+ storeInfo,
+ h5Url,
+ isEnabledDealer
+}
\ No newline at end of file
diff --git a/common/model/dealer/Setting.js b/common/model/dealer/Setting.js
new file mode 100644
index 0000000..0d043e1
--- /dev/null
+++ b/common/model/dealer/Setting.js
@@ -0,0 +1,58 @@
+import * as SettingApi from '@/api/dealer/setting'
+import storage from '@/utils/storage'
+
+const CACHE_KEY = 'Dealer-Setting'
+
+// 写入缓存, 到期时间30分钟
+const setStorage = (data) => {
+ const expireTime = 30 * 60
+ storage.set(CACHE_KEY, data, expireTime)
+}
+
+// 获取缓存中的数据
+const getStorage = () => {
+ return storage.get(CACHE_KEY)
+}
+
+// 获取后端接口商城设置 (最新)
+const getApiData = () => {
+ return new Promise((resolve, reject) => {
+ SettingApi.data()
+ .then(result => {
+ resolve(result.data.setting)
+ })
+ })
+}
+
+/**
+ * 获取商城设置
+ * 有缓存的情况下返回缓存, 没有缓存从后端api获取
+ * @param {bool} isCache 是否从缓存中获取
+ */
+const data = (isCache = false) => {
+ return new Promise((resolve, reject) => {
+ const cacheData = getStorage()
+ if (isCache && cacheData) {
+ resolve(cacheData)
+ } else {
+ getApiData().then(data => {
+ setStorage(data)
+ resolve(data)
+ })
+ }
+ })
+}
+
+// 获取商城设置(指定项)
+const item = (key, isCache = false) => {
+ return new Promise((resolve, reject) => {
+ data(isCache).then(setting => {
+ resolve(setting[key])
+ })
+ })
+}
+
+export default {
+ data,
+ item
+}
diff --git a/common/model/groupon/Setting.js b/common/model/groupon/Setting.js
new file mode 100644
index 0000000..db7c284
--- /dev/null
+++ b/common/model/groupon/Setting.js
@@ -0,0 +1,52 @@
+import Config from '@/core/config'
+import * as SettingApi from '@/api/groupon/setting'
+import storage from '@/utils/storage'
+
+const CACHE_KEY = 'Groupon-Setting'
+
+// 写入缓存, 到期时间30分钟
+const setStorage = (data) => {
+ const expireTime = 30 * 60
+ storage.set(CACHE_KEY, data, expireTime)
+}
+
+// 获取缓存中的数据
+const getStorage = () => {
+ return storage.get(CACHE_KEY)
+}
+
+// 获取后端接口商城设置 (最新)
+const getApiData = () => {
+ return new Promise((resolve, reject) => {
+ SettingApi.data()
+ .then(result => {
+ resolve(result.data.setting)
+ })
+ })
+}
+
+/**
+ * 获取商城设置
+ * 有缓存的情况下返回缓存, 没有缓存从后端api获取
+ * @param {bool} isCache 是否从缓存中获取
+ */
+const data = (isCache = false) => {
+ if (isCache == undefined) {
+ isCache = Config.get('enabledSettingCache')
+ }
+ return new Promise((resolve, reject) => {
+ const cacheData = getStorage()
+ if (isCache && cacheData) {
+ resolve(cacheData)
+ } else {
+ getApiData().then(data => {
+ setStorage(data)
+ resolve(data)
+ })
+ }
+ })
+}
+
+export default {
+ data
+}
diff --git a/common/model/mp/alipay/Setting.js b/common/model/mp/alipay/Setting.js
new file mode 100644
index 0000000..24ad064
--- /dev/null
+++ b/common/model/mp/alipay/Setting.js
@@ -0,0 +1,31 @@
+import StoreModel from '@/common/model/Store'
+
+/**
+ * 获取支付宝小程序设置 (全部)
+ */
+const data = () => {
+ return new Promise((resolve, reject) => {
+ StoreModel.data().then(data => {
+ resolve(data.clientData.mpAlipay.setting ? data.clientData.mpAlipay.setting : [])
+ })
+ })
+}
+
+// 获取支付宝小程序设置 (指定项)
+const item = (key) => {
+ return new Promise((resolve, reject) => {
+ data().then(setting => resolve(setting[key]))
+ })
+}
+
+// 是否显示客服按钮 (仅在支付宝小程序中显示)
+const isShowCustomerBtn = async () => {
+ const setting = await item('customer', true)
+ return setting.enabled
+}
+
+export default {
+ data,
+ item,
+ isShowCustomerBtn
+}
\ No newline at end of file
diff --git a/common/model/wxofficial/Setting.js b/common/model/wxofficial/Setting.js
new file mode 100644
index 0000000..48b1138
--- /dev/null
+++ b/common/model/wxofficial/Setting.js
@@ -0,0 +1,84 @@
+import StoreModel from '@/common/model/Store'
+import { isWeixinOfficial } from '@/core/platform'
+import { isEmptyObject } from '@/utils/util'
+// #ifdef H5
+import wxofficial from '@/core/wxofficial'
+// #endif
+
+// 当前是否存在分享内容
+let existShareData = false
+
+/**
+ * 获取微信公众号设置 (全部)
+ */
+const data = () => {
+ return new Promise((resolve, reject) => {
+ StoreModel.data().then(data => {
+ resolve(data.clientData.wxofficial.setting)
+ })
+ })
+}
+
+// 获取微信公众号设置 (指定项)
+const item = (key) => {
+ return new Promise((resolve, reject) => {
+ data().then(setting => resolve(setting[key]))
+ })
+}
+
+// 是否开启微信公众号链接分享卡片
+// #ifdef H5
+const isWxofficialLinkShareCard = () => {
+ return new Promise((resolve, reject) => {
+ item('share').then(data => resolve(Boolean(data.enabled)))
+ })
+}
+// #endif
+
+/**
+ * 设置微信公众号链接分享卡片内容(全局)
+ * @param {Boolean} force 当已存在存在分享内容时 是否强制写入全局内容(用于页面onUnload事件中)
+ */
+// #ifdef H5
+const setGlobalShareCard = async (force = false) => {
+ const setting = await getSetting()
+ if (isWeixinOfficial && setting.enabled) {
+ // 获取当前页面url (不包含#及其后面部分)
+ const url = window.location.href.split('#')[0]
+ await wxofficial.setConfig()
+ if (!existShareData || force) {
+ // 设置分享卡片的内容
+ wxofficial.updateShareData(setting)
+ }
+ }
+}
+// #endif
+
+// 获取分享设置
+const getSetting = async () => {
+ return await item('share')
+}
+
+// 更新分享卡片内容
+// #ifdef H5
+const updateShareData = async (param) => {
+ // 设置当前已存在分享内容
+ existShareData = true
+ // 合并用户配置和默认配置
+ const setting = await getSetting()
+ const options = Object.assign({}, setting, param)
+ console.log('options', options)
+ // 设置分享卡片的内容
+ wxofficial.updateShareData(options)
+}
+// #endif
+
+export default {
+ data,
+ item,
+ // #ifdef H5
+ isWxofficialLinkShareCard,
+ updateShareData,
+ setGlobalShareCard,
+ // #endif
+}
\ No newline at end of file
diff --git a/components/add-cart-btn/index.vue b/components/add-cart-btn/index.vue
new file mode 100644
index 0000000..1a53294
--- /dev/null
+++ b/components/add-cart-btn/index.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/add-cart-popup/index.vue b/components/add-cart-popup/index.vue
new file mode 100644
index 0000000..f8b7887
--- /dev/null
+++ b/components/add-cart-popup/index.vue
@@ -0,0 +1,178 @@
+
+
+
+
+
+
+
diff --git a/components/avatar-image/index.vue b/components/avatar-image/index.vue
new file mode 100644
index 0000000..f16e91b
--- /dev/null
+++ b/components/avatar-image/index.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/countdown/index.vue b/components/countdown/index.vue
new file mode 100644
index 0000000..ce4208e
--- /dev/null
+++ b/components/countdown/index.vue
@@ -0,0 +1,183 @@
+
+
+
+
+
+ {{ dynamic.day }}
+ {{ separatorText.day }}
+
+ {{ dynamic.hou }}
+ {{ separatorText.hou }}
+ {{ dynamic.min }}
+ {{ separatorText.min }}
+ {{ dynamic.sec }}
+ {{ separatorText.sec }}
+
+
+
+
+
+
+
diff --git a/components/customer-btn/index.vue b/components/customer-btn/index.vue
new file mode 100644
index 0000000..1c73a54
--- /dev/null
+++ b/components/customer-btn/index.vue
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/empty/index.vue b/components/empty/index.vue
new file mode 100644
index 0000000..fe7f6e7
--- /dev/null
+++ b/components/empty/index.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+ {{ tips }}
+
+
+
+
+
+
+
diff --git a/components/goods-poster-popup/index.vue b/components/goods-poster-popup/index.vue
new file mode 100644
index 0000000..50a90f8
--- /dev/null
+++ b/components/goods-poster-popup/index.vue
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+
+ 保存海报图
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/goods-sku-popup/index.vue b/components/goods-sku-popup/index.vue
new file mode 100644
index 0000000..5a62527
--- /dev/null
+++ b/components/goods-sku-popup/index.vue
@@ -0,0 +1,1377 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/goods-sku-popup/number-box/index.vue b/components/goods-sku-popup/number-box/index.vue
new file mode 100644
index 0000000..6e5133f
--- /dev/null
+++ b/components/goods-sku-popup/number-box/index.vue
@@ -0,0 +1,473 @@
+
+
+
+
+ -
+
+
+
+ +
+
+
+
+
+
+
diff --git a/components/page/diyComponents/ICPLicense/index.vue b/components/page/diyComponents/ICPLicense/index.vue
new file mode 100644
index 0000000..c72f288
--- /dev/null
+++ b/components/page/diyComponents/ICPLicense/index.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
+ {{ params.text }}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/page/diyComponents/article/index.vue b/components/page/diyComponents/article/index.vue
new file mode 100644
index 0000000..c67788d
--- /dev/null
+++ b/components/page/diyComponents/article/index.vue
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+ {{ item.show_views }}次浏览
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+ {{ item.show_views }}次浏览
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/banner/index.vue b/components/page/diyComponents/banner/index.vue
new file mode 100644
index 0000000..bc82895
--- /dev/null
+++ b/components/page/diyComponents/banner/index.vue
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/bargain/index.vue b/components/page/diyComponents/bargain/index.vue
new file mode 100644
index 0000000..74a4916
--- /dev/null
+++ b/components/page/diyComponents/bargain/index.vue
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+
+
+
+
+
+
+
+ {{ goods.helpsCount }}人正在砍价
+
+
+
+
+ ¥{{ goods.original_price }}
+
+
+
+ 最低¥
+ {{ goods.floor_price }}
+
+
+
+
+ 立即参加
+
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/blank/index.vue b/components/page/diyComponents/blank/index.vue
new file mode 100644
index 0000000..1ae7bed
--- /dev/null
+++ b/components/page/diyComponents/blank/index.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/coupon/index.vue b/components/page/diyComponents/coupon/index.vue
new file mode 100644
index 0000000..771f577
--- /dev/null
+++ b/components/page/diyComponents/coupon/index.vue
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+
+
+
+ ¥
+ {{ dataItem.reduce_price }}
+
+ {{ dataItem.discount }}折
+
+
+ 满{{ dataItem.min_price }}元可用
+
+
+
+
+ 立即
+ 领取
+
+ {{ dataItem.state.text }}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/page/diyComponents/empty.vue b/components/page/diyComponents/empty.vue
new file mode 100644
index 0000000..706e173
--- /dev/null
+++ b/components/page/diyComponents/empty.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/goods/index.vue b/components/page/diyComponents/goods/index.vue
new file mode 100644
index 0000000..ca35318
--- /dev/null
+++ b/components/page/diyComponents/goods/index.vue
@@ -0,0 +1,257 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ dataItem.goods_name }}
+
+
+
+
+ {{ dataItem.selling_point }}
+
+
+
+ 已售{{ dataItem.goods_sales }}件
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ dataItem.goods_name }}
+
+
+
+ ¥{{ dataItem.goods_price_min }}
+ ¥{{ dataItem.line_price_min }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/groupon/index.vue b/components/page/diyComponents/groupon/index.vue
new file mode 100644
index 0000000..d5f4263
--- /dev/null
+++ b/components/page/diyComponents/groupon/index.vue
@@ -0,0 +1,221 @@
+
+
+
+
+
+
+
+
+ {{ ActiveTypeEnum[goods.active_type].name2 }}
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/page/diyComponents/guide/index.vue b/components/page/diyComponents/guide/index.vue
new file mode 100644
index 0000000..e46ca13
--- /dev/null
+++ b/components/page/diyComponents/guide/index.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/hotZone/index.vue b/components/page/diyComponents/hotZone/index.vue
new file mode 100644
index 0000000..ef60413
--- /dev/null
+++ b/components/page/diyComponents/hotZone/index.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/image/index.vue b/components/page/diyComponents/image/index.vue
new file mode 100644
index 0000000..d44b449
--- /dev/null
+++ b/components/page/diyComponents/image/index.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/mixin.js b/components/page/diyComponents/mixin.js
new file mode 100644
index 0000000..99fbfd9
--- /dev/null
+++ b/components/page/diyComponents/mixin.js
@@ -0,0 +1,52 @@
+import { urlDecode } from '@/utils/util'
+
+export default {
+ data() {
+ return {}
+ },
+ methods: {
+
+ /**
+ * link对象点击事件
+ * 支持tabBar页面
+ */
+ onLink(linkObj) {
+ if (!linkObj) return false
+ // 跳转到指定页面
+ if (linkObj.type === 'PAGE') {
+ this.$navTo(linkObj.param.path, linkObj.param.query)
+ }
+ // 跳转到自定义路径
+ if (linkObj.type === 'CUSTOM') {
+ this.$navTo(linkObj.param.path, urlDecode(linkObj.param.queryStr))
+ }
+ // 跳转到微信小程序
+ // #ifdef MP-WEIXIN
+ if (linkObj.type === 'MP-WEIXIN') {
+ uni.navigateToMiniProgram({
+ appId: linkObj.param.appId,
+ path: linkObj.param.path
+ })
+ }
+ // #endif
+ // 跳转到H5外部链接
+ if (linkObj.type === 'URL') {
+ // #ifdef H5
+ window.open(linkObj.param.url)
+ // #endif
+ // #ifdef APP-PLUS
+ plus.runtime.openWeb(linkObj.param.url)
+ // #endif
+ // #ifdef MP
+ uni.setClipboardData({
+ data: linkObj.param.url,
+ success: () => this.$toast('链接已复制'),
+ fail: ({ errMsg }) => this.$toast('复制失败 ' + errMsg)
+ })
+ // #endif
+ }
+ return true
+ }
+ },
+
+}
\ No newline at end of file
diff --git a/components/page/diyComponents/navBar/index.vue b/components/page/diyComponents/navBar/index.vue
new file mode 100644
index 0000000..f2fdc1d
--- /dev/null
+++ b/components/page/diyComponents/navBar/index.vue
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+ {{ dataItem.text }}
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/notice/index.vue b/components/page/diyComponents/notice/index.vue
new file mode 100644
index 0000000..0fd4028
--- /dev/null
+++ b/components/page/diyComponents/notice/index.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/officialAccount/index.vue b/components/page/diyComponents/officialAccount/index.vue
new file mode 100644
index 0000000..c8f298a
--- /dev/null
+++ b/components/page/diyComponents/officialAccount/index.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/page/diyComponents/richText/index.vue b/components/page/diyComponents/richText/index.vue
new file mode 100644
index 0000000..a6a91e2
--- /dev/null
+++ b/components/page/diyComponents/richText/index.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/search/index.vue b/components/page/diyComponents/search/index.vue
new file mode 100644
index 0000000..d26b6f1
--- /dev/null
+++ b/components/page/diyComponents/search/index.vue
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+ {{ params.placeholder }}
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/service/index.vue b/components/page/diyComponents/service/index.vue
new file mode 100644
index 0000000..0426e38
--- /dev/null
+++ b/components/page/diyComponents/service/index.vue
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/page/diyComponents/sharp/index.vue b/components/page/diyComponents/sharp/index.vue
new file mode 100644
index 0000000..b010fc8
--- /dev/null
+++ b/components/page/diyComponents/sharp/index.vue
@@ -0,0 +1,251 @@
+
+
+
+
+
+
+
+
+ 限时秒杀
+
+
+ {{ data.active.sharp_modular_text }}
+
+
+
+
+
+
+
+
+ 更多
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+
+
+ ¥
+ {{ goods.seckill_price_min }}
+
+ ¥{{ goods.original_price }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/shop/index.vue b/components/page/diyComponents/shop/index.vue
new file mode 100644
index 0000000..c7b94a6
--- /dev/null
+++ b/components/page/diyComponents/shop/index.vue
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+ {{ dataItem.shop_name }}
+
+
+ 门店地址:{{ dataItem.region.province }}{{ dataItem.region.city }}{{ dataItem.region.region }}{{ dataItem.address }}
+
+
+ 联系电话:{{ dataItem.phone }}
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/special/index.vue b/components/page/diyComponents/special/index.vue
new file mode 100644
index 0000000..8a9cb5d
--- /dev/null
+++ b/components/page/diyComponents/special/index.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+ {{ dataItm.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/video/index.vue b/components/page/diyComponents/video/index.vue
new file mode 100644
index 0000000..5af2566
--- /dev/null
+++ b/components/page/diyComponents/video/index.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/page/diyComponents/window/index.vue b/components/page/diyComponents/window/index.vue
new file mode 100644
index 0000000..5fd6064
--- /dev/null
+++ b/components/page/diyComponents/window/index.vue
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/page/index.vue b/components/page/index.vue
new file mode 100644
index 0000000..fe567eb
--- /dev/null
+++ b/components/page/index.vue
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/privacy-popup/index.vue b/components/privacy-popup/index.vue
new file mode 100644
index 0000000..88f48ee
--- /dev/null
+++ b/components/privacy-popup/index.vue
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/recommended/index.vue b/components/recommended/index.vue
new file mode 100644
index 0000000..abf0c85
--- /dev/null
+++ b/components/recommended/index.vue
@@ -0,0 +1,324 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ dataItem.goods_name }}
+
+
+
+
+ {{ dataItem.selling_point }}
+
+
+
+ 已售{{ dataItem.goods_sales }}件
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ dataItem.goods_name }}
+
+
+
+ ¥{{ dataItem.goods_price_min }}
+ ¥{{ dataItem.line_price_min }}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/search/index.vue b/components/search/index.vue
new file mode 100644
index 0000000..eda02a5
--- /dev/null
+++ b/components/search/index.vue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+ {{ tips }}
+
+
+
+
+
+
+
+
diff --git a/components/select-region/select-region.vue b/components/select-region/select-region.vue
new file mode 100644
index 0000000..bc873f7
--- /dev/null
+++ b/components/select-region/select-region.vue
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+ {{ valueText ? valueText: placeholder }}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/share-sheet/index.vue b/components/share-sheet/index.vue
new file mode 100644
index 0000000..585afa9
--- /dev/null
+++ b/components/share-sheet/index.vue
@@ -0,0 +1,373 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 微信好友
+
+
+
+
+
+
+
+
+
+
+ 微信朋友圈
+
+
+
+
+
+
+
+
+ 生成海报
+
+
+
+
+
+
+
+ 复制链接
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/shortcut/index.vue b/components/shortcut/index.vue
new file mode 100644
index 0000000..1f8e99d
--- /dev/null
+++ b/components/shortcut/index.vue
@@ -0,0 +1,293 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config.js b/config.js
new file mode 100644
index 0000000..9f588f8
--- /dev/null
+++ b/config.js
@@ -0,0 +1,30 @@
+export default {
+
+ // 系统名称
+ name: "萤火商城2.0",
+
+ /**
+ * 后端api地址 (必填; 斜杠/结尾; 请确保能访问)
+ * 例如: https://www.你的域名.com/index.php?s=/api/
+ */
+ apiUrl: "https://www.你的域名.com/index.php?s=/api/",
+
+ /**
+ * 商城ID (必填)
+ * 可在超管后台-商城列表中查看
+ */
+ storeId: 10001,
+
+ /**
+ * 是否启用商城设置缓存
+ * 将减少用户端重复请求; 正式运营时请设为true, 开启后商城设置同步前端需10分钟缓存
+ */
+ enabledSettingCache: true,
+
+ /**
+ * 是否启用H5端多开
+ * 启用后将通过获取子域名中的ID作为storeId; 例如域名是 "shop10001.baidu.com", 那么storeId就是10001
+ */
+ enabledH5Multi: true,
+
+}
diff --git a/core/app.js b/core/app.js
new file mode 100644
index 0000000..49b80cf
--- /dev/null
+++ b/core/app.js
@@ -0,0 +1,255 @@
+import store from '@/store'
+import * as util from '@/utils/util'
+import { paginate } from '@/common/constant'
+import Config from './config'
+
+/**
+ * 显示成功提示框
+ */
+export const showSuccess = (msg, callback) => {
+ uni.showToast({
+ title: msg,
+ icon: 'success',
+ // #ifndef MP-ALIPAY
+ mask: true,
+ // #endif
+ duration: 1500,
+ success() {
+ callback && callback()
+ }
+ })
+}
+
+/**
+ * 显示失败提示框
+ */
+export const showError = (msg, callback) => {
+ uni.showModal({
+ title: '友情提示',
+ content: msg,
+ showCancel: false,
+ success(res) {
+ callback && callback()
+ }
+ })
+}
+
+/**
+ * 显示纯文字提示框
+ */
+export const showToast = (msg, duration = 1500, mask = true) => {
+ uni.showToast({
+ title: msg, // 提示的内容
+ icon: 'none',
+ // #ifndef MP-ALIPAY
+ mask, // 是否显示透明蒙层,防止触摸穿透 (支付宝小程序不支持)
+ // #endif
+ duration // 提示的延迟时间,单位毫秒,默认:1500
+ })
+}
+
+/**
+ * tabBar页面路径列表 (用于链接跳转时判断)
+ * tabBarLinks为常量, 无需修改
+ */
+export const getTabBarLinks = () => {
+ const tabBarLinks = [
+ 'pages/index/index',
+ 'pages/category/index',
+ 'pages/cart/index',
+ 'pages/user/index'
+ ]
+ return tabBarLinks
+}
+
+/**
+ * 生成完整的H5地址 [带参数]
+ * @param {string} baseUrl H5访问地址
+ * @param {string} path 页面路径
+ * @param {object} params 页面参数
+ * @return {string}
+ */
+export const buildUrL = (h5Url, path, params) => {
+ let complete = h5Url
+ if (!util.isEmpty(path)) {
+ complete += '#/' + path
+ const shareParamsStr = getShareUrlParams(params)
+ if (!util.isEmpty(shareParamsStr)) {
+ complete += '?' + shareParamsStr
+ }
+ }
+ return complete
+}
+
+/**
+ * 生成转发的url参数(string格式)
+ * @param {object} params
+ * @return {string}
+ */
+export const getShareUrlParams = params => {
+ return util.urlEncode(getShareParams(params))
+}
+
+/**
+ * 生成转发的url参数(object格式)
+ * @param {object} params
+ * @return {object}
+ */
+export const getShareParams = params => {
+ return {
+ refereeId: store.getters.userId, // 推荐人ID
+ ...params
+ }
+}
+
+/**
+ * 跳转到指定页面url
+ * 支持tabBar页面
+ * @param {string} url 页面路径
+ * @param {object} query 页面参数
+ * @param {string} modo 跳转类型(默认navigateTo)
+ */
+export const navTo = (url, query = {}, modo = 'navigateTo') => {
+ if (!url || url.length == 0) {
+ return false
+ }
+ // tabBar页面, 使用switchTab
+ if (util.inArray(url, getTabBarLinks())) {
+ uni.switchTab({
+ url: `/${url}`
+ })
+ return true
+ }
+ // 生成query参数
+ const queryStr = !util.isEmpty(query) ? '?' + util.urlEncode(query) : ''
+ // 普通页面, 使用navigateTo
+ modo === 'navigateTo' && uni.navigateTo({
+ url: `/${url}${queryStr}`
+ })
+ // 特殊指定, 使用redirectTo
+ modo === 'redirectTo' && uni.redirectTo({
+ url: `/${url}${queryStr}`
+ })
+ return true
+}
+
+/**
+ * 获取当前页面数据
+ * @param {object}
+ */
+export const getCurrentPage = () => {
+ const pages = getCurrentPages()
+ const pathInfo = pages[pages.length - 1].$page.fullPath.split('?')
+ return { path: pathInfo[0].slice(1), query: util.urlDecode(pathInfo[1]) }
+}
+
+/**
+ * 获取购物车商品总数量
+ * @param {*} value
+ */
+export const getCartTotalNum = (value) => {
+ const cartTotal = uni.getStorageSync('cartTotalNum') || 0
+ return checkLogin() ? cartTotal : 0
+}
+
+/**
+ * 记录购物车商品总数量
+ * @param {*} value
+ */
+export const setCartTotalNum = (value) => {
+ uni.setStorageSync('cartTotalNum', Number(value))
+}
+
+/**
+ * 设置购物车tabbar的角标
+ * 该方法只能在tabbar页面中调用, 其他页面调用会报错
+ */
+export const setCartTabBadge = () => {
+ const cartTabbarIndex = 2
+ const cartTotal = getCartTotalNum()
+ if (cartTotal > 0) {
+ uni.setTabBarBadge({
+ index: cartTabbarIndex,
+ text: `${cartTotal}`
+ })
+ } else {
+ uni.removeTabBarBadge({
+ index: cartTabbarIndex
+ })
+ }
+ return
+}
+
+/**
+ * 验证是否已登录
+ */
+export const checkLogin = () => {
+ return !!store.getters.userId
+}
+
+/**
+ * 加载更多列表数据
+ * @param {Object} resList 新列表数据
+ * @param {Object} oldList 旧列表数据
+ * @param {int} pageNo 当前页码
+ */
+export const getEmptyPaginateObj = () => {
+ return util.cloneObj(paginate)
+}
+
+/**
+ * 加载更多列表数据
+ * @param {Object} resList 新列表数据
+ * @param {Object} oldList 旧列表数据
+ * @param {int} pageNo 当前页码
+ */
+export const getMoreListData = (resList, oldList, pageNo) => {
+ // 如果是第一页需手动制空列表
+ if (pageNo == 1) oldList.data = []
+ // 合并新数据
+ return oldList.data.concat(resList.data)
+}
+
+/**
+ * scene解码
+ * 用于解码微信小程序二维码参数,并返回对象
+ */
+export const sceneDecode = (str) => {
+ if (str === undefined)
+ return {}
+ const data = {}
+ const params = decodeURIComponent(str).split(',')
+ for (const i in params) {
+ const val = params[i].split(':');
+ val.length > 0 && val[0] && (data[val[0]] = val[1] || null)
+ }
+ return data
+}
+
+/**
+ * 获取二维码场景值(scene)
+ */
+export const getSceneData = query => {
+ return util.hasOwnProperty(query, 'scene') ? sceneDecode(query.scene) : {}
+}
+
+/**
+ * 验证指定的功能模块是否开启
+ */
+export const checkModuleKey = moduleKey => {
+ return util.inArray(moduleKey, store.getters.modules)
+}
+
+/**
+ * 验证指定的功能模块是否开启(批量)
+ */
+export const checkModules = moduleKeys => {
+ return moduleKeys.filter(val => checkModuleKey(val)).length > 0
+}
+
+/**
+ * 验证指定的功能模块是否开启(批量)
+ */
+export const filterModule = array => {
+ return array.filter(item => !item.moduleKey || checkModuleKey(item.moduleKey))
+}
diff --git a/core/bootstrap.js b/core/bootstrap.js
new file mode 100644
index 0000000..7cdce44
--- /dev/null
+++ b/core/bootstrap.js
@@ -0,0 +1,20 @@
+import store from '@/store'
+import storage from '@/utils/storage'
+import Config from '@/core/config'
+import platform from '@/core/platform'
+import { ACCESS_TOKEN, USER_ID, REFEREE_ID, APP_THEME } from '@/store/mutation-types'
+
+export default function YoShop2() {
+ // 当前的商城ID
+ store.commit('SET_STORE_ID', Config.getStoreId())
+ // 当前运行的终端
+ store.commit('SET_PLATFORM', platform)
+ // 用户认证token
+ store.commit('SET_TOKEN', storage.get(ACCESS_TOKEN))
+ // 当前用户ID
+ store.commit('SET_USER_ID', storage.get(USER_ID))
+ // 当前推荐人ID
+ store.commit('SET_REFEREE_ID', storage.get(REFEREE_ID))
+ // 全局自定义主题
+ store.commit('SET_APP_THEME', storage.get(APP_THEME))
+}
diff --git a/core/config/defaultConfig.js b/core/config/defaultConfig.js
new file mode 100644
index 0000000..133bb1f
--- /dev/null
+++ b/core/config/defaultConfig.js
@@ -0,0 +1,43 @@
+// ** 本文件是config.js的默认数据 (请勿修改本文件中的内容)
+// ** 如需修改配置请移步到根目录的config.js文件
+export default {
+
+ // 系统名称
+ name: "萤火商城2.0",
+
+ /**
+ * 后端api地址 (必填; 斜杠/结尾; 请确保能访问)
+ * 例如: https://www.你的域名.com/index.php?s=/api/
+ */
+ apiUrl: "./index.php?s=/api/",
+
+ /**
+ * 商城ID (必填)
+ * 可在超管后台-商城列表中查看
+ */
+ storeId: 10001,
+
+ /**
+ * 是否启用商城设置缓存
+ * 将减少用户端重复请求; 正式运营时请设为true, 开启后商城设置同步前端需10分钟缓存
+ */
+ enabledSettingCache: true,
+
+ /**
+ * 是否开启APP端的微信分享功能
+ * 如果开启, 需配置manifest.json中 APP模块配置 -> Share(分享) -> 微信分享
+ */
+ enabledAppShareWeixin: false,
+
+ /**
+ * 是否启用H5端多开
+ * 启用后将通过获取子域名中的ID作为storeId; 例如域名是 "shop10001.baidu.com", 那么storeId就是10001
+ */
+ enabledH5Multi: false,
+
+ /**
+ * 获取子域名ID的正则
+ */
+ domainIdRegex: /shop[\-]?(\d+)\./
+
+}
diff --git a/core/config/index.js b/core/config/index.js
new file mode 100644
index 0000000..7df5f68
--- /dev/null
+++ b/core/config/index.js
@@ -0,0 +1,54 @@
+import config from '@/config.js'
+import defaultConfig from './defaultConfig.js'
+
+// 合并用户配置和默认配置
+const options = Object.assign({}, defaultConfig, config)
+
+/**
+ * 配置文件工具类
+ * @module Config
+ * mix: 如需在项目中获取配置项, 请使用本工具类的方法, 不要直接import根目录的config.js
+ */
+export default {
+
+ /**
+ * 获取全部配置
+ */
+ all() {
+ return options
+ },
+
+ /**
+ * 获取指定配置
+ * @param {string} key
+ * @param {mixed} def
+ */
+ get(key, def = undefined) {
+ if (options.hasOwnProperty(key)) {
+ return options[key]
+ }
+ console.error(`检测到不存在的配置项: ${key}`)
+ return def
+ },
+
+ /**
+ * 获取当前商城ID
+ */
+ getStoreId() {
+
+ // #ifdef H5
+ // 判断是否启用H5端多开
+ // 启用后将通过获取子域名中的ID作为storeId
+ if (this.get('enabledH5Multi')) {
+ const domain = window.location.hostname
+ const regex = this.get('domainIdRegex')
+ if (domain.match(regex)) {
+ const storeId = regex.exec(domain)[1].trim()
+ return storeId
+ }
+ }
+ // #endif
+ return this.get('storeId')
+ },
+
+}
diff --git a/core/mixins/app.js b/core/mixins/app.js
new file mode 100644
index 0000000..0f0322f
--- /dev/null
+++ b/core/mixins/app.js
@@ -0,0 +1,31 @@
+ import { computed } from 'vue'
+ import { useStore, mapGetters } from 'vuex'
+ import store from '@/store/index'
+ import platform from '@/core/platform'
+
+ // 字符串驼峰转中划线
+ const formatToLine = value => {
+ return value.replace(/([A-Z])/g, '-$1').toLowerCase()
+ }
+
+ // 主题样式 (因小程序端不支持styleObject语法,所以需要转换成字符串)
+ const appTheme2Str = appTheme => {
+ let str = ''
+ for (const index in appTheme) {
+ const name = formatToLine(index)
+ str += `--${name}:${appTheme[index]};`
+ }
+ return str
+ }
+
+ export default {
+ data() {
+ return {
+ platform
+ }
+ },
+ computed: {
+ appTheme: () => store.getters.appTheme,
+ appThemeStyle: () => appTheme2Str(store.getters.appTheme)
+ }
+ }
\ No newline at end of file
diff --git a/core/mixins/wxofficial.js b/core/mixins/wxofficial.js
new file mode 100644
index 0000000..9da94a9
--- /dev/null
+++ b/core/mixins/wxofficial.js
@@ -0,0 +1,50 @@
+import { isWeixinOfficial } from '@/core/platform'
+import WxofficialSettingModel from '@/common/model/wxofficial/Setting'
+
+export default {
+ data() {
+ return {
+ // 微信公众号链接分享卡片内容
+ wxofficialShareData: undefined
+ }
+ },
+
+ /**
+ * 生命周期函数--监听页面隐藏
+ */
+ onShow() {
+ // 设置微信公众号链接分享卡片内容
+ if (isWeixinOfficial && this.wxofficialShareData) {
+ WxofficialSettingModel.updateShareData(this.wxofficialShareData)
+ }
+ },
+
+ /**
+ * 生命周期函数--监听页面隐藏
+ */
+ onHide() {
+ // 将微信分享卡片内容还原
+ isWeixinOfficial && WxofficialSettingModel.setGlobalShareCard(true)
+ },
+
+ /**
+ * 生命周期函数--监听页面卸载
+ */
+ onUnload() {
+ // 将微信分享卡片内容还原
+ isWeixinOfficial && WxofficialSettingModel.setGlobalShareCard(true)
+ },
+
+ methods: {
+
+ // 更新分享卡片内容
+ updateShareCardData(param) {
+ if (isWeixinOfficial) {
+ this.wxofficialShareData = param
+ WxofficialSettingModel.updateShareData(this.wxofficialShareData)
+ }
+ }
+
+ },
+
+}
diff --git a/core/payment/alipay.js b/core/payment/alipay.js
new file mode 100644
index 0000000..3bdc981
--- /dev/null
+++ b/core/payment/alipay.js
@@ -0,0 +1,116 @@
+import platform from '@/core/platform'
+import ClientEnum from '@/common/enum/Client'
+import { PayMethodEnum } from '@/common/enum/payment'
+
+/**
+ * 发起支付请求 (用于H5)
+ * @param {Object} option 参数
+ */
+const paymentAsH5 = option => {
+ const options = { formHtml: '', ...option }
+ // 跳转到支付宝支付页
+ return new Promise((resolve, reject) => {
+ // console.log(options.formHtml)
+ if (options.formHtml) {
+ const div = document.createElement('div')
+ div.innerHTML = options.formHtml
+ document.body.appendChild(div)
+ document.forms[0].submit()
+ }
+ })
+}
+
+/**
+ * 发起支付请求 (用于APP)
+ * @param {Object} option 参数
+ */
+const paymentAsApp = options => {
+ return new Promise((resolve, reject) => {
+ uni.requestPayment({
+ provider: 'alipay',
+ orderInfo: options.orderInfo,
+ success(res) {
+ // isRequireQuery 是否需要主动查单
+ // outTradeNo 交易订单号
+ const option = {
+ isRequireQuery: true,
+ outTradeNo: options.out_trade_no,
+ method: 'alipay'
+ }
+ resolve({ res, option })
+ },
+ fail: res => reject(res)
+ })
+ })
+}
+
+/**
+ * 发起支付请求 (用于支付宝小程序)
+ * @param {Object} option 参数
+ */
+const paymentAsMpAlipayApp = options => {
+ return new Promise((resolve, reject) => {
+ uni.requestPayment({
+ provider: 'alipay',
+ orderInfo: options.orderInfo,
+ success(res) {
+ // isRequireQuery 是否需要主动查单
+ // outTradeNo 交易订单号
+ const option = {
+ isRequireQuery: true,
+ outTradeNo: options.out_trade_no,
+ method: 'alipay'
+ }
+ resolve({ res, option })
+ },
+ fail: res => reject(res)
+ })
+ })
+}
+
+// 获取支付完成后跳转的url
+// #ifdef H5
+const returnUrl = () => {
+ return window.location.href
+}
+// #endif
+
+/**
+ * 统一下单API
+ */
+export const payment = (option) => {
+ const events = {
+ [ClientEnum.H5.value]: paymentAsH5,
+ [ClientEnum.APP.value]: paymentAsApp,
+ [ClientEnum.MP_ALIPAY.value]: paymentAsMpAlipayApp
+ }
+ return events[platform](option)
+}
+
+/**
+ * 统一下单API需要的扩展数据
+ */
+export const extraAsUnify = () => {
+ const extra = {}
+ // #ifdef H5
+ extra.returnUrl = returnUrl()
+ // #endif
+ return extra
+}
+
+// H5端支付宝支付下单时的数据
+// 用于从支付宝支付页返回到收银台页面后拿到下单数据
+// #ifdef H5
+export const performance = () => {
+ const query = getCurrentQuery()
+ if (query.method && query.method === 'alipay.trade.wap.pay.return') {
+ return { method: PayMethodEnum.ALIPAY.value, outTradeNo: query.out_trade_no }
+ }
+ return null
+}
+
+const getCurrentQuery = () => {
+ const pages = getCurrentPages()
+ return pages[pages.length - 1].$route.query
+}
+// #endif
diff --git a/core/payment/index.js b/core/payment/index.js
new file mode 100644
index 0000000..1dee998
--- /dev/null
+++ b/core/payment/index.js
@@ -0,0 +1,4 @@
+import * as Alipay from './alipay'
+import * as Wechat from './wechat'
+
+export { Alipay, Wechat }
diff --git a/core/payment/wechat.js b/core/payment/wechat.js
new file mode 100644
index 0000000..5e07228
--- /dev/null
+++ b/core/payment/wechat.js
@@ -0,0 +1,180 @@
+import platform from '@/core/platform'
+import storage from '@/utils/storage'
+import ClientEnum from '@/common/enum/Client'
+import { PayMethodEnum } from '@/common/enum/payment'
+
+/**
+ * 发起支付请求 (用于微信小程序)
+ * @param {Object} option 参数
+ */
+const paymentAsWxMp = option => {
+ const options = {
+ timeStamp: '',
+ nonceStr: '',
+ package: '',
+ signType: '',
+ paySign: '',
+ ...option
+ }
+ return new Promise((resolve, reject) => {
+ uni.requestPayment({
+ provider: 'wxpay',
+ timeStamp: options.timeStamp,
+ nonceStr: options.nonceStr,
+ package: options.package,
+ signType: options.signType,
+ paySign: options.paySign,
+ success(res) {
+ const option = {
+ isRequireQuery: true, // 是否需要主动查单
+ outTradeNo: options.out_trade_no, // 交易订单号
+ method: 'wechat'
+ }
+ resolve({ res, option })
+ },
+ fail: res => reject(res)
+ })
+ })
+}
+
+/**
+ * 发起支付请求 (用于H5)
+ * @param {Object} option 参数
+ */
+const paymentAsH5 = option => {
+ const options = { orderKey: null, mweb_url: '', h5_url: '', ...option }
+ // 记录下单的信息
+ storage.set('tempUnifyData_' + options.orderKey, {
+ method: PayMethodEnum.WECHAT.value,
+ outTradeNo: options.out_trade_no
+ }, 60 * 60)
+ // 跳转到微信支付页
+ return new Promise((resolve, reject) => {
+ const url = options.mweb_url || options.h5_url
+ if (url) {
+ window.location.href = url
+ }
+ })
+}
+
+/**
+ * 发起支付请求 (用于微信公众号)
+ * @param {Object} option 参数
+ */
+const paymentAsOfficial = option => {
+ const options = {
+ appId: '',
+ timeStamp: '',
+ nonceStr: '',
+ package: '',
+ signType: '',
+ paySign: '',
+ ...option
+ }
+ return onBridgeReady(options)
+ if (platform === ClientEnum.WXOFFICIAL.value) {
+ if (typeof WeixinJSBridge != 'undefined') {
+ return onBridgeReady(options)
+ }
+ if (document.addEventListener) {
+ document.addEventListener('WeixinJSBridgeReady', () => onBridgeReady(options), false)
+ } else if (document.attachEvent) {
+ document.attachEvent('WeixinJSBridgeReady', () => onBridgeReady(options))
+ document.attachEvent('onWeixinJSBridgeReady', () => onBridgeReady(options))
+ }
+ }
+ return new Promise((resolve, reject) => {
+ reject({ message: '当前不支持WeixinJSBridge11' })
+ })
+}
+
+/**
+ * 发起支付请求 (用于APP)
+ * @param {Object} option 参数
+ */
+const paymentAsApp = options => {
+ return new Promise((resolve, reject) => {
+ uni.requestPayment({
+ provider: 'wxpay',
+ orderInfo: {
+ partnerid: options.partnerid,
+ appid: options.appid,
+ package: 'Sign=WXPay',
+ noncestr: options.noncestr,
+ sign: options.sign,
+ prepayid: options.prepayid,
+ timestamp: options.timestamp
+ },
+ success(res) {
+ // isRequireQuery 是否需要主动查单
+ // outTradeNo 交易订单号
+ resolve({ res, option: { isRequireQuery: true, outTradeNo: options.out_trade_no, method: 'wechat' } })
+ },
+ fail: res => reject(res)
+ })
+ })
+}
+
+// 微信公众号调用微信支付
+// #ifdef H5
+const onBridgeReady = (options) => {
+ return new Promise((resolve, reject) => {
+ WeixinJSBridge.invoke(
+ 'getBrandWCPayRequest', {
+ appId: options.appId,
+ timeStamp: options.timeStamp,
+ nonceStr: options.nonceStr,
+ package: options.package,
+ signType: options.signType,
+ paySign: options.paySign,
+ },
+ res => {
+ if (res.err_msg == "get_brand_wcpay_request:ok") {
+ const option = {
+ isRequireQuery: true, // 是否需要主动查单
+ outTradeNo: options.out_trade_no, // 交易订单号
+ method: 'wechat'
+ }
+ resolve({ res, option })
+ } else {
+ reject(res)
+ }
+ })
+ })
+}
+// #endif
+
+/**
+ * 统一下单API
+ */
+export const payment = (option) => {
+ const events = {
+ [ClientEnum.H5.value]: paymentAsH5,
+ [ClientEnum.MP_WEIXIN.value]: paymentAsWxMp,
+ [ClientEnum.WXOFFICIAL.value]: paymentAsOfficial,
+ [ClientEnum.APP.value]: paymentAsApp
+ }
+ return events[platform](option)
+}
+
+/**
+ * 统一下单API需要的扩展数据
+ */
+export const extraAsUnify = () => {
+ return {}
+}
+
+// H5端微信支付下单时的数据
+// 用于从微信支付页返回到收银台页面后拿到下单数据
+// #ifdef H5
+export const performance = (orderKey) => {
+ if (window.performance && window.performance.navigation.type == 2) {
+ const tempUnifyData = storage.get('tempUnifyData_' + orderKey)
+ if (tempUnifyData) {
+ storage.remove('tempUnifyData_' + orderKey)
+ return tempUnifyData
+ }
+ }
+ return null
+}
+// #endif
diff --git a/core/platform.js b/core/platform.js
new file mode 100644
index 0000000..1137472
--- /dev/null
+++ b/core/platform.js
@@ -0,0 +1,64 @@
+/**
+ * 获取当前运行的客户端(APP H5 小程序)
+ * https://uniapp.dcloud.io/platform
+ */
+const getPlatform = () => {
+ // #ifdef APP-PLUS
+ const platform = 'APP'
+ // #endif
+ // #ifdef APP-PLUS-NVUE
+ const platform = 'APP'
+ // #endif
+ // #ifdef H5
+ const platform = weixinOfficial() ? 'WXOFFICIAL' : 'H5'
+ // #endif
+ // #ifdef MP-WEIXIN
+ const platform = 'MP-WEIXIN'
+ // #endif
+ // #ifdef MP-ALIPAY
+ const platform = 'MP-ALIPAY'
+ // #endif
+ // #ifdef MP-BAIDU
+ const platform = 'MP-BAIDU'
+ // #endif
+ // #ifdef MP-TOUTIAO
+ const platform = 'MP-TOUTIAO'
+ // #endif
+ // #ifdef MP-LARK
+ const platform = 'MP-LARK'
+ // #endif
+ // #ifdef MP-QQ
+ const platform = 'MP-QQ'
+ // #endif
+ // #ifdef MP-KUAISHOU
+ const platform = 'MP-KUAISHOU'
+ // #endif
+ // #ifdef MP-360
+ const platform = 'MP-360'
+ // #endif
+ // #ifdef QUICKAPP-WEBVIEW
+ const platform = 'QUICKAPP-WEBVIEW'
+ // #endif
+ return platform
+}
+
+// 是否为微信公众号端
+const weixinOfficial = () => {
+ // #ifdef H5
+ const ua = window.navigator.userAgent.toLowerCase()
+ return String(ua.match(/MicroMessenger/i)) === 'micromessenger'
+ // #endif
+ return false
+}
+
+const platfrom = getPlatform()
+
+export const isH5 = platfrom === 'H5'
+export const isApp = platfrom === 'APP'
+export const isMpWeixin = platfrom === 'MP-WEIXIN'
+
+// 是否为微信公众号端
+// 相当于H5端运行在微信内置浏览器, 但是需要使用微信的jssdk所以要单独区分
+export const isWeixinOfficial = platfrom === 'WXOFFICIAL'
+
+export default platfrom
diff --git a/core/wxofficial.js b/core/wxofficial.js
new file mode 100644
index 0000000..a06f1bd
--- /dev/null
+++ b/core/wxofficial.js
@@ -0,0 +1,50 @@
+// #ifdef H5
+import * as jWeixin from 'weixin-js-sdk'
+import { showError } from '@/core/app'
+import { isWeixinOfficial } from '@/core/platform'
+import wxofficialApi from '@/api/wxofficial'
+import WxofficialSettingModel from '@/common/model/wxofficial/Setting'
+
+/**
+ * 注入微信jssdk配置信息
+ */
+const setConfig = async () => {
+ // 获取当前页面url (不包含#及其后面部分)
+ const url = window.location.href.split('#')[0]
+ // 请求后端获取jssdkConfig
+ const response = await wxofficialApi.jssdkConfig(url)
+ // 注入配置信息
+ jWeixin.config(response.data.config)
+ // 提示错误
+ jWeixin.error(res => {
+ console.error('jWeixin.error', res)
+ showError(`微信链接分享配置错误:${res.errMsg}`)
+ })
+}
+
+/**
+ * 设置分享卡片的内容
+ */
+const updateShareData = async (shareData) => {
+ // 是否开启微信公众号链接分享卡片
+ const enabled = await WxofficialSettingModel.isWxofficialLinkShareCard()
+ if (!isWeixinOfficial || !enabled) {
+ return
+ }
+ // 整理分享数据
+ // const shareData = { title, desc, link, imgUrl }
+ shareData.link = shareData.link || window.location.href
+ jWeixin.ready(() => {
+ console.log('jWeixin.ready', shareData)
+ jWeixin.updateAppMessageShareData(shareData)
+ jWeixin.updateTimelineShareData(shareData)
+ // jWeixin.onMenuShareAppMessage(shareData)
+ // jWeixin.onMenuShareTimeline(shareData)
+ })
+}
+
+export default {
+ setConfig,
+ updateShareData
+}
+// #endif
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..2269a69
--- /dev/null
+++ b/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..424ceda
--- /dev/null
+++ b/main.js
@@ -0,0 +1,30 @@
+import App from './App'
+import { createSSRApp } from 'vue'
+import store from './store'
+import bootstrap from './core/bootstrap'
+import mixin from './core/mixins/app'
+import uView from './uni_modules/vk-uview-ui'
+import { navTo, showToast, showSuccess, showError, getShareUrlParams, checkModuleKey, checkModules } from './core/app'
+
+// 不能修改createApp方法名,不能修改从Vue中导入的createSSRApp
+export function createApp() {
+ // 创建应用实例
+ const app = createSSRApp({ ...App, store, created: bootstrap })
+
+ // 挂载全局函数
+ app.config.globalProperties.$toast = showToast
+ app.config.globalProperties.$success = showSuccess
+ app.config.globalProperties.$error = showError
+ app.config.globalProperties.$navTo = navTo
+ app.config.globalProperties.$getShareUrlParams = getShareUrlParams
+ app.config.globalProperties.$checkModule = checkModuleKey
+ app.config.globalProperties.$checkModules = checkModules
+
+ // 使用 uView UI
+ app.use(uView)
+
+ // 全局mixin
+ app.mixin(mixin)
+
+ return { app }
+}
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..b03174b
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,166 @@
+{
+ "name" : "萤火商城2.0",
+ "appid" : "",
+ "description" : "萤火商城V2.0,是全新推出的一款轻量级、高性能、前后端分离的电商系统,让您快速搭建个性化独立商城",
+ "versionName" : "2.3.12",
+ "versionCode" : 235,
+ "transformPx" : false,
+ /* 5+App特有相关 */
+ "app-plus" : {
+ "usingComponents" : true,
+ "nvueCompiler" : "uni-app",
+ "compilerVersion" : 3,
+ "splashscreen" : {
+ "alwaysShowBeforeRender" : true,
+ "waiting" : true,
+ "autoclose" : true,
+ "delay" : 0
+ },
+ /* 模块配置 */
+ "modules" : {
+ "Payment" : {},
+ "Share" : {},
+ "OAuth" : {}
+ },
+ /* 应用发布信息 */
+ "distribute" : {
+ /* android打包配置 */
+ "android" : {
+ "permissions" : [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "autoSdkPermissions" : true,
+ "permissionExternalStorage" : {
+ "request" : "once",
+ "prompt" : "应用保存运行状态等信息,需要获取读写手机存储(系统提示为访问设备上的照片、媒体内容和文件)权限,请允许。"
+ },
+ "permissionPhoneState" : {
+ "request" : "none",
+ "prompt" : "为保证您正常、安全地使用,需要获取设备识别码(部分手机提示为获取手机号码)使用权限,请允许。"
+ },
+ "abiFilters" : [ "armeabi-v7a" ]
+ },
+ /* ios打包配置 */
+ "ios" : {
+ "idfa" : true,
+ "dSYMs" : false
+ },
+ /* SDK配置 */
+ "sdkConfigs" : {
+ "ad" : {},
+ "geolocation" : {},
+ "oauth" : {},
+ "payment" : {
+ "weixin" : {
+ "__platform__" : [ "android" ],
+ "appid" : "",
+ "UniversalLinks" : ""
+ },
+ "alipay" : {
+ "__platform__" : [ "android" ]
+ }
+ },
+ "share" : {
+ "weixin" : {
+ "appid" : "",
+ "UniversalLinks" : ""
+ }
+ }
+ },
+ "splashscreen" : {
+ "iosStyle" : "common"
+ },
+ "icons" : {}
+ }
+ },
+ /* 快应用特有相关 */
+ "quickapp" : {},
+ /* 小程序特有相关 */
+ "mp-weixin" : {
+ "appid" : "",
+ "setting" : {
+ // 是否检查安全域名和 TLS 版本
+ "urlCheck" : true,
+ // es6转es5
+ "es6" : false,
+ // 上传代码时自动压缩
+ "minified" : true,
+ // 调试器 wxml面板展示 shadow-root
+ "showShadowRootInWxmlPanel" : true,
+ // 上传代码时是否自动压缩样式文件
+ "minifyWXSS" : true,
+ // 上传代码时是否自动压缩wxml文件
+ // 因uniappp构建出来的wxml本身就是压缩好的, 如果再用微信开发工具压缩一次的话, 有可能会破坏到文件, 所以此处设为false
+ "minifyWXML" : false
+ },
+ "usingComponents" : true,
+ "lazyCodeLoading" : "requiredComponents",
+ "permission" : {
+ "scope.userLocation" : {
+ "desc" : "你的位置信息将用于为您提供更合适您的服务"
+ }
+ },
+ "requiredPrivateInfos" : [ "chooseAddress" ]
+ },
+ "mp-alipay" : {
+ "usingComponents" : true
+ },
+ "mp-baidu" : {
+ "usingComponents" : true
+ },
+ "mp-toutiao" : {
+ "usingComponents" : true
+ },
+ "uniStatistics" : {
+ "enable" : false
+ },
+ "h5" : {
+ "sdkConfigs" : {
+ "maps" : {
+ "qqmap" : {
+ "key" : "ZWEBZ-R7N3U-BJSVH-4TCR3-66MDQ-S3FDJ"
+ }
+ }
+ },
+ "template" : "template.h5.html",
+ "optimization" : {
+ "treeShaking" : {
+ "enable" : false
+ }
+ },
+ "router" : {
+ "mode" : "hash",
+ "base" : "./"
+ },
+ "devServer" : {
+ "port" : 8020
+ },
+ "title" : ""
+ },
+ "vueVersion" : "3",
+ "locale" : "zh-Hans"
+}
+/* ios打包配置 *//* SDK配置 */
+
diff --git a/node_modules/.gitignore b/node_modules/.gitignore
new file mode 100644
index 0000000..0f61dba
--- /dev/null
+++ b/node_modules/.gitignore
@@ -0,0 +1 @@
+/.vite
diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
new file mode 100644
index 0000000..83f2e16
--- /dev/null
+++ b/node_modules/.package-lock.json
@@ -0,0 +1,12 @@
+{
+ "name": "@hbuilder/yoshop2-pro",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "node_modules/weixin-js-sdk": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/weixin-js-sdk/-/weixin-js-sdk-1.6.0.tgz",
+ "integrity": "sha512-3IYQH7aalJGFJrwdT3epvTdR1MboMiH7vIZ5BRL2eYOJ12BNah7csoMkmSZzkq1+l92sSq29XdTCVjCJoK2sBQ=="
+ }
+ }
+}
diff --git a/node_modules/weixin-js-sdk/README.md b/node_modules/weixin-js-sdk/README.md
new file mode 100644
index 0000000..233a2ef
--- /dev/null
+++ b/node_modules/weixin-js-sdk/README.md
@@ -0,0 +1,21 @@
+微信官方 js-sdk
+----
+
+说明: 仅将官方 js-sdk 发布到 npm,支持 CommonJS,便于 browserify, webpack 等直接使用
+
+js源码: https://res.wx.qq.com/open/js/jweixin-1.6.0.js
+
+官方使用说明: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
+
+安装:
+
+ npm install weixin-js-sdk
+
+使用:
+
+ var wx = require('weixin-js-sdk');
+
+### Old versions
+
+* [1.0.0](https://github.com/yanxi-me/weixin-js-sdk/tree/1.0.0)
+* [1.2.0](https://github.com/yanxi-me/weixin-js-sdk/tree/1.2.0)
diff --git a/node_modules/weixin-js-sdk/index.js b/node_modules/weixin-js-sdk/index.js
new file mode 100644
index 0000000..98f5ccb
--- /dev/null
+++ b/node_modules/weixin-js-sdk/index.js
@@ -0,0 +1,898 @@
+!(function(e, n) {
+ module.exports = n(e);
+})(window, function(o, e) {
+ if (!o.jWeixin) {
+ var n,
+ c = {
+ config: "preVerifyJSAPI",
+ onMenuShareTimeline: "menu:share:timeline",
+ onMenuShareAppMessage: "menu:share:appmessage",
+ onMenuShareQQ: "menu:share:qq",
+ onMenuShareWeibo: "menu:share:weiboApp",
+ onMenuShareQZone: "menu:share:QZone",
+ previewImage: "imagePreview",
+ getLocation: "geoLocation",
+ openProductSpecificView: "openProductViewWithPid",
+ addCard: "batchAddCard",
+ openCard: "batchViewCard",
+ chooseWXPay: "getBrandWCPayRequest",
+ openEnterpriseRedPacket: "getRecevieBizHongBaoRequest",
+ startSearchBeacons: "startMonitoringBeacons",
+ stopSearchBeacons: "stopMonitoringBeacons",
+ onSearchBeacons: "onBeaconsInRange",
+ consumeAndShareCard: "consumedShareCard",
+ openAddress: "editAddress"
+ },
+ a = (function() {
+ var e = {};
+ for (var n in c) e[c[n]] = n;
+ return e;
+ })(),
+ i = o.document,
+ t = i.title,
+ r = navigator.userAgent.toLowerCase(),
+ s = navigator.platform.toLowerCase(),
+ d = !(!s.match("mac") && !s.match("win")),
+ u = -1 != r.indexOf("wxdebugger"),
+ l = -1 != r.indexOf("micromessenger"),
+ p = -1 != r.indexOf("android"),
+ f = -1 != r.indexOf("iphone") || -1 != r.indexOf("ipad"),
+ m = (n =
+ r.match(/micromessenger\/(\d+\.\d+\.\d+)/) ||
+ r.match(/micromessenger\/(\d+\.\d+)/))
+ ? n[1]
+ : "",
+ g = {
+ initStartTime: L(),
+ initEndTime: 0,
+ preVerifyStartTime: 0,
+ preVerifyEndTime: 0
+ },
+ h = {
+ version: 1,
+ appId: "",
+ initTime: 0,
+ preVerifyTime: 0,
+ networkType: "",
+ isPreVerifyOk: 1,
+ systemType: f ? 1 : p ? 2 : -1,
+ clientVersion: m,
+ url: encodeURIComponent(location.href)
+ },
+ v = {},
+ S = { _completes: [] },
+ y = { state: 0, data: {} };
+ O(function() {
+ g.initEndTime = L();
+ });
+ var I = !1,
+ _ = [],
+ w = {
+ config: function(e) {
+ B("config", (v = e));
+ var t = !1 !== v.check;
+ O(function() {
+ if (t)
+ M(
+ c.config,
+ {
+ verifyJsApiList: C(v.jsApiList),
+ verifyOpenTagList: C(v.openTagList)
+ },
+ (function() {
+ (S._complete = function(e) {
+ (g.preVerifyEndTime = L()), (y.state = 1), (y.data = e);
+ }),
+ (S.success = function(e) {
+ h.isPreVerifyOk = 0;
+ }),
+ (S.fail = function(e) {
+ S._fail ? S._fail(e) : (y.state = -1);
+ });
+ var t = S._completes;
+ return (
+ t.push(function() {
+ !(function() {
+ if (
+ !(
+ d ||
+ u ||
+ v.debug ||
+ m < "6.0.2" ||
+ h.systemType < 0
+ )
+ ) {
+ var i = new Image();
+ (h.appId = v.appId),
+ (h.initTime = g.initEndTime - g.initStartTime),
+ (h.preVerifyTime =
+ g.preVerifyEndTime - g.preVerifyStartTime),
+ w.getNetworkType({
+ isInnerInvoke: !0,
+ success: function(e) {
+ h.networkType = e.networkType;
+ var n =
+ "https://open.weixin.qq.com/sdk/report?v=" +
+ h.version +
+ "&o=" +
+ h.isPreVerifyOk +
+ "&s=" +
+ h.systemType +
+ "&c=" +
+ h.clientVersion +
+ "&a=" +
+ h.appId +
+ "&n=" +
+ h.networkType +
+ "&i=" +
+ h.initTime +
+ "&p=" +
+ h.preVerifyTime +
+ "&u=" +
+ h.url;
+ i.src = n;
+ }
+ });
+ }
+ })();
+ }),
+ (S.complete = function(e) {
+ for (var n = 0, i = t.length; n < i; ++n) t[n]();
+ S._completes = [];
+ }),
+ S
+ );
+ })()
+ ),
+ (g.preVerifyStartTime = L());
+ else {
+ y.state = 1;
+ for (var e = S._completes, n = 0, i = e.length; n < i; ++n)
+ e[n]();
+ S._completes = [];
+ }
+ }),
+ w.invoke ||
+ ((w.invoke = function(e, n, i) {
+ o.WeixinJSBridge && WeixinJSBridge.invoke(e, x(n), i);
+ }),
+ (w.on = function(e, n) {
+ o.WeixinJSBridge && WeixinJSBridge.on(e, n);
+ }));
+ },
+ ready: function(e) {
+ 0 != y.state ? e() : (S._completes.push(e), !l && v.debug && e());
+ },
+ error: function(e) {
+ m < "6.0.2" || (-1 == y.state ? e(y.data) : (S._fail = e));
+ },
+ checkJsApi: function(e) {
+ M(
+ "checkJsApi",
+ { jsApiList: C(e.jsApiList) },
+ ((e._complete = function(e) {
+ if (p) {
+ var n = e.checkResult;
+ n && (e.checkResult = JSON.parse(n));
+ }
+ e = (function(e) {
+ var n = e.checkResult;
+ for (var i in n) {
+ var t = a[i];
+ t && ((n[t] = n[i]), delete n[i]);
+ }
+ return e;
+ })(e);
+ }),
+ e)
+ );
+ },
+ onMenuShareTimeline: function(e) {
+ P(
+ c.onMenuShareTimeline,
+ {
+ complete: function() {
+ M(
+ "shareTimeline",
+ {
+ title: e.title || t,
+ desc: e.title || t,
+ img_url: e.imgUrl || "",
+ link: e.link || location.href,
+ type: e.type || "link",
+ data_url: e.dataUrl || ""
+ },
+ e
+ );
+ }
+ },
+ e
+ );
+ },
+ onMenuShareAppMessage: function(n) {
+ P(
+ c.onMenuShareAppMessage,
+ {
+ complete: function(e) {
+ "favorite" === e.scene
+ ? M("sendAppMessage", {
+ title: n.title || t,
+ desc: n.desc || "",
+ link: n.link || location.href,
+ img_url: n.imgUrl || "",
+ type: n.type || "link",
+ data_url: n.dataUrl || ""
+ })
+ : M(
+ "sendAppMessage",
+ {
+ title: n.title || t,
+ desc: n.desc || "",
+ link: n.link || location.href,
+ img_url: n.imgUrl || "",
+ type: n.type || "link",
+ data_url: n.dataUrl || ""
+ },
+ n
+ );
+ }
+ },
+ n
+ );
+ },
+ onMenuShareQQ: function(e) {
+ P(
+ c.onMenuShareQQ,
+ {
+ complete: function() {
+ M(
+ "shareQQ",
+ {
+ title: e.title || t,
+ desc: e.desc || "",
+ img_url: e.imgUrl || "",
+ link: e.link || location.href
+ },
+ e
+ );
+ }
+ },
+ e
+ );
+ },
+ onMenuShareWeibo: function(e) {
+ P(
+ c.onMenuShareWeibo,
+ {
+ complete: function() {
+ M(
+ "shareWeiboApp",
+ {
+ title: e.title || t,
+ desc: e.desc || "",
+ img_url: e.imgUrl || "",
+ link: e.link || location.href
+ },
+ e
+ );
+ }
+ },
+ e
+ );
+ },
+ onMenuShareQZone: function(e) {
+ P(
+ c.onMenuShareQZone,
+ {
+ complete: function() {
+ M(
+ "shareQZone",
+ {
+ title: e.title || t,
+ desc: e.desc || "",
+ img_url: e.imgUrl || "",
+ link: e.link || location.href
+ },
+ e
+ );
+ }
+ },
+ e
+ );
+ },
+ updateTimelineShareData: function(e) {
+ M(
+ "updateTimelineShareData",
+ { title: e.title, link: e.link, imgUrl: e.imgUrl },
+ e
+ );
+ },
+ updateAppMessageShareData: function(e) {
+ M(
+ "updateAppMessageShareData",
+ { title: e.title, desc: e.desc, link: e.link, imgUrl: e.imgUrl },
+ e
+ );
+ },
+ startRecord: function(e) {
+ M("startRecord", {}, e);
+ },
+ stopRecord: function(e) {
+ M("stopRecord", {}, e);
+ },
+ onVoiceRecordEnd: function(e) {
+ P("onVoiceRecordEnd", e);
+ },
+ playVoice: function(e) {
+ M("playVoice", { localId: e.localId }, e);
+ },
+ pauseVoice: function(e) {
+ M("pauseVoice", { localId: e.localId }, e);
+ },
+ stopVoice: function(e) {
+ M("stopVoice", { localId: e.localId }, e);
+ },
+ onVoicePlayEnd: function(e) {
+ P("onVoicePlayEnd", e);
+ },
+ uploadVoice: function(e) {
+ M(
+ "uploadVoice",
+ {
+ localId: e.localId,
+ isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
+ },
+ e
+ );
+ },
+ downloadVoice: function(e) {
+ M(
+ "downloadVoice",
+ {
+ serverId: e.serverId,
+ isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
+ },
+ e
+ );
+ },
+ translateVoice: function(e) {
+ M(
+ "translateVoice",
+ {
+ localId: e.localId,
+ isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
+ },
+ e
+ );
+ },
+ chooseImage: function(e) {
+ M(
+ "chooseImage",
+ {
+ scene: "1|2",
+ count: e.count || 9,
+ sizeType: e.sizeType || ["original", "compressed"],
+ sourceType: e.sourceType || ["album", "camera"]
+ },
+ ((e._complete = function(e) {
+ if (p) {
+ var n = e.localIds;
+ try {
+ n && (e.localIds = JSON.parse(n));
+ } catch (e) {}
+ }
+ }),
+ e)
+ );
+ },
+ getLocation: function(e) {},
+ previewImage: function(e) {
+ M(c.previewImage, { current: e.current, urls: e.urls }, e);
+ },
+ uploadImage: function(e) {
+ M(
+ "uploadImage",
+ {
+ localId: e.localId,
+ isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
+ },
+ e
+ );
+ },
+ downloadImage: function(e) {
+ M(
+ "downloadImage",
+ {
+ serverId: e.serverId,
+ isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
+ },
+ e
+ );
+ },
+ getLocalImgData: function(e) {
+ !1 === I
+ ? ((I = !0),
+ M(
+ "getLocalImgData",
+ { localId: e.localId },
+ ((e._complete = function(e) {
+ if (((I = !1), 0 < _.length)) {
+ var n = _.shift();
+ wx.getLocalImgData(n);
+ }
+ }),
+ e)
+ ))
+ : _.push(e);
+ },
+ getNetworkType: function(e) {
+ M(
+ "getNetworkType",
+ {},
+ ((e._complete = function(e) {
+ e = (function(e) {
+ var n = e.errMsg;
+ e.errMsg = "getNetworkType:ok";
+ var i = e.subtype;
+ if ((delete e.subtype, i)) e.networkType = i;
+ else {
+ var t = n.indexOf(":"),
+ o = n.substring(t + 1);
+ switch (o) {
+ case "wifi":
+ case "edge":
+ case "wwan":
+ e.networkType = o;
+ break;
+ default:
+ e.errMsg = "getNetworkType:fail";
+ }
+ }
+ return e;
+ })(e);
+ }),
+ e)
+ );
+ },
+ openLocation: function(e) {
+ M(
+ "openLocation",
+ {
+ latitude: e.latitude,
+ longitude: e.longitude,
+ name: e.name || "",
+ address: e.address || "",
+ scale: e.scale || 28,
+ infoUrl: e.infoUrl || ""
+ },
+ e
+ );
+ },
+ getLocation: function(e) {
+ M(
+ c.getLocation,
+ { type: (e = e || {}).type || "wgs84" },
+ ((e._complete = function(e) {
+ delete e.type;
+ }),
+ e)
+ );
+ },
+ hideOptionMenu: function(e) {
+ M("hideOptionMenu", {}, e);
+ },
+ showOptionMenu: function(e) {
+ M("showOptionMenu", {}, e);
+ },
+ closeWindow: function(e) {
+ M("closeWindow", {}, (e = e || {}));
+ },
+ hideMenuItems: function(e) {
+ M("hideMenuItems", { menuList: e.menuList }, e);
+ },
+ showMenuItems: function(e) {
+ M("showMenuItems", { menuList: e.menuList }, e);
+ },
+ hideAllNonBaseMenuItem: function(e) {
+ M("hideAllNonBaseMenuItem", {}, e);
+ },
+ showAllNonBaseMenuItem: function(e) {
+ M("showAllNonBaseMenuItem", {}, e);
+ },
+ scanQRCode: function(e) {
+ M(
+ "scanQRCode",
+ {
+ needResult: (e = e || {}).needResult || 0,
+ scanType: e.scanType || ["qrCode", "barCode"]
+ },
+ ((e._complete = function(e) {
+ if (f) {
+ var n = e.resultStr;
+ if (n) {
+ var i = JSON.parse(n);
+ e.resultStr = i && i.scan_code && i.scan_code.scan_result;
+ }
+ }
+ }),
+ e)
+ );
+ },
+ openAddress: function(e) {
+ M(
+ c.openAddress,
+ {},
+ ((e._complete = function(e) {
+ e = (function(e) {
+ return (
+ (e.postalCode = e.addressPostalCode),
+ delete e.addressPostalCode,
+ (e.provinceName = e.proviceFirstStageName),
+ delete e.proviceFirstStageName,
+ (e.cityName = e.addressCitySecondStageName),
+ delete e.addressCitySecondStageName,
+ (e.countryName = e.addressCountiesThirdStageName),
+ delete e.addressCountiesThirdStageName,
+ (e.detailInfo = e.addressDetailInfo),
+ delete e.addressDetailInfo,
+ e
+ );
+ })(e);
+ }),
+ e)
+ );
+ },
+ openProductSpecificView: function(e) {
+ M(
+ c.openProductSpecificView,
+ {
+ pid: e.productId,
+ view_type: e.viewType || 0,
+ ext_info: e.extInfo
+ },
+ e
+ );
+ },
+ addCard: function(e) {
+ for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
+ var r = n[t],
+ a = { card_id: r.cardId, card_ext: r.cardExt };
+ i.push(a);
+ }
+ M(
+ c.addCard,
+ { card_list: i },
+ ((e._complete = function(e) {
+ var n = e.card_list;
+ if (n) {
+ for (var i = 0, t = (n = JSON.parse(n)).length; i < t; ++i) {
+ var o = n[i];
+ (o.cardId = o.card_id),
+ (o.cardExt = o.card_ext),
+ (o.isSuccess = !!o.is_succ),
+ delete o.card_id,
+ delete o.card_ext,
+ delete o.is_succ;
+ }
+ (e.cardList = n), delete e.card_list;
+ }
+ }),
+ e)
+ );
+ },
+ chooseCard: function(e) {
+ M(
+ "chooseCard",
+ {
+ app_id: v.appId,
+ location_id: e.shopId || "",
+ sign_type: e.signType || "SHA1",
+ card_id: e.cardId || "",
+ card_type: e.cardType || "",
+ card_sign: e.cardSign,
+ time_stamp: e.timestamp + "",
+ nonce_str: e.nonceStr
+ },
+ ((e._complete = function(e) {
+ (e.cardList = e.choose_card_info), delete e.choose_card_info;
+ }),
+ e)
+ );
+ },
+ openCard: function(e) {
+ for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
+ var r = n[t],
+ a = { card_id: r.cardId, code: r.code };
+ i.push(a);
+ }
+ M(c.openCard, { card_list: i }, e);
+ },
+ consumeAndShareCard: function(e) {
+ M(
+ c.consumeAndShareCard,
+ { consumedCardId: e.cardId, consumedCode: e.code },
+ e
+ );
+ },
+ chooseWXPay: function(e) {
+ M(c.chooseWXPay, V(e), e);
+ },
+ openEnterpriseRedPacket: function(e) {
+ M(c.openEnterpriseRedPacket, V(e), e);
+ },
+ startSearchBeacons: function(e) {
+ M(c.startSearchBeacons, { ticket: e.ticket }, e);
+ },
+ stopSearchBeacons: function(e) {
+ M(c.stopSearchBeacons, {}, e);
+ },
+ onSearchBeacons: function(e) {
+ P(c.onSearchBeacons, e);
+ },
+ openEnterpriseChat: function(e) {
+ M(
+ "openEnterpriseChat",
+ { useridlist: e.userIds, chatname: e.groupName },
+ e
+ );
+ },
+ launchMiniProgram: function(e) {
+ M(
+ "launchMiniProgram",
+ {
+ targetAppId: e.targetAppId,
+ path: (function(e) {
+ if ("string" == typeof e && 0 < e.length) {
+ var n = e.split("?")[0],
+ i = e.split("?")[1];
+ return (n += ".html"), void 0 !== i ? n + "?" + i : n;
+ }
+ })(e.path),
+ envVersion: e.envVersion
+ },
+ e
+ );
+ },
+ openBusinessView: function(e) {
+ M(
+ "openBusinessView",
+ {
+ businessType: e.businessType,
+ queryString: e.queryString || "",
+ envVersion: e.envVersion
+ },
+ ((e._complete = function(n) {
+ if (p) {
+ var e = n.extraData;
+ if (e)
+ try {
+ n.extraData = JSON.parse(e);
+ } catch (e) {
+ n.extraData = {};
+ }
+ }
+ }),
+ e)
+ );
+ },
+ miniProgram: {
+ navigateBack: function(e) {
+ (e = e || {}),
+ O(function() {
+ M(
+ "invokeMiniProgramAPI",
+ { name: "navigateBack", arg: { delta: e.delta || 1 } },
+ e
+ );
+ });
+ },
+ navigateTo: function(e) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI",
+ { name: "navigateTo", arg: { url: e.url } },
+ e
+ );
+ });
+ },
+ redirectTo: function(e) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI",
+ { name: "redirectTo", arg: { url: e.url } },
+ e
+ );
+ });
+ },
+ switchTab: function(e) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI",
+ { name: "switchTab", arg: { url: e.url } },
+ e
+ );
+ });
+ },
+ reLaunch: function(e) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI",
+ { name: "reLaunch", arg: { url: e.url } },
+ e
+ );
+ });
+ },
+ postMessage: function(e) {
+ O(function() {
+ M(
+ "invokeMiniProgramAPI",
+ { name: "postMessage", arg: e.data || {} },
+ e
+ );
+ });
+ },
+ getEnv: function(e) {
+ O(function() {
+ e({ miniprogram: "miniprogram" === o.__wxjs_environment });
+ });
+ }
+ }
+ },
+ T = 1,
+ k = {};
+ return (
+ i.addEventListener(
+ "error",
+ function(e) {
+ if (!p) {
+ var n = e.target,
+ i = n.tagName,
+ t = n.src;
+ if ("IMG" == i || "VIDEO" == i || "AUDIO" == i || "SOURCE" == i)
+ if (-1 != t.indexOf("wxlocalresource://")) {
+ e.preventDefault(), e.stopPropagation();
+ var o = n["wx-id"];
+ if ((o || ((o = T++), (n["wx-id"] = o)), k[o])) return;
+ (k[o] = !0),
+ wx.ready(function() {
+ wx.getLocalImgData({
+ localId: t,
+ success: function(e) {
+ n.src = e.localData;
+ }
+ });
+ });
+ }
+ }
+ },
+ !0
+ ),
+ i.addEventListener(
+ "load",
+ function(e) {
+ if (!p) {
+ var n = e.target,
+ i = n.tagName;
+ n.src;
+ if ("IMG" == i || "VIDEO" == i || "AUDIO" == i || "SOURCE" == i) {
+ var t = n["wx-id"];
+ t && (k[t] = !1);
+ }
+ }
+ },
+ !0
+ ),
+ e && (o.wx = o.jWeixin = w),
+ w
+ );
+ }
+ function M(n, e, i) {
+ o.WeixinJSBridge
+ ? WeixinJSBridge.invoke(n, x(e), function(e) {
+ A(n, e, i);
+ })
+ : B(n, i);
+ }
+ function P(n, i, t) {
+ o.WeixinJSBridge
+ ? WeixinJSBridge.on(n, function(e) {
+ t && t.trigger && t.trigger(e), A(n, e, i);
+ })
+ : B(n, t || i);
+ }
+ function x(e) {
+ return (
+ ((e = e || {}).appId = v.appId),
+ (e.verifyAppId = v.appId),
+ (e.verifySignType = "sha1"),
+ (e.verifyTimestamp = v.timestamp + ""),
+ (e.verifyNonceStr = v.nonceStr),
+ (e.verifySignature = v.signature),
+ e
+ );
+ }
+ function V(e) {
+ return {
+ timeStamp: e.timestamp + "",
+ nonceStr: e.nonceStr,
+ package: e.package,
+ paySign: e.paySign,
+ signType: e.signType || "SHA1"
+ };
+ }
+ function A(e, n, i) {
+ ("openEnterpriseChat" != e && "openBusinessView" !== e) ||
+ (n.errCode = n.err_code),
+ delete n.err_code,
+ delete n.err_desc,
+ delete n.err_detail;
+ var t = n.errMsg;
+ t ||
+ ((t = n.err_msg),
+ delete n.err_msg,
+ (t = (function(e, n) {
+ var i = e,
+ t = a[i];
+ t && (i = t);
+ var o = "ok";
+ if (n) {
+ var r = n.indexOf(":");
+ "confirm" == (o = n.substring(r + 1)) && (o = "ok"),
+ "failed" == o && (o = "fail"),
+ -1 != o.indexOf("failed_") && (o = o.substring(7)),
+ -1 != o.indexOf("fail_") && (o = o.substring(5)),
+ ("access denied" !=
+ (o = (o = o.replace(/_/g, " ")).toLowerCase()) &&
+ "no permission to execute" != o) ||
+ (o = "permission denied"),
+ "config" == i && "function not exist" == o && (o = "ok"),
+ "" == o && (o = "fail");
+ }
+ return (n = i + ":" + o);
+ })(e, t)),
+ (n.errMsg = t)),
+ (i = i || {})._complete && (i._complete(n), delete i._complete),
+ (t = n.errMsg || ""),
+ v.debug && !i.isInnerInvoke && alert(JSON.stringify(n));
+ var o = t.indexOf(":");
+ switch (t.substring(o + 1)) {
+ case "ok":
+ i.success && i.success(n);
+ break;
+ case "cancel":
+ i.cancel && i.cancel(n);
+ break;
+ default:
+ i.fail && i.fail(n);
+ }
+ i.complete && i.complete(n);
+ }
+ function C(e) {
+ if (e) {
+ for (var n = 0, i = e.length; n < i; ++n) {
+ var t = e[n],
+ o = c[t];
+ o && (e[n] = o);
+ }
+ return e;
+ }
+ }
+ function B(e, n) {
+ if (!(!v.debug || (n && n.isInnerInvoke))) {
+ var i = a[e];
+ i && (e = i),
+ n && n._complete && delete n._complete,
+ console.log('"' + e + '",', n || "");
+ }
+ }
+ function L() {
+ return new Date().getTime();
+ }
+ function O(e) {
+ l &&
+ (o.WeixinJSBridge
+ ? e()
+ : i.addEventListener &&
+ i.addEventListener("WeixinJSBridgeReady", e, !1));
+ }
+});
diff --git a/node_modules/weixin-js-sdk/index.original.js b/node_modules/weixin-js-sdk/index.original.js
new file mode 100644
index 0000000..1d48001
--- /dev/null
+++ b/node_modules/weixin-js-sdk/index.original.js
@@ -0,0 +1,2 @@
+// from http://res.wx.qq.com/open/js/jweixin-1.6.0.js
+!function(e,n){"function"==typeof define&&(define.amd||define.cmd)?define(function(){return n(e)}):n(e,!0)}(this,function(o,e){if(!o.jWeixin){var n,c={config:"preVerifyJSAPI",onMenuShareTimeline:"menu:share:timeline",onMenuShareAppMessage:"menu:share:appmessage",onMenuShareQQ:"menu:share:qq",onMenuShareWeibo:"menu:share:weiboApp",onMenuShareQZone:"menu:share:QZone",previewImage:"imagePreview",getLocation:"geoLocation",openProductSpecificView:"openProductViewWithPid",addCard:"batchAddCard",openCard:"batchViewCard",chooseWXPay:"getBrandWCPayRequest",openEnterpriseRedPacket:"getRecevieBizHongBaoRequest",startSearchBeacons:"startMonitoringBeacons",stopSearchBeacons:"stopMonitoringBeacons",onSearchBeacons:"onBeaconsInRange",consumeAndShareCard:"consumedShareCard",openAddress:"editAddress"},a=function(){var e={};for(var n in c)e[c[n]]=n;return e}(),i=o.document,t=i.title,r=navigator.userAgent.toLowerCase(),s=navigator.platform.toLowerCase(),d=!(!s.match("mac")&&!s.match("win")),u=-1!=r.indexOf("wxdebugger"),l=-1!=r.indexOf("micromessenger"),p=-1!=r.indexOf("android"),f=-1!=r.indexOf("iphone")||-1!=r.indexOf("ipad"),m=(n=r.match(/micromessenger\/(\d+\.\d+\.\d+)/)||r.match(/micromessenger\/(\d+\.\d+)/))?n[1]:"",g={initStartTime:L(),initEndTime:0,preVerifyStartTime:0,preVerifyEndTime:0},h={version:1,appId:"",initTime:0,preVerifyTime:0,networkType:"",isPreVerifyOk:1,systemType:f?1:p?2:-1,clientVersion:m,url:encodeURIComponent(location.href)},v={},S={_completes:[]},y={state:0,data:{}};O(function(){g.initEndTime=L()});var I=!1,_=[],w={config:function(e){B("config",v=e);var t=!1!==v.check;O(function(){if(t)M(c.config,{verifyJsApiList:C(v.jsApiList),verifyOpenTagList:C(v.openTagList)},function(){S._complete=function(e){g.preVerifyEndTime=L(),y.state=1,y.data=e},S.success=function(e){h.isPreVerifyOk=0},S.fail=function(e){S._fail?S._fail(e):y.state=-1};var t=S._completes;return t.push(function(){!function(){if(!(d||u||v.debug||m<"6.0.2"||h.systemType<0)){var i=new Image;h.appId=v.appId,h.initTime=g.initEndTime-g.initStartTime,h.preVerifyTime=g.preVerifyEndTime-g.preVerifyStartTime,w.getNetworkType({isInnerInvoke:!0,success:function(e){h.networkType=e.networkType;var n="https://open.weixin.qq.com/sdk/report?v="+h.version+"&o="+h.isPreVerifyOk+"&s="+h.systemType+"&c="+h.clientVersion+"&a="+h.appId+"&n="+h.networkType+"&i="+h.initTime+"&p="+h.preVerifyTime+"&u="+h.url;i.src=n}})}}()}),S.complete=function(e){for(var n=0,i=t.length;n
+
+
+
+
+
+
+
+
+
+ 收货地址
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/address/index.vue b/pages/address/index.vue
new file mode 100644
index 0000000..4188d83
--- /dev/null
+++ b/pages/address/index.vue
@@ -0,0 +1,307 @@
+
+
+
+
+
+ {{ item.name }}
+ {{ item.phone }}
+
+
+ {{ region }}
+ {{ item.detail }}
+
+
+
+
+
+
+ {{ item.address_id == defaultId ? '默认' : '选择' }}
+
+
+
+
+
+
+ 编辑
+
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/address/update.vue b/pages/address/update.vue
new file mode 100644
index 0000000..0a58d19
--- /dev/null
+++ b/pages/address/update.vue
@@ -0,0 +1,290 @@
+
+
+
+
+
+
+
+
+
+
+ 收货地址
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/article/detail.vue b/pages/article/detail.vue
new file mode 100644
index 0000000..6c59c01
--- /dev/null
+++ b/pages/article/detail.vue
@@ -0,0 +1,117 @@
+
+
+
+ {{ detail.title }}
+
+
+
+ {{ detail.show_views }}次浏览
+
+
+ {{ detail.view_time }}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/article/index.vue b/pages/article/index.vue
new file mode 100644
index 0000000..4327707
--- /dev/null
+++ b/pages/article/index.vue
@@ -0,0 +1,255 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+ {{ item.show_views }}次浏览
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+ {{ item.show_views }}次浏览
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/bargain/goods/components/SkuPopup.vue b/pages/bargain/goods/components/SkuPopup.vue
new file mode 100644
index 0000000..c24957c
--- /dev/null
+++ b/pages/bargain/goods/components/SkuPopup.vue
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/bargain/goods/index.vue b/pages/bargain/goods/index.vue
new file mode 100644
index 0000000..655d38c
--- /dev/null
+++ b/pages/bargain/goods/index.vue
@@ -0,0 +1,424 @@
+
+
+
+
+
+
+
+
+
+
+
+ 限时砍价
+
+
+ ¥
+ {{ active.floor_price }}
+
+ ¥{{ goods.goods_price_min }}
+
+
+
+
+ 已砍成{{ active.active_sales }}件
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+
+
+
+
+
+
+ {{ goods.selling_point }}
+
+
+
+
+ 距离活动结束
+ 还剩
+
+
+
+
+
+ 砍价活动已结束,下次记得早点来哦~
+
+
+
+
+
+
+
+ 砍价玩法
+
+
+ 查看规则
+
+
+
+
+
+
+ 1
+
+ 点击砍价
+
+
+
+ 2
+
+ 找人帮砍
+
+
+
+ 3
+
+ 砍到最低
+
+
+
+ 4
+
+ 优惠购买
+
+
+
+
+
+
+
+
+ 选择:
+ {{ item.spec_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 商品描述
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ setting.rulesDesc }}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/bargain/goods/style.scss b/pages/bargain/goods/style.scss
new file mode 100644
index 0000000..d4b4848
--- /dev/null
+++ b/pages/bargain/goods/style.scss
@@ -0,0 +1,298 @@
+.container {
+ // 设置ios刘海屏底部横线安全区域
+ // 110 - 18 + 4
+ padding-bottom: calc(constant(safe-area-inset-bottom) + 98rpx + 6rpx);
+ padding-bottom: calc(env(safe-area-inset-bottom) + 98rpx + 6rpx);
+}
+
+/* 商品信息 */
+
+.goods-info {
+ background: #fff;
+ padding: 25rpx 30rpx;
+}
+
+.info-item__top {
+ min-height: 40rpx;
+ margin-bottom: 20rpx;
+}
+
+.info-item__top .active-tag {
+ color: #fff;
+ background: $main-bg;
+ padding: 4rpx 10rpx;
+ border-radius: 15rpx;
+ font-size: 26rpx;
+ text-align: center;
+ margin-right: 15rpx;
+}
+
+.floor-price__samll {
+ font-size: 26rpx;
+ line-height: 1;
+ color: $main-bg;
+ margin-bottom: -10rpx;
+}
+
+/* 商品价 */
+
+.floor-price {
+ color: $main-bg;
+ margin-right: 15rpx;
+ font-size: 42rpx;
+ line-height: 1;
+}
+
+.original-price {
+ font-size: 26rpx;
+ line-height: 1;
+ text-decoration: line-through;
+ color: #959595;
+ margin-bottom: -6rpx;
+}
+
+.goods-sales {
+ font-size: 24rpx;
+ color: #959595;
+}
+
+.info-item__name .goods-name {
+ font-size: 30rpx;
+}
+
+/* 商品分享 */
+
+.goods-share__line {
+ border-left: 1rpx solid #f4f4f4;
+ height: 60rpx;
+ margin: 0 30rpx;
+}
+
+.goods-share .share-btn {
+ line-height: normal;
+ padding: 0;
+ background: none;
+ border-radius: 0;
+ box-shadow: none;
+ font-size: 8pt;
+ border: none;
+ color: #191919;
+}
+
+.goods-share .share-btn::after {
+ border: none;
+}
+
+.goods-share .share__icon {
+ font-size: 40rpx;
+ margin-bottom: 5rpx;
+}
+
+/* 商品卖点 */
+
+.info-item_selling-point {
+ margin-top: 8rpx;
+ font-size: 24rpx;
+ color: #808080;
+}
+
+// 选择商品规格
+.goods-choice {
+ padding: 26rpx 30rpx;
+ font-size: 28rpx;
+
+ .spec-list {
+ display: flex;
+ align-items: center;
+
+ .spec-name {
+ margin-right: 10rpx;
+ }
+ }
+}
+
+/* 商品详情 */
+
+.goods-content .item-title {
+ padding: 26rpx 30rpx;
+ font-size: 28rpx;
+}
+
+/* 底部操作栏 */
+
+.footer-fixed {
+ position: fixed;
+ bottom: var(--window-bottom);
+ left: 0;
+ right: 0;
+ display: flex;
+ z-index: 11;
+ box-shadow: 0 -4rpx 40rpx 0 rgba(151, 151, 151, 0.24);
+ background: #fff;
+
+ // 设置ios刘海屏底部横线安全区域
+ padding-bottom: env(safe-area-inset-bottom);
+ padding-bottom: env(safe-area-inset-bottom);
+}
+
+.footer-container {
+ width: 100%;
+ display: flex;
+ height: 98rpx;
+}
+
+// 快捷菜单
+.foo-item-fast {
+ box-sizing: border-box;
+ width: 256rpx;
+ line-height: 1;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ .fast-item {
+ position: relative;
+ padding: 4rpx 10rpx;
+ line-height: 1;
+ // text-align: center;
+
+ .fast-icon {
+ margin-bottom: 6rpx;
+ }
+
+ &--home {
+ margin-right: 30rpx;
+ }
+
+ &--cart {
+ .fast-icon { padding-left: 3px; }
+ }
+
+ // 角标
+ .fast-badge {
+ display: inline-block;
+ box-sizing: border-box;
+ min-width: 16px;
+ padding: 0 3px;
+ color: #fff;
+ font-weight: 500;
+ font-size: 12px;
+ font-family: -apple-system-font, Helvetica Neue, Arial, sans-serif;
+ line-height: 1.2;
+ text-align: center;
+ background-color: #ee0a24;
+ border: 1px solid #fff;
+ border-radius: 999px;
+ }
+ .fast-badge--fixed {
+ position: absolute;
+ top: 0;
+ right: 0;
+ transform-origin: 100%
+ }
+
+ .fast-icon {
+ font-size: 46rpx;
+ }
+
+ .fast-text {
+ font-size: 24rpx;
+ }
+
+ }
+
+}
+
+// 操作按钮
+.foo-item-btn {
+ flex: 1;
+
+ .btn-wrapper {
+ height: 100%;
+ display: flex;
+ align-items: center;
+ }
+
+ // 立即砍价
+ .btn-item {
+ flex: 1;
+ height: 100%;
+ font-size: 30rpx;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-radius: 0;
+ &.btn--main {
+ background: linear-gradient(to right, $main-bg, $main-bg2);
+ color: $main-text;
+ }
+ &.btn--gray {
+ background-color: #ccc;
+ color: #fff;
+ }
+ }
+}
+
+// 活动状态
+.info-item_status {
+ margin-top: 20rpx;
+ padding: 15rpx 20rpx;
+ font-size: 24rpx;
+ border-radius: 6rpx;
+}
+
+.info-item_status .countdown-icon {
+ font-size: 28rpx;
+ margin-right: 15rpx;
+}
+
+// 活动倒计时
+.info-item_countdown {
+ background: #f0f9ff;
+ color: #8f8f8f;
+}
+
+.info-item_countdown .countdown-icon {
+ color: #1397d8;
+}
+
+// 活动已结束
+.info-item_end {
+ background: #ccc;
+ color: #fff;
+}
+
+// 砍价玩法
+.bargain-rules {
+ padding: 20rpx 0;
+ font-size: 29rpx;
+
+ .item-title {
+ padding: 0 30rpx;
+ }
+
+ .rule-simple {
+ margin-top: 35rpx;
+ color: #737373;
+ }
+
+ .i-number {
+ width: 60rpx;
+ height: 60rpx;
+ border-radius: 50%;
+ margin-bottom: 15rpx;
+ border: 1rpx dashed #c0c0c0;
+ }
+}
+
+// 砍价规则(弹窗)
+.pops-content {
+ padding: 30rpx 48rpx;
+ font-size: 28rpx;
+ line-height: 44rpx;
+ text-align: left;
+ color: #606266;
+ min-height: 320rpx;
+ max-height: 640rpx;
+ box-sizing: border-box;
+}
diff --git a/pages/bargain/index.vue b/pages/bargain/index.vue
new file mode 100644
index 0000000..ad48b3f
--- /dev/null
+++ b/pages/bargain/index.vue
@@ -0,0 +1,478 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods.goods_name }}
+
+
+
+
+
+
+
+
+
+ {{ item.helpsCount }}人正在砍价
+
+
+
+
+ ¥{{ item.goods.goods_price_min }}
+
+
+
+ 最低¥
+ {{ item.floor_price }}
+
+
+
+
+ 立即参加
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods.goods_name }}
+
+
+
+
+ 已砍
+ {{ item.cut_money }}
+ 元,
+ 只差
+ {{ item.surplus_money }}
+ 元
+
+
+ 已砍至最低
+ {{ item.floor_price }}
+ 元
+
+
+
+
+
+
+ 剩余
+
+
+
+ {{ item.is_buy ? '砍价成功' : '已结束' }}
+
+
+
+
+
+ 继续砍价
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/bargain/task.vue b/pages/bargain/task.vue
new file mode 100644
index 0000000..1a9c274
--- /dev/null
+++ b/pages/bargain/task.vue
@@ -0,0 +1,847 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ task.user.nick_name }}
+
+
+
+
+ {{ active.prompt_words }}
+
+
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+
+ 仅剩
+ {{ goodsSkuInfo.stock_num }}
+ 件
+
+
+
+ 底价¥
+ {{ task.floor_price }}
+ ¥{{ task.goods_price }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 已砍
+ {{ task.cut_money }}
+ 元,还差
+ {{ task.surplus_money }}
+ 元
+
+
+ 已砍至最低
+ {{ task.floor_price }}
+ 元,砍价成功!
+
+
+
+ 该砍价任务已结束~
+
+
+
+
+
+
+
+
+
+
+
+
+ 立即购买
+
+
+
+
+
+ 帮TA砍一刀
+
+
+
+ 查看其他砍价活动
+
+
+
+
+
+ 活动还剩
+
+ 结束,快来砍价吧~
+
+
+
+
+
+
+
+
+
+ 好友助力榜
+
+
+
+
+
+ {{ help.user.nick_name }}
+
+
+ 帮砍了
+ ¥{{ help.cut_money }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ setting.rulesDesc }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/cart/index.vue b/pages/cart/index.vue
new file mode 100644
index 0000000..e36b815
--- /dev/null
+++ b/pages/cart/index.vue
@@ -0,0 +1,513 @@
+
+
+
+
+
+ 共
+ {{ total }}
+ 件商品
+
+
+
+
+ 编辑
+
+
+ 完成
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods.goods_name }}
+
+
+
+ {{ props.value.name }}
+
+
+
+
+
+
+
+
+
+
+ 去逛逛
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/category/components/commodity.vue b/pages/category/components/commodity.vue
new file mode 100644
index 0000000..b7bf790
--- /dev/null
+++ b/pages/category/components/commodity.vue
@@ -0,0 +1,398 @@
+
+
+
+
+ 全部
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+ 全部
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/category/components/primary.vue b/pages/category/components/primary.vue
new file mode 100644
index 0000000..80a26c6
--- /dev/null
+++ b/pages/category/components/primary.vue
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/category/components/secondary.vue b/pages/category/components/secondary.vue
new file mode 100644
index 0000000..284ac12
--- /dev/null
+++ b/pages/category/components/secondary.vue
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/category/index.vue b/pages/category/index.vue
new file mode 100644
index 0000000..ac8f0fc
--- /dev/null
+++ b/pages/category/index.vue
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/checkout/cashier/index.vue b/pages/checkout/cashier/index.vue
new file mode 100644
index 0000000..c2dc194
--- /dev/null
+++ b/pages/checkout/cashier/index.vue
@@ -0,0 +1,460 @@
+
+
+
+
+
+
+ 剩余时间
+
+
+
+
+ ¥
+ {{ order.pay_price }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ PayMethodEnum[item.method].name }}
+
+
+ (可用¥{{ personal.balance }}元)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 请在{{ PayMethodClientNameEnum[tempUnifyData.method] }}内完成支付,如果您已经支付成功,请点击“已完成支付”按钮
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/checkout/index.vue b/pages/checkout/index.vue
new file mode 100644
index 0000000..79c63cc
--- /dev/null
+++ b/pages/checkout/index.vue
@@ -0,0 +1,601 @@
+
+
+
+
+
+
+
+
+ 快递配送
+
+
+ 上门自提
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ order.address.name }}
+ {{ order.address.phone }}
+
+
+ {{ region }}
+ {{ order.address.detail }}
+
+
+
+
+ 请选择配送地址
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ order.extractShop.shop_name }}
+
+
+ {{ order.extractShop.region.province }} {{ order.extractShop.region.city }}
+ {{ order.extractShop.region.region }} {{ order.extractShop.address }}
+
+
+
+
+ 请选择自提点
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_name }}
+
+
+
+ {{ props.group.name }}:
+ {{ props.value.name }};
+
+
+
+
+ ×{{ item.total_num }}
+ ¥{{ item.goods_price }}
+
+
+
+ 会员折扣价:¥{{ item.grade_goods_price }}
+
+
+
+
+
+
+ 共{{ order.orderTotalNum }}件商品
+
+
+
+
+
+ 订单总金额:
+
+ ¥{{ order.orderTotalPrice }}
+
+
+
+
+ 优惠券:
+
+
+ -¥{{ order.couponMoney }}
+ 有{{ order.couponList.length }}张优惠券
+
+
+ 无优惠券可用
+
+
+
+
+
+ 可用{{ setting.points_name }}抵扣:
+
+
+
+ -¥{{ order.pointsMoney }}
+
+
+
+
+
+ 配送费用:
+
+
+ +¥{{ order.expressPrice }}
+ 不在配送范围
+
+
+ 请先选择配送地址
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ setting.points_describe }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/checkout/style.scss b/pages/checkout/style.scss
new file mode 100644
index 0000000..f8b7291
--- /dev/null
+++ b/pages/checkout/style.scss
@@ -0,0 +1,479 @@
+// 配送信息
+.flow-delivery {
+ padding: 34rpx 30rpx;
+ background: #fff url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANYAAAANCAYAAADVGpDCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA4ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3Yjk4M2ExYy1jMDhkLTQ1OTktYTI0Ny1kZjNjYzdiYTQ5ZTgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDQwNkY3RkU5N0NGMTFFNUI3N0M4NTU4MzM2RjlFODIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDQwNkY3RkQ5N0NGMTFFNUI3N0M4NTU4MzM2RjlFODIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowNzgwZWI1NS03OGFhLTQzOTUtODQ4OC1lOWI5YmVlYTY1ZDciIHN0UmVmOmRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDo1OTRiYzUyMy1jMzc3LTExNzgtYTdkZS04NGY3YmM1ZGIxMDMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz556PLxAAACBElEQVR42tyaSyhEYRTHP48imlKibDQeSSlkSlEWLCRFsZNH5FE2FqQ8ErIRC9lIkTwXSpMkWWChhEJCSnlkoUZGSsr78f98n43CMFPu/Z/6NZuZ2zn33/+cb869XkmLx8IDEQaGQJbgiytQDSY3MyL+LYnL/HxPXSoHDIJQQq2WQQk4Dbbb/yUB29LJ+6e3B66VB3ZITbUIEqSpCGoJBP1ghtBUD6ARpEtTGSEhXzd+awE9oJzQUPegWdf3QlBPMhgDMYRa7YNisGWkpP5qrBQtVBShUHugUE9hs4fUtwG0utlEjRivoA/Ug1sj3vjffr8FNJEK1auPFHcE9UTq5pdK2PwcoAzMG7mjuRrRYEIfK9jiDJSCBZJ6ynSTsBBqNQ0qgdPISbq6vJCFbJOaagrEk5gqWNczRGiqG1Ah1LLMafRkf5pYIUKtZnMJDXUNasAIST2ZYFioRx9ssQaKwJFZEv5uYmWDXVJTrYBEElP562PfPKGpnkAbSDOTqb6aWAGgW6iHol5kQj2CdtAJngnqkc1hHMQRNr9DPaXWzZj8Z2PZtFCxhEIdaKE2CGqRJ4060AH8CLUaALX6f5VpBZLhI9SaeZXQVHKNLt84SCIxVbhQi5YuQlNd6OVElZlN9TGxrGBUn2PZ4lyoTdIsST0FQj0UDSLUak6ot3gcBLVY3wQYAJoVXxmNERajAAAAAElFTkSuQmCC') bottom left repeat-x;
+ background-size: 120rpx auto;
+ margin-bottom: 25rpx;
+
+ .detail-location {
+ font-size: 36rpx;
+ }
+ .detail-content {
+ padding: 0 20rpx;
+ .detail-content__title-phone {
+ margin-left: 10rpx;
+ }
+ .detail-content__describe {
+ font-size: 28rpx;
+ color: #777;
+ }
+ }
+ .detail-content__title {
+ margin-bottom: 6rpx;
+ }
+}
+
+// 买家留言
+.flow-all-money {
+ .ipt-wrapper {
+ .input {
+ font-size: 28rpx;
+ // width: 100%;
+ display: block;
+ height: 75rpx;
+ }
+ }
+}
+
+// 商品列表
+.checkout_list {
+ padding: 20rpx 30rpx 4rpx 30rpx;
+ background: #fff;
+ border-bottom: 1rpx solid rgb(248, 248, 248);
+ .flow-shopList {
+ padding: 5rpx 0 10rpx;
+ border-bottom: 1rpx solid rgb(248, 248, 248);
+ &:last-child {
+ border-bottom: 0;
+ }
+ }
+}
+
+.flow-header-left {
+ padding-left: 90rpx;
+}
+
+/* 会员价 */
+.flow-shopList {
+
+ .flow-list-right {
+ .flow-cont {
+
+ &.price-delete {
+ font-size: 26rpx;
+ color: #777;
+ text-decoration: line-through;
+ }
+
+ }
+ }
+
+ .grade-price {
+ padding-top: 8rpx;
+ font-size: 28rpx;
+ color: $main-bg;
+ text-align: right;
+ }
+
+ .goods-name{
+ font-size: 28rpx;
+ color: #333;
+ }
+
+}
+
+/* 优惠券选择 */
+.popup__coupon {
+ background: #fff;
+ box-sizing: border-box;
+ padding: 30rpx;
+ // 设置ios刘海屏底部横线安全区域
+ padding-bottom: calc(constant(safe-area-inset-bottom) + 30rpx);
+ padding-bottom: calc(env(safe-area-inset-bottom) + 30rpx);
+
+ .coupon__do_not {
+ .control {
+ width: 90%;
+ height: 72rpx;
+ color: #888;
+ border: 1rpx solid #e3e3e3;
+ border-radius: 10rpx;
+ }
+ }
+
+ .coupon__title {
+ text-align: center;
+ margin-bottom: 30rpx;
+ }
+
+ .coupon-list {
+ /* #ifdef H5 */
+ max-width: 1120rpx;
+ margin: 0 auto;
+ /* #endif */
+ margin-bottom: 24rpx;
+ }
+
+ .coupon-item {
+ position: relative;
+ overflow: hidden;
+ margin-bottom: 22rpx;
+ }
+
+ .item-wrapper {
+ width: 100%;
+ display: flex;
+ background: #fff;
+ border-radius: 8rpx;
+ color: #fff;
+ height: 180rpx;
+
+ .coupon-type {
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 10;
+ width: 128rpx;
+ padding: 6rpx 0;
+ background: #a771ff;
+ font-size: 20rpx;
+ text-align: center;
+ color: #ffffff;
+ transform: rotate(45deg);
+ transform-origin: 64rpx 64rpx;
+ }
+
+ &.color-blue {
+ background: linear-gradient(-125deg, #57bdbf, #2f9de2);
+ }
+
+ &.color-red {
+ background: linear-gradient(-128deg, #ff6d6d, #ff3636);
+ }
+
+ &.color-violet {
+ background: linear-gradient(-113deg, #ef86ff, #b66ff5);
+
+ .coupon-type {
+ background: #55b5ff;
+ }
+ }
+
+ &.color-yellow {
+ background: linear-gradient(-141deg, #f7d059, #fdb054);
+ }
+
+ &.color-gray {
+ background: linear-gradient(-113deg, #bdbdbd, #a2a1a2);
+
+ .coupon-type {
+ background: #9e9e9e;
+ }
+ }
+
+ .content {
+ flex: 1;
+ padding: 30rpx 20rpx;
+ border-radius: 16rpx 0 0 16rpx;
+
+ .title {
+ font-size: 32rpx;
+ }
+
+ .bottom {
+ .time {
+ font-size: 24rpx;
+ }
+
+ .receive {
+ height: 46rpx;
+ width: 122rpx;
+ border: 1rpx solid #fff;
+ border-radius: 30rpx;
+ color: #fff;
+ font-size: 24rpx;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ &.state {
+ border: none;
+ }
+ }
+ }
+ }
+
+ .tip {
+ position: relative;
+ flex: 0 0 32%;
+ text-align: center;
+ border-radius: 0 16rpx 16rpx 0;
+
+ .money {
+ font-weight: bold;
+ font-size: 52rpx;
+ }
+
+ .pay-line {
+ font-size: 22rpx;
+ }
+ }
+
+ .split-line {
+ position: relative;
+ flex: 0 0 0;
+ border-left: 4rpx solid #fff;
+ margin: 0 10rpx 0 6rpx;
+ background: #fff;
+
+ &:before,
+ {
+ border-radius: 0 0 16rpx 16rpx;
+ top: 0;
+ }
+
+ &:after {
+ border-radius: 16rpx 16rpx 0 0;
+ bottom: 0;
+ }
+
+ &:before,
+ &:after {
+ content: '';
+ position: absolute;
+ width: 24rpx;
+ height: 12rpx;
+ background: #f7f7f7;
+ left: -14rpx;
+ z-index: 1;
+ }
+
+
+ }
+ }
+
+}
+
+/* 积分抵扣 */
+.points {
+
+ .title {
+ margin-right: 5rpx;
+ }
+
+ .icon-help {
+ font-size: 28rpx;
+ }
+
+ .points-money {
+ margin-right: 20rpx;
+ }
+
+}
+
+// 商品规格
+.goods-props {
+ padding-top: 10rpx;
+ font-size: 24rpx;
+ color: #999;
+
+ .goods-props-item {
+ float: left;
+ .group-name {
+ margin-right: 6rpx;
+ }
+ }
+}
+
+// 右侧箭头
+.right-arrow {
+ margin-left: 16rpx;
+ // color: #777;
+ font-size: 26rpx;
+}
+
+// 底部操作栏
+.flow-fixed-footer {
+ position: fixed;
+ bottom: var(--window-bottom);
+ left: var(--window-left);
+ right: var(--window-right);
+ // width: 100%;
+ background: #fff;
+ border-top: 1px solid #eee;
+ z-index: 11;
+ // 设置ios刘海屏底部横线安全区域
+ padding-bottom: calc(constant(safe-area-inset-bottom) + var(--window-bottom));
+ padding-bottom: calc(env(safe-area-inset-bottom) + var(--window-bottom));
+
+ .chackout-left {
+ font-size: 28rpx;
+ line-height: 92rpx;
+ color: #777;
+ flex: 4;
+ padding-left: 12px;
+ }
+
+ .chackout-right {
+ font-size: 34rpx;
+ flex: 2;
+ }
+
+
+ // 提交按钮
+ .flow-btn {
+ background: linear-gradient(to right, $main-bg, $main-bg2);
+ color: $main-text;
+ text-align: center;
+ line-height: 92rpx;
+ display: block;
+ font-size: 28rpx;
+ // 禁用按钮
+ &.disabled {
+ opacity: 0.6;
+ }
+ }
+}
+
+ // 积分说明
+.points-content {
+ padding: 30rpx 48rpx;
+ font-size: 28rpx;
+ line-height: 50rpx;
+ text-align: left;
+ color: #606266;
+ height: 620rpx;
+ box-sizing: border-box;
+}
+
+/* 共几件商品 */
+.flow-num-box {
+ font-size: 28rpx;
+ color: #777;
+ padding: 16rpx 24rpx;
+ text-align: right;
+}
+
+/* app.scss */
+.flow-shopList {
+ padding: 18rpx 0;
+
+ .flow-list-left {
+ margin-right: 20rpx;
+
+ image {
+ width: 180rpx;
+ height: 180rpx;
+ border: 1rpx solid #eee;
+ background: #fff;
+ }
+
+ }
+
+ .flow-list-right {
+
+ .flow-cont {
+ font-size: 28rpx;
+ color: $main-bg;
+ }
+
+ .small {
+ font-size: 26rpx;
+ color: #777;
+ }
+
+ .flow-list-cont {
+ padding-top: 10rpx;
+ }
+
+ }
+
+}
+
+.flow-all-money {
+ padding: 0 24rpx;
+ color: #444;
+
+ .flow-all-list {
+ font-size: 28rpx;
+ padding: 20rpx 0;
+ border-bottom: 1rpx solid rgb(248, 248, 248);
+ }
+
+ .flow-all-list:last-child {
+ border-bottom: none;
+ }
+
+ .flow-all-list-cont {
+ font-size: 28rpx;
+ padding: 10rpx 0;
+ }
+
+ .flow-arrow {
+ justify-content: flex-end;
+ align-items: center;
+ }
+
+}
+
+ // 选项卡:配送方式
+ .swiper-tab {
+ width: 100%;
+ text-align: center;
+ height: 85rpx;
+ background-color: #fff;
+ border-bottom: 1px solid rgb(248, 248, 248);
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+
+ .swiper-tab-item {
+ width: 35%;
+ height: 100%;
+ font-size: 28rpx;
+ color: #777;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ box-sizing: border-box;
+ border-bottom: 2px solid #ffffff00;
+
+ &.on {
+ color: $main-bg;
+ border-bottom: 2px solid $main-bg;
+ }
+
+ }
+
+ }
+
+ // 门店自提联系人
+ .flow-extract-contact {
+ padding: 8rpx 24rpx;
+ font-size: 28rpx;
+ color: #444;
+ margin-bottom: 25rpx;
+
+ .contact-item {
+ padding: 20rpx 0;
+ border-bottom: 1rpx solid rgb(248, 248, 248);
+
+ &:last-child {
+ border-bottom: none;
+ }
+ }
+
+ .item-label {
+ margin-right: 26rpx;
+ width: 150rpx;
+ }
+
+ .item-ipt .input {
+ font-size: 28rpx;
+
+ .input-placeholder {
+ font-size: 28rpx;
+ }
+ }
+
+ }
\ No newline at end of file
diff --git a/pages/comment/index.vue b/pages/comment/index.vue
new file mode 100644
index 0000000..f50b1ae
--- /dev/null
+++ b/pages/comment/index.vue
@@ -0,0 +1,276 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/coupon/index.vue b/pages/coupon/index.vue
new file mode 100644
index 0000000..dacfba1
--- /dev/null
+++ b/pages/coupon/index.vue
@@ -0,0 +1,251 @@
+
+
+
+
+
+ {{ CouponTypeEnum[item.coupon_type].name }}
+
+
+ ¥
+ {{ item.reduce_price }}
+
+ {{ item.discount }}折
+ 满{{ item.min_price }}元可用
+
+
+
+ {{ item.name }}
+
+
+ 领取{{ item.expire_day }}天内有效
+
+ {{ item.start_time }} 当天有效
+ {{ item.start_time }}~{{ item.end_time }}
+
+
+
+ 立即领取
+
+
+ {{ item.state.text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/custom/index.vue b/pages/custom/index.vue
new file mode 100644
index 0000000..e025889
--- /dev/null
+++ b/pages/custom/index.vue
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/dealer/apply.vue b/pages/dealer/apply.vue
new file mode 100644
index 0000000..a4cdb97
--- /dev/null
+++ b/pages/dealer/apply.vue
@@ -0,0 +1,320 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ words.wait_audit.value }}
+
+
+
+
+
+
+
+
+
+
+ {{ words.title.value }}
+
+
+
+
+
+
+
+
+
+ {{ license }}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/dealer/index.vue b/pages/dealer/index.vue
new file mode 100644
index 0000000..555a2ef
--- /dev/null
+++ b/pages/dealer/index.vue
@@ -0,0 +1,310 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ user.nick_name }}
+
+ {{ setting.words.index.words.referee.value }}:{{ refereeName }}
+
+
+
+
+
+
+
+ {{ setting.words.index.words.money.value }} {{ dealer.money }}
+ 元
+
+
+ {{ setting.words.index.words.freeze_money.value }} {{ dealer.freeze_money }}
+ 元
+
+
+
+
+ {{ setting.words.index.words.withdraw.value }}
+
+
+
+
+
+ {{ setting.words.index.words.total_money.value }}
+ {{ dealer.total_money }}元
+
+
+
+
+
+
+
+
+
+
+ {{ setting.words.withdraw_list.title.value }}
+
+
+
+
+
+ {{ setting.words.order.title.value }}
+
+
+
+
+
+ {{ setting.words.team.title.value }}
+
+
+
+
+
+ {{ setting.words.poster.title.value }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ setting.words.index.words.not_dealer.value }}
+
+
+
+ {{ setting.words.index.words.apply_now.value }}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/dealer/order.vue b/pages/dealer/order.vue
new file mode 100644
index 0000000..996d188
--- /dev/null
+++ b/pages/dealer/order.vue
@@ -0,0 +1,220 @@
+
+
+
+
+
+
+
+
+
+
+
+ 订单号:{{ item.order.order_no }}
+
+ {{ item.order.state_text }}
+
+
+
+
+
+
+
+
+ {{ item.user.nick_name }}
+ 消费金额:¥{{ item.order_price }}
+
+
+
+
+ +
+ {{ item.my_money }}
+
+ {{ item.create_time }}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/dealer/poster.vue b/pages/dealer/poster.vue
new file mode 100644
index 0000000..36b038b
--- /dev/null
+++ b/pages/dealer/poster.vue
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/dealer/team.vue b/pages/dealer/team.vue
new file mode 100644
index 0000000..a81986a
--- /dev/null
+++ b/pages/dealer/team.vue
@@ -0,0 +1,264 @@
+
+
+
+
+
+
+
+
+ {{ words.total_team.value }}:{{ teamTotal }}人
+
+
+
+
+
+
+
+
+
+ {{ item.user.nick_name }}
+ {{ item.create_time }}
+
+
+
+
+ ¥
+ {{ item.user.expend_money }}
+
+
+ {{ item.subDealer.first_num + item.subDealer.second_num + item.subDealer.third_num }}个成员
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/dealer/withdraw/apply.vue b/pages/dealer/withdraw/apply.vue
new file mode 100644
index 0000000..75970d9
--- /dev/null
+++ b/pages/dealer/withdraw/apply.vue
@@ -0,0 +1,361 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/dealer/withdraw/list.vue b/pages/dealer/withdraw/list.vue
new file mode 100644
index 0000000..160ad1a
--- /dev/null
+++ b/pages/dealer/withdraw/list.vue
@@ -0,0 +1,246 @@
+
+
+
+
+
+
+
+
+
+
+
+ 提现 {{ item.money }}元
+ {{ item.create_time }}
+
+
+
+ {{ ApplyStatusText[item.apply_status] }}
+
+
+ 驳回原因
+
+
+
+
+
+
+
+
+
+
+ {{ rejectReason }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/empty.vue b/pages/empty.vue
new file mode 100644
index 0000000..89f7847
--- /dev/null
+++ b/pages/empty.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
diff --git a/pages/goods/components/Comment.vue b/pages/goods/components/Comment.vue
new file mode 100644
index 0000000..cae86a0
--- /dev/null
+++ b/pages/goods/components/Comment.vue
@@ -0,0 +1,161 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/goods/components/Service.vue b/pages/goods/components/Service.vue
new file mode 100644
index 0000000..56c8766
--- /dev/null
+++ b/pages/goods/components/Service.vue
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+ 服务
+
+
+
+
+ {{ item.name }}
+ {{ item.summary }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/components/SkuPopup.vue b/pages/goods/components/SkuPopup.vue
new file mode 100644
index 0000000..23abfbb
--- /dev/null
+++ b/pages/goods/components/SkuPopup.vue
@@ -0,0 +1,187 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/goods/components/SlideImage.vue b/pages/goods/components/SlideImage.vue
new file mode 100644
index 0000000..6dd873b
--- /dev/null
+++ b/pages/goods/components/SlideImage.vue
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentIndex }}
+ /
+ {{ images.length + (video ? 1 : 0) }}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/goods/detail.scss b/pages/goods/detail.scss
new file mode 100644
index 0000000..3f6c81b
--- /dev/null
+++ b/pages/goods/detail.scss
@@ -0,0 +1,229 @@
+.container {
+ // 设置ios刘海屏底部横线安全区域
+ // 110 - 18 + 4
+ padding-bottom: calc(constant(safe-area-inset-bottom) + 106rpx + 6rpx);
+ padding-bottom: calc(env(safe-area-inset-bottom) + 106rpx + 6rpx);
+}
+
+// 商品信息
+.goods-info {
+ background: #fff;
+ padding: 25rpx 30rpx;
+}
+
+.info-item__top {
+ min-height: 40rpx;
+ margin-bottom: 20rpx;
+ line-height: 1;
+}
+
+.floor-price__samll {
+ font-size: 26rpx;
+ line-height: 1;
+ color: $main-bg;
+ margin-bottom: -10rpx;
+}
+
+// 商品价
+.floor-price {
+ color: $main-bg;
+ margin-right: 15rpx;
+ font-size: 42rpx;
+}
+
+.original-price {
+ font-size: 26rpx;
+ text-decoration: line-through;
+ color: #959595;
+ margin-right: 15rpx;
+ margin-bottom: -6rpx;
+}
+
+// 会员价标签
+.user-grade {
+ background: #3c3c3c;
+ border-radius: 6rpx;
+ padding: 8rpx 14rpx;
+ margin-right: 15rpx;
+ font-size: 24rpx;
+ color: #EEE0C3;
+}
+
+.goods-sales {
+ font-size: 24rpx;
+ color: #959595;
+}
+
+.info-item__name .goods-name {
+ font-size: 30rpx;
+}
+
+/* 商品分享 */
+
+.goods-share__line {
+ border-left: 1rpx solid #f4f4f4;
+ height: 60rpx;
+ margin: 0 30rpx;
+}
+
+.goods-share .share-btn {
+ line-height: normal;
+ padding: 0;
+ background: none;
+ border-radius: 0;
+ box-shadow: none;
+ font-size: 8pt;
+ border: none;
+ color: #191919;
+}
+
+.goods-share .share-btn::after {
+ border: none;
+}
+
+.goods-share .share__icon {
+ font-size: 40rpx;
+ margin-bottom: 5rpx;
+}
+
+// 商品卖点
+.info-item_selling-point {
+ margin-top: 8rpx;
+ font-size: 24rpx;
+ color: #808080;
+}
+
+// 选择商品规格
+.goods-choice {
+ padding: 26rpx 30rpx;
+ font-size: 28rpx;
+
+ .spec-list {
+ display: flex;
+ align-items: center;
+
+ .spec-name {
+ margin-right: 10rpx;
+ }
+ }
+}
+
+// 商品详情
+.goods-content .item-title {
+ padding: 26rpx 30rpx;
+ font-size: 28rpx;
+}
+
+// 底部操作栏
+.footer-fixed {
+ position: fixed;
+ bottom: var(--window-bottom);
+ left: 0;
+ right: 0;
+ display: flex;
+ z-index: 11;
+ box-shadow: 0 -4rpx 40rpx 0 rgba(151, 151, 151, 0.24);
+ background: #fff;
+
+ // 设置ios刘海屏底部横线安全区域
+ padding-bottom: constant(safe-area-inset-bottom);
+ padding-bottom: env(safe-area-inset-bottom);
+}
+
+.footer-container {
+ width: 100%;
+ display: flex;
+ height: 106rpx;
+}
+
+// 快捷菜单
+.foo-item-fast {
+ box-sizing: border-box;
+ min-width: 214rpx;
+ line-height: 1;
+ display: flex;
+ align-items: center;
+ justify-content: space-evenly;
+ margin-right: 12rpx;
+
+ .fast-item {
+ position: relative;
+ padding: 4rpx 0;
+ line-height: 1;
+ text-align: center;
+ width: 84rpx;
+
+ &--cart {
+ margin-left: 6rpx;
+ .fast-icon { margin-left: -12rpx; }
+ }
+
+ // 角标
+ .fast-badge {
+ display: inline-block;
+ box-sizing: border-box;
+ min-width: 16px;
+ padding: 0 3px;
+ color: #fff;
+ font-weight: 500;
+ font-size: 12px;
+ font-family: -apple-system-font, Helvetica Neue, Arial, sans-serif;
+ line-height: 1.2;
+ text-align: center;
+ background-color: #ee0a24;
+ border: 1px solid #fff;
+ border-radius: 999px;
+ }
+
+ .fast-badge--fixed {
+ position: absolute;
+ top: 0;
+ right: 0;
+ transform-origin: 100%
+ }
+
+ .fast-icon {
+ font-size: 44rpx;
+ margin-bottom: 8rpx;
+ }
+
+ .fast-text {
+ font-size: 22rpx;
+ }
+ }
+}
+
+// 操作按钮
+.foo-item-btn {
+ flex: 1;
+
+ .btn-wrapper {
+ height: 100%;
+ display: flex;
+ align-items: center;
+ }
+
+ .btn-item {
+ flex: 1;
+ font-size: 28rpx;
+ height: 72rpx;
+ margin-right: 16rpx;
+ color: #fff;
+ border-radius: 50rpx;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+
+ // 立即购买按钮
+ .btn-item-main {
+ background: linear-gradient(to right, $main-bg, $main-bg2);
+ color: $main-text;
+ }
+
+ // 购物车按钮
+ .btn-item-deputy {
+ background: linear-gradient(to right, $vice-bg, $vice-bg2);
+ color: $vice-text;
+ }
+}
\ No newline at end of file
diff --git a/pages/goods/detail.vue b/pages/goods/detail.vue
new file mode 100644
index 0000000..ec85d52
--- /dev/null
+++ b/pages/goods/detail.vue
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+
+
+
+
+
+ ¥
+ {{ goods.goods_price_min }}
+
+
+ 会员价
+
+
+ ¥{{ goods.line_price_min }}
+
+
+
+
+ 已售{{ goods.goods_sales }}件
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+
+
+
+
+
+
+ {{ goods.selling_point }}
+
+
+
+
+
+
+
+ 选择:
+ {{ item.spec_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 商品描述
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/goods/list.vue b/pages/goods/list.vue
new file mode 100644
index 0000000..50f4e46
--- /dev/null
+++ b/pages/goods/list.vue
@@ -0,0 +1,472 @@
+
+
+
+
+
+
+
+
+ 综合
+
+
+ 销量
+
+
+ 价格
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_name }}
+
+
+
+
+ {{ item.selling_point }}
+
+
+
+ 已售{{ item.goods_sales }}件
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_name }}
+
+
+
+ ¥{{ item.goods_price_min }}
+ ¥{{ item.line_price_min }}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/groupon/goods/components/SkuPopup.vue b/pages/groupon/goods/components/SkuPopup.vue
new file mode 100644
index 0000000..11cfdbf
--- /dev/null
+++ b/pages/groupon/goods/components/SkuPopup.vue
@@ -0,0 +1,212 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/groupon/goods/components/TaskList.vue b/pages/groupon/goods/components/TaskList.vue
new file mode 100644
index 0000000..8317680
--- /dev/null
+++ b/pages/groupon/goods/components/TaskList.vue
@@ -0,0 +1,197 @@
+
+
+
+
+
+ 进行中的团购
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.user.nick_name }}
+
+
+
+ 还差
+ {{ item.surplus_people }}人
+ 成团
+
+
+ 剩余
+
+
+
+
+ 去参团
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.user.nick_name }}
+
+
+ 去参团
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/groupon/goods/components/goods-sku-popup/index.vue b/pages/groupon/goods/components/goods-sku-popup/index.vue
new file mode 100644
index 0000000..4f8fa46
--- /dev/null
+++ b/pages/groupon/goods/components/goods-sku-popup/index.vue
@@ -0,0 +1,1466 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/groupon/goods/components/goods-sku-popup/number-box/index.vue b/pages/groupon/goods/components/goods-sku-popup/number-box/index.vue
new file mode 100644
index 0000000..6e5133f
--- /dev/null
+++ b/pages/groupon/goods/components/goods-sku-popup/number-box/index.vue
@@ -0,0 +1,473 @@
+
+
+
+
+ -
+
+
+
+ +
+
+
+
+
+
+
diff --git a/pages/groupon/goods/index.vue b/pages/groupon/goods/index.vue
new file mode 100644
index 0000000..11de786
--- /dev/null
+++ b/pages/groupon/goods/index.vue
@@ -0,0 +1,396 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ goods.active_type != ActiveTypeEnum.NORMAL.value ? ActiveTypeEnum[goods.active_type].name2 : '多人拼团' }}
+
+
+ ¥
+ {{ goods.groupon_price }}
+
+ ¥{{ goods.original_price }}
+
+
+
+
+ 已抢{{ goods.active_sales }}件
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+
+
+
+
+
+
+ {{ goods.selling_point }}
+
+
+
+
+ 距离拼团活动{{ goods.active_status == ActiveStatusEnum.STATE_SOON.value ? '开始' : '结束' }}
+ 还剩
+
+
+
+
+
+ 拼团活动已结束,下次记得早点来哦~
+
+
+
+
+
+
+
+
+
+
+ 选择:
+ {{ item.spec_name }}
+
+
+
+
+
+
+
+
+
+
+ 拼团玩法
+ 查看规则
+
+
+
+
+
+ 1
+
+ 选择商品
+
+
+
+ 2
+
+ 开团/参团
+
+
+
+ 3
+
+ 邀请好友
+
+
+
+ 4
+
+ 人满成团
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 商品描述
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ setting.ruleDetail }}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/groupon/goods/style.scss b/pages/groupon/goods/style.scss
new file mode 100644
index 0000000..10ccda3
--- /dev/null
+++ b/pages/groupon/goods/style.scss
@@ -0,0 +1,325 @@
+.container {
+ // 设置ios刘海屏底部横线安全区域
+ // 110 - 18 + 4
+ padding-bottom: calc(constant(safe-area-inset-bottom) + 106rpx + 6rpx);
+ padding-bottom: calc(env(safe-area-inset-bottom) + 106rpx + 6rpx);
+}
+
+// 商品信息
+.goods-info {
+ background: #fff;
+ padding: 25rpx 30rpx;
+}
+
+.info-item__top {
+ min-height: 40rpx;
+ margin-bottom: 20rpx;
+}
+
+.info-item__top .active-tag {
+ color: #fff;
+ background: linear-gradient(to right, #ffa600, #f5b914);
+ padding: 4rpx 16rpx;
+ border-radius: 15rpx;
+ font-size: 26rpx;
+ text-align: center;
+ margin-right: 15rpx;
+}
+
+.floor-price__samll {
+ font-size: 26rpx;
+ line-height: 1;
+ color: $main-bg;
+ margin-bottom: -10rpx;
+}
+
+/* 商品价 */
+.floor-price {
+ color: $main-bg;
+ margin-right: 15rpx;
+ font-size: 42rpx;
+ line-height: 1;
+}
+
+.original-price {
+ font-size: 26rpx;
+ line-height: 1;
+ text-decoration: line-through;
+ color: #959595;
+ margin-bottom: -6rpx;
+}
+
+.goods-sales {
+ font-size: 24rpx;
+ color: #959595;
+}
+
+.info-item__name .goods-name {
+ font-size: 30rpx;
+}
+
+/* 商品分享 */
+
+.goods-share__line {
+ border-left: 1rpx solid #f4f4f4;
+ height: 60rpx;
+ margin: 0 30rpx;
+}
+
+.goods-share .share-btn {
+ line-height: normal;
+ padding: 0;
+ background: none;
+ border-radius: 0;
+ box-shadow: none;
+ font-size: 8pt;
+ border: none;
+ color: #191919;
+}
+
+.goods-share .share-btn::after {
+ border: none;
+}
+
+.goods-share .share__icon {
+ font-size: 40rpx;
+ margin-bottom: 5rpx;
+}
+
+/* 商品卖点 */
+
+.info-item_selling-point {
+ margin-top: 8rpx;
+ font-size: 24rpx;
+ color: #808080;
+}
+
+// 选择商品规格
+.goods-choice {
+ padding: 26rpx 30rpx;
+ font-size: 28rpx;
+
+ .spec-list {
+ display: flex;
+ align-items: center;
+
+ .spec-name {
+ margin-right: 10rpx;
+ }
+ }
+}
+
+/* 商品详情 */
+
+.goods-content .item-title {
+ padding: 26rpx 30rpx;
+ font-size: 28rpx;
+}
+
+/* 底部操作栏 */
+
+.footer-fixed {
+ position: fixed;
+ bottom: var(--window-bottom);
+ left: 0;
+ right: 0;
+ display: flex;
+ z-index: 11;
+ box-shadow: 0 -4rpx 40rpx 0 rgba(151, 151, 151, 0.24);
+ background: #fff;
+
+ // 设置ios刘海屏底部横线安全区域
+ padding-bottom: constant(safe-area-inset-bottom);
+ padding-bottom: env(safe-area-inset-bottom);
+}
+
+.footer-container {
+ width: 100%;
+ display: flex;
+ height: 106rpx;
+}
+
+// 快捷菜单
+.foo-item-fast {
+ box-sizing: border-box;
+ min-width: 214rpx;
+ line-height: 1;
+ display: flex;
+ align-items: center;
+ justify-content: space-evenly;
+ margin-right: 12rpx;
+
+ .fast-item {
+ position: relative;
+ padding: 4rpx 0;
+ line-height: 1;
+ text-align: center;
+ width: 84rpx;
+
+ &--cart {
+ margin-left: 6rpx;
+ .fast-icon { margin-left: -12rpx; }
+ }
+
+ // 角标
+ .fast-badge {
+ display: inline-block;
+ box-sizing: border-box;
+ min-width: 16px;
+ padding: 0 3px;
+ color: #fff;
+ font-weight: 500;
+ font-size: 12px;
+ font-family: -apple-system-font, Helvetica Neue, Arial, sans-serif;
+ line-height: 1.2;
+ text-align: center;
+ background-color: #ee0a24;
+ border: 1px solid #fff;
+ border-radius: 999px;
+ }
+
+ .fast-badge--fixed {
+ position: absolute;
+ top: 0;
+ right: 0;
+ transform-origin: 100%
+ }
+
+ .fast-icon {
+ font-size: 44rpx;
+ margin-bottom: 8rpx;
+ }
+
+ .fast-text {
+ font-size: 22rpx;
+ }
+ }
+}
+
+// 操作按钮
+.foo-item-btn {
+ flex: 1;
+
+ .btn-wrapper {
+ height: 100%;
+ display: flex;
+ align-items: center;
+ }
+
+ .btn-item {
+ flex: 1;
+ height: 100%;
+ font-size: 28rpx;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ border-radius: 0;
+ color: #fff;
+
+ // 发起拼团
+ &.btn-item-main {
+ background: linear-gradient(to right, $main-bg, $main-bg2);
+ color: $main-text;
+ }
+
+ // 单独购买
+ &.btn-item-deputy {
+ background: linear-gradient(to right, $vice-bg, $vice-bg2);
+ color: $vice-text;
+ }
+
+ // 活动结束
+ &.btn-item-gray {
+ background-color: #ccc;
+ }
+ }
+
+ .price {
+ font-size: 28rpx;
+ margin-bottom: 4rpx;
+ }
+}
+
+// 活动状态
+.info-item_status {
+ margin-top: 20rpx;
+ padding: 15rpx 20rpx;
+ font-size: 24rpx;
+ border-radius: 6rpx;
+}
+
+.info-item_status .countdown-icon {
+ font-size: 28rpx;
+ margin-right: 15rpx;
+}
+
+// 活动倒计时
+.info-item_countdown {
+ background: #f0f9ff;
+ color: #8f8f8f;
+}
+
+.info-item_countdown .countdown-icon {
+ color: #1397d8;
+}
+
+// 活动已结束
+.info-item_end {
+ background: #ccc;
+ color: #fff;
+}
+
+// 拼团玩法
+.rule-nav {
+ padding: 24rpx;
+ font-size: 28rpx;
+
+ .rule-simple {
+ margin-top: 35rpx;
+ color: #737373;
+ }
+
+ .i-number {
+ width: 60rpx;
+ height: 60rpx;
+ border-radius: 50%;
+ margin-bottom: 15rpx;
+ border: 1rpx dashed #c0c0c0;
+ }
+}
+
+// 拼团玩法
+.groupon-rules {
+ padding: 20rpx 0;
+ font-size: 29rpx;
+
+ .item-title {
+ padding: 0 30rpx;
+ }
+
+ .rule-simple {
+ margin-top: 35rpx;
+ color: #737373;
+ }
+
+ .i-number {
+ width: 60rpx;
+ height: 60rpx;
+ border-radius: 50%;
+ margin-bottom: 15rpx;
+ border: 1rpx dashed #c0c0c0;
+ }
+}
+
+// 拼团规则 (弹窗)
+.pops-content {
+ padding: 30rpx 48rpx;
+ font-size: 28rpx;
+ line-height: 44rpx;
+ text-align: left;
+ color: #606266;
+ min-height: 320rpx;
+ max-height: 640rpx;
+ box-sizing: border-box;
+}
diff --git a/pages/groupon/index.vue b/pages/groupon/index.vue
new file mode 100644
index 0000000..75a7153
--- /dev/null
+++ b/pages/groupon/index.vue
@@ -0,0 +1,510 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ ActiveTypeEnum[item.active_type].name2 }}
+
+
+
+
+
+
+ {{ item.goods_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ ActiveTypeEnum[item.active_type].name2 }}
+
+
+
+
+
+
+ {{ item.goods.goods_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/groupon/task/index.vue b/pages/groupon/task/index.vue
new file mode 100644
index 0000000..7003244
--- /dev/null
+++ b/pages/groupon/task/index.vue
@@ -0,0 +1,548 @@
+
+
+
+
+
+
+
+
+
+ {{ ActiveTypeEnum[detail.active_type].name2 }}
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+ ¥
+ {{ goods.groupon_price }}
+ ¥{{ goods.original_price }}
+
+
+ {{ detail.people }}人团
+ 拼团省{{ goods.diff_price }}元
+
+
+
+
+
+
+
+
+ 超过有效时间,拼团失败
+
+
+
+ 拼团已成功
+
+
+
+
+
+ 团长
+
+
+
+
+
+
+
+
+ 还差
+ {{ detail.people - detail.joined_people }}
+ 个名额,
+
+
+ 后结束
+
+
+
+ 立即参团
+
+
+
+ 去开团
+
+
+
+ 拼团须知
+ {{ setting.ruleBrief }}
+
+
+
+
+
+
+
+
+
+
+ {{ setting.ruleDetail }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/help/index.vue b/pages/help/index.vue
new file mode 100644
index 0000000..9f1c102
--- /dev/null
+++ b/pages/help/index.vue
@@ -0,0 +1,103 @@
+
+
+
+
+
+ {{ item.title }}
+
+
+ {{ item.content }}
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/index.vue b/pages/index/index.vue
new file mode 100644
index 0000000..2ab4dd2
--- /dev/null
+++ b/pages/index/index.vue
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/live/index.vue b/pages/live/index.vue
new file mode 100644
index 0000000..9caac77
--- /dev/null
+++ b/pages/live/index.vue
@@ -0,0 +1,261 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.live_status_text_1 }}
+
+
+
+ {{ item.room_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.anchor_name }}
+
+
+
+ {{ item.live_status_text_2 }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/login/components/main.vue b/pages/login/components/main.vue
new file mode 100644
index 0000000..3874bb2
--- /dev/null
+++ b/pages/login/components/main.vue
@@ -0,0 +1,354 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 获取验证码
+ 重新发送({{ times }})秒
+
+
+
+
+
+ 登录
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/login/components/mp-alipay.vue b/pages/login/components/mp-alipay.vue
new file mode 100644
index 0000000..7fd537e
--- /dev/null
+++ b/pages/login/components/mp-alipay.vue
@@ -0,0 +1,246 @@
+
+
+
+
+
+ 申请获取以下权限
+ 获得你的公开信息(昵称、头像等)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/login/components/mp-weixin-mobile.vue b/pages/login/components/mp-weixin-mobile.vue
new file mode 100644
index 0000000..3897b90
--- /dev/null
+++ b/pages/login/components/mp-weixin-mobile.vue
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/login/components/mp-weixin.vue b/pages/login/components/mp-weixin.vue
new file mode 100644
index 0000000..fc379c6
--- /dev/null
+++ b/pages/login/components/mp-weixin.vue
@@ -0,0 +1,426 @@
+
+
+
+
+
+
+
+
+ 头像
+
+
+
+ 昵称
+
+
+
+
+
+ 确认
+
+
+ 暂不登录
+
+
+
+
+
+
+ 申请获取以下权限
+ 获得你的公开信息(昵称、头像等)
+
+ 一键登录
+
+
+ 暂不登录
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/login/components/wx-official.vue b/pages/login/components/wx-official.vue
new file mode 100644
index 0000000..447808b
--- /dev/null
+++ b/pages/login/components/wx-official.vue
@@ -0,0 +1,126 @@
+
+
+
+
+
diff --git a/pages/login/index.vue b/pages/login/index.vue
new file mode 100644
index 0000000..f685973
--- /dev/null
+++ b/pages/login/index.vue
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/my-coupon/index.vue b/pages/my-coupon/index.vue
new file mode 100644
index 0000000..bd433a7
--- /dev/null
+++ b/pages/my-coupon/index.vue
@@ -0,0 +1,303 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ CouponTypeEnum[item.coupon_type].name }}
+
+
+ ¥
+ {{ item.reduce_price }}
+
+ {{ item.discount }}折
+ 满{{ item.min_price }}元可用
+
+
+
+ {{ item.name }}
+
+
+ {{ item.start_time }} 当天有效
+ {{ item.start_time }}~{{ item.end_time }}
+
+
+ {{ item.state.text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/center.vue b/pages/order/center.vue
new file mode 100644
index 0000000..5351d0f
--- /dev/null
+++ b/pages/order/center.vue
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/comment/index.vue b/pages/order/comment/index.vue
new file mode 100644
index 0000000..fa8fe78
--- /dev/null
+++ b/pages/order/comment/index.vue
@@ -0,0 +1,566 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_name }}
+
+
+ {{ props.value.name }}
+
+
+
+
+
+
+ ¥
+ {{ item.goods_price }}
+
+
+ ×{{ item.total_num }}
+
+
+
+
+
+
+
+
+ 好评
+
+
+
+
+
+ 中评
+
+
+
+
+
+ 差评
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 上传图片
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/detail.vue b/pages/order/detail.vue
new file mode 100644
index 0000000..f8c2dc5
--- /dev/null
+++ b/pages/order/detail.vue
@@ -0,0 +1,915 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ order.address.name }}
+ {{ order.address.phone }}
+
+
+ {{ region }}
+ {{ order.address.detail }}
+
+
+
+
+
+
+
+
+
+
+
+
+ 订单已拆分多个包裹发货
+
+
+
+
+ 已发货{{ order.delivery.length }}个包裹
+
+
+
+
+
+ 物流公司
+
+ {{ order.delivery[0].express ? order.delivery[0].express.express_name : '--' }}
+ 无需物流
+
+
+
+ 物流单号
+
+ {{ order.delivery[0].express_no ? order.delivery[0].express_no : '--' }}
+
+ 复制
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+ {{ props.value.name }}
+
+
+
+
+
+
+ ¥
+ {{ goods.is_user_grade ? goods.grade_goods_price : goods.goods_price }}
+
+
+ ×{{ goods.total_num }}
+
+
+
+
+
+ 已申请售后
+ 申请售后
+
+
+
+
+
+
+
+ 订单编号
+
+ {{ order.order_no }}
+
+ 复制
+
+
+
+
+ 下单时间
+
+ {{ order.create_time }}
+
+
+
+ 买家留言
+
+ {{ order.buyer_remark ? order.buyer_remark : '--' }}
+
+
+
+
+
+
+
+ 订单金额
+
+ ¥{{ order.total_price }}
+
+
+
+ 优惠券抵扣
+
+ -¥{{ order.coupon_money }}
+
+
+
+ {{ setting.points_name }}抵扣
+
+ -¥{{ order.points_money }}
+
+
+
+ 运费
+
+ +¥{{ order.express_price }}
+
+
+
+ 后台改价
+
+ {{ order.update_price.symbol }}
+ ¥{{ order.update_price.value }}
+
+
+
+
+ 实付款
+
+ ¥
+ {{ order.pay_price }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/express/index.vue b/pages/order/express/index.vue
new file mode 100644
index 0000000..e556055
--- /dev/null
+++ b/pages/order/express/index.vue
@@ -0,0 +1,269 @@
+
+
+
+
+
+
+
+
+
+
+ 共{{ goods.delivery_num }}件
+
+
+
+
+
+
+ 物流公司:
+
+ 无需物流
+ {{ express[curTab].express ? express[curTab].express.express_name : '--' }}
+
+
+
+ 物流单号:
+
+ {{ express[curTab].express_no ? express[curTab].express_no : '--' }}
+
+ 复制
+
+
+
+
+
+
+
+
+
+
+ {{ item.context }}
+
+
+ {{ item.time }}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/extract/check.vue b/pages/order/extract/check.vue
new file mode 100644
index 0000000..76ebfe3
--- /dev/null
+++ b/pages/order/extract/check.vue
@@ -0,0 +1,822 @@
+
+
+
+
+
+
+
+
+ {{ order.address.name }}
+ {{ order.address.phone }}
+
+
+ {{ region }}
+ {{ order.address.detail }}
+
+
+
+
+
+
+
+
+
+
+ 物流公司
+
+ {{ order.express.express_name }}
+
+
+
+ 物流单号
+
+ {{ order.express_no }}
+
+ 复制
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+ {{ props.value.name }}
+
+
+
+
+
+
+ ¥
+ {{ goods.goods_price }}
+
+
+ ×{{ goods.total_num }}
+
+
+
+
+
+ 已申请售后
+
+
+
+
+
+
+
+ 订单编号
+
+ {{ order.order_no }}
+
+ 复制
+
+
+
+
+ 下单时间
+
+ {{ order.create_time }}
+
+
+
+ 买家留言
+
+ {{ order.buyer_remark ? order.buyer_remark : '--' }}
+
+
+
+
+
+
+
+ 订单金额
+
+ ¥{{ order.total_price }}
+
+
+
+ 优惠券抵扣
+
+ -¥{{ order.coupon_money }}
+
+
+
+ {{ setting.points_name }}抵扣
+
+ -¥{{ order.points_money }}
+
+
+
+ 运费
+
+ +¥{{ order.express_price }}
+
+
+
+ 后台改价
+
+ {{ order.update_price.symbol }}
+ ¥{{ order.update_price.value }}
+
+
+
+
+ 实付款
+
+ ¥
+ {{ order.pay_price }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/index.vue b/pages/order/index.vue
new file mode 100644
index 0000000..d278668
--- /dev/null
+++ b/pages/order/index.vue
@@ -0,0 +1,523 @@
+
+
+
+
+
+
+
+
+
+
+ {{ item.create_time }}
+
+
+ {{ item.state_text }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+ {{ props.value.name }}
+
+
+
+
+
+
+ ¥
+ {{ goods.is_user_grade ? goods.grade_goods_price : goods.goods_price }}
+
+
+ ×{{ goods.total_num }}
+
+
+
+
+
+
+ 共{{ item.total_num }}件商品,总金额
+ ¥
+ {{ item.pay_price }}
+
+
+
+
+
+
+ 取消
+
+
+
+
+ 申请取消
+
+
+
+
+
+ 核销码
+
+
+
+
+ 取消申请中
+
+
+ 去支付
+
+
+
+ 确认收货
+
+
+
+ 评价
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/points/log.vue b/pages/points/log.vue
new file mode 100644
index 0000000..cbee13b
--- /dev/null
+++ b/pages/points/log.vue
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+ {{ item.describe }}
+
+
+ {{ item.create_time }}
+
+
+
+ {{ item.value > 0 ? '+' : '' }}{{ item.value }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/refund/apply.vue b/pages/refund/apply.vue
new file mode 100644
index 0000000..bd116e6
--- /dev/null
+++ b/pages/refund/apply.vue
@@ -0,0 +1,434 @@
+
+
+
+
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+
+
+
+ {{ props.value.name }}
+
+
+
+ ×{{ goods.total_num }}
+
+
+
+
+
+
+ 服务类型
+
+ {{ item.name }}
+
+
+
+
+
+ 申请原因
+
+
+
+
+
+
+
+ 退款金额
+ ¥{{ goods.total_pay_price }}
+
+
+
+
+ 上传凭证 (最多6张)
+
+
+
+
+
+
+
+
+
+ 上传图片
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/refund/detail.vue b/pages/refund/detail.vue
new file mode 100644
index 0000000..bd30a48
--- /dev/null
+++ b/pages/refund/detail.vue
@@ -0,0 +1,483 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ detail.orderGoods.goods_name }}
+
+
+
+
+
+ {{ props.value.name }}
+
+
+
+ ×{{ detail.orderGoods.total_num }}
+
+
+
+
+
+
+
+ 商品金额:
+ ¥{{ detail.orderGoods.total_pay_price }}
+
+
+
+
+
+ 已退款金额:
+ ¥{{ detail.refund_money }}
+
+
+
+
+
+
+ 售后类型:
+
+
+ {{ RefundTypeEnum[detail.type].name }}
+
+
+
+
+ 申请原因:
+
+
+ {{ detail.apply_desc }}
+
+
+
+
+ 申请凭证:
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 拒绝原因:
+
+
+ {{ detail.refuse_desc }}
+
+
+
+
+
+
+
+ 退货物流信息
+
+
+
+ 物流公司:{{ detail.express.express_name }}
+
+
+ 物流单号:{{ detail.express_no }}
+
+
+
+ 发货时间:{{ detail.send_time }}
+
+
+
+
+
+
+
+ 商家退货地址
+
+
+
+ 收货人:{{ detail.address.name }}
+
+
+ 联系电话:{{ detail.address.phone }}
+
+
+
+ 详细地址:
+
+
+ {{ region }}
+ {{ detail.address.detail }}
+
+
+
+
+
+ · 未与卖家协商一致情况下,请勿寄到付或平邮
+
+
+ · 请填写真实有效物流信息
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/refund/index.vue b/pages/refund/index.vue
new file mode 100644
index 0000000..0887a9e
--- /dev/null
+++ b/pages/refund/index.vue
@@ -0,0 +1,259 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.create_time }}
+
+ {{ item.state_text }}
+
+
+
+
+
+
+
+
+ {{ item.orderGoods.goods_name }}
+
+
+
+ {{ props.value.name }}
+
+
+
+ ×{{ item.orderGoods.total_num }}
+
+
+
+
+
+ 付款金额:
+ ¥{{ item.orderGoods.total_pay_price }}
+
+
+
+ 查看详情
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/search/index.vue b/pages/search/index.vue
new file mode 100644
index 0000000..25eb8f8
--- /dev/null
+++ b/pages/search/index.vue
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+
+
+
+
+ 最近搜索
+
+
+
+
+ {{ val }}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/sharp/goods/components/SkuPopup.vue b/pages/sharp/goods/components/SkuPopup.vue
new file mode 100644
index 0000000..52e4697
--- /dev/null
+++ b/pages/sharp/goods/components/SkuPopup.vue
@@ -0,0 +1,178 @@
+
+
+
+
+
+
+
diff --git a/pages/sharp/goods/index.vue b/pages/sharp/goods/index.vue
new file mode 100644
index 0000000..685b75b
--- /dev/null
+++ b/pages/sharp/goods/index.vue
@@ -0,0 +1,353 @@
+
+
+
+
+
+
+
+
+
+
+
+ 限时秒杀
+
+
+ ¥
+ {{ goods.seckill_price }}
+
+ ¥{{ goods.original_price }}
+
+
+
+
+ 已抢{{ active.sales_actual }}件
+
+
+
+
+
+
+ {{ goods.goods_name }}
+
+
+
+
+
+
+
+
+ {{ goods.selling_point }}
+
+
+
+
+ 距离秒杀{{ active.active_status == GoodsStatusEnum.STATE_SOON.value ? '开始' : '结束' }}
+ 还剩
+
+
+
+
+
+ 秒杀活动已结束,下次记得早点来哦~
+
+
+
+
+
+
+
+ 选择:
+ {{ item.spec_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 商品描述
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/sharp/goods/style.scss b/pages/sharp/goods/style.scss
new file mode 100644
index 0000000..e1a96e7
--- /dev/null
+++ b/pages/sharp/goods/style.scss
@@ -0,0 +1,306 @@
+.container {
+ // 设置ios刘海屏底部横线安全区域
+ // 110 - 18 + 4
+ padding-bottom: calc(constant(safe-area-inset-bottom) + 106rpx + 6rpx);
+ padding-bottom: calc(env(safe-area-inset-bottom) + 106rpx + 6rpx);
+}
+
+/* 商品信息 */
+
+.goods-info {
+ background: #fff;
+ padding: 25rpx 30rpx;
+}
+
+.info-item__top {
+ min-height: 40rpx;
+ margin-bottom: 20rpx;
+}
+
+.info-item__top .active-tag {
+ color: #fff;
+ background: $main-bg;
+ padding: 4rpx 10rpx;
+ border-radius: 15rpx;
+ font-size: 26rpx;
+ text-align: center;
+ margin-right: 15rpx;
+}
+
+.floor-price__samll {
+ font-size: 26rpx;
+ line-height: 1;
+ color: $main-bg;
+ margin-bottom: -10rpx;
+}
+
+/* 商品价 */
+.floor-price {
+ color: $main-bg;
+ margin-right: 15rpx;
+ font-size: 42rpx;
+ line-height: 1;
+}
+
+.original-price {
+ font-size: 26rpx;
+ line-height: 1;
+ text-decoration: line-through;
+ color: #959595;
+ margin-bottom: -6rpx;
+}
+
+.goods-sales {
+ font-size: 24rpx;
+ color: #959595;
+}
+
+.info-item__name .goods-name {
+ font-size: 30rpx;
+}
+
+/* 商品分享 */
+
+.goods-share__line {
+ border-left: 1rpx solid #f4f4f4;
+ height: 60rpx;
+ margin: 0 30rpx;
+}
+
+.goods-share .share-btn {
+ line-height: normal;
+ padding: 0;
+ background: none;
+ border-radius: 0;
+ box-shadow: none;
+ font-size: 8pt;
+ border: none;
+ color: #191919;
+}
+
+.goods-share .share-btn::after {
+ border: none;
+}
+
+.goods-share .share__icon {
+ font-size: 40rpx;
+ margin-bottom: 5rpx;
+}
+
+/* 商品卖点 */
+
+.info-item_selling-point {
+ margin-top: 8rpx;
+ font-size: 24rpx;
+ color: #808080;
+}
+
+// 选择商品规格
+.goods-choice {
+ padding: 26rpx 30rpx;
+ font-size: 28rpx;
+
+ .spec-list {
+ display: flex;
+ align-items: center;
+
+ .spec-name {
+ margin-right: 10rpx;
+ }
+ }
+}
+
+/* 商品详情 */
+
+.goods-content .item-title {
+ padding: 26rpx 30rpx;
+ font-size: 28rpx;
+}
+
+/* 底部操作栏 */
+
+.footer-fixed {
+ position: fixed;
+ bottom: var(--window-bottom);
+ left: 0;
+ right: 0;
+ display: flex;
+ z-index: 11;
+ box-shadow: 0 -4rpx 40rpx 0 rgba(151, 151, 151, 0.24);
+ background: #fff;
+
+ // 设置ios刘海屏底部横线安全区域
+ padding-bottom: constant(safe-area-inset-bottom);
+ padding-bottom: env(safe-area-inset-bottom);
+}
+
+.footer-container {
+ width: 100%;
+ display: flex;
+ height: 106rpx;
+}
+
+// 快捷菜单
+.foo-item-fast {
+ box-sizing: border-box;
+ width: 256rpx;
+ line-height: 1;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ .fast-item {
+ position: relative;
+ padding: 4rpx 10rpx;
+ line-height: 1;
+ // text-align: center;
+
+ .fast-icon {
+ margin-bottom: 6rpx;
+ }
+
+ &--home {
+ margin-right: 30rpx;
+ }
+
+ &--cart {
+ .fast-icon { padding-left: 3px; }
+ }
+
+ // 角标
+ .fast-badge {
+ display: inline-block;
+ box-sizing: border-box;
+ min-width: 16px;
+ padding: 0 3px;
+ color: #fff;
+ font-weight: 500;
+ font-size: 12px;
+ font-family: -apple-system-font, Helvetica Neue, Arial, sans-serif;
+ line-height: 1.2;
+ text-align: center;
+ background-color: #ee0a24;
+ border: 1px solid #fff;
+ border-radius: 999px;
+ }
+ .fast-badge--fixed {
+ position: absolute;
+ top: 0;
+ right: 0;
+ transform-origin: 100%
+ }
+
+ .fast-icon {
+ font-size: 46rpx;
+ }
+
+ .fast-text {
+ font-size: 24rpx;
+ }
+
+ }
+
+
+}
+
+// 操作按钮
+.foo-item-btn {
+ flex: 1;
+
+ .btn-wrapper {
+ height: 100%;
+ display: flex;
+ align-items: center;
+ }
+
+ .btn-item {
+ flex: 1;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-radius: 0;
+ }
+
+ // 立即砍价
+ .btn-item {
+ flex: 1;
+ height: 100%;
+ font-size: 30rpx;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ &.btn--main {
+ background: linear-gradient(to right, $main-bg, $main-bg2);
+ color: $main-text;
+ }
+ &.btn--gray {
+ background-color: #ccc;
+ color: #fff;
+ }
+ }
+}
+
+// 活动状态
+.info-item_status {
+ margin-top: 20rpx;
+ padding: 15rpx 20rpx;
+ font-size: 24rpx;
+ border-radius: 6rpx;
+}
+
+.info-item_status .countdown-icon {
+ font-size: 28rpx;
+ margin-right: 15rpx;
+}
+
+// 活动倒计时
+.info-item_countdown {
+ background: #f0f9ff;
+ color: #8f8f8f;
+}
+
+.info-item_countdown .countdown-icon {
+ color: #1397d8;
+}
+
+// 活动已结束
+.info-item_end {
+ background: #ccc;
+ color: #fff;
+}
+
+// 砍价玩法
+.bargain-rules {
+ padding: 20rpx 0;
+ font-size: 29rpx;
+
+ .item-title {
+ padding: 0 30rpx;
+ }
+
+ .rule-simple {
+ margin-top: 35rpx;
+ color: #737373;
+ }
+
+ .i-number {
+ width: 60rpx;
+ height: 60rpx;
+ border-radius: 50%;
+ margin-bottom: 15rpx;
+ border: 1rpx dashed #c0c0c0;
+ }
+}
+
+// 砍价规则(弹窗)
+.pops-content {
+ padding: 30rpx 48rpx;
+ font-size: 28rpx;
+ line-height: 44rpx;
+ text-align: left;
+ color: #606266;
+ min-height: 320rpx;
+ max-height: 640rpx;
+ box-sizing: border-box;
+}
diff --git a/pages/sharp/index.vue b/pages/sharp/index.vue
new file mode 100644
index 0000000..73b64ba
--- /dev/null
+++ b/pages/sharp/index.vue
@@ -0,0 +1,469 @@
+
+
+
+
+
+
+
+
+
+ {{ item.status_text }}
+
+
+ {{ item.active_time }}
+ {{ item.status_text }}
+
+
+
+
+
+
+
+
+
+
+ {{ tabbar[curTabIndex].active_time }}
+ {{ tabbar[curTabIndex].status_text2 }}
+
+
+
+ {{ tabbar[curTabIndex].status == ActiveStatusEnum.STATE_BEGIN.value ? '距结束' : '距开始' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.goods_name }}
+
+
+
+
+
+
+ {{ item.progress }}%
+
+ 已抢{{ item.sales_actual }}件
+
+
+
+
+ ¥
+ {{ item.seckill_price_min }}
+
+
+ ¥
+ {{ item.original_price }}
+
+
+
+
+
+ {{ tabbar[curTabIndex].status == ActiveStatusEnum.STATE_BEGIN.value ? '马上抢' : '查看商品' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/shop/detail.vue b/pages/shop/detail.vue
new file mode 100644
index 0000000..4ccab81
--- /dev/null
+++ b/pages/shop/detail.vue
@@ -0,0 +1,209 @@
+
+
+
+
+
+
+
+
+
+ {{ detail.shop_hours }}
+
+
+
+
+
+
+
+ {{ detail.region.province }}{{ detail.region.city }}{{ detail.region.region }}{{ detail.address }}
+
+
+
+
+
+
+
+
+
+
+ {{ detail.phone }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/shop/extract.vue b/pages/shop/extract.vue
new file mode 100644
index 0000000..bcd7cbb
--- /dev/null
+++ b/pages/shop/extract.vue
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+ {{ item.shop_name }}
+
+
+ 地址:{{ item.region.province }}{{ item.region.city }}{{ item.region.region }}{{ item.address }}
+
+
+ 联系电话:{{ item.phone }}
+
+
+
+ {{ item.distance_unit }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/bind/index.vue b/pages/user/bind/index.vue
new file mode 100644
index 0000000..19497dc
--- /dev/null
+++ b/pages/user/bind/index.vue
@@ -0,0 +1,311 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 获取验证码
+ 重新发送({{ times }})秒
+
+
+
+
+
+ 确认绑定
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/index.vue b/pages/user/index.vue
new file mode 100644
index 0000000..4d42d6e
--- /dev/null
+++ b/pages/user/index.vue
@@ -0,0 +1,762 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ userInfo.nick_name }}
+
+
+
+
+
+
+
+ {{ userInfo.grade.name }}
+
+
+
+ {{ userInfo.mobile }}
+
+
+
+
+
+
+
+
+ 未登录
+ 点击登录账号
+
+
+
+
+
+
+ 点击绑定手机号,确保账户安全
+ 去绑定
+
+
+
+
+
+
+
+ {{ isLogin ? assets.balance : '--' }}
+
+
+ 账户余额
+
+
+
+
+ {{ isLogin ? assets.points : '--' }}
+
+
+ {{ setting[SettingKeyEnum.POINTS.value].points_name }}
+
+
+
+
+ {{ isLogin ? assets.coupon : '--' }}
+
+
+ 优惠券
+
+
+
+
+
+
+
+
+
+ 我的钱包
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+ {{ item.count }}
+ 99+
+
+
+
+
+
+
+ 我的服务
+
+
+
+
+
+
+ {{ item.name }}
+
+ {{ item.count }}
+ 99+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+ 退出登录
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/personal/index.vue b/pages/user/personal/index.vue
new file mode 100644
index 0000000..60cd051
--- /dev/null
+++ b/pages/user/personal/index.vue
@@ -0,0 +1,240 @@
+
+
+
+ 个人信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/wallet/balance/log.vue b/pages/wallet/balance/log.vue
new file mode 100644
index 0000000..455bddc
--- /dev/null
+++ b/pages/wallet/balance/log.vue
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+ {{ item.describe }}
+
+
+ {{ item.create_time }}
+
+
+
+ {{ item.money > 0 ? '+' : '' }}{{ item.money }}元
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/wallet/index.vue b/pages/wallet/index.vue
new file mode 100644
index 0000000..6624950
--- /dev/null
+++ b/pages/wallet/index.vue
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+
+ {{ userInfo.balance }}
+
+
+ 账户余额(元)
+
+
+
+
+
+ 充 值
+
+
+
+ 充值记录
+
+
+ 账单详情
+
+
+
+
+
+
+
+
+
diff --git a/pages/wallet/recharge/index.vue b/pages/wallet/recharge/index.vue
new file mode 100644
index 0000000..9f71b01
--- /dev/null
+++ b/pages/wallet/recharge/index.vue
@@ -0,0 +1,508 @@
+
+
+
+
+ 账户余额
+
+
+ ¥{{ personal.balance }}
+
+
+
+
+ 充值金额
+
+
+
+
+
+ {{ item.money }}
+
+
+ 送{{ item.gift_money }}
+
+
+
+
+
+
+
+
+
+
+
+ 支付方式
+
+
+
+
+
+
+
+
+ {{ PayMethodEnum[item.method].name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 充值说明
+
+
+ {{ setting.describe }}
+
+
+
+
+
+
+
+ 请在{{ PayMethodClientNameEnum[tempUnifyData.method] }}内完成支付,如果您已经支付成功,请点击“已完成支付”按钮
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/wallet/recharge/order.vue b/pages/wallet/recharge/order.vue
new file mode 100644
index 0000000..a53d22d
--- /dev/null
+++ b/pages/wallet/recharge/order.vue
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+ {{ '充值成功' }}
+
+
+ {{ item.pay_time }}
+
+
+
+ +{{ item.actual_money }}元
+
+
+
+
+
+
+
+
+
+
diff --git a/static/app-plus/privacy.html b/static/app-plus/privacy.html
new file mode 100644
index 0000000..1c3c7c6
--- /dev/null
+++ b/static/app-plus/privacy.html
@@ -0,0 +1,746 @@
+
+
+
+
+
+ 隐私政策
+
+
+
+
+
+
+
+
+
+
隐私政策
+
+
+ 在使用萤火商城各项产品或服务前,请您务必仔细阅读并透彻理解本政策,特别是以粗体或下划线标识的条款,您应重点阅读,在确认充分理解并同意后再开始使用。如对本政策内容有任何疑问、意见或建议,您可通过萤火商城提供的各种联系方式与我们联系。
+
+
+
+
+
+
+ 您的信任对我们非常重要,我们深知个人信息对您的重要性,我们将按法律法规要求,采取相应安全保护措施,尽力保护您的个人信息安全可控。鉴于此,萤火商城服务提供者(或简称“我们”或“萤火商城”)制定本《隐私政策》(下称“本政策/本隐私政策”)并提醒您:本政策适用于萤火商城提供的所有产品和服务及我们的关联公司的产品或服务(如萤火商城小程序),您可使用萤火商城平台帐号登录上述产品或服务,如上述产品或服务未设独立隐私政策的,则本政策同样适用于该部分产品或服务。
+
+
+
+ 需要特别说明的是,本政策不适用于其他第三方向您提供的服务,也不适用于萤火商城中已另行独立设置隐私政策的产品或服务。
+
+
+ 第一部分 定义
+
+
+ 萤火商城服务提供者:烟台晴好网络科技有限公司
+
+
+ 个人信息:指以电子或者其他方式记录的能够单独或者与其他信息结合识别特定自然人身份或者反映特定自然人活动情况的各种信息。
+
+
+ 个人敏感信息:指包括身份证件号码、个人生物识别信息、银行账号、财产信息、行踪轨迹、交易信息、14岁以下(含)儿童信息个人信息(我们将在本隐私政策中对具体个人敏感信息以粗体进行显著标识)。
+
+
+ 个人信息删除:指在实现日常业务功能所涉及的系统中去除个人信息的行为,使其保持不可被检索、访问的状态。
+
+
+ 儿童:指不满十四周岁的未成年人。
+
+
+ 除另有约定外,本政策所用定义与萤火商城平台用户协议中的定义具有相同的涵义。
+
+
+ 第二部分 隐私政策
+
+
+ 本隐私政策部分将帮助您了解以下内容:
+
+
+ 一、我们如何收集和使用您的信息
+
+
+ 二、我们如何使用Cookie
+
+
+ 三、我们如何共享、转让、公开披露您的信息
+
+
+ 四、我们如何存储您的信息
+
+
+ 五、我们如何保护您的信息
+
+
+ 六、您如何管理您的信息
+
+
+ 七、我们如何处理未成年人的信息
+
+
+ 八、您的信息如何在全球范围转移
+
+
+ 九、本隐私政策如何更新
+
+
+ 十、如何联系我们
+
+
+ 一、我们如何收集和使用您的信息
+
+
+ 在您使用我们的产品及/或服务时,我们需要/可能需要收集和使用的您的个人信息包括如下两种:
+
+
+
+ 1、为实现向您提供我们产品及/或服务的基本功能,我们将按照《网络安全法》的规定收集、使用您的个人信息。如您拒绝提供相应信息,您将无法正常使用我们的产品及/或服务,但不影响您浏览我们的网页及客户端页面;
+
+
+
+ 2、为实现向您提供我们产品及/或服务的附加功能,您可选择授权我们收集、使用您的个人敏感信息。如您拒绝提供,您将无法正常使用相关附加功能或无法达到我们拟达到的功能效果,但并不会影响您正常使用我们产品及/或服务的基本功能。
+
+
+ 您理解并同意:
+
+
+
+ 1、我们致力于打造多样的产品和服务以满足您的需求。因我们向您提供的产品和服务种类众多,且不同用户选择使用的具体产品/服务范围存在差异,因此基本/附加功能及收集使用的个人信息类型、范围会有所区别,请以具体的产品/服务功能为准;
+
+
+
+ 2、为给您带来更好的产品和服务体验,我们在持续努力改进我们的技术,随之我们可能会不时推出新的或优化后的功能,可能需要重新收集、使用您的个人信息或变更个人信息使用目的或方式。对此,我们将通过更新本政策、弹窗、页面提示方式另行向您说明对应信息的收集目的、范围及使用方式,并征求您的明示同意。在此过程中,如果您有任何疑问、意见或建议的,您可通过萤火商城提供的各种联系方式与我们联系,我们会尽快为您作出解答。
+
+
+ 我们会为实现本政策下述的各项功能,收集和使用您的个人信息:
+
+
+ (一) 帮助您成为我们的会员
+
+
+ 1、基础会员服务
+
+
+ 注册成为会员并使用我们的会员服务,您需要提供手机号码、拟使用的会员名和密码用于创建萤火商城平台账户。如果您仅需使用浏览、搜索服务,您不需要注册成为我们的会员及提供上述信息。
+
+
+
+ 在您登录帐户时,我们可能会根据您提供的上述信息校验您的会员身份,确保我们是在为您本人提供服务。若存在依法需确定您会员身份的场景(包括依法为您扣缴税费、行政执法或司法诉讼中相关主体认定等)时,您授权我们可获取您对应支付账户的相关认证信息用于上述目的。
+
+
+ 我们会根据您的会员账户使用情况为您提供相应会员所对应的基本权益。
+
+
+ 2、附加会员服务
+
+
+ 如果您选择提供真实姓名、性别、出生年月日、居住地个人信息,我们可以为您提供更加个性化的会员服务。为保证交易辨识度,您的帐户昵称、头像将公开显示。
+
+
+
+ 授权登录:经您同意后我们向第三方共享您的账户信息(如微信,我们可能会共享您的头像、昵称),使您可以便捷地以萤火商城平台帐户实现第三方平台的注册或登录。此外,我们可能会根据您的授权从第三方处获取您的第三方账户信息,并与您的萤火商城平台账户进行绑定,使您可通过第三方账户直接登录、使用我们的产品及/或服务。我们将在您授权同意的范围内使用您的相关信息。
+
+
+
+ 3、账户信息展示:如果您已拥有萤火商城平台账户,我们可能会在萤火商城平台服务中显示您的上述个人信息(实人认证仅显示认证是否通过的结果),以及您在萤火商城平台上或与萤火商城平台账户相关联的产品和服务中执行的操作(您可通过萤火商城平台账户在我们提供的手机萤火商城入口或其他产品/服务入口使用我们及/或关联公司提供的产品或服务),包括通过萤火商城平台账户集中展示您的个人资料、优惠权益、交易订单。我们会尊重您对萤火商城平台服务和萤火商城平台账户设置所做的选择。
+
+
+ (二) 为您提供商品或服务信息展示
+
+
+ 在您使用我们服务过程中,为识别账号异常状态、了解产品适配性、向您提供更契合您需求的页面展示和搜索结果,我们可能会自动收集您的使用情况并存储为网络日志信息,包括:
+
+
+
+ 设备信息:我们会根据您在软件安装及/或使用中的具体操作,接收并记录您所使用的设备相关信息(包括设备型号、操作系统版本、设备设置、唯一设备标识符、设备环境软硬件特征信息)、设备所在位置相关信息(包括您授权的GPS位置以及WLAN接入点)。
+
+
+
+ 服务日志信息:当您使用我们的网站或客户端提供的产品或服务时,我们会自动收集您对我们服务的详细使用情况,作为服务日志保存,包括浏览、点击查看、搜索查询、收藏、添加至购物车、交易、售后、关注分享信息、发布信息,以及IP地址、浏览器类型、电信运营商、使用语言、访问日期和时间。
+
+
+
+ 请注意,单独的设备信息、服务日志信息是无法识别特定自然人身份的信息。如果我们将这类非个人信息与其他信息结合用于识别特定自然人身份,或者将其与个人信息结合使用,则在结合使用期间,这类非个人信息将被视为个人信息,除取得您授权或法律法规另有规定外,我们会将这类信息做匿名化、去标识化处理。
+
+
+ 如果您不想接受我们给您发送的商业广告,您可按照信息中提示的退订步骤进行退订或与我们的客服联系进行退订。在您使用我们提供的站内搜索服务时,我们也同时提供了不针对您个人偏好的商品、服务。
+
+
+ 此外,我们也会为了不断改进和优化上述的功能来使用您的上述信息。
+
+
+ (三) 为您提供收藏、加购、关注与分享功能
+
+
+
+ 在您浏览我们客户端的过程中,您可以选择对感兴趣的商品及/或服务进行收藏、添加至购物车、与您感兴趣的商家/品牌建立关注关系、通过我们提供的功能组件向其他第三方分享信息。在您使用上述功能的过程中,我们会收集包括您的收藏及添加购物车的记录、关注关系、分享历史在内的服务日志信息用于实现上述功能及其他我们明确告知的目的。
+
+
+ (四)帮助您完成下单及订单管理
+
+
+
+ 当您在我们的产品及/或服务中订购具体商品及/或服务时,我们会通过系统为您生成购买该商品及/或服务的订单。在下单过程中,您需至少提供您的收货人姓名、收货地址、收货人联系电话,同时该订单中会载明您所购买的商品及/或服务信息、具体订单号、订单创建时间、您应支付的金额,我们收集这些信息是为了帮助您顺利完成交易、保障您的交易安全、查询订单信息、提供客服与售后服务及其他我们明确告知的目的。
+
+
+ 您可以通过萤火商城为其他人订购商品及/或服务,您需要提供该实际订购人的前述个人信息,若其中涉及儿童个人信息的,您需在提供前征得对应儿童监护人的同意。
+
+
+ 为便于您了解查询订单信息并对订单信息进行管理,我们会收集您在使用我们服务过程中产生的订单信息用于向您展示及便于您对订单进行管理。
+
+
+ 您可额外填写/选择包括其他联系电话、收货时间在内的更多附加信息以确保商品或服务的准确送达。
+
+
+ (五) 帮助您完成支付
+
+
+
+ 为完成订单支付,您需要提供支付账户并选择付款方式,我们会将您的萤火商城平台账户会员名、对应的支付账户会员名、订单支付相关信息及其他反洗钱法律要求的必要信息与第三方支付公司共享。如您选择由其他金融机构为您提供支付服务的,我们或我们的关联公司、合作伙伴还会将您的包括银行卡号、有效期在内的银行卡支付必要信息与您选择的相应金融机构共享。
+
+
+ 您可以请求其他人为您付款,那么您需要提供代付人的支付账户及/或手机号码。
+
+
+ 为使我们及时获悉并确认您的支付进度及状态,为您提供售后与争议解决服务,您同意我们可自您所选择的交易对象、支付公司或您选择的其他金融机构处收集与支付进度相关信息。
+
+
+ (六) 帮助向您完成商品或服务的交付
+
+
+
+ 为保证您购买的商品及/或服务能够顺利、安全、准确送达,我们会向为萤火商城平台提供物流信息系统和技术服务的物流配送公司披露订单相关配送信息,并由其根据商品及/或服务提供主体的指定向相应的物流配送主体同步相关配送信息。您知晓并同意相应物流配送主体不可避免地获知及使用您的配送信息,用于完成交付目的。
+
+
+ 为使我们及时获悉并确认交付进度及状态,向您提供售后与争议解决服务,您同意我们可自物流相关服务主体处收集与交付进度相关信息。
+
+
+ (七) 客服及争议处理
+
+
+ 当您与我们联系或提出售中售后、争议纠纷处理申请时,为了保障您的账户及系统安全,我们需要您提供必要的个人信息以核验您的会员身份。
+
+
+
+ 为便于与您联系、尽快帮助您解决问题或记录相关问题的处理方案及结果,我们可能会保存您与我们的通信/通话记录及相关内容(包括账号信息、订单信息、您为了证明相关事实提供的其他信息,或您留下的联系方式信息),如果您针对具体订单进行咨询、投诉或提供建议的,我们会使用您的账号信息和订单信息。
+
+
+ (八) 为您提供安全保障
+
+
+
+ 为提高您使用我们及我们关联公司、合作伙伴提供服务的安全性,保护您或其他用户或公众的人身财产安全免遭侵害,更好地预防钓鱼网站、欺诈、网络漏洞、计算机病毒、网络攻击、网络侵入安全风险,更准确地识别违反法律法规或萤火商城相关协议规则的情况,我们可能使用或整合您的会员信息、交易信息、设备信息、服务日志信息以及我们关联公司、合作伙伴取得您授权或依据法律共享的信息,来综合判断您账户及交易风险、进行身份验证、检测及防范安全事件,并依法采取必要的记录、审计、分析、处置措施。
+
+
+ (九)为您提供其他附加服务
+
+
+
+ 为向您提供更便捷、更优质、个性化的产品及/或服务,努力提升您的体验,我们在向您提供的以下附加服务中可能会收集、缓存和使用您的个人信息。如果您不提供这些信息,不会影响您使用萤火商城的浏览、搜索基本服务,但您可能无法获得这些附加服务给您带来的用户体验。这些附加服务包括:
+
+
+ 1、基于相机/摄像头的附加服务:您可在开启相机(摄像头)权限后使用该功能。即使您已同意开启相机(摄像头)权限,我们也仅会在您主动点击相应图标或录制视频时通过相机获取照片信息。。
+
+
+ 2、基于读取、写入外置存储卡的附加服务:您可以在开启存储权限后,使用该功能上传您的照片/图片/视频,以实现发表评论/分享或与客服沟通提供证明等功能。
+
+
+ 3.基于读取手机状态和身份信息的附加服务:我们将在您开启权限后收集您的IMEI、MSI、设备MAC地址、软件列表、设备序列号、android ID,根据您的设备确认您的账户安全,实现安全风控。
+
+
+ 4、基于查看WLAN连接的附加功能:查看wifi连接状态,确保网络可靠性以及大流量场景下提示用户流量使用。
+
+
+ 5、基于检索正在运行应用的附加功能:此功能可以使您在浏览萤火商城商品、服务时跳转到第三方APP的指定页面。
+
+
+
+ 6、基于相册(图片库/视频库)的图片/视频访问及上传、外部存储、缓存、发布音视频功能的附加服务:您可在开启相册权限后使用该功能上传您的照片/图片/视频,发表评论/分享、拍照购物或与客服沟通提供证明等功能。我们可能会通过您所上传的照片/图片来识别您需要购买的商品或服务,或使用包含您所上传照片或图片的评论信息。您如果拒绝授权提供,将无法使用此功能,但不影响您正常使用萤火商城的其他功能。
+
+
+
+ 7、基于麦克风的语音技术相关附加服务:您可在开启麦克风权限后使用麦克风实现语音购物功能,或与客服联系或与客服机器人实现语音交互,在这些功能中我们会收集您的录音内容以识别您的购物需求,或响应您的客服及争议处理等需求。请您知晓,即使您已同意开启麦克风权限,我们也仅会在您主动点击客户端内麦克风图标或录制视频时通过麦克风获取语音信息。
+
+
+ 8、基于安装应用的附加服务:平台会定期更新应用的客户端,您可以在更新的时候,打开APP直接进行新版本的更新安装及使用。
+
+
+ 9、基于应用程序获得当前运行任务的信息的附加服务:平台在统计APP数据的情况下,会对APP的页面进行判断。
+
+
+ 10、基于保持APP在唤醒状态下的附加服务:您在本应用观看视频的情况下,需要保持应用为唤醒的状态。
+
+
+ 您理解并同意,上述附加服务可能需要您在您的设备中开启您的位置信息
+
+
+
+ (地理位置)、摄像头(相机)、相册(图片库)、麦克风(语音)及/或日历、外部存储的访问权限,以实现这些权限所涉及信息的收集和使用。请您注意,您开启任一权限即代表您授权我们可以收集和使用相关个人信息来为您提供对应服务,您一旦关闭任一权限即代表您取消了授权,我们将不再基于对应权限继续收集和使用相关个人信息,也无法为您提供该权限所对应的服务。但是,您关闭权限的决定不会影响此前基于您的授权所进行的信息收集及使用。
+
+
+ (十)其他
+
+
+
+ 1、若你提供的信息中含有其他用户的个人信息,在向萤火商城提供这些个人信息之前,您需确保您已经取得合法的授权。若其中涉及儿童个人信息的,您需在发布前取得对应儿童监护人的同意,前述情形下监护人有权通过本政策第十条的途径联系我们,要求更正或删除涉及儿童个人信息的内容。
+
+
+ 2、若我们将信息用于本政策未载明的其他用途,或者将基于特定目的收集而来的信息用于其他目的,或者我们主动从第三方处获取您的个人信息,均会事先获得您的同意。
+
+
+
+ 若我们从第三方处间接获取您的信息的,我们会在收集前明确以书面形式要求该第三方在已依法取得您同意后收集个人信息,并向您告知共享的信息内容,且涉及敏感信息的在提供给我们使用前需经过您的明确确认,要求第三方对个人信息来源的合法性和合规性作出承诺,如第三方有违反行为的,我们会明确要求对方承担相应法律责任;同时,我们对个人信息会进行安全加固(包括敏感信息报备、敏感信息加密存储、访问权限控制)。我们会使用不低于我们对自身用户个人信息同等的保护手段与措施对间接获取的个人信息进行保护。
+
+
+ 3、征得授权同意的例外
+
+
+ 您充分理解并同意,我们在以下情况下收集、使用您的个人信息无需您的授权同意,且我们可能不会响应您提出的更正/修改、删除、注销、撤回同意、索取信息的请求:
+
+
+ (1)与国家安全、国防安全有关的;
+
+
+ (2)与公共安全、公共卫生、重大公共利益有关的;
+
+
+ (3)与犯罪侦查、起诉、审判和判决执行等司法或行政执法有关的;
+
+
+ (4)出于维护您或其他个人的生命、财产相关的重大合法权益但又很难得到本人同意的;
+
+
+ (5)您自行向社会公众公开的个人信息;
+
+
+ (6)从合法公开披露的信息中收集个人信息的,如合法的新闻报道、政府信息公开等渠道。
+
+
+ (7)根据与您签订和履行相关协议或其他书面文件所必需的;
+
+
+ (8)用于维护所提供的产品及/或服务的安全稳定运行所必需的,例如发现、处置产品及/或服务的故障;
+
+
+ (9)为合法的新闻报道所必需的;
+
+
+ (10)学术研究机构基于公共利益开展统计或学术研究所必要,且对外提供学术研究或描述的结果时,对结果中所包含的个人信息进行去标识化处理的;
+
+
+ (11)法律法规规定的其他情形。
+
+
+
+ 请知悉,根据适用的法律,若我们对个人信息采取技术措施和其他必要措施进行处理,使得数据接收方无法重新识别特定个人且不能复原,或我们可能会对收集的信息进行去标识化地研究、统计分析和预测,用于改善萤火商城的内容和布局,为商业决策提供产品或服务支撑,以及改进我们的产品和服务(包括使用匿名数据进行机器学习或模型算法训练),则此类处理后数据的使用无需另行向您通知并征得您的同意。
+
+
+
+ 4、如我们停止运营萤火商城产品或服务,我们将及时停止继续收集您个人信息的活动,将停止运营的通知以逐一送达或公告的形式通知您,并对我们所持有的与已关停业务相关的个人信息进行删除或匿名化处理。涉及儿童个人信息的,我们会并将停止运营的通知及时告知儿童监护人。
+
+
+ 二、我们如何使用Cookie
+
+
+
+ 为使您获得更轻松的访问体验、向您推荐您可能感兴趣的内容,我们会在您的移动设备上存储名为Cookie的小数据文件。Cookie通常包含标识符、站点名称以及一些号码和字符。借助Cookie,我们能够存储您的账户信息、商品记录、订单记录、商品的数据。
+
+
+ 若您不同意我们在您的移动设备上存储Cookie的小数据文件,您可停止使用萤火商城。
+
+
+ 三、我们如何共享、转让、公开披露您的信息
+
+
+ (一)共享
+
+
+ 我们不会与萤火商城服务提供者以外的公司、组织和个人共享您的个人信息,但以下情况除外:
+
+
+ 1、在法定情形下的共享:我们可能会根据法律法规规定、诉讼、争议解决需要,或按行政、司法机关依法提出的要求,对外共享您的个人信息。
+
+
+ 2、在获取明确同意的情况下共享:获得您的明确同意后,我们会与其他方共享您的个人信息。
+
+
+ 3、在您主动选择情况下共享:您通过萤火商城平台购买商品或服务,我们会根据您的选择,将您的订单信息中与交易有关的必要信息共享给相关商品或服务的提供者,以实现您的交易及售后服务需求。
+
+
+
+ 4、与关联公司间共享:为便于我们基于萤火商城平台账户向您提供产品和服务,推荐您可能感兴趣的信息,识别会员账号异常,保护萤火商城关联公司或其他用户或公众的人身财产安全免遭侵害,您的个人信息可能会与我们的关联公司和/或其指定的服务提供商共享。我们只会共享必要的个人信息,且受本隐私政策中所声明目的的约束,如果我们共享您的个人敏感信息或关联公司改变个人信息的使用及处理目的,将再次征求您的授权同意。
+
+
+
+ 5、与授权合作伙伴共享:我们可能委托授权合作伙伴为您提供某些服务或代表我们履行职能,我们仅会出于本隐私政策声明的合法、正当、必要、特定、明确的目的共享您的信息,授权合作伙伴只能接触到其履行职责所需信息,且不得将此信息用于其他任何目的。对于涉及儿童个人信息的,我们不允许合作伙伴进行转委托。
+
+
+ 目前,我们的授权合作伙伴包括以下类型:
+
+
+
+ (1)广告、分析服务类的授权合作伙伴。我们会委托这些合作伙伴处理与广告覆盖面和有效性相关的信息,但不会提供您的个人身份信息,或者我们将这些信息进行去标识化处理,以便它不会识别您个人。这类合作伙伴可能将上述信息与他们合法获取的其他数据相结合,以执行我们委托的广告服务或决策建议,帮助其在不识别您个人身份的前提下提升广告有效触达率。
+
+
+
+ (2)供应商、服务提供商和其他合作伙伴。我们将信息发送给支持我们业务的供应商、服务提供商和其他合作伙伴,这些支持包括受我们委托提供的技术基础设施服务、分析我们服务的使用方式、衡量广告和服务的有效性、提供客户服务、支付便利或进行学术研究和调查,这些信息难以与您的身份信息相关联,这些信息将帮助我们分析、衡量广告和相关服务的有效性。
+
+
+
+ 为保障我们客户端的稳定运行、功能实现,使您能够使用和享受更多的服务及功能,我们的应用中会嵌入授权合作伙伴的SDK。我们会对授权合作伙伴获取有关信息的应用程序接口(API)、软件工具开发包(SDK)进行严格的安全检测,并与授权合作伙伴约定严格的数据保护措施,令其按照本政策以及其他任何相关的保密和安全措施来处理个人信息。
+
+
+ (二)转让
+
+
+ 我们不会将您的个人信息转让给任何公司、组织和个人,但以下情况除外:
+
+
+ 1、在获取明确同意的情况下转让:获得您的明确同意后,我们会向其他方转让您的个人信息;
+
+
+
+ 2、在萤火商城服务提供者发生合并、收购或破产清算情形,或其他涉及合并、收购或破产清算情形时,如涉及到个人信息转让,我们会要求新的持有您个人信息的公司、组织继续受本政策的约束,否则我们将要求该公司、组织和个人重新向您征求授权同意。
+
+
+ (三)公开披露
+
+
+ 我们仅会在以下情况下,公开披露您的个人信息:
+
+
+ 1、获得您明确同意或基于您的主动选择,我们可能会公开披露您的个人信息;
+
+
+
+ 2、如果我们确定您出现违反法律法规或严重违反萤火商城平台相关协议及规则的情况,或为保护萤火商城平台用户或公众的人身财产安全免遭侵害,我们可能依据法律法规或征得您同意的情况下披露关于您的个人信息,包括相关违规行为以及萤火商城平台已对您采取的措施。
+
+
+ (四)共享、转让、公开披露个人信息时事先征得授权同意的例外
+
+
+ 以下情形中,共享、转让、公开披露您的个人信息无需事先征得您的授权同意:
+
+
+ 1、与国家安全、国防安全有关的;
+
+
+ 2、与公共安全、公共卫生、重大公共利益有关的;
+
+
+ 3、与犯罪侦查、起诉、审判和判决执行等司法或行政执法有关的;
+
+
+ 4、出于维护您或其他个人的生命、财产相关的重大合法权益但又很难得到本人同意的;
+
+
+ 5、您自行向社会公众公开的个人信息;
+
+
+ 6、从合法公开披露的信息中收集个人信息的,如合法的新闻报道、政府信息公开。
+
+
+ 请知悉,根据适用的法律,若我们对个人信息采取技术措施和其他必要措施进行处理,使得数据接收方无法重新识别特定个人且不能复原,则此类处理后数据的共享、转让、公开披露无需另行向您通知并征得您的同意。
+
+
+ 四、我们如何存储您的信息
+
+
+ (一)存储地点
+
+
+ 我们在中华人民共和国境内运营中收集和产生的个人信息,将存储在中国境内。以下情形下,我们会在履行了法律规定的义务后,向境外实体提供您的个人信息:
+
+
+ 1、适用的法律有明确规定;
+
+
+ 2、获得您的明确授权;
+
+
+ 3、您通过互联网进行跨境交易等个人主动行为。
+
+
+ 针对以上情形,我们会通过合同等形式确保以不低于本政策规定的程度保护您的个人信息。
+
+
+ (二)存储期限
+
+
+
+ 我们会采取合理可行的措施,尽力避免收集和处理无关的个人信息。我们只会在达成本政策所述目的所需的期限内保留您的个人信息,除非法律有强制的留存要求,例如《中华人民共和国电子商务法》要求商品和服务信息、交易信息保存时间自交易完成之日起不少于三年。我们判断个人信息的存储期限主要参考以下标准并以其中较长者为准:
+
+
+ 1、完成与您相关的交易目的、维护相应交易及业务记录,以应对您可能的查询或投诉;
+
+
+ 2、保证我们为您提供服务的安全和质量;
+
+
+ 3、您是否同意更长的留存期间;
+
+
+ 4、是否存在保留期限的其他特别约定。
+
+
+
+ 在超出保留期间后,我们会在15天内根据适用法律的要求删除您的个人信息,或使其匿名化处理。此外,在注销账户后,我们将在15天内停止为您提供产品和服务,并根据您的要求,删除您的个人信息或匿名化处理,法律法规另有规定的除外。
+
+
+ 五、我们如何保护您的信息
+
+
+ (一)我们已采取符合业界标准、合理可行的安全防护措施保护您的信息,防止个人信息遭到未经授权访问、公开披露、使用、修改、损坏或丢失。例如,在您的浏览器与服务器之间交换数据时受
+
+
+
+ SSL协议加密保护;我们同时对萤火商城网站提供HTTPS协议安全浏览方式;我们会使用加密技术提高个人信息的安全性;我们会使用受信赖的保护机制防止个人信息遭到恶意攻击;我们会部署访问控制机制,尽力确保只有授权人员才可访问个人信息;以及我们会举办安全和隐私保护培训课程,加强员工对于保护个人信息重要性的认识。
+
+
+
+ (二)我们会采取合理可行的措施,尽力避免收集无关的个人信息。我们只会在达成本政策所述目的所需的期限内保留您的个人信息,除非法律有强制的存留要求,例如《中华人民共和国电子商务法》要求商品和服务信息、交易信息保存时间自交易完成之日起不少于三年。而我们判断前述期限的标准包括:
+
+
+ 1、完成与您相关的交易目的、维护相应交易及业务记录、应对您可能的查询或投诉;
+
+
+ 2、保证我们为您提供服务的安全和质量;
+
+
+ 3、您是否同意更长的留存期间;
+
+
+ 4、是否存在保留期限的其他特别约定。
+
+
+ 在您的个人信息超出保留期间后,我们会根据适用法律的要求删除您的个人信息,或使其匿名化处理。
+
+
+
+ (三)互联网并非绝对安全的环境,使用萤火商城平台服务时,我们强烈建议您不要使用非萤火商城平台推荐的通信方式发送您的信息。您可以通过我们的服务建立联系和相互分享。当您通过我们的服务创建交流、交易或分享时,您可以自主选择沟通、交易或分享的对象,作为能够看到您的交易内容、联络方式、交流信息或分享内容相关信息的第三方。
+
+
+
+ 在使用萤火商城服务进行网上交易时,您不可避免地要向交易对方或潜在的交易对方披露自己的个人信息,如联络方式或联系地址。请您妥善保护自己的个人信息,仅在必要的情形下向他人提供。如您发现自己的个人信息尤其是您的账户或密码发生泄露,请您立即联络萤火商城客服,以便我们根据您的申请采取相应措施。
+
+
+ 请注意,您在使用我们服务时自愿共享甚至公开分享的信息,可能会涉及您或他人的个人信息甚至个人敏感信息。请您更加谨慎地考虑,是否在使用我们的服务时共享甚至公开分享相关信息。
+
+
+
+ 请使用复杂密码,协助我们保证您的账号安全。我们将尽力保障您发送给我们的任何信息的安全性。如果我们的物理、技术或管理防护设施遭到破坏,导致信息被非授权访问、公开披露、篡改或毁坏,导致您的合法权益受损,我们将承担相应的法律责任。
+
+
+ (四)我们将不定期更新并公开安全风险、个人信息安全影响有关内容,您可通过萤火商城公告方式获得。
+
+
+
+ (五)在不幸发生个人信息安全事件后,我们将按照法律法规的要求向您告知:安全事件的基本情况和可能的影响、我们已采取或将要采取的处置措施、您可自主防范和降低风险的建议、对您的补救措施。事件相关情况我们将以邮件、信函、电话、推送通知的方式告知您,难以逐一告知个人信息主体时,我们会采取合理、有效的方式发布公告。
+
+
+
+ 在不幸发生儿童个人信息安全事件后,我们将按照法律法规的要求,及时向儿童及其监护人告知:安全事件的基本情况和可能的影响、我们已采取或将要采取的处置措施、儿童及其监护人可自主防范和降低风险的建议、对儿童及其监护人的补救措施。我们将及时将事件相关情况以APP推送通知、发送邮件/短消息告知儿童及其监护人。难以逐一告知时,我们会采取合理、有效的方式发布相关警示信息。同时,我们还将按照监管部门要求,主动上报儿童个人信息安全事件的处置情况。若儿童及其监护人的合法权益受损,我们将依法承担相应的法律责任。同时,我们还将按照监管部门要求,上报个人信息安全事件的处置情况。
+
+
+ 六、您如何管理您的信息
+
+
+ 您可以通过以下方式访问及管理您的信息:
+
+
+ (一)查询、更正和补充您的信息
+
+
+ 您有权查询、更正或补充您的信息。您可以通过以下方式自行进行:
+
+
+ 1、登录手机萤火商城客户端,进入“我的”页面,点击页面右上方设置的图标查询、更正个人资料及个人账户相关信息;
+
+
+ (二)删除您的信息
+
+
+ 您可以通过“(一)查询、更正和补充您的信息”中列明的方式注销您的部分信息。
+
+
+ 在以下情形中,您可以向我们提出删除个人信息的请求:
+
+
+ 1、如果我们处理个人信息的行为违反法律法规;
+
+
+ 2、如果我们收集、使用您的个人信息,却未征得您的明确同意;
+
+
+ 3、如果我们处理个人信息的行为严重违反了与您的约定;
+
+
+ 4、如果您不再使用我们的产品或服务,或您主动注销了账号;
+
+
+ 5、如果我们永久不再为您提供产品或服务。
+
+
+ 若我们决定响应您的删除请求,我们还将同时尽可能通知从我们处获得您的个人信息的主体,并要求其及时删除(除非法律法规另有规定,或这些主体已独立获得您的授权)。
+
+
+ 当您或我们协助您删除相关信息后,因为适用的法律和安全技术,我们可能无法立即从备份系统中删除相应的信息,我们将安全地存储您的个人信息并将其与任何进一步处理隔离,直到备份可以清除或实现匿名。
+
+
+ (三)改变您授权同意的范围
+
+
+
+ 如果您不再选择将您的个人信息提供给我们或拒绝使用我们提供的部分服务,您可以通过设置您的智能移动设备关闭您授权给萤火商城的部分权限。以华为手机为例:通过手机中的“设置--隐私--权限管理”,选择关闭部分或全部您已授权给我们的权限。
+
+
+ 当您收回同意后,我们将不再处理相应的个人信息。但您收回同意的决定,不会影响此前基于您的授权而开展的个人信息处理。
+
+
+ (四)约束信息系统自动决策
+
+
+
+ 在某些业务功能中,我们可能仅依据信息系统、算法在内的非人工自动决策机制做出决定。如果这些决定显著影响您的合法权益,您有权要求我们做出解释,我们也将在不侵害萤火商城商业秘密或其他用户权益、社会公共利益的前提下提供申诉方法。
+
+
+ (五)响应您的上述请求
+
+
+ 为保障安全,您可能需要提供书面请求,或以其他方式证明您的身份。我们可能会先要求您验证自己的身份,然后再处理您的请求。
+
+
+ 我们将在15天内做出答复。如您不满意,还可以通过萤火商城客服发起投诉。
+
+
+
+ 对于您合理的请求,我们原则上不收取费用,但对多次重复、超出合理限度的请求,我们将酌情收取一定费用。对于与您的身份不直接关联的信息、无端重复信息,或者需要过多技术手段(例如,需要开发新系统或从根本上改变现行惯例)、给他人合法权益带来风险或者不切实际的请求,我们可能会予以拒绝。
+
+
+ 在以下情形中,按照法律法规要求,我们将无法响应您的请求:
+
+
+ 1、与国家安全、国防安全有关的;
+
+
+ 2、与公共安全、公共卫生、重大公共利益有关的;
+
+
+ 3、与犯罪侦查、起诉、审判和执行判决有关的;
+
+
+ 4、有充分证据表明个人信息主体存在主观恶意或滥用权利的;
+
+
+ 5、响应您的请求将导致您或其他个人、组织的合法权益受到严重损害的;
+
+
+ 6、涉及商业秘密的。
+
+
+ 七、我们如何处理未成年人的信息
+
+
+ 在电子商务活动中我们推定您具有相应的民事行为能力。如您为未成年人,我们要求您请您的父母或其他监护人仔细阅读本隐私政策,并在征得您的父母或其他监护人同意的前提下使用我们的服务或向我们提供信息。
+
+
+
+ 如果我们识别出您是儿童用户的,请您告知我们您的监护人信息,我们将通知您的监护人并要求您的监护人同意儿童个人信息收集使用规则。对于经父母或其他监护人同意使用我们的产品或服务而收集儿童个人信息的情况,我们只会在法律法规允许、父母或其他监护人明确同意或者保护儿童所必要的情况下使用、共享、转让或披露此信息。
+
+
+ 若您是儿童的父母或其他监护人,请您关注您监护的儿童是否是在取得您的授权同意之后使用我们的服务的。如您对您所监护的儿童的个人信息有疑问,请通过第九节中的联系方式与我们联系。
+
+
+ 八、您的信息如何在全球范围转移
+
+
+ 我们在中华人民共和国境内运营中收集和产生的个人信息,存储在中国境内,以下情形除外:
+
+
+ 1、适用的法律有明确规定;
+
+
+ 2、获得您的明确授权;
+
+
+ 3、您通过互联网进行跨境交易的个人主动行为。
+
+
+ 针对以上情形,我们会确保依据本隐私政策对您的个人信息提供足够的保护。
+
+
+ 九、本隐私政策如何更新
+
+
+ 我们的隐私政策可能变更。
+
+
+ 未经您明确同意,我们不会限制您按照本隐私政策所应享有的权利。我们会在App上发布对隐私政策的更新。
+
+
+ 对于重大变更,我们还会提供更为显著的通知(包括我们会通过萤火商城公示的方式进行通知甚至向您提供弹窗提示)。
+
+
+ 本政策所指的重大变更包括但不限于:
+
+
+ 1、我们的服务模式发生重大变化。如处理个人信息的目的、处理的个人信息类型、个人信息的使用方式;
+
+
+ 2、我们在控制权方面发生重大变化。如并购重组引起的信息控制者变更;
+
+
+ 3、个人信息共享、转让或公开披露的主要对象发生变化;
+
+
+ 4、您参与个人信息处理方面的权利及其行使方式发生重大变化;
+
+
+ 5、我们负责处理个人信息安全的责任部门、联络方式及投诉渠道发生变化;
+
+
+ 6、个人信息安全影响评估报告表明存在高风险。
+
+
+ 十、如何联系我们
+
+
+ 您可以通过以下方式与我们联系,我们将在15天内回复您的请求:
+
+
+ 1、如对本政策内容、儿童个人信息有任何疑问、意见或建议,您可通过萤火商城客服邮箱:admin@yiovo.com与我们联系。
+
+
+ 2、如发现个人信息可能被泄露,您可以联系我们的客服人员进行投诉举报;
+
+
+ 如果您对我们的回复不满意,特别是您认为我们的个人信息处理行为损害了您的合法权
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/static/app-plus/protocol.html b/static/app-plus/protocol.html
new file mode 100644
index 0000000..f7a36d1
--- /dev/null
+++ b/static/app-plus/protocol.html
@@ -0,0 +1,604 @@
+
+
+
+
+
+ 服务协议
+
+
+
+
+
+
+
+
+
+
服务协议
+
+
+ 本应用在此特别提醒,在您注册使用本应用提供的软件、小程序、网站等(以下统称“本应用产品和服务”或“本应用”)前,仔细阅读本《服务协议》(下称本协议)中的各个条款,尤其是以粗体或下划线标示的条款,包括但不限于免除或者限制本应用责任的条款、对用户权利进行限制的条款以及约定争议解决方式、司法管辖的条款。您有权同意或者不同意本协议。
+
+
+
+
+
+
+ 如您决定注册使用本应用,完成我们的注册流程并通过点击同意的形式在线签署本协议即表示您已充分理解并同意接受本协议所有及任何条款的约束。本协议包括我们根据法律法规规定、本协议制定的其他政策、规则、公告声明以及本协议包含的超链接协议等(除非特有所指,合称为“本协议”)。
+
+
+
+
+
+
+
+
+ 第一条 本应用平台服务
+
+
+
+
+
+ 1. 本协议是由烟台晴好网络科技有限公司的萤火商城APP(简称“本应用”或者“我们”)与用户(或称为“您”)就您使用本应用产品和服务所做的权利义务的约定。
+
+
+
+
+
+
+
+
+ 2. 本应用平台为用户提供以下平台服务:
+
+
+
+
+
+ (1)为您展示商品或服务
+
+
+
+
+
+ 本应用会为您展示商品或服务的相关信息,供您浏览、了解所需的商品或服务。
+
+
+
+
+
+ (2)为您推送商品或服务
+
+
+
+
+
+ 本应用会为您制定更符合您喜好和需求的个性化推送商品或服务的页面展示和搜索结果,提升您的使用体验。
+
+
+
+
+
+ (3)为您在购物平台上购买商品或服务提供优惠通道
+
+
+
+
+
+ 当您欲购买在本应用上浏览的商品或服务时,您通过本应用领取优惠券或其他福利后,直接进入销售该商品或服务的淘宝、天猫店铺和其他商家店铺并完成下单流程。
+
+
+
+
+
+ (4)为您提供持续、稳定的技术平台服务
+
+
+
+
+
+ 无论用户是否登录APP,本应用将持续、稳定的为您提供技术平台服务,直至您以书面告知或注销账户的方式停止使用本应用服务。
+
+
+
+
+
+
+ 4.
+ 使用本应用或通过本应用相关链接产生的购买行为应当基于真实的消费需求,不得存在对商品及/或服务实施恶意购买、恶意维权等扰乱电商平台正常交易秩序的行为。若您严重违背社会公德、提供虚假注册身份信息、经我们判定认为存在恶意退货或不合常理的高退货率以及其他不符合正常消费习惯的情形、或经判定认为属于损害本应用不正当行为时,基于维护交易秩序及交易安全的需要,本应用发现上述情形时有权主动执行对订单不予结算、冻结该用户账号等操作。
+
+
+
+
+
+ 5. 为了更好的服务用户,本应用可能会不定时举办各类活动,如果您选择参加活动,应当认真查阅各类活动另行制定的规则。您同意不会采取作弊、利用系统漏洞等手段扰乱本应用秩序。
+
+
+
+
+
+ 第二条 用户账户的注册、使用与注销
+
+
+
+
+
+ 1.
+ 本应用重视未成年人的安全与个人信息保护,注册本应用的用户应是具备完全民事行为能力和民事权利能力的自然人。用户一旦注册成功,我们将推定您具有相应的民事行为能力。若您不具备前述与您行为相适应的民事行为能力,则您及您的监护人应依照法律规定承担因使用本APP而可能产生的一切法律后果。
+
+
+
+
+
+ 2.
+ 用户应提供本人正在合法有效使用的手机号码进行“本应用”账号注册,并且您同意本应用将您手机号码及手机设备识别码等作为用户身份识别信息。该号码是我们与您联系的重要渠道,如发生变更,应及时通知我们。否则,可能会因无法有效联系到您,或无法及时处理与您相关的争议等事项而影响您的相关权益。
+
+
+
+
+
+ 3.
+ 用户注册账号所提供和使用的信息应当真实、有效、合法。注册成功后,本应用将为您配置账户,该账户之所有权本应用所有,您在本协议有效期内仅享有使用权。由于账户关联用户的个人信息及本应用商业信息,该账户仅限您本人使用,未经本应用书面同意,您不得出借、出租或作其它形式的转让。
+
+
+
+
+
+ 4.
+ 本应用有权根据法律法规或政策规定,或根据自行制定的规范或规则,对违规、不当使用账户等行为予以限制或予以注销,如本应用判断您的账户可能涉及信息泄漏及/或影响本应用信息安全或者正常运营的及/或侵害或影响其他用户权益的,本应用可拒绝向您提供服务或终止本协议。
+
+
+
+
+
+ 5.
+ 用户可以申请注销已注册的账户。如果您需要注销您的帐户,我们将在核实您的身份、要求您完成未完成的交易、完成资金结算等(例如已充值或已获得的虚拟资产等)后,为您提供帐户注销服务。在账户注销完成后,本应用不在为您提供任何服务。账户注销后,您的个人信息我们会使其在前台系统保持不可检索、访问的状态,或对其进行匿名化处理。您知晓,根据法律法规规定,相关交易信息保存时间应自交易完成之日起不少于三年。
+
+
+
+
+
+
+ 6.
+ 为使您更好地使用本应用的各项服务,并保障您的账户安全,我们将按照相关法律法规规定要求您完成实名认证。如涉及第三方支付、资金结算或其他可能需要您提供银行卡信息的业务,您应当保证提供的银行帐户信息或第三方支付帐户信息真实、有效、合法,且属于您本人所有,我们及关联公司或我们合作的第三方支付机构将根据您提供的银行帐户信息或第三方支付帐户信息与您进行资金结算。您提供的银行帐户信息或第三方支付帐户信息错误或您拒绝提供,您应当理解您将无法使用本APP部分功能、第三方支付机构提供的支付功能以及您将无法获得结算资金。您理解并同意如因您未能提供有效的上述信息导致资金无法结算时,该部分资金不会因为未支付给您而产生利息。我们可以向您发送通知以便于您可以及时提供信息,若超出一定时间未得到回复,我们有权收回该部分结算资金自行处理。
+
+
+
+
+
+ 7.
+ 如发现任何未经您授权使用您的账户登录本应用的情形,我们建议您第一时间与我们联系,但您应理解本应用对任何请求采取行动均需要合理时间,且本应用所采取的行动可能无法避免或者阻止侵害结果的形成或者扩大,除本应用存在法定过错外,本应用不对该侵害结果及扩大承担任何责任。
+
+
+
+
+
+
+
+
+
+
+
+ 第三条 用户个人信息收集、使用与保护
+
+
+
+
+
+ 1. 详见《隐私协议》。
+
+
+
+
+
+ 2. 《隐私协议》是本协议正文的主要组成部分,与本协议共同约束用户与本应用。
+
+
+
+
+
+ 3.
+ 本应用接入第三方SDK初衷是为了向用户提供更成熟、优质的平台技术服务,有关服务可能会涉及到个人信息收集,在收集用户信息之前,本应用会征求您的授权同意。如您对此存在疑问,您可以通过附件链接查阅第三方SDK发布的隐私协议。您的明示授权或继续使用,将视为您同意信息的合理采集以及相关的隐私协议。
+
+
+
+
+
+ 第四条 本应用使用规范
+
+
+
+
+
+ 1.
+ 用户在注册、使用本应用过程中制作、复制、发布、上传、传播的任何形式的内容,包括但不限于账号头像、昵称、标签、地址等注册信息及认证资料,或以文字、语音、图片、视频、图文等任何形式发送、回复或自动回复的消息、相关链接页面以及其他使用账号或本服务所产生的内容均不得违反现行法律、法规、规章、政策规定。
+
+
+
+
+
+ 2. 如果用户在境外注册、使用本应用,应同时遵守所在地或相关国家(地区)的法律法规。
+
+
+
+
+
+ 3. 用户不得利用“本应用”账号或提供的服务以任何形式制作、复制、发布、上传、传播如下法律、法规和政策禁止的内容:
+
+
+
+
+
+ (1) 反对宪法所确定的基本原则的;
+
+
+
+
+
+ (2) 危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家统一的;
+
+
+
+
+
+ (3) 损害国家荣誉和利益的;
+
+
+
+
+
+ (4) 煽动民族仇恨、民族歧视,破坏民族团结的;
+
+
+
+
+
+ (5) 破坏国家宗教政策,宣扬邪教和封建迷信的;
+
+
+
+
+
+ (6) 散布谣言,扰乱社会秩序,破坏社会稳定的;
+
+
+
+
+
+ (7) 散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;
+
+
+
+
+
+ (8) 侮辱或者诽谤他人,侵害他人合法权益的;
+
+
+
+
+
+ (9) 含有法律、行政法规禁止的其他内容的信息。
+
+
+
+
+
+ 4.用户不得利用“本应用”账号或服务以任何形式制作、复制、发布、上传、传播如下干扰“本应用”正常运营,以及侵犯其他用户或第三方合法权益的内容:
+
+
+
+
+
+ (1) 含有任何性或性暗示的;
+
+
+
+
+
+ (2) 含有辱骂、恐吓、威胁内容的;
+
+
+
+
+
+ (3) 含有骚扰、垃圾广告、恶意信息、诱骗信息的;
+
+
+
+
+
+ (4) 涉及他人隐私、个人信息或资料的;
+
+
+
+
+
+ (5) 侵害他人名誉权、肖像权、知识产权、商业秘密等合法权利的;
+
+
+
+
+
+ (6) 含有其他干扰本服务正常运营和侵犯其他用户或第三方合法权益内容的信息。
+
+
+
+
+
+ 5. 用户不得利用“本应用”账号或服务进行如下行为:
+
+
+
+
+
+ (1) 提交、发布虚假信息,或盗用他人头像或资料,冒充、利用他人名义的;
+
+
+
+
+
+ (2) 虚构事实、隐瞒真相以误导、欺骗他人的;
+
+
+
+
+
+ (3) 利用技术手段批量建立虚假账号的;
+
+
+
+
+
+ (4) 利用“本应用”账号或服务从事任何违法犯罪活动的;
+
+
+
+
+
+ (5) 制作、发布与以上行为相关的方法、工具,或对此类方法、工具进行运营或传播,无论这些行为是否为商业目的;
+
+
+
+
+
+ (6) 其他违反法律法规规定、侵犯其他用户合法权益、干扰“本应用”正常运营或本应用未明示授权的行为。
+
+
+
+
+
+ 6.
+ 用户不得利用或针对本应用及相关服务进行任何危害计算机网络安全、危害社会经济秩序的相关行为,如果我们有理由认为您的行为违反或可能违反上述约定的,我们可独立进行判断并处理,且在任何时候有权在不事先通知的情况下终止向您提供服务,并依法追究相关责任。
+
+
+
+
+
+ 7.
+ 用户不得以本应用的名义传送或发布信息;也不得以易被公众或第三方混淆为本应用官方意见的方式传送或发布信息。用户在本应用传送、发布的任何内容并不反映或代表,也不得被视为反映或代表本应用的观点、立场;用户须保证其通过“本应用”账号或服务所传送的信息真实、合法、无害、准确、有效。如因用户传送的信息违法、给本应用或第三方造成损害的,用户应当依法予以赔偿,本应用有权依据法律法规、政策、本协议条款对相关违法、错误信息作出的处理。
+
+
+
+
+
+ 8. 经许可后,用户、第三方对本APP软件及相关服务的信息内容的分享、转发等行为,应符合以下规范:
+
+
+
+
+
+ (1)对抓取、统计、获得的相关搜索热词、命中率、分类、搜索量、点击率、阅读量等相关数据,未经公司事先书面同意,不得将上述数据以任何方式公示、提供、泄露给任何第三人;
+
+
+
+
+
+ (2)不得对本APP软件及相关服务的源网页进行任何形式的任何改动,包括但不限于本APP软件及相关服务的首页链接、广告系统链接等入口,也不得对本APP软件及相关服务的源页面的展示进行任何形式的遮挡、插入、弹窗等妨碍;
+
+
+
+
+
+ (4)不得把相关数据内容用于公司许可范围之外的目的,进行任何形式的销售和商业使用,或向第三方泄露、提供或允许第三方为任何方式的使用。
+
+
+
+
+
+ (5)用户向任何第三人分享、转发、复制本APP软件及相关服务信息内容的行为,还应遵守公司为此制定的其他规范和标准。
+
+
+
+
+
+ 9.
+ 未经本应用许可,任何人不得以包括通过机器人、蜘蛛等程序或设备监视、复制、传播、展示、镜像、上载、下载等方式直接或间接盗取本APP软件及相关服务的视频、图文等信息内容,或以任何方式(包括但不限于隐藏或者修改域名、平台特有标识、用户名等)删除或改变相关信息内容的权利管理电子信息。本应用等文字及/或标识,以及其他标识、徽记、产品和服务名称均为本应用所有,如有宣传、展示等任何使用需要,您必须取得本应用事先书面授权。
+
+
+
+
+
+ 第五条 违规用户的处理
+
+
+
+
+
+ 1.
+ 如果本应用发现用户有违反法律法规、政策规定、“外部电商平台”管理规定、本协议条款约定,或被其他用户投诉具有违反法律法规、政策规定、本协议条款约定的行为,本应用有权依据法律法规、政策及本协议条款对用户的违法、错误的行为或内容进行处理,并视情节轻重对违规的用户处以包括但不限于警告、账号封禁、功能封禁、账户冻结、不予结算资金等处罚,并将有关违法信息向有关部门报告,用户应承担由此产生的一切法律后果。
+
+
+
+
+
+ 2. 本应用对上述违规内容的违规内容的审查仅为初步表面审查,不对审查结论承担责任;如果用户对处理结果存在异议,则应提供相应的证明文件,并与我们或投诉方沟通或采取法律途径解决争议。
+
+
+
+
+
+ 3.
+ 因用户违反法律法规、政策规定、本协议约定或发生其它过错,导致任何第三方向本应用或其合作方、关联方主张任何索赔、要求的,用户应承担相关责任。如果因此造成本应用或其合作方、关联方承担相关责任或发生其他任何损失的,包括律师费、调查取证费、电子数据公证费、差旅费等,本应用或其合作方、关联方有权要求该用户承担赔偿责任或者向该用户追偿。
+
+
+
+
+
+ 4.
+ 被处理用户如对投诉内容或处理决定有异议,可提交申诉意见,本应用将对申诉进行审查,并自行合理判断决定是否变更处罚措施。对于因投诉所导致的处理,本应用仍有权根据投诉方与用户共同确定的意见或司法机关生效法律文书增加、变更或撤销对用户的处理。
+
+
+
+
+
+ 第六条本协议的生效、变更与终止
+
+
+
+
+
+ 1. 本协议自您勾选并点击“我已阅读并同意”本协议时即生效。如未点击确认本协议之前事实上已在使用本平台功能的,则本协议在您的事实行为发生之时生效。
+
+
+
+
+
+ 2.
+ 由于互联网行业发展迅速、APP及服务频繁迭代更新等特点,我们可能会对相关的产品或服务进行升级优化,您理解并同意我们会根据商业需要,在符合法律规定的情况下对本协议的部分条款进行更新,更新后的协议条款将代替原来的协议并在正式发布之日起生效,您可以在相关服务页面查阅最新版本的协议条款。
+
+
+
+
+
+ 3.
+ 如本协议后续发生变更,我们在APP公布更新后的协议,该公布行为视为我们已通知您更新内容。我们也可能会采用本协议约定的其他通知方式通知您。如您对更新后的服务协议有任何疑问,您可通过本协议提及的联系邮箱向本应用工作人员反馈,我们会及时为您解答。如您不同意更新后的协议,您可以停止使用本APP,本协议修改后,如果您继续使用本APP的,即视为您已接受修改后的协议。
+
+
+
+
+
+ 4. 存在以下任一情形的,本协议在用户与本应用之间终止。因终止本协议给对方或其他第三方合法权益造成损失的,有权要求对造成的损失承担法律责任:
+
+
+
+
+
+ (1)用户账号注销的,本协议自注销之日起在用户和本应用之间终止;
+
+
+
+
+
+ (2)因违反法律法规、政策规定或本协议约定导致本协议终止的;
+
+
+
+
+
+ (3)因 任一方违反本协议约定、发生其他违法或不当行为导致本协议终止的;
+
+
+
+
+
+ (4)发生其他导致本协议终止的情形。
+
+
+
+
+
+ 5. 本协议终止时,本应用有权要求您就您账户下未完成的交易、未支付的订单、未结算的资金等进行处理,若您在合理时间内未处理,本应用有权以合理的方式代为处理,并就处理过程中可能带来损失的向您追偿。
+
+
+
+
+
+ 第七条 争议解决条款
+
+
+
+
+
+ 本协议的效力、解释及纠纷的解决,适用于中华人民共和国法律。若用户和本应用之间发生任何纠纷或争议,首先应友好协商解决,协商不成的,用户同意将纠纷或争议提交本应用住所地有管辖权的人民法院管辖。
+
+
+
+
+
+
+
+
+
+
+
+ 第八条 不可抗力条款
+
+
+
+
+
+ 1. “不可抗力”是指本协议双方不能合理控制、不可预见或即使预见亦无法避免的事件,该事件妨碍、影响或延误任何一方根据本协议履行其全部或部分义务。该事件包括但不限于政府行为、自然灾害、战争或任何其他类似事件。
+
+
+
+
+
+ 2. 遭受不可抗力事件的一方可暂行中止履行本合同项下的义务直至不可抗力事件的影响消除为止并且无需为此而承担违约责任;但应尽最大努力克服该事件,减轻负面影响。
+
+
+
+
+
+ 第九条其他条款
+
+
+
+
+
+ 1. 除非我们另行声明,本应用的所有产品、技术、软件、程序、数据及其他信息(包括文字、图标、图片、照片、音频、视频、图表、色彩组合、版面设计等)的所有权利(包括版权、商标权、专利权、商业秘密及其他相关权利)均归本应用所有。
+
+
+
+
+
+ 2. 用户理解并接受:本协议的正文还包括《隐私协议》,与本协议具有同等法律效力,共同约束用户与本应用。
+
+
+
+
+
+ 3. 本协议的任何条款不论因何种原因无效或不具可执行性,不影响其余条款在用户与本应用双方之间的法律效力。
+
+
+
+
+
+ 4. 如您对本协议条款有任何疑问或者需要帮助,您可通过客服邮箱:admin@yiovo.com与我们联系。
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/static/background/user-header2.png b/static/background/user-header2.png
new file mode 100644
index 0000000..c53235e
Binary files /dev/null and b/static/background/user-header2.png differ
diff --git a/static/channel/wechat.png b/static/channel/wechat.png
new file mode 100644
index 0000000..4e62d40
Binary files /dev/null and b/static/channel/wechat.png differ
diff --git a/static/default-avatar.png b/static/default-avatar.png
new file mode 100644
index 0000000..94e0a72
Binary files /dev/null and b/static/default-avatar.png differ
diff --git a/static/default-logo.png b/static/default-logo.png
new file mode 100644
index 0000000..f0a6e47
Binary files /dev/null and b/static/default-logo.png differ
diff --git a/static/empty-02.png b/static/empty-02.png
new file mode 100644
index 0000000..3520e86
Binary files /dev/null and b/static/empty-02.png differ
diff --git a/static/empty.png b/static/empty.png
new file mode 100644
index 0000000..f9e360b
Binary files /dev/null and b/static/empty.png differ
diff --git a/static/not-dealer.png b/static/not-dealer.png
new file mode 100644
index 0000000..4f26e8e
Binary files /dev/null and b/static/not-dealer.png differ
diff --git a/static/order/refund-bg.png b/static/order/refund-bg.png
new file mode 100644
index 0000000..817a45e
Binary files /dev/null and b/static/order/refund-bg.png differ
diff --git a/static/order/status/close.png b/static/order/status/close.png
new file mode 100644
index 0000000..ca5739b
Binary files /dev/null and b/static/order/status/close.png differ
diff --git a/static/order/status/received.png b/static/order/status/received.png
new file mode 100644
index 0000000..27f8a26
Binary files /dev/null and b/static/order/status/received.png differ
diff --git a/static/order/status/wait_deliver.png b/static/order/status/wait_deliver.png
new file mode 100644
index 0000000..b42c2e3
Binary files /dev/null and b/static/order/status/wait_deliver.png differ
diff --git a/static/order/status/wait_pay.png b/static/order/status/wait_pay.png
new file mode 100644
index 0000000..fe14070
Binary files /dev/null and b/static/order/status/wait_pay.png differ
diff --git a/static/order/status/wait_receipt.png b/static/order/status/wait_receipt.png
new file mode 100644
index 0000000..5837b74
Binary files /dev/null and b/static/order/status/wait_receipt.png differ
diff --git a/static/tabbar/cart-active.png b/static/tabbar/cart-active.png
new file mode 100644
index 0000000..e31a406
Binary files /dev/null and b/static/tabbar/cart-active.png differ
diff --git a/static/tabbar/cart.png b/static/tabbar/cart.png
new file mode 100644
index 0000000..7a44d8b
Binary files /dev/null and b/static/tabbar/cart.png differ
diff --git a/static/tabbar/cate-active.png b/static/tabbar/cate-active.png
new file mode 100644
index 0000000..0718f58
Binary files /dev/null and b/static/tabbar/cate-active.png differ
diff --git a/static/tabbar/cate.png b/static/tabbar/cate.png
new file mode 100644
index 0000000..8290f99
Binary files /dev/null and b/static/tabbar/cate.png differ
diff --git a/static/tabbar/home-active.png b/static/tabbar/home-active.png
new file mode 100644
index 0000000..c4bf42d
Binary files /dev/null and b/static/tabbar/home-active.png differ
diff --git a/static/tabbar/home.png b/static/tabbar/home.png
new file mode 100644
index 0000000..1766d72
Binary files /dev/null and b/static/tabbar/home.png differ
diff --git a/static/tabbar/user-active.png b/static/tabbar/user-active.png
new file mode 100644
index 0000000..8db5285
Binary files /dev/null and b/static/tabbar/user-active.png differ
diff --git a/static/tabbar/user.png b/static/tabbar/user.png
new file mode 100644
index 0000000..f1a527e
Binary files /dev/null and b/static/tabbar/user.png differ
diff --git a/static/wallet.png b/static/wallet.png
new file mode 100644
index 0000000..d343bb5
Binary files /dev/null and b/static/wallet.png differ
diff --git a/store/getters.js b/store/getters.js
new file mode 100644
index 0000000..5a8e2fd
--- /dev/null
+++ b/store/getters.js
@@ -0,0 +1,11 @@
+const getters = {
+ storeId: state => state.app.storeId,
+ platform: state => state.app.platform,
+ token: state => state.user.token,
+ userId: state => state.user.userId,
+ refereeId: state => state.app.refereeId,
+ appTheme: state => state.theme.appTheme,
+ modules: state => state.app.modules
+}
+
+export default getters
diff --git a/store/index.js b/store/index.js
new file mode 100644
index 0000000..344fd1e
--- /dev/null
+++ b/store/index.js
@@ -0,0 +1,22 @@
+import { createStore } from 'vuex'
+import { app, user, theme } from './modules'
+import getters from './getters'
+
+const store = createStore({
+ modules: {
+ app,
+ user,
+ theme
+ },
+ state: {
+
+ },
+ mutations: {
+
+ },
+ actions: {
+
+ },
+ getters
+})
+export default store
\ No newline at end of file
diff --git a/store/modules/app.js b/store/modules/app.js
new file mode 100644
index 0000000..e6a2549
--- /dev/null
+++ b/store/modules/app.js
@@ -0,0 +1,56 @@
+import { REFEREE_ID } from '@/store/mutation-types'
+import storage from '@/utils/storage'
+
+const app = {
+ state: {
+ // 当前商城的ID
+ storeId: null,
+ // 当前终端平台
+ platform: '',
+ // 推荐人ID
+ refereeId: null,
+ // 开启的功能模块
+ modules: []
+ },
+
+ mutations: {
+ SET_STORE_ID: (state, value) => {
+ state.storeId = value
+ },
+ SET_PLATFORM: (state, value) => {
+ state.platform = value
+ },
+ SET_REFEREE_ID: (state, value) => {
+ state.refereeId = value
+ },
+ SET_MODULES: (state, value) => {
+ state.modules = value
+ },
+ },
+
+ actions: {
+
+ // 记录推荐人ID
+ setRefereeId({ commit }, value) {
+ const store = this
+ const refereeId = parseInt(value)
+ return new Promise((resolve, reject) => {
+ if (refereeId > 0 && store.getters.userId != refereeId) {
+ // 保存推荐人ID到缓存
+ storage.set(REFEREE_ID, refereeId)
+ // 记录到store全局变量
+ commit('SET_REFEREE_ID', refereeId)
+ resolve()
+ }
+ })
+ },
+
+ // 记录开启的功能模块
+ SetModules({ commit }, modules) {
+ commit('SET_MODULES', modules)
+ }
+
+ }
+}
+
+export default app
\ No newline at end of file
diff --git a/store/modules/index.js b/store/modules/index.js
new file mode 100644
index 0000000..403e6d9
--- /dev/null
+++ b/store/modules/index.js
@@ -0,0 +1,5 @@
+import app from './app'
+import user from './user'
+import theme from './theme'
+
+export { app, user, theme }
diff --git a/store/modules/theme.js b/store/modules/theme.js
new file mode 100644
index 0000000..08f692b
--- /dev/null
+++ b/store/modules/theme.js
@@ -0,0 +1,40 @@
+import storage from '@/utils/storage'
+import { isEmpty } from '@/utils/util'
+import { APP_THEME } from '@/store/mutation-types'
+
+const theme = {
+ state: {
+ // 当前自定义主题
+ appTheme: {
+ mainBg: '#fa2209',
+ mainBg2: '#ff6335',
+ mainText: '#ffffff',
+ viceBg: '#ffb100',
+ viceBg2: '#ffb900',
+ viceText: '#ffffff',
+ },
+ },
+
+ mutations: {
+ SET_APP_THEME: (state, value) => {
+ if (!isEmpty(value)) {
+ state.appTheme = value
+ }
+ }
+ },
+
+ actions: {
+
+ // 记录自定义主题
+ SetAppTheme({ commit }, value) {
+ return new Promise((resolve, reject) => {
+ storage.set(APP_THEME, value)
+ commit('SET_APP_THEME', value)
+ resolve()
+ })
+ }
+
+ }
+}
+
+export default theme
diff --git a/store/modules/user.js b/store/modules/user.js
new file mode 100644
index 0000000..6175f13
--- /dev/null
+++ b/store/modules/user.js
@@ -0,0 +1,120 @@
+import { ACCESS_TOKEN, USER_ID } from '@/store/mutation-types'
+import storage from '@/utils/storage'
+import * as LoginApi from '@/api/login'
+
+// 登陆成功后执行
+const loginSuccess = (commit, { token, userId }) => {
+ // 过期时间30天
+ const expiryTime = 30 * 86400
+ // 保存tokne和userId到缓存
+ storage.set(USER_ID, userId, expiryTime)
+ storage.set(ACCESS_TOKEN, token, expiryTime)
+ // 记录到store全局变量
+ commit('SET_TOKEN', token)
+ commit('SET_USER_ID', userId)
+}
+
+const user = {
+ state: {
+ // 用户认证token
+ token: '',
+ // 用户ID
+ userId: null
+ },
+
+ mutations: {
+ SET_TOKEN: (state, value) => {
+ state.token = value
+ },
+ SET_USER_ID: (state, value) => {
+ state.userId = value
+ }
+ },
+
+ actions: {
+
+ // 用户登录 (普通登录: 输入手机号和验证码)
+ Login({ commit }, data) {
+ return new Promise((resolve, reject) => {
+ LoginApi.login({ form: data })
+ .then(response => {
+ const result = response.data
+ loginSuccess(commit, result)
+ resolve(response)
+ })
+ .catch(reject)
+ })
+ },
+
+ // 微信小程序一键授权登录 (获取用户基本信息)
+ LoginMpWx({ commit }, data) {
+ return new Promise((resolve, reject) => {
+ LoginApi.loginMpWx({ form: data }, { isPrompt: false })
+ .then(response => {
+ const result = response.data
+ loginSuccess(commit, result)
+ resolve(response)
+ })
+ .catch(reject)
+ })
+ },
+
+ // 微信公众号一键授权登录 (获取用户基本信息)
+ LoginWxOfficial({ commit }, data) {
+ return new Promise((resolve, reject) => {
+ LoginApi.loginWxOfficial({ form: data }, { isPrompt: false })
+ .then(response => {
+ const result = response.data
+ loginSuccess(commit, result)
+ resolve(response)
+ })
+ .catch(reject)
+ })
+ },
+
+ // 微信小程序一键授权登录 (授权手机号)
+ LoginMpWxMobile({ commit }, data) {
+ return new Promise((resolve, reject) => {
+ LoginApi.loginMpWxMobile({ form: data }, { isPrompt: false })
+ .then(response => {
+ const result = response.data
+ loginSuccess(commit, result)
+ resolve(response)
+ })
+ .catch(reject)
+ })
+ },
+
+ // 支付宝小程序一键授权登录 (获取用户基本信息)
+ LoginMpAlipay({ commit }, data) {
+ return new Promise((resolve, reject) => {
+ LoginApi.loginMpAlipay({ form: data }, { isPrompt: false })
+ .then(response => {
+ const result = response.data
+ loginSuccess(commit, result)
+ resolve(response)
+ })
+ .catch(reject)
+ })
+ },
+
+ // 退出登录
+ Logout({ commit }, data) {
+ const store = this
+ return new Promise((resolve, reject) => {
+ if (store.getters.userId > 0) {
+ // 删除缓存中的tokne和userId
+ storage.remove(USER_ID)
+ storage.remove(ACCESS_TOKEN)
+ // 记录到store全局变量
+ commit('SET_TOKEN', '')
+ commit('SET_USER_ID', null)
+ resolve()
+ }
+ })
+ }
+
+ }
+}
+
+export default user
diff --git a/store/mutation-types.js b/store/mutation-types.js
new file mode 100644
index 0000000..a6f272d
--- /dev/null
+++ b/store/mutation-types.js
@@ -0,0 +1,6 @@
+export const ACCESS_TOKEN = 'AccessToken'
+export const USER_ID = 'userId'
+export const REFEREE_ID = 'refereeId'
+export const PLATFORM = 'platform'
+export const STORE_ID = 'storeId'
+export const APP_THEME = 'appTheme'
\ No newline at end of file
diff --git a/template.h5.html b/template.h5.html
new file mode 100644
index 0000000..1571e4f
--- /dev/null
+++ b/template.h5.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ <%= htmlWebpackPlugin.options.title %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni.scss b/uni.scss
new file mode 100644
index 0000000..8b9b9df
--- /dev/null
+++ b/uni.scss
@@ -0,0 +1,90 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+
+/* 颜色变量 */
+
+/* 行为相关颜色 */
+$uni-main-bg: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 文字基本颜色 */
+$uni-text-color: #333;//基本色
+$uni-text-color-inverse:#fff;//反色
+$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable:#c0c0c0;
+$uni-text-color-active:#fa2209; // 激活的颜色红
+
+/* 背景颜色 */
+$uni-bg-color:#ffffff;
+$uni-bg-color-grey:#f8f8f8;
+$uni-bg-color-hover:#f1f1f1;//点击状态颜色
+$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
+
+/* 边框颜色 */
+$uni-border-color:#c8c7cc;
+
+/* 尺寸变量 */
+
+/* 文字尺寸 */
+$uni-font-size-sm:24rpx;
+$uni-font-size-base:28rpx;
+$uni-font-size-lg:32rpx;
+
+/* 图片尺寸 */
+$uni-img-size-sm:40rpx;
+$uni-img-size-base:52rpx;
+$uni-img-size-lg:80rpx;
+
+/* Border Radius */
+$uni-border-radius-sm: 4rpx;
+$uni-border-radius-base: 6rpx;
+$uni-border-radius-lg: 12rpx;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 10px;
+$uni-spacing-row-base: 20rpx;
+$uni-spacing-row-lg: 30rpx;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 8rpx;
+$uni-spacing-col-base: 16rpx;
+$uni-spacing-col-lg: 24rpx;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2C405A; // 文章标题颜色
+$uni-font-size-title:40rpx;
+$uni-color-subtitle: #555555; // 二级标题颜色
+$uni-font-size-subtitle:36rpx;
+$uni-color-paragraph: #3F536E; // 文章段落颜色
+$uni-font-size-paragraph:30rpx;
+
+
+/* 引入uView全局scss变量文件 */
+@import "@/uni_modules/vk-uview-ui/theme.scss";
+
+
+/* 引入自定义主题 */
+$main-bg: var(--main-bg);
+$main-bg2: var(--main-bg2);
+$main-text: var(--main-text);
+$vice-bg: var(--vice-bg);
+$vice-bg2: var(--vice-bg2);
+$vice-text: var(--vice-text);
\ No newline at end of file
diff --git a/uni_modules/mescroll-uni/changelog.md b/uni_modules/mescroll-uni/changelog.md
new file mode 100644
index 0000000..dd6dd72
--- /dev/null
+++ b/uni_modules/mescroll-uni/changelog.md
@@ -0,0 +1,8 @@
+## 1.3.8(2023-03-27)
+1. 新增useMescroll的hook, 支持vue3 script setup的写法
+2. 新增vue3 script setup的示例 ( 根据vue2的示例,全部重写了一遍 )
+3. mescroll-body 和 mescroll-uni 无需再写 ref="mescrollRef"
+4. 解决mescroll-uni在页面渲染之后,无法动态设置height的问题
+5. 解决renderjs在h5返回有时候无法正常滑动的问题
+6. 修复小程序编辑器提示 Cannot read property 'nv_optDown' of undefined 的错误
+-by 小瑾同学
diff --git a/uni_modules/mescroll-uni/components/mescroll-body/mescroll-body.css b/uni_modules/mescroll-uni/components/mescroll-body/mescroll-body.css
new file mode 100644
index 0000000..1107710
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-body/mescroll-body.css
@@ -0,0 +1,19 @@
+.mescroll-body {
+ position: relative; /* 下拉刷新区域相对自身定位 */
+ height: auto; /* 不可固定高度,否则overflow:hidden导致无法滑动; 同时使设置的最小高生效,实现列表不满屏仍可下拉*/
+ overflow: hidden; /* 当有元素写在mescroll-body标签前面时,可遮住下拉刷新区域 */
+ box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
+}
+
+/* 使sticky生效: 父元素不能overflow:hidden或者overflow:auto属性 */
+.mescroll-body.mescorll-sticky{
+ overflow: unset !important
+}
+
+/* 适配 iPhoneX */
+@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
+ .mescroll-safearea {
+ padding-bottom: constant(safe-area-inset-bottom);
+ padding-bottom: env(safe-area-inset-bottom);
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/mescroll-uni/components/mescroll-body/mescroll-body.vue b/uni_modules/mescroll-uni/components/mescroll-body/mescroll-body.vue
new file mode 100644
index 0000000..1b57733
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-body/mescroll-body.vue
@@ -0,0 +1,403 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{downText}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ mescroll.optUp.textLoading }}
+
+
+ {{ mescroll.optUp.textNoMore }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/uni_modules/mescroll-uni/components/mescroll-empty/mescroll-empty.vue b/uni_modules/mescroll-uni/components/mescroll-empty/mescroll-empty.vue
new file mode 100644
index 0000000..48de49c
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-empty/mescroll-empty.vue
@@ -0,0 +1,116 @@
+
+
+
+
+ {{ tip }}
+ {{ btnText }}
+
+
+
+
+
+
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-down.css b/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-down.css
new file mode 100644
index 0000000..72bf106
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-down.css
@@ -0,0 +1,55 @@
+/* 下拉刷新区域 */
+.mescroll-downwarp {
+ position: absolute;
+ top: -100%;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ text-align: center;
+}
+
+/* 下拉刷新--内容区,定位于区域底部 */
+.mescroll-downwarp .downwarp-content {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ min-height: 60rpx;
+ padding: 20rpx 0;
+ text-align: center;
+}
+
+/* 下拉刷新--提示文本 */
+.mescroll-downwarp .downwarp-tip {
+ display: inline-block;
+ font-size: 28rpx;
+ vertical-align: middle;
+ margin-left: 16rpx;
+ /* color: gray; 已在style设置color,此处删去*/
+}
+
+/* 下拉刷新--旋转进度条 */
+.mescroll-downwarp .downwarp-progress {
+ display: inline-block;
+ width: 32rpx;
+ height: 32rpx;
+ border-radius: 50%;
+ border: 2rpx solid gray;
+ border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
+ vertical-align: middle;
+}
+
+/* 旋转动画 */
+.mescroll-downwarp .mescroll-rotate {
+ animation: mescrollDownRotate 0.6s linear infinite;
+}
+
+@keyframes mescrollDownRotate {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-down.vue b/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-down.vue
new file mode 100644
index 0000000..9fd1567
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-down.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+ {{downText}}
+
+
+
+
+
+
+
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-top.vue b/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-top.vue
new file mode 100644
index 0000000..a7c7e3a
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-top.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-up.css b/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-up.css
new file mode 100644
index 0000000..cbf48cd
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-up.css
@@ -0,0 +1,47 @@
+/* 上拉加载区域 */
+.mescroll-upwarp {
+ box-sizing: border-box;
+ min-height: 110rpx;
+ padding: 30rpx 0;
+ text-align: center;
+ clear: both;
+}
+
+/*提示文本 */
+.mescroll-upwarp .upwarp-tip,
+.mescroll-upwarp .upwarp-nodata {
+ display: inline-block;
+ font-size: 28rpx;
+ vertical-align: middle;
+ /* color: gray; 已在style设置color,此处删去*/
+}
+
+.mescroll-upwarp .upwarp-tip {
+ margin-left: 16rpx;
+}
+
+/*旋转进度条 */
+.mescroll-upwarp .upwarp-progress {
+ display: inline-block;
+ width: 32rpx;
+ height: 32rpx;
+ border-radius: 50%;
+ border: 2rpx solid gray;
+ border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
+ vertical-align: middle;
+}
+
+/* 旋转动画 */
+.mescroll-upwarp .mescroll-rotate {
+ animation: mescrollUpRotate 0.6s linear infinite;
+}
+
+@keyframes mescrollUpRotate {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-up.vue b/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-up.vue
new file mode 100644
index 0000000..11c2e1f
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/components/mescroll-up.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ {{ mOption.textLoading }}
+
+
+ {{ mOption.textNoMore }}
+
+
+
+
+
+
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-i18n.js b/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-i18n.js
new file mode 100644
index 0000000..2b6a50f
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-i18n.js
@@ -0,0 +1,15 @@
+// 国际化工具类
+const mescrollI18n = {
+ // 默认语言
+ def: "zh",
+ // 获取当前语言类型
+ getType(){
+ return uni.getStorageSync("mescroll-i18n") || this.def
+ },
+ // 设置当前语言类型
+ setType(type){
+ uni.setStorageSync("mescroll-i18n", type)
+ }
+}
+
+export default mescrollI18n
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js b/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js
new file mode 100644
index 0000000..10f68c0
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js
@@ -0,0 +1,46 @@
+// mescroll-body 和 mescroll-uni 通用
+const MescrollMixin = {
+ data() {
+ return {
+ mescroll: null //mescroll实例对象
+ }
+ },
+ // 注册系统自带的下拉刷新 (配置down.native为true时生效, 还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+ onPullDownRefresh(){
+ this.mescroll && this.mescroll.onPullDownRefresh();
+ },
+ // 注册列表滚动事件,用于判定在顶部可下拉刷新,在指定位置可显示隐藏回到顶部按钮 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
+ onPageScroll(e) {
+ this.mescroll && this.mescroll.onPageScroll(e);
+ },
+ // 注册滚动到底部的事件,用于上拉加载 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
+ onReachBottom() {
+ this.mescroll && this.mescroll.onReachBottom();
+ },
+ methods: {
+ // mescroll组件初始化的回调,可获取到mescroll对象
+ mescrollInit(mescroll) {
+ this.mescroll = mescroll;
+ },
+ // 下拉刷新的回调 (mixin默认resetUpScroll)
+ downCallback() {
+ if(this.mescroll.optUp.use){
+ this.mescroll.resetUpScroll()
+ }else{
+ setTimeout(()=>{
+ this.mescroll.endSuccess();
+ }, 500)
+ }
+ },
+ // 上拉加载的回调
+ upCallback() {
+ // mixin默认延时500自动结束加载
+ setTimeout(()=>{
+ this.mescroll.endErr();
+ }, 500)
+ }
+ }
+
+}
+
+export default MescrollMixin;
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni-option.js b/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni-option.js
new file mode 100644
index 0000000..b0e6961
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni-option.js
@@ -0,0 +1,65 @@
+// 全局配置
+// mescroll-body 和 mescroll-uni 通用
+const GlobalOption = {
+ down: {
+ // 其他down的配置参数也可以写,这里只展示了常用的配置:
+ offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
+ native: false // 是否使用系统自带的下拉刷新; 默认false; 仅在mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+ },
+ up: {
+ // 其他up的配置参数也可以写,这里只展示了常用的配置:
+ offset: 150, // 距底部多远时,触发upCallback,仅mescroll-uni生效 ( mescroll-body配置的是pages.json的 onReachBottomDistance )
+ toTop: {
+ // 回到顶部按钮,需配置src才显示
+ src: "https://www.mescroll.com/img/mescroll-totop.png", // 图片路径 (建议放入static目录, 如 /static/img/mescroll-totop.png )
+ offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000px
+ right: 20, // 到右边的距离, 默认20 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
+ bottom: 120, // 到底部的距离, 默认120 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
+ width: 72 // 回到顶部图标的宽度, 默认72 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
+ },
+ empty: {
+ use: true, // 是否显示空布局
+ // icon: "https://www.mescroll.com/img/mescroll-empty.png" // 图标路径 (建议放入static目录, 如 /static/img/mescroll-empty.png )
+ icon: '/static/empty.png',
+ }
+ },
+ // 国际化配置
+ i18n: {
+ // 中文
+ zh: {
+ down: {
+ textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
+ textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
+ textLoading: '加载中 ...', // 加载中的提示文本
+ textSuccess: '加载成功', // 加载成功的文本
+ textErr: '加载失败', // 加载失败的文本
+ },
+ up: {
+ textLoading: '加载中 ...', // 加载中的提示文本
+ textNoMore: '亲, 没有更多了', // 没有更多数据的提示文本
+ empty: {
+ tip: '亲,暂无相关数据' // 空提示
+ }
+ }
+ },
+ // 英文
+ en: {
+ down: {
+ textInOffset: 'drop down refresh',
+ textOutOffset: 'release updates',
+ textLoading: 'loading ...',
+ textSuccess: 'loaded successfully',
+ textErr: 'loading failed'
+ },
+ up: {
+ textLoading: 'loading ...',
+ textNoMore: '-- END --',
+ empty: {
+ tip: '~ absolutely empty ~'
+ }
+ }
+ }
+ }
+}
+
+export default GlobalOption
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni.css b/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni.css
new file mode 100644
index 0000000..39438cd
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni.css
@@ -0,0 +1,36 @@
+.mescroll-uni-warp{
+ height: 100%;
+}
+
+.mescroll-uni-content{
+ height: 100%;
+}
+
+.mescroll-uni {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ min-height: 200rpx;
+ overflow-y: auto;
+ box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
+}
+
+/* 定位的方式固定高度 */
+.mescroll-uni-fixed{
+ z-index: 1;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ width: auto; /* 使right生效 */
+ height: auto; /* 使bottom生效 */
+}
+
+/* 适配 iPhoneX */
+@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
+ .mescroll-safearea {
+ padding-bottom: constant(safe-area-inset-bottom);
+ padding-bottom: env(safe-area-inset-bottom);
+ }
+}
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni.js b/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni.js
new file mode 100644
index 0000000..3bfdac1
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni.js
@@ -0,0 +1,799 @@
+/* mescroll
+ * version 1.3.7
+ * 2021-04-12 wenju
+ * https://www.mescroll.com
+ */
+
+export default function MeScroll(options, isScrollBody) {
+ let me = this;
+ me.version = '1.3.7'; // mescroll版本号
+ me.options = options || {}; // 配置
+ me.isScrollBody = isScrollBody || false; // 滚动区域是否为原生页面滚动; 默认为scroll-view
+
+ me.isDownScrolling = false; // 是否在执行下拉刷新的回调
+ me.isUpScrolling = false; // 是否在执行上拉加载的回调
+ let hasDownCallback = me.options.down && me.options.down.callback; // 是否配置了down的callback
+
+ // 初始化下拉刷新
+ me.initDownScroll();
+ // 初始化上拉加载,则初始化
+ me.initUpScroll();
+
+ // 自动加载
+ setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+ // 自动触发下拉刷新 (只有配置了down的callback才自动触发下拉刷新)
+ if ((me.optDown.use || me.optDown.native) && me.optDown.auto && hasDownCallback) {
+ if (me.optDown.autoShowLoading) {
+ me.triggerDownScroll(); // 显示下拉进度,执行下拉回调
+ } else {
+ me.optDown.callback && me.optDown.callback(me); // 不显示下拉进度,直接执行下拉回调
+ }
+ }
+ // 自动触发上拉加载
+ if(!me.isUpAutoLoad){ // 部分小程序(头条小程序)emit是异步, 会导致isUpAutoLoad判断有误, 先延时确保先执行down的callback,再执行up的callback
+ setTimeout(function(){
+ me.optUp.use && me.optUp.auto && !me.isUpAutoLoad && me.triggerUpScroll();
+ },100)
+ }
+ }, 30); // 需让me.optDown.inited和me.optUp.inited先执行
+}
+
+/* 配置参数:下拉刷新 */
+MeScroll.prototype.extendDownScroll = function(optDown) {
+ // 下拉刷新的配置
+ MeScroll.extend(optDown, {
+ use: true, // 是否启用下拉刷新; 默认true
+ auto: true, // 是否在初始化完毕之后自动执行下拉刷新的回调; 默认true
+ native: false, // 是否使用系统自带的下拉刷新; 默认false; 仅mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+ autoShowLoading: false, // 如果设置auto=true(在初始化完毕之后自动执行下拉刷新的回调),那么是否显示下拉刷新的进度; 默认false
+ isLock: false, // 是否锁定下拉刷新,默认false;
+ offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
+ startTop: 100, // scroll-view快速滚动到顶部时,此时的scroll-top可能大于0, 此值用于控制最大的误差
+ inOffsetRate: 1, // 在列表顶部,下拉的距离小于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
+ outOffsetRate: 0.2, // 在列表顶部,下拉的距离大于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
+ bottomOffset: 20, // 当手指touchmove位置在距离body底部20px范围内的时候结束上拉刷新,避免Webview嵌套导致touchend事件不执行
+ minAngle: 45, // 向下滑动最少偏移的角度,取值区间 [0,90];默认45度,即向下滑动的角度大于45度则触发下拉;而小于45度,将不触发下拉,避免与左右滑动的轮播等组件冲突;
+ textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
+ textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
+ textLoading: '加载中 ...', // 加载中的提示文本
+ textSuccess: '加载成功', // 加载成功的文本
+ textErr: '加载失败', // 加载失败的文本
+ beforeEndDelay: 0, // 延时结束的时长 (显示加载成功/失败的时长, android小程序设置此项结束下拉会卡顿, 配置后请注意测试)
+ bgColor: "transparent", // 背景颜色 (建议在pages.json中再设置一下backgroundColorTop)
+ textColor: "gray", // 文本颜色 (当bgColor配置了颜色,而textColor未配置时,则textColor会默认为白色)
+ inited: null, // 下拉刷新初始化完毕的回调
+ inOffset: null, // 下拉的距离进入offset范围内那一刻的回调
+ outOffset: null, // 下拉的距离大于offset那一刻的回调
+ onMoving: null, // 下拉过程中的回调,滑动过程一直在执行; rate下拉区域当前高度与指定距离的比值(inOffset: rate<1; outOffset: rate>=1); downHight当前下拉区域的高度
+ beforeLoading: null, // 准备触发下拉刷新的回调: 如果return true,将不触发showLoading和callback回调; 常用来完全自定义下拉刷新, 参考案例【淘宝 v6.8.0】
+ showLoading: null, // 显示下拉刷新进度的回调
+ afterLoading: null, // 显示下拉刷新进度的回调之后,马上要执行的代码 (如: 在wxs中使用)
+ beforeEndDownScroll: null, // 准备结束下拉的回调. 返回结束下拉的延时执行时间,默认0ms; 常用于结束下拉之前再显示另外一小段动画,才去隐藏下拉刷新的场景, 参考案例【dotJump】
+ endDownScroll: null, // 结束下拉刷新的回调
+ afterEndDownScroll: null, // 结束下拉刷新的回调,马上要执行的代码 (如: 在wxs中使用)
+ callback: function(mescroll) {
+ // 下拉刷新的回调;默认重置上拉加载列表为第一页
+ mescroll.resetUpScroll();
+ }
+ })
+}
+
+/* 配置参数:上拉加载 */
+MeScroll.prototype.extendUpScroll = function(optUp) {
+ // 上拉加载的配置
+ MeScroll.extend(optUp, {
+ use: true, // 是否启用上拉加载; 默认true
+ auto: true, // 是否在初始化完毕之后自动执行上拉加载的回调; 默认true
+ isLock: false, // 是否锁定上拉加载,默认false;
+ isBoth: true, // 上拉加载时,如果滑动到列表顶部是否可以同时触发下拉刷新;默认true,两者可同时触发;
+ callback: null, // 上拉加载的回调;function(page,mescroll){ }
+ page: {
+ num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
+ size: 10, // 每页数据的数量
+ time: null // 加载第一页数据服务器返回的时间; 防止用户翻页时,后台新增了数据从而导致下一页数据重复;
+ },
+ noMoreSize: 5, // 如果列表已无数据,可设置列表的总数量要大于等于5条才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看
+ offset: 150, // 距底部多远时,触发upCallback,仅mescroll-uni生效 ( mescroll-body配置的是pages.json的 onReachBottomDistance )
+ textLoading: '加载中 ...', // 加载中的提示文本
+ textNoMore: '-- END --', // 没有更多数据的提示文本
+ bgColor: "transparent", // 背景颜色 (建议在pages.json中再设置一下backgroundColorBottom)
+ textColor: "gray", // 文本颜色 (当bgColor配置了颜色,而textColor未配置时,则textColor会默认为白色)
+ inited: null, // 初始化完毕的回调
+ showLoading: null, // 显示加载中的回调
+ showNoMore: null, // 显示无更多数据的回调
+ hideUpScroll: null, // 隐藏上拉加载的回调
+ errDistance: 60, // endErr的时候需往上滑动一段距离,使其往下滑动时再次触发onReachBottom,仅mescroll-body生效
+ toTop: {
+ // 回到顶部按钮,需配置src才显示
+ src: null, // 图片路径,默认null (绝对路径或网络图)
+ offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000
+ duration: 300, // 回到顶部的动画时长,默认300ms (当值为0或300则使用系统自带回到顶部,更流畅; 其他值则通过step模拟,部分机型可能不够流畅,所以非特殊情况不建议修改此项)
+ btnClick: null, // 点击按钮的回调
+ onShow: null, // 是否显示的回调
+ zIndex: 9990, // fixed定位z-index值
+ left: null, // 到左边的距离, 默认null. 此项有值时,right不生效. (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+ right: 20, // 到右边的距离, 默认20 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+ bottom: 120, // 到底部的距离, 默认120 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+ safearea: false, // bottom的偏移量是否加上底部安全区的距离, 默认false, 需要适配iPhoneX时使用 (具体的界面如果不配置此项,则取本vue的safearea值)
+ width: 72, // 回到顶部图标的宽度, 默认72 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+ radius: "50%" // 圆角, 默认"50%" (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+ },
+ empty: {
+ use: true, // 是否显示空布局
+ icon: null, // 图标路径
+ tip: '~ 暂无相关数据 ~', // 提示
+ btnText: '', // 按钮
+ btnClick: null, // 点击按钮的回调
+ onShow: null, // 是否显示的回调
+ fixed: false, // 是否使用fixed定位,默认false; 配置fixed为true,以下的top和zIndex才生效 (transform会使fixed失效,最终会降级为absolute)
+ top: "100rpx", // fixed定位的top值 (完整的单位值,如 "10%"; "100rpx")
+ zIndex: 99 // fixed定位z-index值
+ },
+ onScroll: false // 是否监听滚动事件
+ })
+}
+
+/* 配置参数 */
+MeScroll.extend = function(userOption, defaultOption) {
+ if (!userOption) return defaultOption;
+ for (let key in defaultOption) {
+ if (userOption[key] == null) {
+ let def = defaultOption[key];
+ if (def != null && typeof def === 'object') {
+ userOption[key] = MeScroll.extend({}, def); // 深度匹配
+ } else {
+ userOption[key] = def;
+ }
+ } else if (typeof userOption[key] === 'object') {
+ MeScroll.extend(userOption[key], defaultOption[key]); // 深度匹配
+ }
+ }
+ return userOption;
+}
+
+/* 简单判断是否配置了颜色 (非透明,非白色) */
+MeScroll.prototype.hasColor = function(color) {
+ if(!color) return false;
+ let c = color.toLowerCase();
+ return c != "#fff" && c != "#ffffff" && c != "transparent" && c != "white"
+}
+
+/* -------初始化下拉刷新------- */
+MeScroll.prototype.initDownScroll = function() {
+ let me = this;
+ // 配置参数
+ me.optDown = me.options.down || {};
+ if(!me.optDown.textColor && me.hasColor(me.optDown.bgColor)) me.optDown.textColor = "#fff"; // 当bgColor有值且textColor未设置,则textColor默认白色
+ me.extendDownScroll(me.optDown);
+
+ // 如果是mescroll-body且配置了native,则禁止自定义的下拉刷新
+ if(me.isScrollBody && me.optDown.native){
+ me.optDown.use = false
+ }else{
+ me.optDown.native = false // 仅mescroll-body支持,mescroll-uni不支持
+ }
+
+ me.downHight = 0; // 下拉区域的高度
+
+ // 在页面中加入下拉布局
+ if (me.optDown.use && me.optDown.inited) {
+ // 初始化完毕的回调
+ setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+ me.optDown.inited(me);
+ }, 0)
+ }
+}
+
+/* 列表touchstart事件 */
+MeScroll.prototype.touchstartEvent = function(e) {
+ if (!this.optDown.use) return;
+
+ this.startPoint = this.getPoint(e); // 记录起点
+ this.startTop = this.getScrollTop(); // 记录此时的滚动条位置
+ this.startAngle = 0; // 初始角度
+ this.lastPoint = this.startPoint; // 重置上次move的点
+ this.maxTouchmoveY = this.getBodyHeight() - this.optDown.bottomOffset; // 手指触摸的最大范围(写在touchstart避免body获取高度为0的情况)
+ this.inTouchend = false; // 标记不是touchend
+}
+
+/* 列表touchmove事件 */
+MeScroll.prototype.touchmoveEvent = function(e) {
+ if (!this.optDown.use) return;
+ let me = this;
+
+ let scrollTop = me.getScrollTop(); // 当前滚动条的距离
+ let curPoint = me.getPoint(e); // 当前点
+
+ let moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+
+ // 向下拉 && 在顶部
+ // mescroll-body,直接判定在顶部即可
+ // scroll-view在滚动时不会触发touchmove,当触顶/底/左/右时,才会触发touchmove
+ // scroll-view滚动到顶部时,scrollTop不一定为0,也有可能大于0; 在iOS的APP中scrollTop可能为负数,不一定和startTop相等
+ if (moveY > 0 && (
+ (me.isScrollBody && scrollTop <= 0)
+ ||
+ (!me.isScrollBody && (scrollTop <= 0 || (scrollTop <= me.optDown.startTop && scrollTop === me.startTop)) )
+ )) {
+ // 可下拉的条件
+ if (!me.inTouchend && !me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling &&
+ me.optUp.isBoth))) {
+
+ // 下拉的初始角度是否在配置的范围内
+ if(!me.startAngle) me.startAngle = me.getAngle(me.lastPoint, curPoint); // 两点之间的角度,区间 [0,90]
+ if (me.startAngle < me.optDown.minAngle) return; // 如果小于配置的角度,则不往下执行下拉刷新
+
+ // 如果手指的位置超过配置的距离,则提前结束下拉,避免Webview嵌套导致touchend无法触发
+ if (me.maxTouchmoveY > 0 && curPoint.y >= me.maxTouchmoveY) {
+ me.inTouchend = true; // 标记执行touchend
+ me.touchendEvent(); // 提前触发touchend
+ return;
+ }
+
+ me.preventDefault(e); // 阻止默认事件
+
+ let diff = curPoint.y - me.lastPoint.y; // 和上次比,移动的距离 (大于0向下,小于0向上)
+
+ // 下拉距离 < 指定距离
+ if (me.downHight < me.optDown.offset) {
+ if (me.movetype !== 1) {
+ me.movetype = 1; // 加入标记,保证只执行一次
+ me.isDownEndSuccess = null; // 重置是否加载成功的状态 (wxs执行的是wxs.wxs)
+ me.optDown.inOffset && me.optDown.inOffset(me); // 进入指定距离范围内那一刻的回调,只执行一次
+ me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+ }
+ me.downHight += diff * me.optDown.inOffsetRate; // 越往下,高度变化越小
+
+ // 指定距离 <= 下拉距离
+ } else {
+ if (me.movetype !== 2) {
+ me.movetype = 2; // 加入标记,保证只执行一次
+ me.optDown.outOffset && me.optDown.outOffset(me); // 下拉超过指定距离那一刻的回调,只执行一次
+ me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+ }
+ if (diff > 0) { // 向下拉
+ me.downHight += diff * me.optDown.outOffsetRate; // 越往下,高度变化越小
+ } else { // 向上收
+ me.downHight += diff; // 向上收回高度,则向上滑多少收多少高度
+ }
+ }
+
+ me.downHight = Math.round(me.downHight) // 取整
+ let rate = me.downHight / me.optDown.offset; // 下拉区域当前高度与指定距离的比值
+ me.optDown.onMoving && me.optDown.onMoving(me, rate, me.downHight); // 下拉过程中的回调,一直在执行
+ }
+ }
+
+ me.lastPoint = curPoint; // 记录本次移动的点
+}
+
+/* 列表touchend事件 */
+MeScroll.prototype.touchendEvent = function(e) {
+ if (!this.optDown.use) return;
+ // 如果下拉区域高度已改变,则需重置回来
+ if (this.isMoveDown) {
+ if (this.downHight >= this.optDown.offset) {
+ // 符合触发刷新的条件
+ this.triggerDownScroll();
+ } else {
+ // 不符合的话 则重置
+ this.downHight = 0;
+ this.endDownScrollCall(this);
+ }
+ this.movetype = 0;
+ this.isMoveDown = false;
+ } else if (!this.isScrollBody && this.getScrollTop() === this.startTop) { // scroll-view到顶/左/右/底的滑动事件
+ let isScrollUp = this.getPoint(e).y - this.startPoint.y < 0; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+ // 上滑
+ if (isScrollUp) {
+ // 需检查滑动的角度
+ let angle = this.getAngle(this.getPoint(e), this.startPoint); // 两点之间的角度,区间 [0,90]
+ if (angle > 80) {
+ // 检查并触发上拉
+ this.triggerUpScroll(true);
+ }
+ }
+ }
+}
+
+/* 根据点击滑动事件获取第一个手指的坐标 */
+MeScroll.prototype.getPoint = function(e) {
+ if (!e) {
+ return {
+ x: 0,
+ y: 0
+ }
+ }
+ if (e.touches && e.touches[0]) {
+ return {
+ x: e.touches[0].pageX,
+ y: e.touches[0].pageY
+ }
+ } else if (e.changedTouches && e.changedTouches[0]) {
+ return {
+ x: e.changedTouches[0].pageX,
+ y: e.changedTouches[0].pageY
+ }
+ } else {
+ return {
+ x: e.clientX,
+ y: e.clientY
+ }
+ }
+}
+
+/* 计算两点之间的角度: 区间 [0,90]*/
+MeScroll.prototype.getAngle = function(p1, p2) {
+ let x = Math.abs(p1.x - p2.x);
+ let y = Math.abs(p1.y - p2.y);
+ let z = Math.sqrt(x * x + y * y);
+ let angle = 0;
+ if (z !== 0) {
+ angle = Math.asin(y / z) / Math.PI * 180;
+ }
+ return angle
+}
+
+/* 触发下拉刷新 */
+MeScroll.prototype.triggerDownScroll = function() {
+ if (this.optDown.beforeLoading && this.optDown.beforeLoading(this)) {
+ //return true则处于完全自定义状态
+ } else {
+ this.showDownScroll(); // 下拉刷新中...
+ !this.optDown.native && this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
+ }
+}
+
+/* 显示下拉进度布局 */
+MeScroll.prototype.showDownScroll = function() {
+ this.isDownScrolling = true; // 标记下拉中
+ if (this.optDown.native) {
+ uni.startPullDownRefresh(); // 系统自带的下拉刷新
+ this.showDownLoadingCall(0); // 仍触发showLoading,因为上拉加载用到
+ } else{
+ this.downHight = this.optDown.offset; // 更新下拉区域高度
+ this.showDownLoadingCall(this.downHight); // 下拉刷新中...
+ }
+}
+
+MeScroll.prototype.showDownLoadingCall = function(downHight) {
+ this.optDown.showLoading && this.optDown.showLoading(this, downHight); // 下拉刷新中...
+ this.optDown.afterLoading && this.optDown.afterLoading(this, downHight); // 下拉刷新中...触发之后马上要执行的代码
+}
+
+/* 显示系统自带的下拉刷新时需要处理的业务 */
+MeScroll.prototype.onPullDownRefresh = function() {
+ this.isDownScrolling = true; // 标记下拉中
+ this.showDownLoadingCall(0); // 仍触发showLoading,因为上拉加载用到
+ this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
+}
+
+/* 结束下拉刷新 */
+MeScroll.prototype.endDownScroll = function() {
+ if (this.optDown.native) { // 结束原生下拉刷新
+ this.isDownScrolling = false;
+ this.endDownScrollCall(this);
+ uni.stopPullDownRefresh();
+ return
+ }
+ let me = this;
+ // 结束下拉刷新的方法
+ let endScroll = function() {
+ me.downHight = 0;
+ me.isDownScrolling = false;
+ me.endDownScrollCall(me);
+ if(!me.isScrollBody){
+ me.setScrollHeight(0) // scroll-view重置滚动区域,使数据不满屏时仍可检查触发翻页
+ me.scrollTo(0,0) // scroll-view需重置滚动条到顶部,避免startTop大于0时,对下拉刷新的影响
+ }
+ }
+ // 结束下拉刷新时的回调
+ let delay = 0;
+ if (me.optDown.beforeEndDownScroll) {
+ delay = me.optDown.beforeEndDownScroll(me); // 结束下拉刷新的延时,单位ms
+ if(me.isDownEndSuccess == null) delay = 0; // 没有执行加载中,则不延时
+ }
+ if (typeof delay === 'number' && delay > 0) {
+ setTimeout(endScroll, delay);
+ } else {
+ endScroll();
+ }
+}
+
+MeScroll.prototype.endDownScrollCall = function() {
+ this.optDown.endDownScroll && this.optDown.endDownScroll(this);
+ this.optDown.afterEndDownScroll && this.optDown.afterEndDownScroll(this);
+}
+
+/* 锁定下拉刷新:isLock=ture,null锁定;isLock=false解锁 */
+MeScroll.prototype.lockDownScroll = function(isLock) {
+ if (isLock == null) isLock = true;
+ this.optDown.isLock = isLock;
+}
+
+/* 锁定上拉加载:isLock=ture,null锁定;isLock=false解锁 */
+MeScroll.prototype.lockUpScroll = function(isLock) {
+ if (isLock == null) isLock = true;
+ this.optUp.isLock = isLock;
+}
+
+/* -------初始化上拉加载------- */
+MeScroll.prototype.initUpScroll = function() {
+ let me = this;
+ // 配置参数
+ me.optUp = me.options.up || {use: false}
+ if(!me.optUp.textColor && me.hasColor(me.optUp.bgColor)) me.optUp.textColor = "#fff"; // 当bgColor有值且textColor未设置,则textColor默认白色
+ me.extendUpScroll(me.optUp);
+
+ if (me.optUp.use === false) return; // 配置不使用上拉加载时,则不初始化上拉布局
+ me.optUp.hasNext = true; // 如果使用上拉,则默认有下一页
+ me.startNum = me.optUp.page.num + 1; // 记录page开始的页码
+
+ // 初始化完毕的回调
+ if (me.optUp.inited) {
+ setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+ me.optUp.inited(me);
+ }, 0)
+ }
+}
+
+/*滚动到底部的事件 (仅mescroll-body生效)*/
+MeScroll.prototype.onReachBottom = function() {
+ if (this.isScrollBody && !this.isUpScrolling) { // 只能支持下拉刷新的时候同时可以触发上拉加载,否则滚动到底部就需要上滑一点才能触发onReachBottom
+ if (!this.optUp.isLock && this.optUp.hasNext) {
+ this.triggerUpScroll();
+ }
+ }
+}
+
+/*列表滚动事件 (仅mescroll-body生效)*/
+MeScroll.prototype.onPageScroll = function(e) {
+ if (!this.isScrollBody) return;
+
+ // 更新滚动条的位置 (主要用于判断下拉刷新时,滚动条是否在顶部)
+ this.setScrollTop(e.scrollTop);
+
+ // 顶部按钮的显示隐藏
+ if (e.scrollTop >= this.optUp.toTop.offset) {
+ this.showTopBtn();
+ } else {
+ this.hideTopBtn();
+ }
+}
+
+/*列表滚动事件*/
+MeScroll.prototype.scroll = function(e, onScroll) {
+ // 更新滚动条的位置
+ this.setScrollTop(e.scrollTop);
+ // 更新滚动内容高度
+ this.setScrollHeight(e.scrollHeight);
+
+ // 向上滑还是向下滑动
+ if (this.preScrollY == null) this.preScrollY = 0;
+ this.isScrollUp = e.scrollTop - this.preScrollY > 0;
+ this.preScrollY = e.scrollTop;
+
+ // 上滑 && 检查并触发上拉
+ this.isScrollUp && this.triggerUpScroll(true);
+
+ // 顶部按钮的显示隐藏
+ if (e.scrollTop >= this.optUp.toTop.offset) {
+ this.showTopBtn();
+ } else {
+ this.hideTopBtn();
+ }
+
+ // 滑动监听
+ this.optUp.onScroll && onScroll && onScroll()
+}
+
+/* 触发上拉加载 */
+MeScroll.prototype.triggerUpScroll = function(isCheck) {
+ if (!this.isUpScrolling && this.optUp.use && this.optUp.callback) {
+ // 是否校验在底部; 默认不校验
+ if (isCheck === true) {
+ let canUp = false;
+ // 还有下一页 && 没有锁定 && 不在下拉中
+ if (this.optUp.hasNext && !this.optUp.isLock && !this.isDownScrolling) {
+ if (this.getScrollBottom() <= this.optUp.offset) { // 到底部
+ canUp = true; // 标记可上拉
+ }
+ }
+ if (canUp === false) return;
+ }
+ this.showUpScroll(); // 上拉加载中...
+ this.optUp.page.num++; // 预先加一页,如果失败则减回
+ this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
+ this.num = this.optUp.page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
+ this.size = this.optUp.page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
+ this.time = this.optUp.page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
+ this.optUp.callback(this); // 执行回调,联网加载数据
+ }
+}
+
+/* 显示上拉加载中 */
+MeScroll.prototype.showUpScroll = function() {
+ this.isUpScrolling = true; // 标记上拉加载中
+ this.optUp.showLoading && this.optUp.showLoading(this); // 回调
+}
+
+/* 显示上拉无更多数据 */
+MeScroll.prototype.showNoMore = function() {
+ this.optUp.hasNext = false; // 标记无更多数据
+ this.optUp.showNoMore && this.optUp.showNoMore(this); // 回调
+}
+
+/* 隐藏上拉区域**/
+MeScroll.prototype.hideUpScroll = function() {
+ this.optUp.hideUpScroll && this.optUp.hideUpScroll(this); // 回调
+}
+
+/* 结束上拉加载 */
+MeScroll.prototype.endUpScroll = function(isShowNoMore) {
+ if (isShowNoMore != null) { // isShowNoMore=null,不处理下拉状态,下拉刷新的时候调用
+ if (isShowNoMore) {
+ this.showNoMore(); // isShowNoMore=true,显示无更多数据
+ } else {
+ this.hideUpScroll(); // isShowNoMore=false,隐藏上拉加载
+ }
+ }
+ this.isUpScrolling = false; // 标记结束上拉加载
+}
+
+/* 重置上拉加载列表为第一页
+ *isShowLoading 是否显示进度布局;
+ * 1.默认null,不传参,则显示上拉加载的进度布局
+ * 2.传参true, 则显示下拉刷新的进度布局
+ * 3.传参false,则不显示上拉和下拉的进度 (常用于静默更新列表数据)
+ */
+MeScroll.prototype.resetUpScroll = function(isShowLoading) {
+ if (this.optUp && this.optUp.use) {
+ let page = this.optUp.page;
+ this.prePageNum = page.num; // 缓存重置前的页码,加载失败可退回
+ this.prePageTime = page.time; // 缓存重置前的时间,加载失败可退回
+ page.num = this.startNum; // 重置为第一页
+ page.time = null; // 重置时间为空
+ if (!this.isDownScrolling && isShowLoading !== false) { // 如果不是下拉刷新触发的resetUpScroll并且不配置列表静默更新,则显示进度;
+ if (isShowLoading == null) {
+ this.removeEmpty(); // 移除空布局
+ this.showUpScroll(); // 不传参,默认显示上拉加载的进度布局
+ } else {
+ this.showDownScroll(); // 传true,显示下拉刷新的进度布局,不清空列表
+ }
+ }
+ this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
+ this.num = page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
+ this.size = page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
+ this.time = page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
+ this.optUp.callback && this.optUp.callback(this); // 执行上拉回调
+ }
+}
+
+/* 设置page.num的值 */
+MeScroll.prototype.setPageNum = function(num) {
+ this.optUp.page.num = num - 1;
+}
+
+/* 设置page.size的值 */
+MeScroll.prototype.setPageSize = function(size) {
+ this.optUp.page.size = size;
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据量(必传)
+ * totalPage: 总页数(必传)
+ * systime: 服务器时间 (可空)
+ */
+MeScroll.prototype.endByPage = function(dataSize, totalPage, systime) {
+ let hasNext;
+ if (this.optUp.use && totalPage != null) hasNext = this.optUp.page.num < totalPage; // 是否还有下一页
+ this.endSuccess(dataSize, hasNext, systime);
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据量(必传)
+ * totalSize: 列表所有数据总数量(必传)
+ * systime: 服务器时间 (可空)
+ */
+MeScroll.prototype.endBySize = function(dataSize, totalSize, systime) {
+ let hasNext;
+ if (this.optUp.use && totalSize != null) {
+ let loadSize = (this.optUp.page.num - 1) * this.optUp.page.size + dataSize; // 已加载的数据总数
+ hasNext = loadSize < totalSize; // 是否还有下一页
+ }
+ this.endSuccess(dataSize, hasNext, systime);
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据个数(不是所有页的数据总和),用于上拉加载判断是否还有下一页.如果不传,则会判断还有下一页
+ * hasNext: 是否还有下一页,布尔类型;用来解决这个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据dataSize判断,则需翻到第三页才会知道无更多数据,如果传了hasNext,则翻到第二页即可显示无更多数据.
+ * systime: 服务器时间(可空);用来解决这个小问题:当准备翻下一页时,数据库新增了几条记录,此时翻下一页,前面的几条数据会和上一页的重复;这里传入了systime,那么upCallback的page.time就会有值,把page.time传给服务器,让后台过滤新加入的那几条记录
+ */
+MeScroll.prototype.endSuccess = function(dataSize, hasNext, systime) {
+ let me = this;
+ // 结束下拉刷新
+ if (me.isDownScrolling) {
+ me.isDownEndSuccess = true
+ me.endDownScroll();
+ }
+
+ // 结束上拉加载
+ if (me.optUp.use) {
+ let isShowNoMore; // 是否已无更多数据
+ if (dataSize != null) {
+ let pageNum = me.optUp.page.num; // 当前页码
+ let pageSize = me.optUp.page.size; // 每页长度
+ // 如果是第一页
+ if (pageNum === 1) {
+ if (systime) me.optUp.page.time = systime; // 设置加载列表数据第一页的时间
+ }
+ if (dataSize < pageSize || hasNext === false) {
+ // 返回的数据不满一页时,则说明已无更多数据
+ me.optUp.hasNext = false;
+ if (dataSize === 0 && pageNum === 1) {
+ // 如果第一页无任何数据且配置了空布局
+ isShowNoMore = false;
+ me.showEmpty();
+ } else {
+ // 总列表数少于配置的数量,则不显示无更多数据
+ let allDataSize = (pageNum - 1) * pageSize + dataSize;
+ if (allDataSize < me.optUp.noMoreSize) {
+ isShowNoMore = false;
+ } else {
+ isShowNoMore = true;
+ }
+ me.removeEmpty(); // 移除空布局
+ }
+ } else {
+ // 还有下一页
+ isShowNoMore = false;
+ me.optUp.hasNext = true;
+ me.removeEmpty(); // 移除空布局
+ }
+ }
+
+ // 隐藏上拉
+ me.endUpScroll(isShowNoMore);
+ }
+}
+
+/* 回调失败,结束下拉刷新和上拉加载 */
+MeScroll.prototype.endErr = function(errDistance) {
+ // 结束下拉,回调失败重置回原来的页码和时间
+ if (this.isDownScrolling) {
+ this.isDownEndSuccess = false
+ let page = this.optUp.page;
+ if (page && this.prePageNum) {
+ page.num = this.prePageNum;
+ page.time = this.prePageTime;
+ }
+ this.endDownScroll();
+ }
+ // 结束上拉,回调失败重置回原来的页码
+ if (this.isUpScrolling) {
+ this.optUp.page.num--;
+ this.endUpScroll(false);
+ // 如果是mescroll-body,则需往回滚一定距离
+ if(this.isScrollBody && errDistance !== 0){ // 不处理0
+ if(!errDistance) errDistance = this.optUp.errDistance; // 不传,则取默认
+ this.scrollTo(this.getScrollTop() - errDistance, 0) // 往上回滚的距离
+ }
+ }
+}
+
+/* 显示空布局 */
+MeScroll.prototype.showEmpty = function() {
+ this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(true)
+}
+
+/* 移除空布局 */
+MeScroll.prototype.removeEmpty = function() {
+ this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(false)
+}
+
+/* 显示回到顶部的按钮 */
+MeScroll.prototype.showTopBtn = function() {
+ if (!this.topBtnShow) {
+ this.topBtnShow = true;
+ this.optUp.toTop.onShow && this.optUp.toTop.onShow(true);
+ }
+}
+
+/* 隐藏回到顶部的按钮 */
+MeScroll.prototype.hideTopBtn = function() {
+ if (this.topBtnShow) {
+ this.topBtnShow = false;
+ this.optUp.toTop.onShow && this.optUp.toTop.onShow(false);
+ }
+}
+
+/* 获取滚动条的位置 */
+MeScroll.prototype.getScrollTop = function() {
+ return this.scrollTop || 0
+}
+
+/* 记录滚动条的位置 */
+MeScroll.prototype.setScrollTop = function(y) {
+ this.scrollTop = y;
+}
+
+/* 滚动到指定位置 */
+MeScroll.prototype.scrollTo = function(y, t) {
+ this.myScrollTo && this.myScrollTo(y, t) // scrollview需自定义回到顶部方法
+}
+
+/* 自定义scrollTo */
+MeScroll.prototype.resetScrollTo = function(myScrollTo) {
+ this.myScrollTo = myScrollTo
+}
+
+/* 滚动条到底部的距离 */
+MeScroll.prototype.getScrollBottom = function() {
+ return this.getScrollHeight() - this.getClientHeight() - this.getScrollTop()
+}
+
+/* 计步器
+ star: 开始值
+ end: 结束值
+ callback(step,timer): 回调step值,计步器timer,可自行通过window.clearInterval(timer)结束计步器;
+ t: 计步时长,传0则直接回调end值;不传则默认300ms
+ rate: 周期;不传则默认30ms计步一次
+ * */
+MeScroll.prototype.getStep = function(star, end, callback, t, rate) {
+ let diff = end - star; // 差值
+ if (t === 0 || diff === 0) {
+ callback && callback(end);
+ return;
+ }
+ t = t || 300; // 时长 300ms
+ rate = rate || 30; // 周期 30ms
+ let count = t / rate; // 次数
+ let step = diff / count; // 步长
+ let i = 0; // 计数
+ let timer = setInterval(function() {
+ if (i < count - 1) {
+ star += step;
+ callback && callback(star, timer);
+ i++;
+ } else {
+ callback && callback(end, timer); // 最后一次直接设置end,避免计算误差
+ clearInterval(timer);
+ }
+ }, rate);
+}
+
+/* 滚动容器的高度 */
+MeScroll.prototype.getClientHeight = function(isReal) {
+ let h = this.clientHeight || 0
+ if (h === 0 && isReal !== true) { // 未获取到容器的高度,可临时取body的高度 (可能会有误差)
+ h = this.getBodyHeight()
+ }
+ return h
+}
+MeScroll.prototype.setClientHeight = function(h) {
+ this.clientHeight = h;
+}
+
+/* 滚动内容的高度 */
+MeScroll.prototype.getScrollHeight = function() {
+ return this.scrollHeight || 0;
+}
+MeScroll.prototype.setScrollHeight = function(h) {
+ this.scrollHeight = h;
+}
+
+/* body的高度 */
+MeScroll.prototype.getBodyHeight = function() {
+ return this.bodyHeight || 0;
+}
+MeScroll.prototype.setBodyHeight = function(h) {
+ this.bodyHeight = h;
+}
+
+/* 阻止浏览器默认滚动事件 */
+MeScroll.prototype.preventDefault = function(e) {
+ // 小程序不支持e.preventDefault, 已在wxs中禁止
+ // app的bounce只能通过配置pages.json的style.app-plus.bounce为"none"来禁止, 或使用renderjs禁止
+ // cancelable:是否可以被禁用; defaultPrevented:是否已经被禁用
+ if (e && e.cancelable && !e.defaultPrevented) e.preventDefault()
+}
\ No newline at end of file
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni.vue b/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni.vue
new file mode 100644
index 0000000..cb5d026
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-uni.vue
@@ -0,0 +1,480 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{downText}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ mescroll.optUp.textLoading }}
+
+
+ {{ mescroll.optUp.textNoMore }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-comp.js b/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-comp.js
new file mode 100644
index 0000000..abe7cd7
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-comp.js
@@ -0,0 +1,47 @@
+/**
+ * mescroll-body写在子组件时,需通过mescroll的mixins补充子组件缺少的生命周期
+ */
+const MescrollCompMixin = {
+ // 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件 (一级)
+ onPageScroll(e) {
+ this.handlePageScroll(e)
+ },
+ onReachBottom() {
+ this.handleReachBottom()
+ },
+ // 当down的native: true时, 还需传递此方法进到子组件
+ onPullDownRefresh(){
+ this.handlePullDownRefresh()
+ },
+ data() {
+ return {
+ mescroll: { // mescroll-body写在子子子...组件的情况 (多级)
+ onPageScroll: e=>{
+ this.handlePageScroll(e)
+ },
+ onReachBottom: ()=>{
+ this.handleReachBottom()
+ },
+ onPullDownRefresh: ()=>{
+ this.handlePullDownRefresh()
+ }
+ }
+ }
+ },
+ methods:{
+ handlePageScroll(e){
+ let item = this.$refs["mescrollItem"];
+ if(item && item.mescroll) item.mescroll.onPageScroll(e);
+ },
+ handleReachBottom(){
+ let item = this.$refs["mescrollItem"];
+ if(item && item.mescroll) item.mescroll.onReachBottom();
+ },
+ handlePullDownRefresh(){
+ let item = this.$refs["mescrollItem"];
+ if(item && item.mescroll) item.mescroll.onPullDownRefresh();
+ }
+ }
+}
+
+export default MescrollCompMixin;
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more-item.js b/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more-item.js
new file mode 100644
index 0000000..96ca9bf
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more-item.js
@@ -0,0 +1,57 @@
+/**
+ * mescroll-more-item的mixins, 仅在多个 mescroll-body 写在子组件时使用 (参考 mescroll-more 案例)
+ */
+const MescrollMoreItemMixin = {
+ // 支付宝小程序不支持props的mixin,需写在具体的页面中
+ // #ifndef MP-ALIPAY || MP-DINGTALK
+ props:{
+ i: Number, // 每个tab页的专属下标
+ index: { // 当前tab的下标
+ type: Number,
+ default(){
+ return 0
+ }
+ }
+ },
+ // #endif
+ data() {
+ return {
+ downOption:{
+ auto:false // 不自动加载
+ },
+ upOption:{
+ auto:false // 不自动加载
+ },
+ isInit: false // 当前tab是否已初始化
+ }
+ },
+ watch:{
+ // 监听下标的变化
+ index(val){
+ if (this.i === val && !this.isInit) this.mescrollTrigger()
+ }
+ },
+ methods: {
+ // mescroll组件初始化的回调,可获取到mescroll对象 (覆盖mescroll-mixins.js的mescrollInit, 为了标记isInit)
+ mescrollInit(mescroll) {
+ this.mescroll = mescroll;
+ // 自动加载当前tab的数据
+ if(this.i === this.index){
+ this.mescrollTrigger()
+ }
+ },
+ // 主动触发加载
+ mescrollTrigger(){
+ this.isInit = true; // 标记为true
+ if (this.mescroll) {
+ if (this.mescroll.optDown.use) {
+ this.mescroll.triggerDownScroll();
+ } else{
+ this.mescroll.triggerUpScroll();
+ }
+ }
+ }
+ }
+}
+
+export default MescrollMoreItemMixin;
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more.js b/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more.js
new file mode 100644
index 0000000..16b47d8
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more.js
@@ -0,0 +1,77 @@
+/**
+ * mescroll-body写在子组件时, 需通过mescroll的mixins补充子组件缺少的生命周期
+ */
+const MescrollMoreMixin = {
+ data() {
+ return {
+ tabIndex: 0, // 当前tab下标
+ mescroll: { // mescroll-body写在子子子...组件的情况 (多级)
+ onPageScroll: e=>{
+ this.handlePageScroll(e)
+ },
+ onReachBottom: ()=>{
+ this.handleReachBottom()
+ },
+ onPullDownRefresh: ()=>{
+ this.handlePullDownRefresh()
+ }
+ }
+ }
+ },
+ // 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件
+ onPageScroll(e) {
+ this.handlePageScroll(e)
+ },
+ onReachBottom() {
+ this.handleReachBottom()
+ },
+ // 当down的native: true时, 还需传递此方法进到子组件
+ onPullDownRefresh(){
+ this.handlePullDownRefresh()
+ },
+ methods:{
+ handlePageScroll(e){
+ let mescroll = this.getMescroll(this.tabIndex);
+ mescroll && mescroll.onPageScroll(e);
+ },
+ handleReachBottom(){
+ let mescroll = this.getMescroll(this.tabIndex);
+ mescroll && mescroll.onReachBottom();
+ },
+ handlePullDownRefresh(){
+ let mescroll = this.getMescroll(this.tabIndex);
+ mescroll && mescroll.onPullDownRefresh();
+ },
+ // 根据下标获取对应子组件的mescroll
+ getMescroll(i){
+ if(!this.mescrollItems) this.mescrollItems = [];
+ if(!this.mescrollItems[i]) {
+ // v-for中的refs
+ let vForItem = this.$refs["mescrollItem"];
+ if(vForItem){
+ this.mescrollItems[i] = vForItem[i]
+ }else{
+ // 普通的refs,不可重复
+ this.mescrollItems[i] = this.$refs["mescrollItem"+i];
+ }
+ }
+ let item = this.mescrollItems[i]
+ return item ? item.mescroll : null
+ },
+ // 切换tab,恢复滚动条位置
+ tabChange(i){
+ let mescroll = this.getMescroll(i);
+ if(mescroll){
+ // 恢复上次滚动条的位置
+ let y = mescroll.getScrollTop()
+ mescroll.scrollTo(y, 0)
+ // 再次恢复上次滚动条的位置, 确保元素已渲染
+ setTimeout(()=>{
+ mescroll.scrollTo(y, 0)
+ },30)
+ }
+ }
+ }
+}
+
+export default MescrollMoreMixin;
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/wxs/mixins.js b/uni_modules/mescroll-uni/components/mescroll-uni/wxs/mixins.js
new file mode 100644
index 0000000..34ffa3c
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/wxs/mixins.js
@@ -0,0 +1,109 @@
+// 定义在wxs (含renderjs) 逻辑层的数据和方法, 与视图层相互通信
+const WxsMixin = {
+ data() {
+ return {
+ // 传入wxs视图层的数据 (响应式)
+ wxsProp: {
+ optDown:{}, // 下拉刷新的配置
+ scrollTop:0, // 滚动条的距离
+ bodyHeight:0, // body的高度
+ isDownScrolling:false, // 是否正在下拉刷新中
+ isUpScrolling:false, // 是否正在上拉加载中
+ isScrollBody:true, // 是否为mescroll-body滚动
+ isUpBoth:true, // 上拉加载时,是否同时可以下拉刷新
+ t: 0 // 数据更新的标记 (只有数据更新了,才会触发wxs的Observer)
+ },
+
+ // 标记调用wxs视图层的方法
+ callProp: {
+ callType: '', // 方法名
+ t: 0 // 数据更新的标记 (只有数据更新了,才会触发wxs的Observer)
+ },
+
+ // 不用wxs的平台使用此处的wxsBiz对象,抹平wxs的写法 (微信小程序和APP使用的wxsBiz对象是./wxs/wxs.wxs)
+ // #ifndef MP-WEIXIN || MP-QQ || APP-PLUS || H5
+ wxsBiz: {
+ //注册列表touchstart事件,用于下拉刷新
+ touchstartEvent: e=> {
+ this.mescroll.touchstartEvent(e);
+ },
+ //注册列表touchmove事件,用于下拉刷新
+ touchmoveEvent: e=> {
+ this.mescroll.touchmoveEvent(e);
+ },
+ //注册列表touchend事件,用于下拉刷新
+ touchendEvent: e=> {
+ this.mescroll.touchendEvent(e);
+ },
+ propObserver(){}, // 抹平wxs的写法
+ callObserver(){} // 抹平wxs的写法
+ },
+ // #endif
+
+ // 不用renderjs的平台使用此处的renderBiz对象,抹平renderjs的写法 (app 和 h5 使用的renderBiz对象是./wxs/renderjs.js)
+ // #ifndef APP-PLUS || H5
+ renderBiz: {
+ propObserver(){} // 抹平renderjs的写法
+ }
+ // #endif
+ }
+ },
+ methods: {
+ // wxs视图层调用逻辑层的回调
+ wxsCall(msg){
+ if(msg.type === 'setWxsProp'){
+ // 更新wxsProp数据 (值改变才触发更新)
+ this.wxsProp = {
+ optDown: this.mescroll.optDown,
+ scrollTop: this.mescroll.getScrollTop(),
+ bodyHeight: this.mescroll.getBodyHeight(),
+ isDownScrolling: this.mescroll.isDownScrolling,
+ isUpScrolling: this.mescroll.isUpScrolling,
+ isUpBoth: this.mescroll.optUp.isBoth,
+ isScrollBody:this.mescroll.isScrollBody,
+ t: Date.now()
+ }
+ }else if(msg.type === 'setLoadType'){
+ // 设置inOffset,outOffset的状态
+ this.downLoadType = msg.downLoadType
+ // 状态挂载到mescroll对象, 以便在其他组件中使用, 比如中
+ this.$set(this.mescroll, 'downLoadType', this.downLoadType)
+ // 重置是否加载成功的状态
+ this.$set(this.mescroll, 'isDownEndSuccess', null)
+ }else if(msg.type === 'triggerDownScroll'){
+ // 主动触发下拉刷新
+ this.mescroll.triggerDownScroll();
+ }else if(msg.type === 'endDownScroll'){
+ // 结束下拉刷新
+ this.mescroll.endDownScroll();
+ }else if(msg.type === 'triggerUpScroll'){
+ // 主动触发上拉加载
+ this.mescroll.triggerUpScroll(true);
+ }
+ }
+ },
+ mounted() {
+ // #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5
+ // 配置主动触发wxs显示加载进度的回调
+ this.mescroll.optDown.afterLoading = ()=>{
+ this.callProp = {callType: "showLoading", t: Date.now()} // 触发wxs的方法 (值改变才触发更新)
+ }
+ // 配置主动触发wxs隐藏加载进度的回调
+ this.mescroll.optDown.afterEndDownScroll = ()=>{
+ this.callProp = {callType: "endDownScroll", t: Date.now()} // 触发wxs的方法 (值改变才触发更新)
+ let delay = 300 + (this.mescroll.optDown.beforeEndDelay || 0)
+ setTimeout(()=>{
+ if(this.downLoadType === 4 || this.downLoadType === 0){
+ this.callProp = {callType: "clearTransform", t: Date.now()} // 触发wxs的方法 (值改变才触发更新)
+ }
+ // 状态挂载到mescroll对象, 以便在其他组件中使用, 比如中
+ this.$set(this.mescroll, 'downLoadType', this.downLoadType)
+ }, delay)
+ }
+ // 初始化wxs的数据
+ this.wxsCall({type: 'setWxsProp'})
+ // #endif
+ }
+}
+
+export default WxsMixin;
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/wxs/renderjs.js b/uni_modules/mescroll-uni/components/mescroll-uni/wxs/renderjs.js
new file mode 100644
index 0000000..6cd1301
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/wxs/renderjs.js
@@ -0,0 +1,92 @@
+// 使用renderjs直接操作window对象,实现动态控制app和h5的bounce
+// bounce: iOS橡皮筋,Android半月弧,h5浏览器下拉背景等效果 (下拉刷新时禁止)
+// https://uniapp.dcloud.io/frame?id=renderjs
+
+// 与wxs的me实例一致
+var me = {}
+
+// 初始化window对象的touch事件 (仅初始化一次)
+if(window && !window.$mescrollRenderInit){
+ window.$mescrollRenderInit = true
+
+
+ window.addEventListener('touchstart', function(e){
+ if (me.disabled()) return;
+ me.startPoint = me.getPoint(e); // 记录起点
+ }, {passive: true})
+
+
+ window.addEventListener('touchmove', function(e){
+ if (me.disabled()) return;
+ if (me.getScrollTop() > 0) return; // 需在顶部下拉,才禁止bounce
+
+ var curPoint = me.getPoint(e); // 当前点
+ var moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+ // 向下拉
+ if (moveY > 0) {
+ // 可下拉的条件
+ if (!me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling && me.isUpBoth))) {
+
+ // 只有touch在mescroll的view上面,才禁止bounce
+ var el = e.target;
+ var isMescrollTouch = false;
+ while (el && el.tagName && el.tagName !== 'UNI-PAGE-BODY' && el.tagName != "BODY") {
+ var cls = el.classList;
+ if (cls && cls.contains('mescroll-render-touch')) {
+ isMescrollTouch = true
+ break;
+ }
+ el = el.parentNode; // 继续检查其父元素
+ }
+ // 禁止bounce (不会对swiper和iOS侧滑返回造成影响)
+ if (isMescrollTouch && e.cancelable && !e.defaultPrevented) e.preventDefault();
+ }
+ }
+ }, {passive: false})
+}
+
+/* 获取滚动条的位置 */
+me.getScrollTop = function() {
+ return me.scrollTop || document.documentElement.scrollTop || document.body.scrollTop || 0
+}
+
+/* 是否禁用下拉刷新 */
+me.disabled = function(){
+ return !me.optDown || !me.optDown.use || me.optDown.native
+}
+
+/* 根据点击滑动事件获取第一个手指的坐标 */
+me.getPoint = function(e) {
+ if (!e) {
+ return {x: 0,y: 0}
+ }
+ if (e.touches && e.touches[0]) {
+ return {x: e.touches[0].pageX,y: e.touches[0].pageY}
+ } else if (e.changedTouches && e.changedTouches[0]) {
+ return {x: e.changedTouches[0].pageX,y: e.changedTouches[0].pageY}
+ } else {
+ return {x: e.clientX,y: e.clientY}
+ }
+}
+
+/**
+ * 监听逻辑层数据的变化 (实时更新数据)
+ */
+function propObserver(wxsProp) {
+ me.optDown = wxsProp.optDown
+ me.scrollTop = wxsProp.scrollTop
+ me.isDownScrolling = wxsProp.isDownScrolling
+ me.isUpScrolling = wxsProp.isUpScrolling
+ me.isUpBoth = wxsProp.isUpBoth
+}
+
+/* 导出模块 */
+const renderBiz = {
+ data() {
+ return {
+ propObserver: propObserver,
+ }
+ }
+}
+
+export default renderBiz;
\ No newline at end of file
diff --git a/uni_modules/mescroll-uni/components/mescroll-uni/wxs/wxs.wxs b/uni_modules/mescroll-uni/components/mescroll-uni/wxs/wxs.wxs
new file mode 100644
index 0000000..4af4201
--- /dev/null
+++ b/uni_modules/mescroll-uni/components/mescroll-uni/wxs/wxs.wxs
@@ -0,0 +1,269 @@
+// 使用wxs处理交互动画, 提高性能, 同时避免小程序bounce对下拉刷新的影响
+// https://uniapp.dcloud.io/frame?id=wxs
+// https://developers.weixin.qq.com/miniprogram/dev/framework/view/interactive-animation.html
+
+// 模拟mescroll实例, 与mescroll.js的写法尽量保持一致
+var me = {}
+
+// ------ 自定义下拉刷新动画 start ------
+
+/* 下拉过程中的回调,滑动过程一直在执行 (rate<1为inOffset; rate>1为outOffset) */
+me.onMoving = function (ins, rate, downHight){
+ ins.requestAnimationFrame(function () {
+ ins.selectComponent('.mescroll-wxs-content').setStyle({
+ 'will-change': 'transform', // 可解决下拉过程中, image和swiper脱离文档流的问题
+ 'transform': 'translateY(' + downHight + 'px)',
+ 'transition': ''
+ })
+ // 环形进度条
+ var progress = ins.selectComponent('.mescroll-wxs-progress')
+ progress && progress.setStyle({transform: 'rotate(' + 360 * rate + 'deg)'})
+ })
+}
+
+/* 显示下拉刷新进度 */
+me.showLoading = function (ins){
+ me.downHight = me.optDown.offset
+ ins.requestAnimationFrame(function () {
+ ins.selectComponent('.mescroll-wxs-content').setStyle({
+ 'will-change': 'auto',
+ 'transform': 'translateY(' + me.downHight + 'px)',
+ 'transition': 'transform 300ms'
+ })
+ })
+}
+
+/* 结束下拉 */
+me.endDownScroll = function (ins){
+ me.downHight = 0;
+ me.isDownScrolling = false;
+ ins.requestAnimationFrame(function () {
+ ins.selectComponent('.mescroll-wxs-content').setStyle({
+ 'will-change': 'auto',
+ 'transform': 'translateY(0)', // 不可以写空串,否则scroll-view渲染不完整 (延时350ms会调clearTransform置空)
+ 'transition': 'transform 300ms'
+ })
+ })
+}
+
+/* 结束下拉动画执行完毕后, 清除transform和transition, 避免对列表内容样式造成影响, 如: h5的list-msg示例下拉进度条漏出来等 */
+me.clearTransform = function (ins){
+ ins.requestAnimationFrame(function () {
+ ins.selectComponent('.mescroll-wxs-content').setStyle({
+ 'will-change': '',
+ 'transform': '',
+ 'transition': ''
+ })
+ })
+}
+
+// ------ 自定义下拉刷新动画 end ------
+
+/**
+ * 监听逻辑层数据的变化 (实时更新数据)
+ */
+function propObserver(wxsProp) {
+ if(!wxsProp) return
+ me.optDown = wxsProp.optDown
+ me.scrollTop = wxsProp.scrollTop
+ me.bodyHeight = wxsProp.bodyHeight
+ me.isDownScrolling = wxsProp.isDownScrolling
+ me.isUpScrolling = wxsProp.isUpScrolling
+ me.isUpBoth = wxsProp.isUpBoth
+ me.isScrollBody = wxsProp.isScrollBody
+ me.startTop = wxsProp.scrollTop // 及时更新touchstart触发的startTop, 避免scroll-view快速惯性滚动到顶部取值不准确
+}
+
+/**
+ * 监听逻辑层数据的变化 (调用wxs的方法)
+ */
+function callObserver(callProp, oldValue, ins) {
+ if (me.disabled()) return;
+ if(callProp.callType){
+ // 逻辑层(App Service)的style已失效,需在视图层(Webview)设置style
+ if(callProp.callType === 'showLoading'){
+ me.showLoading(ins)
+ }else if(callProp.callType === 'endDownScroll'){
+ me.endDownScroll(ins)
+ }else if(callProp.callType === 'clearTransform'){
+ me.clearTransform(ins)
+ }
+ }
+}
+
+/**
+ * touch事件
+ */
+function touchstartEvent(e, ins) {
+ me.downHight = 0; // 下拉的距离
+ me.startPoint = me.getPoint(e); // 记录起点
+ me.startTop = me.getScrollTop(); // 记录此时的滚动条位置
+ me.startAngle = 0; // 初始角度
+ me.lastPoint = me.startPoint; // 重置上次move的点
+ me.maxTouchmoveY = me.getBodyHeight() - me.optDown.bottomOffset; // 手指触摸的最大范围(写在touchstart避免body获取高度为0的情况)
+ me.inTouchend = false; // 标记不是touchend
+
+ me.callMethod(ins, {type: 'setWxsProp'}) // 同步更新wxsProp的数据 (小程序是异步的,可能touchmove先执行,才到propObserver; h5和app是同步)
+}
+
+function touchmoveEvent(e, ins) {
+ var isPrevent = true // false表示不往上冒泡,相当于调用了同时调用了stopPropagation和preventDefault (对小程序生效, h5和app无效)
+
+ if (me.disabled()) return isPrevent;
+
+ var scrollTop = me.getScrollTop(); // 当前滚动条的距离
+ var curPoint = me.getPoint(e); // 当前点
+
+ var moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+
+ // 向下拉 && 在顶部
+ // mescroll-body,直接判定在顶部即可
+ // scroll-view在滚动时不会触发touchmove,当触顶/底/左/右时,才会触发touchmove
+ // scroll-view滚动到顶部时,scrollTop不一定为0,也有可能大于0; 在iOS的APP中scrollTop可能为负数,不一定和startTop相等
+ if (moveY > 0 && (
+ (me.isScrollBody && scrollTop <= 0)
+ ||
+ (!me.isScrollBody && (scrollTop <= 0 || (scrollTop <= me.optDown.startTop && scrollTop === me.startTop)) )
+ )) {
+ // 可下拉的条件
+ if (!me.inTouchend && !me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling &&
+ me.isUpBoth))) {
+
+ // 下拉的角度是否在配置的范围内
+ if(!me.startAngle) me.startAngle = me.getAngle(me.lastPoint, curPoint); // 两点之间的角度,区间 [0,90]
+ if (me.startAngle < me.optDown.minAngle) return isPrevent; // 如果小于配置的角度,则不往下执行下拉刷新
+
+ // 如果手指的位置超过配置的距离,则提前结束下拉,避免Webview嵌套导致touchend无法触发
+ if (me.maxTouchmoveY > 0 && curPoint.y >= me.maxTouchmoveY) {
+ me.inTouchend = true; // 标记执行touchend
+ touchendEvent(e, ins); // 提前触发touchend
+ return isPrevent;
+ }
+
+ isPrevent = false // 小程序是return false
+
+ var diff = curPoint.y - me.lastPoint.y; // 和上次比,移动的距离 (大于0向下,小于0向上)
+
+ // 下拉距离 < 指定距离
+ if (me.downHight < me.optDown.offset) {
+ if (me.movetype !== 1) {
+ me.movetype = 1; // 加入标记,保证只执行一次
+ // me.optDown.inOffset && me.optDown.inOffset(me); // 进入指定距离范围内那一刻的回调,只执行一次
+ me.callMethod(ins, {type: 'setLoadType', downLoadType: 1})
+ me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+ }
+ me.downHight += diff * me.optDown.inOffsetRate; // 越往下,高度变化越小
+
+ // 指定距离 <= 下拉距离
+ } else {
+ if (me.movetype !== 2) {
+ me.movetype = 2; // 加入标记,保证只执行一次
+ // me.optDown.outOffset && me.optDown.outOffset(me); // 下拉超过指定距离那一刻的回调,只执行一次
+ me.callMethod(ins, {type: 'setLoadType', downLoadType: 2})
+ me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+ }
+ if (diff > 0) { // 向下拉
+ me.downHight += diff * me.optDown.outOffsetRate; // 越往下,高度变化越小
+ } else { // 向上收
+ me.downHight += diff; // 向上收回高度,则向上滑多少收多少高度
+ }
+ }
+
+ me.downHight = Math.round(me.downHight) // 取整
+ var rate = me.downHight / me.optDown.offset; // 下拉区域当前高度与指定距离的比值
+ // me.optDown.onMoving && me.optDown.onMoving(me, rate, me.downHight); // 下拉过程中的回调,一直在执行
+ me.onMoving(ins, rate, me.downHight)
+ }
+ }
+
+ me.lastPoint = curPoint; // 记录本次移动的点
+
+ return isPrevent // false表示不往上冒泡,相当于调用了同时调用了stopPropagation和preventDefault (对小程序生效, h5和app无效)
+}
+
+function touchendEvent(e, ins) {
+ // 如果下拉区域高度已改变,则需重置回来
+ if (me.isMoveDown) {
+ if (me.downHight >= me.optDown.offset) {
+ // 符合触发刷新的条件
+ me.downHight = me.optDown.offset; // 更新下拉区域高度
+ // me.triggerDownScroll();
+ me.callMethod(ins, {type: 'triggerDownScroll'})
+ } else {
+ // 不符合的话 则重置
+ me.downHight = 0;
+ // me.optDown.endDownScroll && me.optDown.endDownScroll(me);
+ me.callMethod(ins, {type: 'endDownScroll'})
+ }
+ me.movetype = 0;
+ me.isMoveDown = false;
+ } else if (!me.isScrollBody && me.getScrollTop() === me.startTop) { // scroll-view到顶/左/右/底的滑动事件
+ var isScrollUp = me.getPoint(e).y - me.startPoint.y < 0; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+ // 上滑
+ if (isScrollUp) {
+ // 需检查滑动的角度
+ var angle = me.getAngle(me.getPoint(e), me.startPoint); // 两点之间的角度,区间 [0,90]
+ if (angle > 80) {
+ // 检查并触发上拉
+ // me.triggerUpScroll(true);
+ me.callMethod(ins, {type: 'triggerUpScroll'})
+ }
+ }
+ }
+ me.callMethod(ins, {type: 'setWxsProp'}) // 同步更新wxsProp的数据 (小程序是异步的,可能touchmove先执行,才到propObserver; h5和app是同步)
+}
+
+/* 是否禁用下拉刷新 */
+me.disabled = function(){
+ return !me.optDown || !me.optDown.use || me.optDown.native
+}
+
+/* 根据点击滑动事件获取第一个手指的坐标 */
+me.getPoint = function(e) {
+ if (!e) {
+ return {x: 0,y: 0}
+ }
+ if (e.touches && e.touches[0]) {
+ return {x: e.touches[0].pageX,y: e.touches[0].pageY}
+ } else if (e.changedTouches && e.changedTouches[0]) {
+ return {x: e.changedTouches[0].pageX,y: e.changedTouches[0].pageY}
+ } else {
+ return {x: e.clientX,y: e.clientY}
+ }
+}
+
+/* 计算两点之间的角度: 区间 [0,90]*/
+me.getAngle = function (p1, p2) {
+ var x = Math.abs(p1.x - p2.x);
+ var y = Math.abs(p1.y - p2.y);
+ var z = Math.sqrt(x * x + y * y);
+ var angle = 0;
+ if (z !== 0) {
+ angle = Math.asin(y / z) / Math.PI * 180;
+ }
+ return angle
+}
+
+/* 获取滚动条的位置 */
+me.getScrollTop = function() {
+ return me.scrollTop || 0
+}
+
+/* 获取body的高度 */
+me.getBodyHeight = function() {
+ return me.bodyHeight || 0;
+}
+
+/* 调用逻辑层的方法 */
+me.callMethod = function(ins, param) {
+ if(ins) ins.callMethod('wxsCall', param)
+}
+
+/* 导出模块 */
+module.exports = {
+ propObserver: propObserver,
+ callObserver: callObserver,
+ touchstartEvent: touchstartEvent,
+ touchmoveEvent: touchmoveEvent,
+ touchendEvent: touchendEvent
+}
\ No newline at end of file
diff --git a/uni_modules/mescroll-uni/hooks/useMescroll.js b/uni_modules/mescroll-uni/hooks/useMescroll.js
new file mode 100644
index 0000000..ef91cd1
--- /dev/null
+++ b/uni_modules/mescroll-uni/hooks/useMescroll.js
@@ -0,0 +1,66 @@
+// 小程序无法在hook中使用页面级别生命周期,需单独传入: https://ask.dcloud.net.cn/question/161173
+// import { onPageScroll, onReachBottom, onPullDownRefresh} from '@dcloudio/uni-app';
+
+/**
+ * 初始化mescroll, 相当于vue2的mescroll-mixins.js文件 (mescroll-body 和 mescroll-uni 通用)
+ * mescroll-body需传入onPageScroll, onReachBottom
+ * mescroll-uni无需传onPageScroll, onReachBottom
+ * 当down.native为true时,需传入onPullDownRefresh
+ */
+function useMescroll(onPageScroll, onReachBottom, onPullDownRefresh){
+ // mescroll实例对象
+ let mescroll = null;
+
+ // mescroll组件初始化的回调,可获取到mescroll对象
+ const mescrollInit = (e)=> {
+ mescroll = e;
+ }
+
+ // 获取mescroll对象, mescrollInit执行之后会有值, 生命周期created中会有值
+ const getMescroll = ()=>{
+ return mescroll
+ }
+
+ // 下拉刷新的回调 (mixin默认resetUpScroll)
+ const downCallback = ()=> {
+ if(mescroll.optUp.use){
+ mescroll.resetUpScroll()
+ }else{
+ setTimeout(()=>{
+ mescroll.endSuccess();
+ }, 500)
+ }
+ }
+
+ // 上拉加载的回调
+ const upCallback = ()=> {
+ // mixin默认延时500自动结束加载
+ setTimeout(()=>{
+ mescroll.endErr();
+ }, 500)
+ }
+
+ // 注册系统自带的下拉刷新 (配置down.native为true时生效, 还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+ onPullDownRefresh && onPullDownRefresh(() => {
+ mescroll && mescroll.onPullDownRefresh();
+ })
+
+ // 注册列表滚动事件,用于判定在顶部可下拉刷新,在指定位置可显示隐藏回到顶部按钮 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
+ onPageScroll && onPageScroll(e=>{
+ mescroll && mescroll.onPageScroll(e);
+ })
+
+ // 注册滚动到底部的事件,用于上拉加载 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
+ onReachBottom && onReachBottom(()=>{
+ mescroll && mescroll.onReachBottom();
+ })
+
+ return {
+ getMescroll,
+ mescrollInit,
+ downCallback,
+ upCallback
+ }
+}
+
+export default useMescroll
\ No newline at end of file
diff --git a/uni_modules/mescroll-uni/hooks/useMescrollComp.js b/uni_modules/mescroll-uni/hooks/useMescrollComp.js
new file mode 100644
index 0000000..3b83847
--- /dev/null
+++ b/uni_modules/mescroll-uni/hooks/useMescrollComp.js
@@ -0,0 +1,56 @@
+import { ref } from 'vue';
+
+// 小程序无法在hook中使用页面级别生命周期,需单独传入: https://ask.dcloud.net.cn/question/161173
+// import { onPageScroll, onReachBottom, onPullDownRefresh} from '@dcloudio/uni-app';
+
+/**
+ * mescroll-body写在子组件时,需通过useMescrollComp补充子组件缺少的生命周期, 相当于vue2的mescroll-comp.js文件
+ * 必须传入onPageScroll, onReachBottom
+ * 当down.native为true时,需传入onPullDownRefresh
+ */
+function useMescrollComp(onPageScroll, onReachBottom, onPullDownRefresh){
+ // 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件
+ onPageScroll(e=>{
+ handlePageScroll(e)
+ })
+
+ onReachBottom(()=>{
+ handleReachBottom()
+ })
+
+ // 当down的native: true时, 还需传递此方法进到子组件
+ onPullDownRefresh && onPullDownRefresh(()=>{
+ handlePullDownRefresh()
+ })
+
+ const mescrollItem = ref(null)
+
+ const handlePageScroll = (e)=>{
+ const mescroll = getMescroll()
+ mescroll && mescroll.onPageScroll(e);
+ }
+
+ const handleReachBottom = ()=>{
+ const mescroll = getMescroll()
+ mescroll && mescroll.onReachBottom();
+ }
+
+ const handlePullDownRefresh = ()=>{
+ const mescroll = getMescroll()
+ mescroll && mescroll.onPullDownRefresh();
+ }
+
+ const getMescroll = ()=>{
+ if(mescrollItem.value && mescrollItem.value.getMescroll){
+ return mescrollItem.value.getMescroll()
+ }
+ return null
+ }
+
+ return {
+ mescrollItem,
+ getMescroll
+ }
+}
+
+export default useMescrollComp
\ No newline at end of file
diff --git a/uni_modules/mescroll-uni/hooks/useMescrollMore.js b/uni_modules/mescroll-uni/hooks/useMescrollMore.js
new file mode 100644
index 0000000..f9a3cd0
--- /dev/null
+++ b/uni_modules/mescroll-uni/hooks/useMescrollMore.js
@@ -0,0 +1,69 @@
+import { ref } from 'vue';
+
+// 小程序无法在hook中使用页面级别生命周期,需单独传入: https://ask.dcloud.net.cn/question/161173
+// import { onPageScroll, onReachBottom, onPullDownRefresh} from '@dcloudio/uni-app';
+
+/** mescroll-more示例写在子组件时,需通过useMescrollMore补充子组件缺少的生命周期, 相当于vue2的mescroll-more.js文件 */
+function useMescrollMore(mescrollItems, onPageScroll, onReachBottom, onPullDownRefresh){
+ // 当前tab下标
+ const tabIndex = ref(0)
+
+ // 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件
+ onPageScroll && onPageScroll(e=>{
+ handlePageScroll(e)
+ })
+
+ onReachBottom && onReachBottom(()=>{
+ handleReachBottom()
+ })
+
+ // 当down的native: true时, 还需传递此方法进到子组件
+ onPullDownRefresh && onPullDownRefresh(()=>{
+ handlePullDownRefresh()
+ })
+
+ const handlePageScroll = (e)=>{
+ let mescroll = getMescroll(tabIndex.value);
+ mescroll && mescroll.onPageScroll(e);
+ }
+ const handleReachBottom = ()=>{
+ let mescroll = getMescroll(tabIndex.value);
+ mescroll && mescroll.onReachBottom();
+ }
+
+ const handlePullDownRefresh = ()=>{
+ let mescroll = getMescroll(tabIndex.value);
+ mescroll && mescroll.onPullDownRefresh();
+ }
+
+ // 根据下标获取对应子组件的mescroll
+ const getMescroll = (i)=>{
+ if (mescrollItems && mescrollItems[i]) {
+ return mescrollItems[i].value.getMescroll()
+ } else{
+ return null
+ }
+ }
+
+ // 切换tab,恢复滚动条位置
+ const scrollToLastY = ()=>{
+ let mescroll = getMescroll(tabIndex.value);
+ if(mescroll){
+ // 恢复上次滚动条的位置
+ let y = mescroll.getScrollTop()
+ mescroll.scrollTo(y, 0)
+ // 再次恢复上次滚动条的位置, 确保元素已渲染
+ setTimeout(()=>{
+ mescroll.scrollTo(y, 0)
+ },20)
+ }
+ }
+
+ return {
+ tabIndex,
+ getMescroll,
+ scrollToLastY
+ }
+}
+
+export default useMescrollMore
\ No newline at end of file
diff --git a/uni_modules/mescroll-uni/package.json b/uni_modules/mescroll-uni/package.json
new file mode 100644
index 0000000..ef37663
--- /dev/null
+++ b/uni_modules/mescroll-uni/package.json
@@ -0,0 +1,76 @@
+{
+ "id": "mescroll-uni",
+ "displayName": "高性能下拉刷新上拉加载组件 支持vue3 setup",
+ "version": "1.3.8",
+ "description": "wxs+renderjs实现, 支持原生页面和局部区域滚动, 支持vue3 script setup的写法",
+ "keywords": [
+ "下拉刷新",
+ "上拉加载",
+ "翻页分页",
+ "wxs",
+ "setup"
+],
+ "repository": "https://github.com/mescroll/mescroll",
+"engines": {
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/mescroll-uni",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "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"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/mescroll-uni/readme.md b/uni_modules/mescroll-uni/readme.md
new file mode 100644
index 0000000..4bce178
--- /dev/null
+++ b/uni_modules/mescroll-uni/readme.md
@@ -0,0 +1,45 @@
+## mescroll --【wxs+renderjs实现】高性能的下拉刷新上拉加载组件
+1. mescroll的uni版本 是专门用在uni-app的下拉刷新和上拉加载的组件
+
+2. mescroll的uni版本 继承了mescroll.js的实用功能: 自动处理分页, 自动控制无数据, 空布局提示, 回到顶部按钮 ..
+
+3. mescroll的uni版本 丰富的案例, 自由灵活的api, 超详细的注释, 可让您快速自定义真正属于自己的下拉上拉组件
+
+
+
+
+## 最新文档(1.3.8版本): https://www.mescroll.com/uni.html
+2023-03-26 by 小瑾同学 (文档可能会有缓存,建议打开时刷新一下)
+
+
+## 1.3.5版本已调整为[uni_modules](https://uniapp.dcloud.io/uni_modules)
+uni_modules版本的mescroll-body 和 mescroll-empty 支持 [easycom规范](https://uniapp.dcloud.io/collocation/pages?id=easycom)
+所以 main.js 无需再为mescroll-body注册全局组件
+所以个别页面要单独使用 mescroll-empty , 也无需手动注册
+#### 1.3.5以前的用户升级为uni_modules版本:
+```
+1. 删除原来的 @/components/mescroll-uni 组件
+2. 删除 main.js 注册的 mescroll 组件
+3. 从插件市场导入最新mescroll组件 (1.3.5+uni_modules版本)
+4. 全局搜索 '@/components/mescroll-uni/' 替换为 '@/uni_modules/mescroll-uni/components/mescroll-uni/'
+5. mescroll-empty遵循easycom规范, 若某些页面单独使用 'mescroll-empty.vue', 可删除手动导入的代码
+```
+
+## 近期已更新优化的内容:
+1. 新增vue3 script setup的示例
+2. 新增`入门极简`示例, 国际化`mescroll-i18n.vue`示例, 轮播吸顶菜单`mescroll-swiper-sticky.vue`示例
+3. 新增 "局部区域滚动" 的案例: mescroll-body-part.vue 和 mescroll-uni-part.vue
+4. 新增 me-video 视频组件, 解决APP端视频下拉悬浮错位的问题, 参考 mescroll-options.vue 示例
+5. 新增 me-tabs 组件,tabs支持水平滑动; 优化mescroll-more和mescroll-swiper的案例, 顶部tab支持水平滑动
+6. 吸顶悬浮提供了原生sticky和监听滚动条实现的示例: sticky.vue 和 sticky-scroll.vue (推荐使用sticky样式实现)
+7. mescroll.scrollTo(y)的y支持css选择器, 包括跨自定义组件的后代选择器, 支持滚动到子组件的view (参考 mescroll-options.vue)
+8. topbar 顶部是否预留状态栏的高度, 默认false; 还可支持设置状态栏背景: 如 '#ffff00', 'url(xxx) 0 0/100% 100%', 'linear-gradient(xx)'
+9. down.bgColor 和 up.bgColor 加载区域的背景,不仅支持色值, 而且还是支持背景图和渐变: 如 'url(xxx) 0 0/100% 100%', 'linear-gradient(xx)'
+10. topbar,bgColor支持一行代码定义background: [https://www.runoob.com/cssref/css3-pr-background.html](https://www.runoob.com/cssref/css3-pr-background.html)
+
+
+查看更多 ...
+
+
+
+#### mescroll不支持nvue,也暂无支持的计划哈,so sorry~
\ No newline at end of file
diff --git a/uni_modules/mp-html/README.md b/uni_modules/mp-html/README.md
new file mode 100644
index 0000000..f825383
--- /dev/null
+++ b/uni_modules/mp-html/README.md
@@ -0,0 +1,191 @@
+## 为减小组件包的大小,默认组件包中不包含编辑、latex 公式等扩展功能,需要使用扩展功能的请参考下方的 插件扩展 栏的说明
+
+## 功能介绍
+- 全端支持(含 `v3、NVUE`)
+- 支持丰富的标签(包括 `table`、`video`、`svg` 等)
+- 支持丰富的事件效果(自动预览图片、链接处理等)
+- 支持设置占位图(加载中、出错时、预览时)
+- 支持锚点跳转、长按复制等丰富功能
+- 支持大部分 *html* 实体
+- 丰富的插件(关键词搜索、内容编辑、`latex` 公式等)
+- 效率高、容错性强且轻量化
+
+查看 [功能介绍](https://jin-yufeng.gitee.io/mp-html/#/overview/feature) 了解更多
+
+## 使用方法
+- `uni_modules` 方式
+ 1. 点击右上角的 `使用 HBuilder X 导入插件` 按钮直接导入项目或点击 `下载插件 ZIP` 按钮下载插件包并解压到项目的 `uni_modules/mp-html` 目录下
+ 2. 在需要使用页面的 `(n)vue` 文件中添加
+ ```html
+
+
+ ```
+ ```javascript
+ export default {
+ data() {
+ return {
+ html: 'Hello World!
'
+ }
+ }
+ }
+ ```
+ 3. 需要更新版本时在 `HBuilder X` 中右键 `uni_modules/mp-html` 目录选择 `从插件市场更新` 即可
+
+- 源码方式
+ 1. 从 [github](https://github.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 或 [gitee](https://gitee.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 下载源码
+ 插件市场的 **非 uni_modules 版本** 无法更新,不建议从插件市场获取
+ 2. 在需要使用页面的 `(n)vue` 文件中添加
+ ```html
+
+ ```
+ ```javascript
+ import mpHtml from '@/components/mp-html/mp-html'
+ export default {
+ // HBuilderX 2.5.5+ 可以通过 easycom 自动引入
+ components: {
+ mpHtml
+ },
+ data() {
+ return {
+ html: 'Hello World!
'
+ }
+ }
+ }
+ ```
+
+- npm 方式
+ 1. 在项目根目录下执行
+ ```bash
+ npm install mp-html
+ ```
+ 2. 在需要使用页面的 `(n)vue` 文件中添加
+ ```html
+
+ ```
+ ```javascript
+ import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html'
+ export default {
+ // 不可省略
+ components: {
+ mpHtml
+ },
+ data() {
+ return {
+ html: 'Hello World!
'
+ }
+ }
+ }
+ ```
+ 3. 需要更新版本时执行以下命令即可
+ ```bash
+ npm update mp-html
+ ```
+
+ 使用 *cli* 方式运行的项目,通过 *npm* 方式引入时,需要在 *vue.config.js* 中配置 *transpileDependencies*,详情可见 [#330](https://github.com/jin-yufeng/mp-html/issues/330#issuecomment-913617687)
+ 如果在 **nvue** 中使用还要将 `dist/uni-app/static` 目录下的内容拷贝到项目的 `static` 目录下,否则无法运行
+
+查看 [快速开始](https://jin-yufeng.gitee.io/mp-html/#/overview/quickstart) 了解更多
+
+## 组件属性
+
+| 属性 | 类型 | 默认值 | 说明 |
+|:---:|:---:|:---:|---|
+| container-style | String | | 容器的样式([2.1.0+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v210)) |
+| content | String | | 用于渲染的 html 字符串 |
+| copy-link | Boolean | true | 是否允许外部链接被点击时自动复制 |
+| domain | String | | 主域名(用于链接拼接) |
+| error-img | String | | 图片出错时的占位图链接 |
+| lazy-load | Boolean | false | 是否开启图片懒加载 |
+| loading-img | String | | 图片加载过程中的占位图链接 |
+| pause-video | Boolean | true | 是否在播放一个视频时自动暂停其他视频 |
+| preview-img | Boolean | true | 是否允许图片被点击时自动预览 |
+| scroll-table | Boolean | false | 是否给每个表格添加一个滚动层使其能单独横向滚动 |
+| selectable | Boolean | false | 是否开启文本长按复制 |
+| set-title | Boolean | true | 是否将 title 标签的内容设置到页面标题 |
+| show-img-menu | Boolean | true | 是否允许图片被长按时显示菜单 |
+| tag-style | Object | | 设置标签的默认样式 |
+| use-anchor | Boolean | false | 是否使用锚点链接 |
+
+查看 [属性](https://jin-yufeng.gitee.io/mp-html/#/basic/prop) 了解更多
+
+## 组件事件
+
+| 名称 | 触发时机 |
+|:---:|---|
+| load | dom 树加载完毕时 |
+| ready | 图片加载完毕时 |
+| error | 发生渲染错误时 |
+| imgtap | 图片被点击时 |
+| linktap | 链接被点击时 |
+| play | 音视频播放时 |
+
+查看 [事件](https://jin-yufeng.gitee.io/mp-html/#/basic/event) 了解更多
+
+## api
+组件实例上提供了一些 `api` 方法可供调用
+
+| 名称 | 作用 |
+|:---:|---|
+| in | 将锚点跳转的范围限定在一个 scroll-view 内 |
+| navigateTo | 锚点跳转 |
+| getText | 获取文本内容 |
+| getRect | 获取富文本内容的位置和大小 |
+| setContent | 设置富文本内容 |
+| imgList | 获取所有图片的数组 |
+| pauseMedia | 暂停播放音视频([2.2.2+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v222)) |
+| setPlaybackRate | 设置音视频播放速率([2.4.0+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v240)) |
+
+查看 [api](https://jin-yufeng.gitee.io/mp-html/#/advanced/api) 了解更多
+
+## 插件扩展
+除基本功能外,本组件还提供了丰富的扩展,可按照需要选用
+
+| 名称 | 作用 |
+|:---:|---|
+| audio | 音乐播放器 |
+| editable | 富文本 **编辑**([示例项目](https://mp-html.oss-cn-hangzhou.aliyuncs.com/editable.zip)) |
+| emoji | 解析 emoji |
+| highlight | 代码块高亮显示 |
+| markdown | 渲染 markdown |
+| search | 关键词搜索 |
+| style | 匹配 style 标签中的样式 |
+| txv-video | 使用腾讯视频 |
+| img-cache | 图片缓存 by [@PentaTea](https://github.com/PentaTea) |
+| latex | 渲染 latex 公式 by [@Zeng-J](https://github.com/Zeng-J) |
+
+从插件市场导入的包中 **不含有** 扩展插件,使用插件需通过微信小程序 `富文本插件` 获取或参考以下方法进行打包:
+1. 获取完整组件包
+ ```bash
+ npm install mp-html
+ ```
+2. 编辑 `tools/config.js` 中的 `plugins` 项,选择需要的插件
+3. 生成新的组件包
+ 在 `node_modules/mp-html` 目录下执行
+ ```bash
+ npm install
+ npm run build:uni-app
+ ```
+4. 拷贝 `dist/uni-app` 中的内容到项目根目录
+
+查看 [插件](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin) 了解更多
+
+## 关于 nvue
+`nvue` 使用原生渲染,不支持部分 `css` 样式,为实现和 `html` 相同的效果,组件内部通过 `web-view` 进行渲染,性能上差于原生,根据 `weex` 官方建议,`web` 标签仅应用在非常规的降级场景。因此,如果通过原生的方式(如 `richtext`)能够满足需要,则不建议使用本组件,如果有较多的富文本内容,则可以直接使用 `vue` 页面
+由于渲染方式与其他端不同,有以下限制:
+1. 不支持 `lazy-load` 属性
+2. 视频不支持全屏播放
+3. 如果在 `flex-direction: row` 的容器中使用,需要给组件设置宽度或设置 `flex: 1` 占满剩余宽度
+
+纯 `nvue` 模式下,[此问题](https://ask.dcloud.net.cn/question/119678) 修复前,不支持通过 `uni_modules` 引入,需要本地引入(将 [dist/uni-app](https://github.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 中的内容拷贝到项目根目录下)
+
+## 立即体验
+
+
+## 问题反馈
+遇到问题时,请先查阅 [常见问题](https://jin-yufeng.gitee.io/mp-html/#/question/faq) 和 [issue](https://github.com/jin-yufeng/mp-html/issues) 中是否已有相同的问题
+可通过 [issue](https://github.com/jin-yufeng/mp-html/issues/new/choose) 、插件问答或发送邮件到 [mp_html@126.com](mailto:mp_html@126.com) 提问,不建议在评论区提问(不方便回复)
+提问请严格按照 [issue 模板](https://github.com/jin-yufeng/mp-html/issues/new/choose) ,描述清楚使用环境、`html` 内容或可复现的 `demo` 项目以及复现方式,对于 **描述不清**、**无法复现** 或重复的问题将不予回复
+
+欢迎加入 `QQ` 交流群:`699734691`
+
+查看 [问题反馈](https://jin-yufeng.gitee.io/mp-html/#/question/feedback) 了解更多
diff --git a/uni_modules/mp-html/changelog.md b/uni_modules/mp-html/changelog.md
new file mode 100644
index 0000000..51d049e
--- /dev/null
+++ b/uni_modules/mp-html/changelog.md
@@ -0,0 +1,121 @@
+## v2.4.1(2022-12-25)
+1. `F` 修复了没有图片时 `ready` 事件可能不触发的问题
+2. `F` 修复了加载过程中可能出现 `Root label not found` 错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/470)
+3. `F` 修复了 `audio` 插件退出页面可能会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/457)
+4. `F` 修复了 `vue3` 运行到 `app` 在 `HBuilder X 3.6.10` 以上报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/480)
+5. `F` 修复了 `nvue` 端链接中包含 `%22` 时可能无法显示的问题
+6. `F` 修复了 `vue3` 使用 `highlight` 插件可能报错的问题
+## v2.4.0(2022-08-27)
+1. `A` 增加了 [setPlaybackRate](https://jin-yufeng.gitee.io/mp-html/#/advanced/api#setPlaybackRate) 的 `api`,可以设置音视频的播放速率 [详细](https://github.com/jin-yufeng/mp-html/issues/452)
+2. `A` 示例小程序代码开源 [详细](https://github.com/jin-yufeng/mp-html-demo)
+3. `U` 优化 `ready` 事件触发时机,未设置懒加载的情况下基本可以准确触发 [详细](https://github.com/jin-yufeng/mp-html/issues/195)
+4. `U` `highlight` 插件在编辑状态下不进行高亮处理,便于编辑
+5. `F` 修复了 `flex` 布局下图片大小可能不正确的问题
+6. `F` 修复了 `selectable` 属性没有设置 `force` 也可能出现渲染异常的问题
+7. `F` 修复了表格中的图片大小可能不正确的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/448)
+8. `F` 修复了含有合并单元格的表格可能无法设置竖直对齐的问题
+9. `F` 修复了 `editable` 插件在 `scroll-view` 中使用时工具条位置可能不正确的问题
+10. `F` 修复了 `vue3` 使用 [search](advanced/plugin#search) 插件可能导致错误换行的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/449)
+## v2.3.2(2022-08-13)
+1. `A` 增加 [latex](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#latex) 插件,可以渲染数学公式 [详细](https://github.com/jin-yufeng/mp-html/pull/447) by [@Zeng-J](https://github.com/Zeng-J)
+2. `U` 优化根节点下有很多标签的长内容渲染速度
+3. `U` `highlight` 插件适配 `lang-xxx` 格式
+4. `F` 修复了 `table` 标签设置 `border` 属性后可能无法修改边框样式的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/439) by [@zouxingjie](https://github.com/zouxingjie)
+5. `F` 修复了 `editable` 插件输入连续空格无效的问题
+6. `F` 修复了 `vue3` 图片设置 `inline` 会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/438)
+7. `F` 修复了 `vue3` 使用 `table` 可能报错的问题
+## v2.3.1(2022-05-20)
+1. `U` `app` 端支持使用本地图片
+2. `U` 优化了微信小程序 `selectable` 属性在 `ios` 端的处理 [详细](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#selectable)
+3. `F` 修复了 `editable` 插件不在顶部时 `tooltip` 位置可能错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/430)
+4. `F` 修复了 `vue3` 运行到微信小程序可能报错丢失内容的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/414)
+5. `F` 修复了 `vue3` 部分标签可能被错误换行的问题
+6. `F` 修复了 `editable` 插件 `app` 端插入视频无法预览的问题
+## v2.3.0(2022-04-01)
+1. `A` 增加了 `play` 事件,音视频播放时触发,可用于与页面其他音视频进行互斥播放 [详细](basic/event#play)
+2. `U` `show-img-menu` 属性支持控制预览时是否长按弹出菜单
+3. `U` 优化 `wxs` 处理,提高渲染性能 [详细](https://developers.weixin.qq.com/community/develop/article/doc/0006cc2b204740f601bd43fa25a413)
+4. `U` `video` 标签支持 `object-fit` 属性
+5. `U` 增加支持一些常用实体编码 [详细](https://github.com/jin-yufeng/mp-html/issues/418)
+6. `F` 修复了图片仅设置高度可能不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/410)
+7. `F` 修复了 `video` 标签高度设置为 `auto` 不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/411)
+8. `F` 修复了使用 `grid` 布局时可能样式错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/413)
+9. `F` 修复了含有合并单元格的表格部分情况下显示异常的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/417)
+10. `F` 修复了 `editable` 插件连续插入内容时顺序不正确的问题
+11. `F` 修复了 `uni-app` 包 `vue3` 使用 `audio` 插件报错的问题
+12. `F` 修复了 `uni-app` 包 `highlight` 插件使用自定义的 `prism.min.js` 报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/416)
+## v2.2.2(2022-02-26)
+1. `A` 增加了 [pauseMedia](https://jin-yufeng.gitee.io/mp-html/#/advanced/api#pauseMedia) 的 `api`,可用于暂停播放音视频 [详细](https://github.com/jin-yufeng/mp-html/issues/317)
+2. `U` 优化了长内容的加载速度
+3. `U` 适配 `vue3` [#389](https://github.com/jin-yufeng/mp-html/issues/389)、[#398](https://github.com/jin-yufeng/mp-html/pull/398) by [@zhouhuafei](https://github.com/zhouhuafei)、[#400](https://github.com/jin-yufeng/mp-html/issues/400)
+4. `F` 修复了小程序端图片高度设置为百分比时可能不显示的问题
+5. `F` 修复了 `highlight` 插件部分情况下可能显示不完整的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/403)
+## v2.2.1(2021-12-24)
+1. `A` `editable` 插件增加上下移动标签功能
+2. `U` `editable` 插件支持在文本中间光标处插入内容
+3. `F` 修复了 `nvue` 端设置 `margin` 后可能导致高度不正确的问题
+4. `F` 修复了 `highlight` 插件使用压缩版的 `prism.css` 可能导致背景失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/367)
+5. `F` 修复了编辑状态下使用 `emoji` 插件内容为空时可能报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/371)
+6. `F` 修复了使用 `editable` 插件后将 `selectable` 属性设置为 `force` 不生效的问题
+## v2.2.0(2021-10-12)
+1. `A` 增加 `customElements` 配置项,便于添加自定义功能性标签 [详细](https://github.com/jin-yufeng/mp-html/issues/350)
+2. `A` `editable` 插件增加切换音视频自动播放状态的功能 [详细](https://github.com/jin-yufeng/mp-html/pull/341) by [@leeseett](https://github.com/leeseett)
+3. `A` `editable` 插件删除媒体标签时触发 `remove` 事件,便于删除已上传的文件
+4. `U` `editable` 插件 `insertImg` 方法支持同时插入多张图片 [详细](https://github.com/jin-yufeng/mp-html/issues/342)
+5. `U` `editable` 插入图片和音视频时支持拼接 `domian` 主域名
+6. `F` 修复了内部链接参数中包含 `://` 时被认为是外部链接的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/356)
+7. `F` 修复了部分 `svg` 标签名或属性名大小写不正确时不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/351)
+8. `F` 修复了 `nvue` 页面运行到非 `app` 平台时可能样式错误的问题
+## v2.1.5(2021-08-13)
+1. `A` 增加支持标签的 `dir` 属性
+2. `F` 修复了 `ruby` 标签文字与拼音没有居中对齐的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/325)
+3. `F` 修复了音视频标签内有 `a` 标签时可能无法播放的问题
+4. `F` 修复了 `externStyle` 中的 `class` 名包含下划线或数字时可能失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/326)
+5. `F` 修复了 `h5` 端引入 `externStyle` 可能不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/326)
+## v2.1.4(2021-07-14)
+1. `F` 修复了 `rt` 标签无法设置样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/318)
+2. `F` 修复了表格中有单元格同时合并行和列时可能显示不正确的问题
+3. `F` 修复了 `app` 端无法关闭图片长按菜单的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/322)
+4. `F` 修复了 `editable` 插件只能添加图片链接不能修改的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/312) by [@leeseett](https://github.com/leeseett)
+## v2.1.3(2021-06-12)
+1. `A` `editable` 插件增加 `insertTable` 方法
+2. `U` `editable` 插件支持编辑表格中的空白单元格 [详细](https://github.com/jin-yufeng/mp-html/issues/310)
+3. `F` 修复了 `externStyle` 中使用伪类可能失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/298)
+4. `F` 修复了多个组件同时使用时 `tag-style` 属性时可能互相影响的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/305) by [@woodguoyu](https://github.com/woodguoyu)
+5. `F` 修复了包含 `linearGradient` 的 `svg` 可能无法显示的问题
+6. `F` 修复了编译到头条小程序时可能报错的问题
+7. `F` 修复了 `nvue` 端不触发 `click` 事件的问题
+8. `F` 修复了 `editable` 插件尾部插入时无法撤销的问题
+9. `F` 修复了 `editable` 插件的 `insertHtml` 方法只能在末尾插入的问题
+10. `F` 修复了 `editable` 插件插入音频不显示的问题
+## v2.1.2(2021-04-24)
+1. `A` 增加了 [img-cache](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#img-cache) 插件,可以在 `app` 端缓存图片 [详细](https://github.com/jin-yufeng/mp-html/issues/292) by [@PentaTea](https://github.com/PentaTea)
+2. `U` 支持通过 `container-style` 属性设置 `white-space` 来保留连续空格和换行符 [详细](https://jin-yufeng.gitee.io/mp-html/#/question/faq#space)
+3. `U` 代码风格符合 [standard](https://standardjs.com) 标准
+4. `U` `editable` 插件编辑状态下支持预览视频 [详细](https://github.com/jin-yufeng/mp-html/issues/286)
+5. `F` 修复了 `svg` 标签内嵌 `svg` 时无法显示的问题
+6. `F` 修复了编译到支付宝和头条小程序时部分区域不可复制的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/291)
+## v2.1.1(2021-04-09)
+1. 修复了对 `p` 标签设置 `tag-style` 可能不生效的问题
+2. 修复了 `svg` 标签中的文本无法显示的问题
+3. 修复了使用 `editable` 插件编辑表格时可能报错的问题
+4. 修复了使用 `highlight` 插件运行到头条小程序时可能没有样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/280)
+5. 修复了使用 `editable` 插件 `editable` 属性为 `false` 时会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/284)
+6. 修复了 `style` 插件连续子选择器失效的问题
+7. 修复了 `editable` 插件无法修改图片和字体大小的问题
+## v2.1.0.2(2021-03-21)
+修复了 `nvue` 端使用可能报错的问题
+## v2.1.0(2021-03-20)
+1. `A` 增加了 [container-style](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#container-style) 属性 [详细](https://gitee.com/jin-yufeng/mp-html/pulls/1)
+2. `A` 增加支持 `strike` 标签
+3. `A` `editable` 插件增加 `placeholder` 属性 [详细](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#editable)
+4. `A` `editable` 插件增加 `insertHtml` 方法 [详细](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#editable)
+5. `U` 外部样式支持标签名选择器 [详细](https://jin-yufeng.gitee.io/mp-html/#/overview/quickstart#setting)
+6. `F` 修复了 `nvue` 端部分情况下可能不显示的问题
+## v2.0.5(2021-03-12)
+1. `U` [linktap](https://jin-yufeng.gitee.io/mp-html/#/basic/event#linktap) 事件增加返回内部文本内容 `innerText` [详细](https://github.com/jin-yufeng/mp-html/issues/271)
+2. `U` [selectable](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#selectable) 属性设置为 `force` 时能够在微信 `iOS` 端生效(文本块会变成 `inline-block`) [详细](https://github.com/jin-yufeng/mp-html/issues/267)
+3. `F` 修复了部分情况下竖向无法滚动的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/182)
+4. `F` 修复了多次修改富文本数据时部分内容可能不显示的问题
+5. `F` 修复了 [腾讯视频](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#txv-video) 插件可能无法播放的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/265)
+6. `F` 修复了 [highlight](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#highlight) 插件没有设置高亮语言时没有应用默认样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/276) by [@fuzui](https://github.com/fuzui)
diff --git a/uni_modules/mp-html/components/mp-html/mp-html.vue b/uni_modules/mp-html/components/mp-html/mp-html.vue
new file mode 100644
index 0000000..a9b5dec
--- /dev/null
+++ b/uni_modules/mp-html/components/mp-html/mp-html.vue
@@ -0,0 +1,498 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/mp-html/components/mp-html/node/node.vue b/uni_modules/mp-html/components/mp-html/node/node.vue
new file mode 100644
index 0000000..d2f8fb8
--- /dev/null
+++ b/uni_modules/mp-html/components/mp-html/node/node.vue
@@ -0,0 +1,577 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{n.text}}
+
+
+ {{n.text}}
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/uni_modules/mp-html/components/mp-html/parser.js b/uni_modules/mp-html/components/mp-html/parser.js
new file mode 100644
index 0000000..47d8212
--- /dev/null
+++ b/uni_modules/mp-html/components/mp-html/parser.js
@@ -0,0 +1,1334 @@
+/**
+ * @fileoverview html 解析器
+ */
+
+// 配置
+const config = {
+ // 信任的标签(保持标签名不变)
+ trustTags: makeMap('a,abbr,ad,audio,b,blockquote,br,code,col,colgroup,dd,del,dl,dt,div,em,fieldset,h1,h2,h3,h4,h5,h6,hr,i,img,ins,label,legend,li,ol,p,q,ruby,rt,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video'),
+
+ // 块级标签(转为 div,其他的非信任标签转为 span)
+ blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,pre,section'),
+
+ // #ifdef (MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE3
+ // 行内标签
+ inlineTags: makeMap('abbr,b,big,code,del,em,i,ins,label,q,small,span,strong,sub,sup'),
+ // #endif
+
+ // 要移除的标签
+ ignoreTags: makeMap('area,base,canvas,embed,frame,head,iframe,input,link,map,meta,param,rp,script,source,style,textarea,title,track,wbr'),
+
+ // 自闭合的标签
+ voidTags: makeMap('area,base,br,col,circle,ellipse,embed,frame,hr,img,input,line,link,meta,param,path,polygon,rect,source,track,use,wbr'),
+
+ // html 实体
+ entities: {
+ lt: '<',
+ gt: '>',
+ quot: '"',
+ apos: "'",
+ ensp: '\u2002',
+ emsp: '\u2003',
+ nbsp: '\xA0',
+ semi: ';',
+ ndash: '–',
+ mdash: '—',
+ middot: '·',
+ lsquo: '‘',
+ rsquo: '’',
+ ldquo: '“',
+ rdquo: '”',
+ bull: '•',
+ hellip: '…',
+ larr: '←',
+ uarr: '↑',
+ rarr: '→',
+ darr: '↓'
+ },
+
+ // 默认的标签样式
+ tagStyle: {
+ // #ifndef APP-PLUS-NVUE
+ address: 'font-style:italic',
+ big: 'display:inline;font-size:1.2em',
+ caption: 'display:table-caption;text-align:center',
+ center: 'text-align:center',
+ cite: 'font-style:italic',
+ dd: 'margin-left:40px',
+ mark: 'background-color:yellow',
+ pre: 'font-family:monospace;white-space:pre',
+ s: 'text-decoration:line-through',
+ small: 'display:inline;font-size:0.8em',
+ strike: 'text-decoration:line-through',
+ u: 'text-decoration:underline',
+ p: 'margin:0;padding:0;'
+ // #endif
+ },
+
+ // svg 大小写对照表
+ svgDict: {
+ animatetransform: 'animateTransform',
+ lineargradient: 'linearGradient',
+ viewbox: 'viewBox',
+ attributename: 'attributeName',
+ repeatcount: 'repeatCount',
+ repeatdur: 'repeatDur'
+ }
+}
+const tagSelector={}
+const {
+ windowWidth,
+ // #ifdef MP-WEIXIN
+ system
+ // #endif
+} = uni.getSystemInfoSync()
+const blankChar = makeMap(' ,\r,\n,\t,\f')
+let idIndex = 0
+
+// #ifdef H5 || APP-PLUS
+config.ignoreTags.iframe = undefined
+config.trustTags.iframe = true
+config.ignoreTags.embed = undefined
+config.trustTags.embed = true
+// #endif
+// #ifdef APP-PLUS-NVUE
+config.ignoreTags.source = undefined
+config.ignoreTags.style = undefined
+// #endif
+
+/**
+ * @description 创建 map
+ * @param {String} str 逗号分隔
+ */
+function makeMap (str) {
+ const map = Object.create(null)
+ const list = str.split(',')
+ for (let i = list.length; i--;) {
+ map[list[i]] = true
+ }
+ return map
+}
+
+/**
+ * @description 解码 html 实体
+ * @param {String} str 要解码的字符串
+ * @param {Boolean} amp 要不要解码 &
+ * @returns {String} 解码后的字符串
+ */
+function decodeEntity (str, amp) {
+ let i = str.indexOf('&')
+ while (i !== -1) {
+ const j = str.indexOf(';', i + 3)
+ let code
+ if (j === -1) break
+ if (str[i + 1] === '#') {
+ // { 形式的实体
+ code = parseInt((str[i + 2] === 'x' ? '0' : '') + str.substring(i + 2, j))
+ if (!isNaN(code)) {
+ str = str.substr(0, i) + String.fromCharCode(code) + str.substr(j + 1)
+ }
+ } else {
+ // 形式的实体
+ code = str.substring(i + 1, j)
+ if (config.entities[code] || (code === 'amp' && amp)) {
+ str = str.substr(0, i) + (config.entities[code] || '&') + str.substr(j + 1)
+ }
+ }
+ i = str.indexOf('&', i + 1)
+ }
+ return str
+}
+
+/**
+ * @description 合并多个块级标签,加快长内容渲染
+ * @param {Array} nodes 要合并的标签数组
+ */
+function mergeNodes (nodes) {
+ let i = nodes.length - 1
+ for (let j = i; j >= -1; j--) {
+ if (j === -1 || nodes[j].c || !nodes[j].name || (nodes[j].name !== 'div' && nodes[j].name !== 'p' && nodes[j].name[0] !== 'h') || (nodes[j].attrs.style || '').includes('inline')) {
+ if (i - j >= 5) {
+ nodes.splice(j + 1, i - j, {
+ name: 'div',
+ attrs: {},
+ children: nodes.slice(j + 1, i + 1)
+ })
+ }
+ i = j - 1
+ }
+ }
+}
+
+/**
+ * @description html 解析器
+ * @param {Object} vm 组件实例
+ */
+function Parser (vm) {
+ this.options = vm || {}
+ this.tagStyle = Object.assign({}, config.tagStyle, this.options.tagStyle)
+ this.imgList = vm.imgList || []
+ this.imgList._unloadimgs = 0
+ this.plugins = vm.plugins || []
+ this.attrs = Object.create(null)
+ this.stack = []
+ this.nodes = []
+ this.pre = (this.options.containerStyle || '').includes('white-space') && this.options.containerStyle.includes('pre') ? 2 : 0
+}
+
+/**
+ * @description 执行解析
+ * @param {String} content 要解析的文本
+ */
+Parser.prototype.parse = function (content) {
+ // 插件处理
+ for (let i = this.plugins.length; i--;) {
+ if (this.plugins[i].onUpdate) {
+ content = this.plugins[i].onUpdate(content, config) || content
+ }
+ }
+
+ new Lexer(this).parse(content)
+ // 出栈未闭合的标签
+ while (this.stack.length) {
+ this.popNode()
+ }
+ if (this.nodes.length > 50) {
+ mergeNodes(this.nodes)
+ }
+ return this.nodes
+}
+
+/**
+ * @description 将标签暴露出来(不被 rich-text 包含)
+ */
+Parser.prototype.expose = function () {
+ // #ifndef APP-PLUS-NVUE
+ for (let i = this.stack.length; i--;) {
+ const item = this.stack[i]
+ if (item.c || item.name === 'a' || item.name === 'video' || item.name === 'audio') return
+ item.c = 1
+ }
+ // #endif
+}
+
+/**
+ * @description 处理插件
+ * @param {Object} node 要处理的标签
+ * @returns {Boolean} 是否要移除此标签
+ */
+Parser.prototype.hook = function (node) {
+ for (let i = this.plugins.length; i--;) {
+ if (this.plugins[i].onParse && this.plugins[i].onParse(node, this) === false) {
+ return false
+ }
+ }
+ return true
+}
+
+/**
+ * @description 将链接拼接上主域名
+ * @param {String} url 需要拼接的链接
+ * @returns {String} 拼接后的链接
+ */
+Parser.prototype.getUrl = function (url) {
+ const domain = this.options.domain
+ if (url[0] === '/') {
+ if (url[1] === '/') {
+ // // 开头的补充协议名
+ url = (domain ? domain.split('://')[0] : 'http') + ':' + url
+ } else if (domain) {
+ // 否则补充整个域名
+ url = domain + url
+ } /* #ifdef APP-PLUS */ else {
+ url = plus.io.convertLocalFileSystemURL(url)
+ } /* #endif */
+ } else if (!url.includes('data:') && !url.includes('://')) {
+ if (domain) {
+ url = domain + '/' + url
+ } /* #ifdef APP-PLUS */ else {
+ url = plus.io.convertLocalFileSystemURL(url)
+ } /* #endif */
+ }
+ return url
+}
+
+/**
+ * @description 解析样式表
+ * @param {Object} node 标签
+ * @returns {Object}
+ */
+Parser.prototype.parseStyle = function (node) {
+ const attrs = node.attrs
+ const list = (this.tagStyle[node.name] || '').split(';').concat((attrs.style || '').split(';'))
+ const styleObj = {}
+ let tmp = ''
+
+ if (attrs.id && !this.xml) {
+ // 暴露锚点
+ if (this.options.useAnchor) {
+ this.expose()
+ } else if (node.name !== 'img' && node.name !== 'a' && node.name !== 'video' && node.name !== 'audio') {
+ attrs.id = undefined
+ }
+ }
+
+ // 转换 width 和 height 属性
+ if (attrs.width) {
+ styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px')
+ attrs.width = undefined
+ }
+ if (attrs.height) {
+ styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px')
+ attrs.height = undefined
+ }
+
+ for (let i = 0, len = list.length; i < len; i++) {
+ const info = list[i].split(':')
+ if (info.length < 2) continue
+ const key = info.shift().trim().toLowerCase()
+ let value = info.join(':').trim()
+ if ((value[0] === '-' && value.lastIndexOf('-') > 0) || value.includes('safe')) {
+ // 兼容性的 css 不压缩
+ tmp += `;${key}:${value}`
+ } else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import')) {
+ // 重复的样式进行覆盖
+ if (value.includes('url')) {
+ // 填充链接
+ let j = value.indexOf('(') + 1
+ if (j) {
+ while (value[j] === '"' || value[j] === "'" || blankChar[value[j]]) {
+ j++
+ }
+ value = value.substr(0, j) + this.getUrl(value.substr(j))
+ }
+ } else if (value.includes('rpx')) {
+ // 转换 rpx(rich-text 内部不支持 rpx)
+ value = value.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * windowWidth / 750 + 'px')
+ }
+ styleObj[key] = value
+ }
+ }
+
+ node.attrs.style = tmp
+ return styleObj
+}
+
+/**
+ * @description 解析到标签名
+ * @param {String} name 标签名
+ * @private
+ */
+Parser.prototype.onTagName = function (name) {
+ this.tagName = this.xml ? name : name.toLowerCase()
+ if (this.tagName === 'svg') {
+ this.xml = (this.xml || 0) + 1 // svg 标签内大小写敏感
+ }
+}
+
+/**
+ * @description 解析到属性名
+ * @param {String} name 属性名
+ * @private
+ */
+Parser.prototype.onAttrName = function (name) {
+ name = this.xml ? name : name.toLowerCase()
+ if (name.substr(0, 5) === 'data-') {
+ if (name === 'data-src' && !this.attrs.src) {
+ // data-src 自动转为 src
+ this.attrName = 'src'
+ } else if (this.tagName === 'img' || this.tagName === 'a') {
+ // a 和 img 标签保留 data- 的属性,可以在 imgtap 和 linktap 事件中使用
+ this.attrName = name
+ } else {
+ // 剩余的移除以减小大小
+ this.attrName = undefined
+ }
+ } else {
+ this.attrName = name
+ this.attrs[name] = 'T' // boolean 型属性缺省设置
+ }
+}
+
+/**
+ * @description 解析到属性值
+ * @param {String} val 属性值
+ * @private
+ */
+Parser.prototype.onAttrVal = function (val) {
+ const name = this.attrName || ''
+ if (name === 'style' || name === 'href') {
+ // 部分属性进行实体解码
+ this.attrs[name] = decodeEntity(val, true)
+ } else if (name.includes('src')) {
+ // 拼接主域名
+ this.attrs[name] = this.getUrl(decodeEntity(val, true))
+ } else if (name) {
+ this.attrs[name] = val
+ }
+}
+
+/**
+ * @description 解析到标签开始
+ * @param {Boolean} selfClose 是否有自闭合标识 />
+ * @private
+ */
+Parser.prototype.onOpenTag = function (selfClose) {
+ // 拼装 node
+ const node = Object.create(null)
+ node.name = this.tagName
+ node.attrs = this.attrs
+ // 避免因为自动 diff 使得 type 被设置为 null 导致部分内容不显示
+ if (this.options.nodes.length) {
+ node.type = 'node'
+ }
+ this.attrs = Object.create(null)
+
+ const attrs = node.attrs
+ const parent = this.stack[this.stack.length - 1]
+ const siblings = parent ? parent.children : this.nodes
+ const close = this.xml ? selfClose : config.voidTags[node.name]
+
+ // 替换标签名选择器
+ if (tagSelector[node.name]) {
+ attrs.class = tagSelector[node.name] + (attrs.class ? ' ' + attrs.class : '')
+ }
+
+ // 转换 embed 标签
+ if (node.name === 'embed') {
+ // #ifndef H5 || APP-PLUS
+ const src = attrs.src || ''
+ // 按照后缀名和 type 将 embed 转为 video 或 audio
+ if (src.includes('.mp4') || src.includes('.3gp') || src.includes('.m3u8') || (attrs.type || '').includes('video')) {
+ node.name = 'video'
+ } else if (src.includes('.mp3') || src.includes('.wav') || src.includes('.aac') || src.includes('.m4a') || (attrs.type || '').includes('audio')) {
+ node.name = 'audio'
+ }
+ if (attrs.autostart) {
+ attrs.autoplay = 'T'
+ }
+ attrs.controls = 'T'
+ // #endif
+ // #ifdef H5 || APP-PLUS
+ this.expose()
+ // #endif
+ }
+
+ // #ifndef APP-PLUS-NVUE
+ // 处理音视频
+ if (node.name === 'video' || node.name === 'audio') {
+ // 设置 id 以便获取 context
+ if (node.name === 'video' && !attrs.id) {
+ attrs.id = 'v' + idIndex++
+ }
+ // 没有设置 controls 也没有设置 autoplay 的自动设置 controls
+ if (!attrs.controls && !attrs.autoplay) {
+ attrs.controls = 'T'
+ }
+ // 用数组存储所有可用的 source
+ node.src = []
+ if (attrs.src) {
+ node.src.push(attrs.src)
+ attrs.src = undefined
+ }
+ this.expose()
+ }
+ // #endif
+
+ // 处理自闭合标签
+ if (close) {
+ if (!this.hook(node) || config.ignoreTags[node.name]) {
+ // 通过 base 标签设置主域名
+ if (node.name === 'base' && !this.options.domain) {
+ this.options.domain = attrs.href
+ } /* #ifndef APP-PLUS-NVUE */ else if (node.name === 'source' && parent && (parent.name === 'video' || parent.name === 'audio') && attrs.src) {
+ // 设置 source 标签(仅父节点为 video 或 audio 时有效)
+ parent.src.push(attrs.src)
+ } /* #endif */
+ return
+ }
+
+ // 解析 style
+ const styleObj = this.parseStyle(node)
+
+ // 处理图片
+ if (node.name === 'img') {
+ if (attrs.src) {
+ // 标记 webp
+ if (attrs.src.includes('webp')) {
+ node.webp = 'T'
+ }
+ // data url 图片如果没有设置 original-src 默认为不可预览的小图片
+ if (attrs.src.includes('data:') && !attrs['original-src']) {
+ attrs.ignore = 'T'
+ }
+ if (!attrs.ignore || node.webp || attrs.src.includes('cloud://')) {
+ for (let i = this.stack.length; i--;) {
+ const item = this.stack[i]
+ if (item.name === 'a') {
+ node.a = item.attrs
+ }
+ if (item.name === 'table' && !node.webp && !attrs.src.includes('cloud://')) {
+ if (!styleObj.display || styleObj.display.includes('inline')) {
+ node.t = 'inline-block'
+ } else {
+ node.t = styleObj.display
+ }
+ styleObj.display = undefined
+ }
+ // #ifndef H5 || APP-PLUS
+ const style = item.attrs.style || ''
+ if (style.includes('flex:') && !style.includes('flex:0') && !style.includes('flex: 0') && (!styleObj.width || parseInt(styleObj.width) > 100)) {
+ styleObj.width = '100% !important'
+ styleObj.height = ''
+ for (let j = i + 1; j < this.stack.length; j++) {
+ this.stack[j].attrs.style = (this.stack[j].attrs.style || '').replace('inline-', '')
+ }
+ } else if (style.includes('flex') && styleObj.width === '100%') {
+ for (let j = i + 1; j < this.stack.length; j++) {
+ const style = this.stack[j].attrs.style || ''
+ if (!style.includes(';width') && !style.includes(' width') && style.indexOf('width') !== 0) {
+ styleObj.width = ''
+ break
+ }
+ }
+ } else if (style.includes('inline-block')) {
+ if (styleObj.width && styleObj.width[styleObj.width.length - 1] === '%') {
+ item.attrs.style += ';max-width:' + styleObj.width
+ styleObj.width = ''
+ } else {
+ item.attrs.style += ';max-width:100%'
+ }
+ }
+ // #endif
+ item.c = 1
+ }
+ attrs.i = this.imgList.length.toString()
+ let src = attrs['original-src'] || attrs.src
+ // #ifndef H5 || MP-ALIPAY || APP-PLUS || MP-360
+ if (this.imgList.includes(src)) {
+ // 如果有重复的链接则对域名进行随机大小写变换避免预览时错位
+ let i = src.indexOf('://')
+ if (i !== -1) {
+ i += 3
+ let newSrc = src.substr(0, i)
+ for (; i < src.length; i++) {
+ if (src[i] === '/') break
+ newSrc += Math.random() > 0.5 ? src[i].toUpperCase() : src[i]
+ }
+ newSrc += src.substr(i)
+ src = newSrc
+ }
+ }
+ // #endif
+ this.imgList.push(src)
+ if (!node.t) {
+ this.imgList._unloadimgs += 1
+ }
+ // #ifdef H5 || APP-PLUS
+ if (this.options.lazyLoad) {
+ attrs['data-src'] = attrs.src
+ attrs.src = undefined
+ }
+ // #endif
+ }
+ }
+ if (styleObj.display === 'inline') {
+ styleObj.display = ''
+ }
+ // #ifndef APP-PLUS-NVUE
+ if (attrs.ignore) {
+ styleObj['max-width'] = styleObj['max-width'] || '100%'
+ attrs.style += ';-webkit-touch-callout:none'
+ }
+ // #endif
+ // 设置的宽度超出屏幕,为避免变形,高度转为自动
+ if (parseInt(styleObj.width) > windowWidth) {
+ styleObj.height = undefined
+ }
+ // 记录是否设置了宽高
+ if (!isNaN(parseInt(styleObj.width))) {
+ node.w = 'T'
+ }
+ if (!isNaN(parseInt(styleObj.height)) && (!styleObj.height.includes('%') || (parent && (parent.attrs.style || '').includes('height')))) {
+ node.h = 'T'
+ }
+ } else if (node.name === 'svg') {
+ siblings.push(node)
+ this.stack.push(node)
+ this.popNode()
+ return
+ }
+ for (const key in styleObj) {
+ if (styleObj[key]) {
+ attrs.style += `;${key}:${styleObj[key].replace(' !important', '')}`
+ }
+ }
+ attrs.style = attrs.style.substr(1) || undefined
+ // #ifdef (MP-WEIXIN || MP-QQ) && VUE3
+ if (!attrs.style) {
+ delete attrs.style
+ }
+ // #endif
+ } else {
+ if ((node.name === 'pre' || ((attrs.style || '').includes('white-space') && attrs.style.includes('pre'))) && this.pre !== 2) {
+ this.pre = node.pre = 1
+ }
+ node.children = []
+ this.stack.push(node)
+ }
+
+ // 加入节点树
+ siblings.push(node)
+}
+
+/**
+ * @description 解析到标签结束
+ * @param {String} name 标签名
+ * @private
+ */
+Parser.prototype.onCloseTag = function (name) {
+ // 依次出栈到匹配为止
+ name = this.xml ? name : name.toLowerCase()
+ let i
+ for (i = this.stack.length; i--;) {
+ if (this.stack[i].name === name) break
+ }
+ if (i !== -1) {
+ while (this.stack.length > i) {
+ this.popNode()
+ }
+ } else if (name === 'p' || name === 'br') {
+ const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes
+ siblings.push({
+ name,
+ attrs: {
+ class: tagSelector[name] || '',
+ style: this.tagStyle[name] || ''
+ }
+ })
+ }
+}
+
+/**
+ * @description 处理标签出栈
+ * @private
+ */
+Parser.prototype.popNode = function () {
+ const node = this.stack.pop()
+ let attrs = node.attrs
+ const children = node.children
+ const parent = this.stack[this.stack.length - 1]
+ const siblings = parent ? parent.children : this.nodes
+
+ if (!this.hook(node) || config.ignoreTags[node.name]) {
+ // 获取标题
+ if (node.name === 'title' && children.length && children[0].type === 'text' && this.options.setTitle) {
+ uni.setNavigationBarTitle({
+ title: children[0].text
+ })
+ }
+ siblings.pop()
+ return
+ }
+
+ if (node.pre && this.pre !== 2) {
+ // 是否合并空白符标识
+ this.pre = node.pre = undefined
+ for (let i = this.stack.length; i--;) {
+ if (this.stack[i].pre) {
+ this.pre = 1
+ }
+ }
+ }
+
+ const styleObj = {}
+
+ // 转换 svg
+ if (node.name === 'svg') {
+ if (this.xml > 1) {
+ // 多层 svg 嵌套
+ this.xml--
+ return
+ }
+ // #ifdef APP-PLUS-NVUE
+ (function traversal (node) {
+ if (node.name) {
+ // 调整 svg 的大小写
+ node.name = config.svgDict[node.name] || node.name
+ for (const item in node.attrs) {
+ if (config.svgDict[item]) {
+ node.attrs[config.svgDict[item]] = node.attrs[item]
+ node.attrs[item] = undefined
+ }
+ }
+ for (let i = 0; i < (node.children || []).length; i++) {
+ traversal(node.children[i])
+ }
+ }
+ })(node)
+ // #endif
+ // #ifndef APP-PLUS-NVUE
+ let src = ''
+ const style = attrs.style
+ attrs.style = ''
+ attrs.xmlns = 'http://www.w3.org/2000/svg';
+ (function traversal (node) {
+ if (node.type === 'text') {
+ src += node.text
+ return
+ }
+ const name = config.svgDict[node.name] || node.name
+ src += '<' + name
+ for (const item in node.attrs) {
+ const val = node.attrs[item]
+ if (val) {
+ src += ` ${config.svgDict[item] || item}="${val}"`
+ }
+ }
+ if (!node.children) {
+ src += '/>'
+ } else {
+ src += '>'
+ for (let i = 0; i < node.children.length; i++) {
+ traversal(node.children[i])
+ }
+ src += '' + name + '>'
+ }
+ })(node)
+ node.name = 'img'
+ node.attrs = {
+ src: 'data:image/svg+xml;utf8,' + src.replace(/#/g, '%23'),
+ style,
+ ignore: 'T'
+ }
+ node.children = undefined
+ // #endif
+ this.xml = false
+ return
+ }
+
+ // #ifndef APP-PLUS-NVUE
+ // 转换 align 属性
+ if (attrs.align) {
+ if (node.name === 'table') {
+ if (attrs.align === 'center') {
+ styleObj['margin-inline-start'] = styleObj['margin-inline-end'] = 'auto'
+ } else {
+ styleObj.float = attrs.align
+ }
+ } else {
+ styleObj['text-align'] = attrs.align
+ }
+ attrs.align = undefined
+ }
+
+ // 转换 dir 属性
+ if (attrs.dir) {
+ styleObj.direction = attrs.dir
+ attrs.dir = undefined
+ }
+
+ // 转换 font 标签的属性
+ if (node.name === 'font') {
+ if (attrs.color) {
+ styleObj.color = attrs.color
+ attrs.color = undefined
+ }
+ if (attrs.face) {
+ styleObj['font-family'] = attrs.face
+ attrs.face = undefined
+ }
+ if (attrs.size) {
+ let size = parseInt(attrs.size)
+ if (!isNaN(size)) {
+ if (size < 1) {
+ size = 1
+ } else if (size > 7) {
+ size = 7
+ }
+ styleObj['font-size'] = ['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', 'xxx-large'][size - 1]
+ }
+ attrs.size = undefined
+ }
+ }
+ // #endif
+
+ // 一些编辑器的自带 class
+ if ((attrs.class || '').includes('align-center')) {
+ styleObj['text-align'] = 'center'
+ }
+
+ Object.assign(styleObj, this.parseStyle(node))
+
+ if (node.name !== 'table' && parseInt(styleObj.width) > windowWidth) {
+ styleObj['max-width'] = '100%'
+ styleObj['box-sizing'] = 'border-box'
+ }
+
+ // #ifndef APP-PLUS-NVUE
+ if (config.blockTags[node.name]) {
+ node.name = 'div'
+ } else if (!config.trustTags[node.name] && !this.xml) {
+ // 未知标签转为 span,避免无法显示
+ node.name = 'span'
+ }
+
+ if (node.name === 'a' || node.name === 'ad'
+ // #ifdef H5 || APP-PLUS
+ || node.name === 'iframe' // eslint-disable-line
+ // #endif
+ ) {
+ this.expose()
+ } else if (node.name === 'video') {
+ if ((styleObj.height || '').includes('auto')) {
+ styleObj.height = undefined
+ }
+ /* #ifdef APP-PLUS */
+ let str = ''
+ node.html = str
+ /* #endif */
+ } else if ((node.name === 'ul' || node.name === 'ol') && node.c) {
+ // 列表处理
+ const types = {
+ a: 'lower-alpha',
+ A: 'upper-alpha',
+ i: 'lower-roman',
+ I: 'upper-roman'
+ }
+ if (types[attrs.type]) {
+ attrs.style += ';list-style-type:' + types[attrs.type]
+ attrs.type = undefined
+ }
+ for (let i = children.length; i--;) {
+ if (children[i].name === 'li') {
+ children[i].c = 1
+ }
+ }
+ } else if (node.name === 'table') {
+ // 表格处理
+ // cellpadding、cellspacing、border 这几个常用表格属性需要通过转换实现
+ let padding = parseFloat(attrs.cellpadding)
+ let spacing = parseFloat(attrs.cellspacing)
+ const border = parseFloat(attrs.border)
+ const bordercolor = styleObj['border-color']
+ const borderstyle = styleObj['border-style']
+ if (node.c) {
+ // padding 和 spacing 默认 2
+ if (isNaN(padding)) {
+ padding = 2
+ }
+ if (isNaN(spacing)) {
+ spacing = 2
+ }
+ }
+ if (border) {
+ attrs.style += `;border:${border}px ${borderstyle || 'solid'} ${bordercolor || 'gray'}`
+ }
+ if (node.flag && node.c) {
+ // 有 colspan 或 rowspan 且含有链接的表格通过 grid 布局实现
+ styleObj.display = 'grid'
+ if (spacing) {
+ styleObj['grid-gap'] = spacing + 'px'
+ styleObj.padding = spacing + 'px'
+ } else if (border) {
+ // 无间隔的情况下避免边框重叠
+ attrs.style += ';border-left:0;border-top:0'
+ }
+
+ const width = [] // 表格的列宽
+ const trList = [] // tr 列表
+ const cells = [] // 保存新的单元格
+ const map = {}; // 被合并单元格占用的格子
+
+ (function traversal (nodes) {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].name === 'tr') {
+ trList.push(nodes[i])
+ } else {
+ traversal(nodes[i].children || [])
+ }
+ }
+ })(children)
+
+ for (let row = 1; row <= trList.length; row++) {
+ let col = 1
+ for (let j = 0; j < trList[row - 1].children.length; j++) {
+ const td = trList[row - 1].children[j]
+ if (td.name === 'td' || td.name === 'th') {
+ // 这个格子被上面的单元格占用,则列号++
+ while (map[row + '.' + col]) {
+ col++
+ }
+ let style = td.attrs.style || ''
+ let start = style.indexOf('width') ? style.indexOf(';width') : 0
+ // 提取出 td 的宽度
+ if (start !== -1) {
+ let end = style.indexOf(';', start + 6)
+ if (end === -1) {
+ end = style.length
+ }
+ if (!td.attrs.colspan) {
+ width[col] = style.substring(start ? start + 7 : 6, end)
+ }
+ style = style.substr(0, start) + style.substr(end)
+ }
+ // 设置竖直对齐
+ style += ';display:flex'
+ start = style.indexOf('vertical-align')
+ if (start !== -1) {
+ const val = style.substr(start + 15, 10)
+ if (val.includes('middle')) {
+ style += ';align-items:center'
+ } else if (val.includes('bottom')) {
+ style += ';align-items:flex-end'
+ }
+ } else {
+ style += ';align-items:center'
+ }
+ // 设置水平对齐
+ start = style.indexOf('text-align')
+ if (start !== -1) {
+ const val = style.substr(start + 11, 10)
+ if (val.includes('center')) {
+ style += ';justify-content: center'
+ } else if (val.includes('right')) {
+ style += ';justify-content: right'
+ }
+ }
+ style = (border ? `;border:${border}px ${borderstyle || 'solid'} ${bordercolor || 'gray'}` + (spacing ? '' : ';border-right:0;border-bottom:0') : '') + (padding ? `;padding:${padding}px` : '') + ';' + style
+ // 处理列合并
+ if (td.attrs.colspan) {
+ style += `;grid-column-start:${col};grid-column-end:${col + parseInt(td.attrs.colspan)}`
+ if (!td.attrs.rowspan) {
+ style += `;grid-row-start:${row};grid-row-end:${row + 1}`
+ }
+ col += parseInt(td.attrs.colspan) - 1
+ }
+ // 处理行合并
+ if (td.attrs.rowspan) {
+ style += `;grid-row-start:${row};grid-row-end:${row + parseInt(td.attrs.rowspan)}`
+ if (!td.attrs.colspan) {
+ style += `;grid-column-start:${col};grid-column-end:${col + 1}`
+ }
+ // 记录下方单元格被占用
+ for (let rowspan = 1; rowspan < td.attrs.rowspan; rowspan++) {
+ for (let colspan = 0; colspan < (td.attrs.colspan || 1); colspan++) {
+ map[(row + rowspan) + '.' + (col - colspan)] = 1
+ }
+ }
+ }
+ if (style) {
+ td.attrs.style = style
+ }
+ cells.push(td)
+ col++
+ }
+ }
+ if (row === 1) {
+ let temp = ''
+ for (let i = 1; i < col; i++) {
+ temp += (width[i] ? width[i] : 'auto') + ' '
+ }
+ styleObj['grid-template-columns'] = temp
+ }
+ }
+ node.children = cells
+ } else {
+ // 没有使用合并单元格的表格通过 table 布局实现
+ if (node.c) {
+ styleObj.display = 'table'
+ }
+ if (!isNaN(spacing)) {
+ styleObj['border-spacing'] = spacing + 'px'
+ }
+ if (border || padding) {
+ // 遍历
+ (function traversal (nodes) {
+ for (let i = 0; i < nodes.length; i++) {
+ const td = nodes[i]
+ if (td.name === 'th' || td.name === 'td') {
+ if (border) {
+ td.attrs.style = `border:${border}px ${borderstyle || 'solid'} ${bordercolor || 'gray'};${td.attrs.style || ''}`
+ }
+ if (padding) {
+ td.attrs.style = `padding:${padding}px;${td.attrs.style || ''}`
+ }
+ } else if (td.children) {
+ traversal(td.children)
+ }
+ }
+ })(children)
+ }
+ }
+ // 给表格添加一个单独的横向滚动层
+ if (this.options.scrollTable && !(attrs.style || '').includes('inline')) {
+ const table = Object.assign({}, node)
+ node.name = 'div'
+ node.attrs = {
+ style: 'overflow:auto'
+ }
+ node.children = [table]
+ attrs = table.attrs
+ }
+ } else if ((node.name === 'td' || node.name === 'th') && (attrs.colspan || attrs.rowspan)) {
+ for (let i = this.stack.length; i--;) {
+ if (this.stack[i].name === 'table') {
+ this.stack[i].flag = 1 // 指示含有合并单元格
+ break
+ }
+ }
+ } else if (node.name === 'ruby') {
+ // 转换 ruby
+ node.name = 'span'
+ for (let i = 0; i < children.length - 1; i++) {
+ if (children[i].type === 'text' && children[i + 1].name === 'rt') {
+ children[i] = {
+ name: 'div',
+ attrs: {
+ style: 'display:inline-block;text-align:center'
+ },
+ children: [{
+ name: 'div',
+ attrs: {
+ style: 'font-size:50%;' + (children[i + 1].attrs.style || '')
+ },
+ children: children[i + 1].children
+ }, children[i]]
+ }
+ children.splice(i + 1, 1)
+ }
+ }
+ } else if (node.c) {
+ (function traversal (node) {
+ node.c = 2
+ for (let i = node.children.length; i--;) {
+ const child = node.children[i]
+ // #ifdef (MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE3
+ if (child.name && (config.inlineTags[child.name] || ((child.attrs.style || '').includes('inline') && child.children)) && !child.c) {
+ traversal(child)
+ }
+ // #endif
+ if (!child.c || child.name === 'table') {
+ node.c = 1
+ }
+ }
+ })(node)
+ }
+
+ if ((styleObj.display || '').includes('flex') && !node.c) {
+ for (let i = children.length; i--;) {
+ const item = children[i]
+ if (item.f) {
+ item.attrs.style = (item.attrs.style || '') + item.f
+ item.f = undefined
+ }
+ }
+ }
+ // flex 布局时部分样式需要提取到 rich-text 外层
+ const flex = parent && ((parent.attrs.style || '').includes('flex') || (parent.attrs.style || '').includes('grid'))
+ // #ifdef MP-WEIXIN
+ // 检查基础库版本 virtualHost 是否可用
+ && !(node.c && wx.getNFCAdapter) // eslint-disable-line
+ // #endif
+ // #ifndef MP-WEIXIN || MP-QQ || MP-BAIDU || MP-TOUTIAO
+ && !node.c // eslint-disable-line
+ // #endif
+ if (flex) {
+ node.f = ';max-width:100%'
+ }
+
+ if (children.length >= 50 && node.c && !(styleObj.display || '').includes('flex')) {
+ mergeNodes(children)
+ }
+ // #endif
+
+ for (const key in styleObj) {
+ if (styleObj[key]) {
+ const val = `;${key}:${styleObj[key].replace(' !important', '')}`
+ /* #ifndef APP-PLUS-NVUE */
+ if (flex && ((key.includes('flex') && key !== 'flex-direction') || key === 'align-self' || key.includes('grid') || styleObj[key][0] === '-' || (key.includes('width') && val.includes('%')))) {
+ node.f += val
+ if (key === 'width') {
+ attrs.style += ';width:100%'
+ }
+ } else /* #endif */ {
+ attrs.style += val
+ }
+ }
+ }
+ attrs.style = attrs.style.substr(1) || undefined
+ // #ifdef (MP-WEIXIN || MP-QQ) && VUE3
+ for (const key in attrs) {
+ if (!attrs[key]) {
+ delete attrs[key]
+ }
+ }
+ // #endif
+}
+
+/**
+ * @description 解析到文本
+ * @param {String} text 文本内容
+ */
+Parser.prototype.onText = function (text) {
+ if (!this.pre) {
+ // 合并空白符
+ let trim = ''
+ let flag
+ for (let i = 0, len = text.length; i < len; i++) {
+ if (!blankChar[text[i]]) {
+ trim += text[i]
+ } else {
+ if (trim[trim.length - 1] !== ' ') {
+ trim += ' '
+ }
+ if (text[i] === '\n' && !flag) {
+ flag = true
+ }
+ }
+ }
+ // 去除含有换行符的空串
+ if (trim === ' ') {
+ if (flag) return
+ // #ifdef VUE3
+ else {
+ const parent = this.stack[this.stack.length - 1]
+ if (parent && parent.name[0] === 't') return
+ }
+ // #endif
+ }
+ text = trim
+ }
+ const node = Object.create(null)
+ node.type = 'text'
+ // #ifdef (MP-BAIDU || MP-ALIPAY || MP-TOUTIAO) && VUE3
+ node.attrs = {}
+ // #endif
+ node.text = decodeEntity(text)
+ if (this.hook(node)) {
+ // #ifdef MP-WEIXIN
+ if (this.options.selectable === 'force' && system.includes('iOS') && !uni.canIUse('rich-text.user-select')) {
+ this.expose()
+ }
+ // #endif
+ const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes
+ siblings.push(node)
+ }
+}
+
+/**
+ * @description html 词法分析器
+ * @param {Object} handler 高层处理器
+ */
+function Lexer (handler) {
+ this.handler = handler
+}
+
+/**
+ * @description 执行解析
+ * @param {String} content 要解析的文本
+ */
+Lexer.prototype.parse = function (content) {
+ this.content = content || ''
+ this.i = 0 // 标记解析位置
+ this.start = 0 // 标记一个单词的开始位置
+ this.state = this.text // 当前状态
+ for (let len = this.content.length; this.i !== -1 && this.i < len;) {
+ this.state()
+ }
+}
+
+/**
+ * @description 检查标签是否闭合
+ * @param {String} method 如果闭合要进行的操作
+ * @returns {Boolean} 是否闭合
+ * @private
+ */
+Lexer.prototype.checkClose = function (method) {
+ const selfClose = this.content[this.i] === '/'
+ if (this.content[this.i] === '>' || (selfClose && this.content[this.i + 1] === '>')) {
+ if (method) {
+ this.handler[method](this.content.substring(this.start, this.i))
+ }
+ this.i += selfClose ? 2 : 1
+ this.start = this.i
+ this.handler.onOpenTag(selfClose)
+ if (this.handler.tagName === 'script') {
+ this.i = this.content.indexOf('', this.i)
+ if (this.i !== -1) {
+ this.i += 2
+ this.start = this.i
+ }
+ this.state = this.endTag
+ } else {
+ this.state = this.text
+ }
+ return true
+ }
+ return false
+}
+
+/**
+ * @description 文本状态
+ * @private
+ */
+Lexer.prototype.text = function () {
+ this.i = this.content.indexOf('<', this.i) // 查找最近的标签
+ if (this.i === -1) {
+ // 没有标签了
+ if (this.start < this.content.length) {
+ this.handler.onText(this.content.substring(this.start, this.content.length))
+ }
+ return
+ }
+ const c = this.content[this.i + 1]
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+ // 标签开头
+ if (this.start !== this.i) {
+ this.handler.onText(this.content.substring(this.start, this.i))
+ }
+ this.start = ++this.i
+ this.state = this.tagName
+ } else if (c === '/' || c === '!' || c === '?') {
+ if (this.start !== this.i) {
+ this.handler.onText(this.content.substring(this.start, this.i))
+ }
+ const next = this.content[this.i + 2]
+ if (c === '/' && ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
+ // 标签结尾
+ this.i += 2
+ this.start = this.i
+ this.state = this.endTag
+ return
+ }
+ // 处理注释
+ let end = '-->'
+ if (c !== '!' || this.content[this.i + 2] !== '-' || this.content[this.i + 3] !== '-') {
+ end = '>'
+ }
+ this.i = this.content.indexOf(end, this.i)
+ if (this.i !== -1) {
+ this.i += end.length
+ this.start = this.i
+ }
+ } else {
+ this.i++
+ }
+}
+
+/**
+ * @description 标签名状态
+ * @private
+ */
+Lexer.prototype.tagName = function () {
+ if (blankChar[this.content[this.i]]) {
+ // 解析到标签名
+ this.handler.onTagName(this.content.substring(this.start, this.i))
+ while (blankChar[this.content[++this.i]]);
+ if (this.i < this.content.length && !this.checkClose()) {
+ this.start = this.i
+ this.state = this.attrName
+ }
+ } else if (!this.checkClose('onTagName')) {
+ this.i++
+ }
+}
+
+/**
+ * @description 属性名状态
+ * @private
+ */
+Lexer.prototype.attrName = function () {
+ let c = this.content[this.i]
+ if (blankChar[c] || c === '=') {
+ // 解析到属性名
+ this.handler.onAttrName(this.content.substring(this.start, this.i))
+ let needVal = c === '='
+ const len = this.content.length
+ while (++this.i < len) {
+ c = this.content[this.i]
+ if (!blankChar[c]) {
+ if (this.checkClose()) return
+ if (needVal) {
+ // 等号后遇到第一个非空字符
+ this.start = this.i
+ this.state = this.attrVal
+ return
+ }
+ if (this.content[this.i] === '=') {
+ needVal = true
+ } else {
+ this.start = this.i
+ this.state = this.attrName
+ return
+ }
+ }
+ }
+ } else if (!this.checkClose('onAttrName')) {
+ this.i++
+ }
+}
+
+/**
+ * @description 属性值状态
+ * @private
+ */
+Lexer.prototype.attrVal = function () {
+ const c = this.content[this.i]
+ const len = this.content.length
+ if (c === '"' || c === "'") {
+ // 有冒号的属性
+ this.start = ++this.i
+ this.i = this.content.indexOf(c, this.i)
+ if (this.i === -1) return
+ this.handler.onAttrVal(this.content.substring(this.start, this.i))
+ } else {
+ // 没有冒号的属性
+ for (; this.i < len; this.i++) {
+ if (blankChar[this.content[this.i]]) {
+ this.handler.onAttrVal(this.content.substring(this.start, this.i))
+ break
+ } else if (this.checkClose('onAttrVal')) return
+ }
+ }
+ while (blankChar[this.content[++this.i]]);
+ if (this.i < len && !this.checkClose()) {
+ this.start = this.i
+ this.state = this.attrName
+ }
+}
+
+/**
+ * @description 结束标签状态
+ * @returns {String} 结束的标签名
+ * @private
+ */
+Lexer.prototype.endTag = function () {
+ const c = this.content[this.i]
+ if (blankChar[c] || c === '>' || c === '/') {
+ this.handler.onCloseTag(this.content.substring(this.start, this.i))
+ if (c !== '>') {
+ this.i = this.content.indexOf('>', this.i)
+ if (this.i === -1) return
+ }
+ this.start = ++this.i
+ this.state = this.text
+ } else {
+ this.i++
+ }
+}
+
+export default Parser
diff --git a/uni_modules/mp-html/package.json b/uni_modules/mp-html/package.json
new file mode 100644
index 0000000..982c9af
--- /dev/null
+++ b/uni_modules/mp-html/package.json
@@ -0,0 +1,76 @@
+{
+ "id": "mp-html",
+ "displayName": "mp-html 富文本组件【全端支持,支持编辑、latex等扩展】",
+ "version": "v2.4.1",
+ "description": "一个强大的富文本组件,高效轻量,功能丰富",
+ "keywords": [
+ "富文本",
+ "编辑器",
+ "html",
+ "rich-text",
+ "editor"
+ ],
+ "repository": "https://github.com/jin-yufeng/mp-html",
+ "dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/mp-html",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "u",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "y",
+ "联盟": "y"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/mp-html/static/app-plus/mp-html/js/handler.js b/uni_modules/mp-html/static/app-plus/mp-html/js/handler.js
new file mode 100644
index 0000000..1d986bd
--- /dev/null
+++ b/uni_modules/mp-html/static/app-plus/mp-html/js/handler.js
@@ -0,0 +1 @@
+"use strict";function t(t){for(var e=Object.create(null),n=t.attributes.length;n--;)e[t.attributes[n].name]=t.attributes[n].value;return e}function e(){a[1]&&(this.src=a[1],this.onerror=null),this.onclick=null,this.ontouchstart=null,uni.postMessage({data:{action:"onError",source:"img",attrs:t(this)}})}function n(){window.unloadimgs-=1,0===window.unloadimgs&&uni.postMessage({data:{action:"onReady"}})}function o(r,s,c){for(var d=0;d0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;a("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("redirectTo",{url:encodeURI(n)})},getEnv:function(e){window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};a("postMessage",e.data||{})}},r=/uni-app/i.test(navigator.userAgent),d=/Html5Plus/i.test(navigator.userAgent),s=/complete|loaded|interactive/;var w=window.my&&navigator.userAgent.indexOf("AlipayClient")>-1;var u=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var g=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var v=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.qa&&/quickapp/i.test(navigator.userAgent);for(var l,_=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},f=[function(e){if(r||d)return window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&s.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),o},function(e){if(v)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(w){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(u)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(g)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(p){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){return document.addEventListener("DOMContentLoaded",e),o}],m=0;m
\ No newline at end of file
diff --git a/uni_modules/vk-uview-ui/changelog.md b/uni_modules/vk-uview-ui/changelog.md
new file mode 100644
index 0000000..2c79278
--- /dev/null
+++ b/uni_modules/vk-uview-ui/changelog.md
@@ -0,0 +1,137 @@
+## 1.4.7(2023-04-24)
+* 【修复】`u-picker` 在vue3的App环境下默认值无效的bug
+## 1.4.5(2022-12-05)
+* 【修复】`u-row`、`u-col` 使用 `@click.stop` 会报错的问题,同时建议改用 `@click.native.stop` 来代替 `@click.stop`
+## 1.4.4(2022-11-12)
+* 【修复】`u-calendar` `u-modal` `u-picker` `u-popup` 组件在页面进入后马上需要弹窗时,无法正常弹窗的问题。
+## 1.4.3(2022-10-22)
+* 【优化】部分组件的细节
+## 1.4.2(2022-10-15)
+* 【修复】`1.4.1` 引出的 `u-subsection` 的部分问题
+## 1.4.1(2022-10-14)
+* 【修复】`u-count-to` 若设置了千分位符合,会错误显示-的问题
+* 【修复】`u-subsection` 部分细节问题
+## 1.4.0(2022-10-07)
+* 【修复】`u-section` 点击更多,会触发两次事件的问题
+* 【修复】`loadMore` 加载更多,icon-type为circle不会转动的问题
+* 【修复】`u-subsection` current 有转入值时,变更值,样式不更新(需用 `v-model="current"` 代替 `:current="current"`)
+## 1.3.13(2022-09-28)
+* 【修复】`u-avatar-cropper` 组件在vue3中会报错的问题。
+## 1.3.12(2022-08-30)
+* 【优化】`u-keyboard` 组件内部细节。
+## 1.3.11(2022-08-30)
+* 【修复】`u-subsection` 组件的 `list` 属性不支持动态修改的问题。
+## 1.3.10(2022-07-30)
+* 【优化】上传组件部分细节
+## 1.3.9(2022-07-07)
+* 【更新】省市区数据源
+* 【优化】`u-subsection` 组件支持在右上角显示数字角标
+```html
+
+
+
+```
+
+```js
+export default {
+ data() {
+ return {
+ list: [
+ {
+ name: '待发货',
+ num: 10
+ },
+ {
+ name: '待付款',
+ num: 5
+ },
+ {
+ name: '待评价',
+ num: 15
+ }
+ ]
+ }
+ }
+}
+```
+## 1.3.8(2022-06-13)
+* 【优化】组件 `u-icon`,使之更方便的兼容第三方icon(满足规则自动计算customPrefix)
+**规则如下:**
+* 当 `name` 中包含 `-icon-` 字符串时
+* 如 `vk-icon-goods`,则组件的 `customPrefix` 属性自动识别为 `vk-icon` ,`name`属性 自动识别为 `goods`
+* 如 `vk-2-icon-goods-list`,则组件的 `customPrefix` 属性自动识别为 `vk-2-icon` ,`name`属性 自动识别为 `goods-list`
+## 1.3.7(2022-06-10)
+* 【优化】组件 `u-action-sheet` `u-calendar` `u-dropdown-item` `u-field` `u-input` `u-keyboard` `u-modal` `u-radio-group` `u-rate` `u-search` `u-slider` `u-switch` `u-tabbar` `u-waterfall` 在 `vue3` 模式下的细节问题。
+## 1.3.6(2022-06-10)
+* 【优化】组件 `u-action-sheet` `u-calendar` `u-dropdown-item` `u-field` `u-input` `u-keyboard` `u-modal` `u-radio-group` `u-rate` `u-search` `u-slider` `u-switch` `u-tabbar` `u-waterfall` 在 `vue3` 模式下的细节问题。
+## 1.3.5(2022-05-28)
+* 【优化】组件 `u-mask` `u-popup` `u-select` `u-modal` `u-keyboard` `u-calendar` `u-action-sheet` `u-picker` 均新增 `blur` 属性,可用于设置弹出遮罩的模糊度,默认为0(不模糊)
+* 
+## 1.3.4(2022-05-03)
+* 【修复】`u-tabs` 组件细节问题。
+## 1.1.4(2022-03-22)
+* 【修复】`u-field` 组件 `arrowDirection` 属性无效的问题。
+## 1.1.3(2022-03-21)
+* 【优化】部分细节。
+## 1.1.2(2022-03-21)
+* 【优化】部分细节。
+## 1.1.1(2022-03-17)
+* 【优化】部分细节。
+## 1.1.0(2022-03-12)
+* 【重要】`u-picker` 组件新增 `regionDiscern` 方法 智能识别省市区街道地址
+如将字符串 `浙江省杭州市西湖区希望路1333弄是啊我庭12号楼1203` 中识别为
+```json
+{
+ "province": {
+ "code": "330000",
+ "name": "浙江省"
+ },
+ "city": {
+ "code": "330100",
+ "name": "杭州市"
+ },
+ "area": {
+ "code": "330106",
+ "name": "西湖区"
+ },
+ "address": "龙井路1号",
+ "formatted_address": "浙江省杭州市西湖区龙井路1号"
+}
+```
+而组件的 `addressDiscern` 方法还可以识别收货信息,如 `张三 13888888888 上海市嘉定区希望路1333弄是啊我庭12号楼1203` 中识别姓名、手机号、地址(支持多种格式)
+## 1.0.13(2022-03-12)
+* 【优化】部分细节。
+## 1.0.12(2022-03-09)
+* 【修复】`u-radio-group` 在 vue3 模式下,设置默认值可能会无效的问题。
+## 1.0.11(2022-03-07)
+* 【优化】部分细节。
+## 1.0.10(2022-03-05)
+* 【修复】`u-radio` 中的值相等的判断 == 改为 ===
+* 【优化】部分注释的错别字。
+## 1.0.9(2022-03-03)
+* 【修复】`u-parse` 在 vue3模式下编译到app无法正常显示的问题。
+## 1.0.8(2022-02-26)
+* 【优化】`u-form` 组件新增2个属性 `inputAlign` 和 `clearable` 用于统一设置表单内所有 `u-input` 组件的对应属性默认值
+* 【优化】更新城市数据源信息
+## 1.0.7(2022-02-25)
+* 【重要】`u-picker` 组件新增 `addressDiscern` 方法 智能识别收货信息
+
+如在 `张三 13888888888 上海市嘉定区希望路1333弄是啊我庭12号楼1203` 中识别姓名、手机号、地址(支持多种格式)
+即使这样的字符串也能识别 `!!!!~~~$张三~~~上海市嘉定区希望路1333弄是啊我庭12号楼1203【【【【13888888888】`
+## 1.0.6(2022-02-24)
+* 【优化】`u-form-item` 组件的 `prop` 属性支持 a.b 形式
+## 1.0.5(2022-01-11)
+* 【修复】`u-sticky` 组件 在微信小程序中无法正常吸顶的问题
+## 1.0.4(2021-12-31)
+* 【优化】`u-dropdown-item` 组件 0和"" 无法区分的问题。
+* 【修复】`u-modal` 在Vue3版本中使用了mask-close-able属性无效的问题
+## 1.0.3(2021-12-20)
+【优化】u-icon在微信小程序下可能会显示null字符串的问题
+## 1.0.2(2021-12-09)
+* 1、【优化】`u-button` 组件新增 `timerId` 属性
+* 之前的效果是:所有按钮一定时间内只能点击1次(`共用计算时间`)导致点击按钮A后无法马上点击按钮B
+* 优化的效果是:每个按钮一定时间内只能点击1次(`分开计算时间`)且支持设置相同的 timerId 来达到指定按钮 `共用计算时间`
+## 1.0.1(2021-11-22)
+* 修复 u-parse 组件在微信小程序上的显示问题。
+## 1.0.0(2021-11-18)
+uView Vue3.0 横空出世,继承uView1.0意志,再战江湖,风云再起!by vk 2021-11-18
diff --git a/uni_modules/vk-uview-ui/components/u-action-sheet/u-action-sheet.vue b/uni_modules/vk-uview-ui/components/u-action-sheet/u-action-sheet.vue
new file mode 100644
index 0000000..c5261a1
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-action-sheet/u-action-sheet.vue
@@ -0,0 +1,246 @@
+
+
+
+ {{ tips.text }}
+
+
+
+ {{ item[labelName] }}
+
+ {{ item.subText }}
+
+
+
+
+
+ {{ cancelText }}
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-alert-tips/u-alert-tips.vue b/uni_modules/vk-uview-ui/components/u-alert-tips/u-alert-tips.vue
new file mode 100644
index 0000000..48b3d85
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-alert-tips/u-alert-tips.vue
@@ -0,0 +1,257 @@
+
+
+
+
+
+
+
+ {{title}}
+
+
+ {{description}}
+
+
+
+
+
+ {{closeText}}
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue b/uni_modules/vk-uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue
new file mode 100644
index 0000000..a48dd54
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue
@@ -0,0 +1,290 @@
+
+
+
+
+
+
+
+
+ 选择图片
+
+
+ 重新选择
+
+ 确定
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-avatar-cropper/weCropper.js b/uni_modules/vk-uview-ui/components/u-avatar-cropper/weCropper.js
new file mode 100644
index 0000000..6dac900
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-avatar-cropper/weCropper.js
@@ -0,0 +1,1256 @@
+/**
+ * we-cropper v1.3.9
+ * (c) 2020 dlhandsome
+ * @license MIT
+ */
+'use strict';
+
+var device = void 0;
+var TOUCH_STATE = ['touchstarted', 'touchmoved', 'touchended'];
+
+function firstLetterUpper(str) {
+ return str.charAt(0).toUpperCase() + str.slice(1)
+}
+
+function setTouchState(instance) {
+ var arg = [],
+ len = arguments.length - 1;
+ while (len-- > 0) arg[len] = arguments[len + 1];
+
+ TOUCH_STATE.forEach(function(key, i) {
+ if (arg[i] !== undefined) {
+ instance[key] = arg[i];
+ }
+ });
+}
+
+function validator(instance, o) {
+ Object.defineProperties(instance, o);
+}
+
+function getDevice() {
+ if (!device) {
+ device = uni.getSystemInfoSync();
+ }
+ return device
+}
+
+var tmp = {};
+
+var ref = getDevice();
+var pixelRatio = ref.pixelRatio;
+
+var DEFAULT = {
+ id: {
+ default: 'cropper',
+ get: function get() {
+ return tmp.id
+ },
+ set: function set(value) {
+ if (typeof(value) !== 'string') {
+ console.error(("id:" + value + " is invalid"));
+ }
+ tmp.id = value;
+ }
+ },
+ width: {
+ default: 750,
+ get: function get() {
+ return tmp.width
+ },
+ set: function set(value) {
+ if (typeof(value) !== 'number') {
+ console.error(("width:" + value + " is invalid"));
+ }
+ tmp.width = value;
+ }
+ },
+ height: {
+ default: 750,
+ get: function get() {
+ return tmp.height
+ },
+ set: function set(value) {
+ if (typeof(value) !== 'number') {
+ console.error(("height:" + value + " is invalid"));
+ }
+ tmp.height = value;
+ }
+ },
+ pixelRatio: {
+ default: pixelRatio,
+ get: function get() {
+ return tmp.pixelRatio
+ },
+ set: function set(value) {
+ if (typeof(value) !== 'number') {
+ console.error(("pixelRatio:" + value + " is invalid"));
+ }
+ tmp.pixelRatio = value;
+ }
+ },
+ scale: {
+ default: 2.5,
+ get: function get() {
+ return tmp.scale
+ },
+ set: function set(value) {
+ if (typeof(value) !== 'number') {
+ console.error(("scale:" + value + " is invalid"));
+ }
+ tmp.scale = value;
+ }
+ },
+ zoom: {
+ default: 5,
+ get: function get() {
+ return tmp.zoom
+ },
+ set: function set(value) {
+ if (typeof(value) !== 'number') {
+ console.error(("zoom:" + value + " is invalid"));
+ } else if (value < 0 || value > 10) {
+ console.error("zoom should be ranged in 0 ~ 10");
+ }
+ tmp.zoom = value;
+ }
+ },
+ src: {
+ default: '',
+ get: function get() {
+ return tmp.src
+ },
+ set: function set(value) {
+ if (typeof(value) !== 'string') {
+ console.error(("src:" + value + " is invalid"));
+ }
+ tmp.src = value;
+ }
+ },
+ cut: {
+ default: {},
+ get: function get() {
+ return tmp.cut
+ },
+ set: function set(value) {
+ if (typeof(value) !== 'object') {
+ console.error(("cut:" + value + " is invalid"));
+ }
+ tmp.cut = value;
+ }
+ },
+ boundStyle: {
+ default: {},
+ get: function get() {
+ return tmp.boundStyle
+ },
+ set: function set(value) {
+ if (typeof(value) !== 'object') {
+ console.error(("boundStyle:" + value + " is invalid"));
+ }
+ tmp.boundStyle = value;
+ }
+ },
+ onReady: {
+ default: null,
+ get: function get() {
+ return tmp.ready
+ },
+ set: function set(value) {
+ tmp.ready = value;
+ }
+ },
+ onBeforeImageLoad: {
+ default: null,
+ get: function get() {
+ return tmp.beforeImageLoad
+ },
+ set: function set(value) {
+ tmp.beforeImageLoad = value;
+ }
+ },
+ onImageLoad: {
+ default: null,
+ get: function get() {
+ return tmp.imageLoad
+ },
+ set: function set(value) {
+ tmp.imageLoad = value;
+ }
+ },
+ onBeforeDraw: {
+ default: null,
+ get: function get() {
+ return tmp.beforeDraw
+ },
+ set: function set(value) {
+ tmp.beforeDraw = value;
+ }
+ }
+};
+
+var ref$1 = getDevice();
+var windowWidth = ref$1.windowWidth;
+
+function prepare() {
+ var self = this;
+
+ // v1.4.0 版本中将不再自动绑定we-cropper实例
+ self.attachPage = function() {
+ var pages = getCurrentPages();
+ // 获取到当前page上下文
+ var pageContext = pages[pages.length - 1];
+ // 把this依附在Page上下文的wecropper属性上,便于在page钩子函数中访问
+ Object.defineProperty(pageContext, 'wecropper', {
+ get: function get() {
+ console.warn(
+ 'Instance will not be automatically bound to the page after v1.4.0\n\n' +
+ 'Please use a custom instance name instead\n\n' +
+ 'Example: \n' +
+ 'this.mycropper = new WeCropper(options)\n\n' +
+ '// ...\n' +
+ 'this.mycropper.getCropperImage()'
+ );
+ return self
+ },
+ configurable: true
+ });
+ };
+
+ self.createCtx = function() {
+ var id = self.id;
+ var targetId = self.targetId;
+
+ if (id) {
+ self.ctx = self.ctx || uni.createCanvasContext(id);
+ self.targetCtx = self.targetCtx || uni.createCanvasContext(targetId);
+ } else {
+ console.error("constructor: create canvas context failed, 'id' must be valuable");
+ }
+ };
+
+ self.deviceRadio = windowWidth / 750;
+}
+
+var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !==
+ 'undefined' ? self : {};
+
+
+
+
+
+function createCommonjsModule(fn, module) {
+ return module = {
+ exports: {}
+ }, fn(module, module.exports), module.exports;
+}
+
+var tools = createCommonjsModule(function(module, exports) {
+ /**
+ * String type check
+ */
+ exports.isStr = function(v) {
+ return typeof v === 'string';
+ };
+ /**
+ * Number type check
+ */
+ exports.isNum = function(v) {
+ return typeof v === 'number';
+ };
+ /**
+ * Array type check
+ */
+ exports.isArr = Array.isArray;
+ /**
+ * undefined type check
+ */
+ exports.isUndef = function(v) {
+ return v === undefined;
+ };
+
+ exports.isTrue = function(v) {
+ return v === true;
+ };
+
+ exports.isFalse = function(v) {
+ return v === false;
+ };
+ /**
+ * Function type check
+ */
+ exports.isFunc = function(v) {
+ return typeof v === 'function';
+ };
+ /**
+ * Quick object check - this is primarily used to tell
+ * Objects from primitive values when we know the value
+ * is a JSON-compliant type.
+ */
+ exports.isObj = exports.isObject = function(obj) {
+ return obj !== null && typeof obj === 'object'
+ };
+
+ /**
+ * Strict object type check. Only returns true
+ * for plain JavaScript objects.
+ */
+ var _toString = Object.prototype.toString;
+ exports.isPlainObject = function(obj) {
+ return _toString.call(obj) === '[object Object]'
+ };
+
+ /**
+ * Check whether the object has the property.
+ */
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
+ exports.hasOwn = function(obj, key) {
+ return hasOwnProperty.call(obj, key)
+ };
+
+ /**
+ * Perform no operation.
+ * Stubbing args to make Flow happy without leaving useless transpiled code
+ * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/)
+ */
+ exports.noop = function(a, b, c) {};
+
+ /**
+ * Check if val is a valid array index.
+ */
+ exports.isValidArrayIndex = function(val) {
+ var n = parseFloat(String(val));
+ return n >= 0 && Math.floor(n) === n && isFinite(val)
+ };
+});
+
+var tools_7 = tools.isFunc;
+var tools_10 = tools.isPlainObject;
+
+var EVENT_TYPE = ['ready', 'beforeImageLoad', 'beforeDraw', 'imageLoad'];
+
+function observer() {
+ var self = this;
+
+ self.on = function(event, fn) {
+ if (EVENT_TYPE.indexOf(event) > -1) {
+ if (tools_7(fn)) {
+ event === 'ready' ?
+ fn(self) :
+ self[("on" + (firstLetterUpper(event)))] = fn;
+ }
+ } else {
+ console.error(("event: " + event + " is invalid"));
+ }
+ return self
+ };
+}
+
+function wxPromise(fn) {
+ return function(obj) {
+ var args = [],
+ len = arguments.length - 1;
+ while (len-- > 0) args[len] = arguments[len + 1];
+
+ if (obj === void 0) obj = {};
+ return new Promise(function(resolve, reject) {
+ obj.success = function(res) {
+ resolve(res);
+ };
+ obj.fail = function(err) {
+ reject(err);
+ };
+ fn.apply(void 0, [obj].concat(args));
+ })
+ }
+}
+
+function draw(ctx, reserve) {
+ if (reserve === void 0) reserve = false;
+
+ return new Promise(function(resolve) {
+ ctx.draw(reserve, resolve);
+ })
+}
+
+var getImageInfo = wxPromise(uni.getImageInfo);
+
+var canvasToTempFilePath = wxPromise(uni.canvasToTempFilePath);
+
+var base64 = createCommonjsModule(function(module, exports) {
+ /*! http://mths.be/base64 v0.1.0 by @mathias | MIT license */
+ (function(root) {
+
+ // Detect free variables `exports`.
+ var freeExports = 'object' == 'object' && exports;
+
+ // Detect free variable `module`.
+ var freeModule = 'object' == 'object' && module &&
+ module.exports == freeExports && module;
+
+ // Detect free variable `global`, from Node.js or Browserified code, and use
+ // it as `root`.
+ var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal;
+ if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
+ root = freeGlobal;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ var InvalidCharacterError = function(message) {
+ this.message = message;
+ };
+ InvalidCharacterError.prototype = new Error;
+ InvalidCharacterError.prototype.name = 'InvalidCharacterError';
+
+ var error = function(message) {
+ // Note: the error messages used throughout this file match those used by
+ // the native `atob`/`btoa` implementation in Chromium.
+ throw new InvalidCharacterError(message);
+ };
+
+ var TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+ // http://whatwg.org/html/common-microsyntaxes.html#space-character
+ var REGEX_SPACE_CHARACTERS = /[\t\n\f\r ]/g;
+
+ // `decode` is designed to be fully compatible with `atob` as described in the
+ // HTML Standard. http://whatwg.org/html/webappapis.html#dom-windowbase64-atob
+ // The optimized base64-decoding algorithm used is based on @atk’s excellent
+ // implementation. https://gist.github.com/atk/1020396
+ var decode = function(input) {
+ input = String(input)
+ .replace(REGEX_SPACE_CHARACTERS, '');
+ var length = input.length;
+ if (length % 4 == 0) {
+ input = input.replace(/==?$/, '');
+ length = input.length;
+ }
+ if (
+ length % 4 == 1 ||
+ // http://whatwg.org/C#alphanumeric-ascii-characters
+ /[^+a-zA-Z0-9/]/.test(input)
+ ) {
+ error(
+ 'Invalid character: the string to be decoded is not correctly encoded.'
+ );
+ }
+ var bitCounter = 0;
+ var bitStorage;
+ var buffer;
+ var output = '';
+ var position = -1;
+ while (++position < length) {
+ buffer = TABLE.indexOf(input.charAt(position));
+ bitStorage = bitCounter % 4 ? bitStorage * 64 + buffer : buffer;
+ // Unless this is the first of a group of 4 characters…
+ if (bitCounter++ % 4) {
+ // …convert the first 8 bits to a single ASCII character.
+ output += String.fromCharCode(
+ 0xFF & bitStorage >> (-2 * bitCounter & 6)
+ );
+ }
+ }
+ return output;
+ };
+
+ // `encode` is designed to be fully compatible with `btoa` as described in the
+ // HTML Standard: http://whatwg.org/html/webappapis.html#dom-windowbase64-btoa
+ var encode = function(input) {
+ input = String(input);
+ if (/[^\0-\xFF]/.test(input)) {
+ // Note: no need to special-case astral symbols here, as surrogates are
+ // matched, and the input is supposed to only contain ASCII anyway.
+ error(
+ 'The string to be encoded contains characters outside of the ' +
+ 'Latin1 range.'
+ );
+ }
+ var padding = input.length % 3;
+ var output = '';
+ var position = -1;
+ var a;
+ var b;
+ var c;
+ var buffer;
+ // Make sure any padding is handled outside of the loop.
+ var length = input.length - padding;
+
+ while (++position < length) {
+ // Read three bytes, i.e. 24 bits.
+ a = input.charCodeAt(position) << 16;
+ b = input.charCodeAt(++position) << 8;
+ c = input.charCodeAt(++position);
+ buffer = a + b + c;
+ // Turn the 24 bits into four chunks of 6 bits each, and append the
+ // matching character for each of them to the output.
+ output += (
+ TABLE.charAt(buffer >> 18 & 0x3F) +
+ TABLE.charAt(buffer >> 12 & 0x3F) +
+ TABLE.charAt(buffer >> 6 & 0x3F) +
+ TABLE.charAt(buffer & 0x3F)
+ );
+ }
+
+ if (padding == 2) {
+ a = input.charCodeAt(position) << 8;
+ b = input.charCodeAt(++position);
+ buffer = a + b;
+ output += (
+ TABLE.charAt(buffer >> 10) +
+ TABLE.charAt((buffer >> 4) & 0x3F) +
+ TABLE.charAt((buffer << 2) & 0x3F) +
+ '='
+ );
+ } else if (padding == 1) {
+ buffer = input.charCodeAt(position);
+ output += (
+ TABLE.charAt(buffer >> 2) +
+ TABLE.charAt((buffer << 4) & 0x3F) +
+ '=='
+ );
+ }
+
+ return output;
+ };
+
+ var base64 = {
+ 'encode': encode,
+ 'decode': decode,
+ 'version': '0.1.0'
+ };
+
+ // Some AMD build optimizers, like r.js, check for specific condition patterns
+ // like the following:
+ if (
+ typeof undefined == 'function' &&
+ typeof undefined.amd == 'object' &&
+ undefined.amd
+ ) {
+ undefined(function() {
+ return base64;
+ });
+ } else if (freeExports && !freeExports.nodeType) {
+ if (freeModule) { // in Node.js or RingoJS v0.8.0+
+ freeModule.exports = base64;
+ } else { // in Narwhal or RingoJS v0.7.0-
+ for (var key in base64) {
+ base64.hasOwnProperty(key) && (freeExports[key] = base64[key]);
+ }
+ }
+ } else { // in Rhino or a web browser
+ root.base64 = base64;
+ }
+
+ }(commonjsGlobal));
+});
+
+function makeURI(strData, type) {
+ return 'data:' + type + ';base64,' + strData
+}
+
+function fixType(type) {
+ type = type.toLowerCase().replace(/jpg/i, 'jpeg');
+ var r = type.match(/png|jpeg|bmp|gif/)[0];
+ return 'image/' + r
+}
+
+function encodeData(data) {
+ var str = '';
+ if (typeof data === 'string') {
+ str = data;
+ } else {
+ for (var i = 0; i < data.length; i++) {
+ str += String.fromCharCode(data[i]);
+ }
+ }
+ return base64.encode(str)
+}
+
+/**
+ * 获取图像区域隐含的像素数据
+ * @param canvasId canvas标识
+ * @param x 将要被提取的图像数据矩形区域的左上角 x 坐标
+ * @param y 将要被提取的图像数据矩形区域的左上角 y 坐标
+ * @param width 将要被提取的图像数据矩形区域的宽度
+ * @param height 将要被提取的图像数据矩形区域的高度
+ * @param done 完成回调
+ */
+function getImageData(canvasId, x, y, width, height, done) {
+ uni.canvasGetImageData({
+ canvasId: canvasId,
+ x: x,
+ y: y,
+ width: width,
+ height: height,
+ success: function success(res) {
+ done(res, null);
+ },
+ fail: function fail(res) {
+ done(null, res);
+ }
+ });
+}
+
+/**
+ * 生成bmp格式图片
+ * 按照规则生成图片响应头和响应体
+ * @param oData 用来描述 canvas 区域隐含的像素数据 { data, width, height } = oData
+ * @returns {*} base64字符串
+ */
+function genBitmapImage(oData) {
+ //
+ // BITMAPFILEHEADER: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx
+ // BITMAPINFOHEADER: http://msdn.microsoft.com/en-us/library/dd183376.aspx
+ //
+ var biWidth = oData.width;
+ var biHeight = oData.height;
+ var biSizeImage = biWidth * biHeight * 3;
+ var bfSize = biSizeImage + 54; // total header size = 54 bytes
+
+ //
+ // typedef struct tagBITMAPFILEHEADER {
+ // WORD bfType;
+ // DWORD bfSize;
+ // WORD bfReserved1;
+ // WORD bfReserved2;
+ // DWORD bfOffBits;
+ // } BITMAPFILEHEADER;
+ //
+ var BITMAPFILEHEADER = [
+ // WORD bfType -- The file type signature; must be "BM"
+ 0x42, 0x4D,
+ // DWORD bfSize -- The size, in bytes, of the bitmap file
+ bfSize & 0xff, bfSize >> 8 & 0xff, bfSize >> 16 & 0xff, bfSize >> 24 & 0xff,
+ // WORD bfReserved1 -- Reserved; must be zero
+ 0, 0,
+ // WORD bfReserved2 -- Reserved; must be zero
+ 0, 0,
+ // DWORD bfOffBits -- The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits.
+ 54, 0, 0, 0
+ ];
+
+ //
+ // typedef struct tagBITMAPINFOHEADER {
+ // DWORD biSize;
+ // LONG biWidth;
+ // LONG biHeight;
+ // WORD biPlanes;
+ // WORD biBitCount;
+ // DWORD biCompression;
+ // DWORD biSizeImage;
+ // LONG biXPelsPerMeter;
+ // LONG biYPelsPerMeter;
+ // DWORD biClrUsed;
+ // DWORD biClrImportant;
+ // } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
+ //
+ var BITMAPINFOHEADER = [
+ // DWORD biSize -- The number of bytes required by the structure
+ 40, 0, 0, 0,
+ // LONG biWidth -- The width of the bitmap, in pixels
+ biWidth & 0xff, biWidth >> 8 & 0xff, biWidth >> 16 & 0xff, biWidth >> 24 & 0xff,
+ // LONG biHeight -- The height of the bitmap, in pixels
+ biHeight & 0xff, biHeight >> 8 & 0xff, biHeight >> 16 & 0xff, biHeight >> 24 & 0xff,
+ // WORD biPlanes -- The number of planes for the target device. This value must be set to 1
+ 1, 0,
+ // WORD biBitCount -- The number of bits-per-pixel, 24 bits-per-pixel -- the bitmap
+ // has a maximum of 2^24 colors (16777216, Truecolor)
+ 24, 0,
+ // DWORD biCompression -- The type of compression, BI_RGB (code 0) -- uncompressed
+ 0, 0, 0, 0,
+ // DWORD biSizeImage -- The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps
+ biSizeImage & 0xff, biSizeImage >> 8 & 0xff, biSizeImage >> 16 & 0xff, biSizeImage >> 24 & 0xff,
+ // LONG biXPelsPerMeter, unused
+ 0, 0, 0, 0,
+ // LONG biYPelsPerMeter, unused
+ 0, 0, 0, 0,
+ // DWORD biClrUsed, the number of color indexes of palette, unused
+ 0, 0, 0, 0,
+ // DWORD biClrImportant, unused
+ 0, 0, 0, 0
+ ];
+
+ var iPadding = (4 - ((biWidth * 3) % 4)) % 4;
+
+ var aImgData = oData.data;
+
+ var strPixelData = '';
+ var biWidth4 = biWidth << 2;
+ var y = biHeight;
+ var fromCharCode = String.fromCharCode;
+
+ do {
+ var iOffsetY = biWidth4 * (y - 1);
+ var strPixelRow = '';
+ for (var x = 0; x < biWidth; x++) {
+ var iOffsetX = x << 2;
+ strPixelRow += fromCharCode(aImgData[iOffsetY + iOffsetX + 2]) +
+ fromCharCode(aImgData[iOffsetY + iOffsetX + 1]) +
+ fromCharCode(aImgData[iOffsetY + iOffsetX]);
+ }
+
+ for (var c = 0; c < iPadding; c++) {
+ strPixelRow += String.fromCharCode(0);
+ }
+
+ strPixelData += strPixelRow;
+ } while (--y)
+
+ var strEncoded = encodeData(BITMAPFILEHEADER.concat(BITMAPINFOHEADER)) + encodeData(strPixelData);
+
+ return strEncoded
+}
+
+/**
+ * 转换为图片base64
+ * @param canvasId canvas标识
+ * @param x 将要被提取的图像数据矩形区域的左上角 x 坐标
+ * @param y 将要被提取的图像数据矩形区域的左上角 y 坐标
+ * @param width 将要被提取的图像数据矩形区域的宽度
+ * @param height 将要被提取的图像数据矩形区域的高度
+ * @param type 转换图片类型
+ * @param done 完成回调
+ */
+function convertToImage(canvasId, x, y, width, height, type, done) {
+ if (done === void 0) done = function() {};
+
+ if (type === undefined) {
+ type = 'png';
+ }
+ type = fixType(type);
+ if (/bmp/.test(type)) {
+ getImageData(canvasId, x, y, width, height, function(data, err) {
+ var strData = genBitmapImage(data);
+ tools_7(done) && done(makeURI(strData, 'image/' + type), err);
+ });
+ } else {
+ console.error('暂不支持生成\'' + type + '\'类型的base64图片');
+ }
+}
+
+var CanvasToBase64 = {
+ convertToImage: convertToImage,
+ // convertToPNG: function (width, height, done) {
+ // return convertToImage(width, height, 'png', done)
+ // },
+ // convertToJPEG: function (width, height, done) {
+ // return convertToImage(width, height, 'jpeg', done)
+ // },
+ // convertToGIF: function (width, height, done) {
+ // return convertToImage(width, height, 'gif', done)
+ // },
+ convertToBMP: function(ref, done) {
+ if (ref === void 0) ref = {};
+ var canvasId = ref.canvasId;
+ var x = ref.x;
+ var y = ref.y;
+ var width = ref.width;
+ var height = ref.height;
+ if (done === void 0) done = function() {};
+
+ return convertToImage(canvasId, x, y, width, height, 'bmp', done)
+ }
+};
+
+function methods() {
+ var self = this;
+
+ var boundWidth = self.width; // 裁剪框默认宽度,即整个画布宽度
+ var boundHeight = self.height; // 裁剪框默认高度,即整个画布高度
+
+ var id = self.id;
+ var targetId = self.targetId;
+ var pixelRatio = self.pixelRatio;
+
+ var ref = self.cut;
+ var x = ref.x;
+ if (x === void 0) x = 0;
+ var y = ref.y;
+ if (y === void 0) y = 0;
+ var width = ref.width;
+ if (width === void 0) width = boundWidth;
+ var height = ref.height;
+ if (height === void 0) height = boundHeight;
+
+ self.updateCanvas = function(done) {
+ if (self.croperTarget) {
+ // 画布绘制图片
+ self.ctx.drawImage(
+ self.croperTarget,
+ self.imgLeft,
+ self.imgTop,
+ self.scaleWidth,
+ self.scaleHeight
+ );
+ }
+ tools_7(self.onBeforeDraw) && self.onBeforeDraw(self.ctx, self);
+
+ self.setBoundStyle(self.boundStyle); // 设置边界样式
+
+ self.ctx.draw(false, done);
+ return self
+ };
+
+ self.pushOrigin = self.pushOrign = function(src) {
+ self.src = src;
+
+ tools_7(self.onBeforeImageLoad) && self.onBeforeImageLoad(self.ctx, self);
+
+ return getImageInfo({
+ src: src
+ })
+ .then(function(res) {
+ var innerAspectRadio = res.width / res.height;
+ var customAspectRadio = width / height;
+
+ self.croperTarget = res.path;
+
+ if (innerAspectRadio < customAspectRadio) {
+ self.rectX = x;
+ self.baseWidth = width;
+ self.baseHeight = width / innerAspectRadio;
+ self.rectY = y - Math.abs((height - self.baseHeight) / 2);
+ } else {
+ self.rectY = y;
+ self.baseWidth = height * innerAspectRadio;
+ self.baseHeight = height;
+ self.rectX = x - Math.abs((width - self.baseWidth) / 2);
+ }
+
+ self.imgLeft = self.rectX;
+ self.imgTop = self.rectY;
+ self.scaleWidth = self.baseWidth;
+ self.scaleHeight = self.baseHeight;
+
+ self.update();
+
+ return new Promise(function(resolve) {
+ self.updateCanvas(resolve);
+ })
+ })
+ .then(function() {
+ tools_7(self.onImageLoad) && self.onImageLoad(self.ctx, self);
+ })
+ };
+
+ self.removeImage = function() {
+ self.src = '';
+ self.croperTarget = '';
+ return draw(self.ctx)
+ };
+
+ self.getCropperBase64 = function(done) {
+ if (done === void 0) done = function() {};
+
+ CanvasToBase64.convertToBMP({
+ canvasId: id,
+ x: x,
+ y: y,
+ width: width,
+ height: height
+ }, done);
+ };
+
+ self.getCropperImage = function(opt, fn) {
+ var customOptions = opt;
+
+ var canvasOptions = {
+ canvasId: id,
+ x: x,
+ y: y,
+ width: width,
+ height: height
+ };
+
+ var task = function() {
+ return Promise.resolve();
+ };
+
+ if (
+ tools_10(customOptions) &&
+ customOptions.original
+ ) {
+ // original mode
+ task = function() {
+ self.targetCtx.drawImage(
+ self.croperTarget,
+ self.imgLeft * pixelRatio,
+ self.imgTop * pixelRatio,
+ self.scaleWidth * pixelRatio,
+ self.scaleHeight * pixelRatio
+ );
+
+ canvasOptions = {
+ canvasId: targetId,
+ x: x * pixelRatio,
+ y: y * pixelRatio,
+ width: width * pixelRatio,
+ height: height * pixelRatio
+ };
+
+ return draw(self.targetCtx)
+ };
+ }
+
+ return task()
+ .then(function() {
+ if (tools_10(customOptions)) {
+ canvasOptions = Object.assign({}, canvasOptions, customOptions);
+ }
+
+ if (tools_7(customOptions)) {
+ fn = customOptions;
+ }
+
+ var arg = canvasOptions.componentContext ? [canvasOptions, canvasOptions.componentContext] : [canvasOptions];
+
+ return canvasToTempFilePath.apply(null, arg)
+ })
+ .then(function(res) {
+ var tempFilePath = res.tempFilePath;
+
+ return tools_7(fn) ?
+ fn.call(self, tempFilePath, null) :
+ tempFilePath
+ })
+ .catch(function(err) {
+ if (tools_7(fn)) {
+ fn.call(self, null, err);
+ } else {
+ throw err
+ }
+ })
+ };
+}
+
+/**
+ * 获取最新缩放值
+ * @param oldScale 上一次触摸结束后的缩放值
+ * @param oldDistance 上一次触摸结束后的双指距离
+ * @param zoom 缩放系数
+ * @param touch0 第一指touch对象
+ * @param touch1 第二指touch对象
+ * @returns {*}
+ */
+var getNewScale = function(oldScale, oldDistance, zoom, touch0, touch1) {
+ var xMove, yMove, newDistance;
+ // 计算二指最新距离
+ xMove = Math.round(touch1.x - touch0.x);
+ yMove = Math.round(touch1.y - touch0.y);
+ newDistance = Math.round(Math.sqrt(xMove * xMove + yMove * yMove));
+
+ return oldScale + 0.001 * zoom * (newDistance - oldDistance)
+};
+
+function update() {
+ var self = this;
+
+ if (!self.src) {
+ return
+ }
+
+ self.__oneTouchStart = function(touch) {
+ self.touchX0 = Math.round(touch.x);
+ self.touchY0 = Math.round(touch.y);
+ };
+
+ self.__oneTouchMove = function(touch) {
+ var xMove, yMove;
+ // 计算单指移动的距离
+ if (self.touchended) {
+ return self.updateCanvas()
+ }
+ xMove = Math.round(touch.x - self.touchX0);
+ yMove = Math.round(touch.y - self.touchY0);
+
+ var imgLeft = Math.round(self.rectX + xMove);
+ var imgTop = Math.round(self.rectY + yMove);
+
+ self.outsideBound(imgLeft, imgTop);
+
+ self.updateCanvas();
+ };
+
+ self.__twoTouchStart = function(touch0, touch1) {
+ var xMove, yMove, oldDistance;
+
+ self.touchX1 = Math.round(self.rectX + self.scaleWidth / 2);
+ self.touchY1 = Math.round(self.rectY + self.scaleHeight / 2);
+
+ // 计算两指距离
+ xMove = Math.round(touch1.x - touch0.x);
+ yMove = Math.round(touch1.y - touch0.y);
+ oldDistance = Math.round(Math.sqrt(xMove * xMove + yMove * yMove));
+
+ self.oldDistance = oldDistance;
+ };
+
+ self.__twoTouchMove = function(touch0, touch1) {
+ var oldScale = self.oldScale;
+ var oldDistance = self.oldDistance;
+ var scale = self.scale;
+ var zoom = self.zoom;
+
+ self.newScale = getNewScale(oldScale, oldDistance, zoom, touch0, touch1);
+
+ // 设定缩放范围
+ self.newScale <= 1 && (self.newScale = 1);
+ self.newScale >= scale && (self.newScale = scale);
+
+ self.scaleWidth = Math.round(self.newScale * self.baseWidth);
+ self.scaleHeight = Math.round(self.newScale * self.baseHeight);
+ var imgLeft = Math.round(self.touchX1 - self.scaleWidth / 2);
+ var imgTop = Math.round(self.touchY1 - self.scaleHeight / 2);
+
+ self.outsideBound(imgLeft, imgTop);
+
+ self.updateCanvas();
+ };
+
+ self.__xtouchEnd = function() {
+ self.oldScale = self.newScale;
+ self.rectX = self.imgLeft;
+ self.rectY = self.imgTop;
+ };
+}
+
+var handle = {
+ // 图片手势初始监测
+ touchStart: function touchStart(e) {
+ var self = this;
+ var ref = e.touches;
+ var touch0 = ref[0];
+ var touch1 = ref[1];
+
+ if (!self.src) {
+ return
+ }
+
+ setTouchState(self, true, null, null);
+
+ // 计算第一个触摸点的位置,并参照改点进行缩放
+ self.__oneTouchStart(touch0);
+
+ // 两指手势触发
+ if (e.touches.length >= 2) {
+ self.__twoTouchStart(touch0, touch1);
+ }
+ },
+
+ // 图片手势动态缩放
+ touchMove: function touchMove(e) {
+ var self = this;
+ var ref = e.touches;
+ var touch0 = ref[0];
+ var touch1 = ref[1];
+
+ if (!self.src) {
+ return
+ }
+
+ setTouchState(self, null, true);
+
+ // 单指手势时触发
+ if (e.touches.length === 1) {
+ self.__oneTouchMove(touch0);
+ }
+ // 两指手势触发
+ if (e.touches.length >= 2) {
+ self.__twoTouchMove(touch0, touch1);
+ }
+ },
+
+ touchEnd: function touchEnd(e) {
+ var self = this;
+
+ if (!self.src) {
+ return
+ }
+
+ setTouchState(self, false, false, true);
+ self.__xtouchEnd();
+ }
+};
+
+function cut() {
+ var self = this;
+ var boundWidth = self.width; // 裁剪框默认宽度,即整个画布宽度
+ var boundHeight = self.height;
+ // 裁剪框默认高度,即整个画布高度
+ var ref = self.cut;
+ var x = ref.x;
+ if (x === void 0) x = 0;
+ var y = ref.y;
+ if (y === void 0) y = 0;
+ var width = ref.width;
+ if (width === void 0) width = boundWidth;
+ var height = ref.height;
+ if (height === void 0) height = boundHeight;
+
+ /**
+ * 设置边界
+ * @param imgLeft 图片左上角横坐标值
+ * @param imgTop 图片左上角纵坐标值
+ */
+ self.outsideBound = function(imgLeft, imgTop) {
+ self.imgLeft = imgLeft >= x ?
+ x :
+ self.scaleWidth + imgLeft - x <= width ?
+ x + width - self.scaleWidth :
+ imgLeft;
+
+ self.imgTop = imgTop >= y ?
+ y :
+ self.scaleHeight + imgTop - y <= height ?
+ y + height - self.scaleHeight :
+ imgTop;
+ };
+
+ /**
+ * 设置边界样式
+ * @param color 边界颜色
+ */
+ self.setBoundStyle = function(ref) {
+ if (ref === void 0) ref = {};
+ var color = ref.color;
+ if (color === void 0) color = '#04b00f';
+ var mask = ref.mask;
+ if (mask === void 0) mask = 'rgba(0, 0, 0, 0.3)';
+ var lineWidth = ref.lineWidth;
+ if (lineWidth === void 0) lineWidth = 1;
+
+ var half = lineWidth / 2;
+ var boundOption = [{
+ start: {
+ x: x - half,
+ y: y + 10 - half
+ },
+ step1: {
+ x: x - half,
+ y: y - half
+ },
+ step2: {
+ x: x + 10 - half,
+ y: y - half
+ }
+ },
+ {
+ start: {
+ x: x - half,
+ y: y + height - 10 + half
+ },
+ step1: {
+ x: x - half,
+ y: y + height + half
+ },
+ step2: {
+ x: x + 10 - half,
+ y: y + height + half
+ }
+ },
+ {
+ start: {
+ x: x + width - 10 + half,
+ y: y - half
+ },
+ step1: {
+ x: x + width + half,
+ y: y - half
+ },
+ step2: {
+ x: x + width + half,
+ y: y + 10 - half
+ }
+ },
+ {
+ start: {
+ x: x + width + half,
+ y: y + height - 10 + half
+ },
+ step1: {
+ x: x + width + half,
+ y: y + height + half
+ },
+ step2: {
+ x: x + width - 10 + half,
+ y: y + height + half
+ }
+ }
+ ];
+
+ // 绘制半透明层
+ self.ctx.beginPath();
+ self.ctx.setFillStyle(mask);
+ self.ctx.fillRect(0, 0, x, boundHeight);
+ self.ctx.fillRect(x, 0, width, y);
+ self.ctx.fillRect(x, y + height, width, boundHeight - y - height);
+ self.ctx.fillRect(x + width, 0, boundWidth - x - width, boundHeight);
+ self.ctx.fill();
+
+ boundOption.forEach(function(op) {
+ self.ctx.beginPath();
+ self.ctx.setStrokeStyle(color);
+ self.ctx.setLineWidth(lineWidth);
+ self.ctx.moveTo(op.start.x, op.start.y);
+ self.ctx.lineTo(op.step1.x, op.step1.y);
+ self.ctx.lineTo(op.step2.x, op.step2.y);
+ self.ctx.stroke();
+ });
+ };
+}
+
+var version = "1.3.9";
+
+var WeCropper = function WeCropper(params) {
+ var self = this;
+ var _default = {};
+
+ validator(self, DEFAULT);
+
+ Object.keys(DEFAULT).forEach(function(key) {
+ _default[key] = DEFAULT[key].default;
+ });
+ Object.assign(self, _default, params);
+
+ self.prepare();
+ self.attachPage();
+ self.createCtx();
+ self.observer();
+ self.cutt();
+ self.methods();
+ self.init();
+ self.update();
+
+ return self
+};
+
+WeCropper.prototype.init = function init() {
+ var self = this;
+ var src = self.src;
+
+ self.version = version;
+
+ typeof self.onReady === 'function' && self.onReady(self.ctx, self);
+
+ if (src) {
+ self.pushOrign(src);
+ } else {
+ self.updateCanvas();
+ }
+ setTouchState(self, false, false, false);
+
+ self.oldScale = 1;
+ self.newScale = 1;
+
+ return self
+};
+
+Object.assign(WeCropper.prototype, handle);
+
+WeCropper.prototype.prepare = prepare;
+WeCropper.prototype.observer = observer;
+WeCropper.prototype.methods = methods;
+WeCropper.prototype.cutt = cut;
+WeCropper.prototype.update = update;
+
+export default WeCropper;
diff --git a/uni_modules/vk-uview-ui/components/u-avatar/u-avatar.vue b/uni_modules/vk-uview-ui/components/u-avatar/u-avatar.vue
new file mode 100644
index 0000000..ab21c46
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-avatar/u-avatar.vue
@@ -0,0 +1,263 @@
+
+
+
+
+ {{ uText }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-back-top/u-back-top.vue b/uni_modules/vk-uview-ui/components/u-back-top/u-back-top.vue
new file mode 100644
index 0000000..7970fc7
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-back-top/u-back-top.vue
@@ -0,0 +1,153 @@
+
+
+
+
+
+ {{tips}}
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-badge/u-badge.vue b/uni_modules/vk-uview-ui/components/u-badge/u-badge.vue
new file mode 100644
index 0000000..0efa751
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-badge/u-badge.vue
@@ -0,0 +1,216 @@
+
+
+ {{showText}}
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-button/u-button.vue b/uni_modules/vk-uview-ui/components/u-button/u-button.vue
new file mode 100644
index 0000000..a05dd83
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-button/u-button.vue
@@ -0,0 +1,607 @@
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-calendar/u-calendar.vue b/uni_modules/vk-uview-ui/components/u-calendar/u-calendar.vue
new file mode 100644
index 0000000..fe9f2dc
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-calendar/u-calendar.vue
@@ -0,0 +1,666 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ showTitle }}
+
+
+
+
+
+
+
+
+ {{item}}
+
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+ {{startText}}
+ {{endText}}
+
+ {{month}}
+
+
+
+ {{mode == 'date' ? activeDate : startDate}}
+ 至{{endDate}}
+
+
+ 确定
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-car-keyboard/u-car-keyboard.vue b/uni_modules/vk-uview-ui/components/u-car-keyboard/u-car-keyboard.vue
new file mode 100644
index 0000000..e55db26
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-car-keyboard/u-car-keyboard.vue
@@ -0,0 +1,267 @@
+
+ {}">
+
+
+
+ {{ item }}
+
+
+
+
+
+
+ 中
+ /
+ 英
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-card/u-card.vue b/uni_modules/vk-uview-ui/components/u-card/u-card.vue
new file mode 100644
index 0000000..03f9924
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-card/u-card.vue
@@ -0,0 +1,300 @@
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+ {{ subTitle }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-cell-group/u-cell-group.vue b/uni_modules/vk-uview-ui/components/u-cell-group/u-cell-group.vue
new file mode 100644
index 0000000..3fbca72
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-cell-group/u-cell-group.vue
@@ -0,0 +1,70 @@
+
+
+
+ {{title}}
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-cell-item/u-cell-item.vue b/uni_modules/vk-uview-ui/components/u-cell-item/u-cell-item.vue
new file mode 100644
index 0000000..90ee117
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-cell-item/u-cell-item.vue
@@ -0,0 +1,317 @@
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+ {{ label }}
+
+
+
+
+
+ {{ value }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-checkbox-group/u-checkbox-group.vue b/uni_modules/vk-uview-ui/components/u-checkbox-group/u-checkbox-group.vue
new file mode 100644
index 0000000..18c39e7
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-checkbox-group/u-checkbox-group.vue
@@ -0,0 +1,178 @@
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-checkbox/u-checkbox.vue b/uni_modules/vk-uview-ui/components/u-checkbox/u-checkbox.vue
new file mode 100644
index 0000000..bf8a20f
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-checkbox/u-checkbox.vue
@@ -0,0 +1,322 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-circle-progress/u-circle-progress.vue b/uni_modules/vk-uview-ui/components/u-circle-progress/u-circle-progress.vue
new file mode 100644
index 0000000..46e7c18
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-circle-progress/u-circle-progress.vue
@@ -0,0 +1,220 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-col/u-col.vue b/uni_modules/vk-uview-ui/components/u-col/u-col.vue
new file mode 100644
index 0000000..fc47dfa
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-col/u-col.vue
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-collapse-item/u-collapse-item.vue b/uni_modules/vk-uview-ui/components/u-collapse-item/u-collapse-item.vue
new file mode 100644
index 0000000..963e98f
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-collapse-item/u-collapse-item.vue
@@ -0,0 +1,206 @@
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-collapse/u-collapse.vue b/uni_modules/vk-uview-ui/components/u-collapse/u-collapse.vue
new file mode 100644
index 0000000..f6e4bf0
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-collapse/u-collapse.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-column-notice/u-column-notice.vue b/uni_modules/vk-uview-ui/components/u-column-notice/u-column-notice.vue
new file mode 100644
index 0000000..709ca5c
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-column-notice/u-column-notice.vue
@@ -0,0 +1,238 @@
+
+
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-count-down/u-count-down.vue b/uni_modules/vk-uview-ui/components/u-count-down/u-count-down.vue
new file mode 100644
index 0000000..0d7cc21
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-count-down/u-count-down.vue
@@ -0,0 +1,175 @@
+
+
+
+ {{ formattedTime }}
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-count-down/utils.js b/uni_modules/vk-uview-ui/components/u-count-down/utils.js
new file mode 100644
index 0000000..8c75005
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-count-down/utils.js
@@ -0,0 +1,62 @@
+// 补0,如1 -> 01
+function padZero(num, targetLength = 2) {
+ let str = `${num}`
+ while (str.length < targetLength) {
+ str = `0${str}`
+ }
+ return str
+}
+const SECOND = 1000
+const MINUTE = 60 * SECOND
+const HOUR = 60 * MINUTE
+const DAY = 24 * HOUR
+export function parseTimeData(time) {
+ const days = Math.floor(time / DAY)
+ const hours = Math.floor((time % DAY) / HOUR)
+ const minutes = Math.floor((time % HOUR) / MINUTE)
+ const seconds = Math.floor((time % MINUTE) / SECOND)
+ const milliseconds = Math.floor(time % SECOND)
+ return {
+ days,
+ hours,
+ minutes,
+ seconds,
+ milliseconds
+ }
+}
+export function parseFormat(format, timeData) {
+ let {
+ days,
+ hours,
+ minutes,
+ seconds,
+ milliseconds
+ } = timeData
+ // 如果格式化字符串中不存在DD(天),则将天的时间转为小时中去
+ if (format.indexOf('DD') === -1) {
+ hours += days * 24
+ } else {
+ // 对天补0
+ format = format.replace('DD', padZero(days))
+ }
+ // 其他同理于DD的格式化处理方式
+ if (format.indexOf('HH') === -1) {
+ minutes += hours * 60
+ } else {
+ format = format.replace('HH', padZero(hours))
+ }
+ if (format.indexOf('mm') === -1) {
+ seconds += minutes * 60
+ } else {
+ format = format.replace('mm', padZero(minutes))
+ }
+ if (format.indexOf('ss') === -1) {
+ milliseconds += seconds * 1000
+ } else {
+ format = format.replace('ss', padZero(seconds))
+ }
+ return format.replace('SSS', padZero(milliseconds, 3))
+}
+export function isSameSecond(time1, time2) {
+ return Math.floor(time1 / 1000) === Math.floor(time2 / 1000)
+}
diff --git a/uni_modules/vk-uview-ui/components/u-count-to/u-count-to.vue b/uni_modules/vk-uview-ui/components/u-count-to/u-count-to.vue
new file mode 100644
index 0000000..1825072
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-count-to/u-count-to.vue
@@ -0,0 +1,266 @@
+
+
+ {{ displayValueCom }}
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-divider/u-divider.vue b/uni_modules/vk-uview-ui/components/u-divider/u-divider.vue
new file mode 100644
index 0000000..6f8d7e6
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-divider/u-divider.vue
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-dropdown-item/u-dropdown-item.vue b/uni_modules/vk-uview-ui/components/u-dropdown-item/u-dropdown-item.vue
new file mode 100644
index 0000000..380268a
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-dropdown-item/u-dropdown-item.vue
@@ -0,0 +1,166 @@
+
+ {}"
+ @tap.stop.prevent="() => {}"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-dropdown/u-dropdown.vue b/uni_modules/vk-uview-ui/components/u-dropdown/u-dropdown.vue
new file mode 100644
index 0000000..b9438b4
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-dropdown/u-dropdown.vue
@@ -0,0 +1,299 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-empty/u-empty.vue b/uni_modules/vk-uview-ui/components/u-empty/u-empty.vue
new file mode 100644
index 0000000..2c77b24
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-empty/u-empty.vue
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-field/u-field.vue b/uni_modules/vk-uview-ui/components/u-field/u-field.vue
new file mode 100644
index 0000000..efa31e6
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-field/u-field.vue
@@ -0,0 +1,402 @@
+
+
+
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ errorMessage }}
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-form-item/u-form-item.vue b/uni_modules/vk-uview-ui/components/u-form-item/u-form-item.vue
new file mode 100644
index 0000000..c893cfd
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-form-item/u-form-item.vue
@@ -0,0 +1,509 @@
+
+
+
+
+
+
+
+
+ *
+
+
+
+
+ {{label}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{validateMessage}}
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-form/u-form.vue b/uni_modules/vk-uview-ui/components/u-form/u-form.vue
new file mode 100644
index 0000000..ce502ae
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-form/u-form.vue
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-full-screen/u-full-screen.vue b/uni_modules/vk-uview-ui/components/u-full-screen/u-full-screen.vue
new file mode 100644
index 0000000..4f7e7d9
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-full-screen/u-full-screen.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-gap/u-gap.vue b/uni_modules/vk-uview-ui/components/u-gap/u-gap.vue
new file mode 100644
index 0000000..6c01f94
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-gap/u-gap.vue
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-grid-item/u-grid-item.vue b/uni_modules/vk-uview-ui/components/u-grid-item/u-grid-item.vue
new file mode 100644
index 0000000..c5b3033
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-grid-item/u-grid-item.vue
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-grid/u-grid.vue b/uni_modules/vk-uview-ui/components/u-grid/u-grid.vue
new file mode 100644
index 0000000..125b6f1
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-grid/u-grid.vue
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-icon/u-icon.vue b/uni_modules/vk-uview-ui/components/u-icon/u-icon.vue
new file mode 100644
index 0000000..ed95a9c
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-icon/u-icon.vue
@@ -0,0 +1,369 @@
+
+
+
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-image/u-image.vue b/uni_modules/vk-uview-ui/components/u-image/u-image.vue
new file mode 100644
index 0000000..a90adbc
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-image/u-image.vue
@@ -0,0 +1,269 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-index-anchor/u-index-anchor.vue b/uni_modules/vk-uview-ui/components/u-index-anchor/u-index-anchor.vue
new file mode 100644
index 0000000..5038827
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-index-anchor/u-index-anchor.vue
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+ {{ index }}
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-index-list/u-index-list.vue b/uni_modules/vk-uview-ui/components/u-index-list/u-index-list.vue
new file mode 100644
index 0000000..30fcda0
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-index-list/u-index-list.vue
@@ -0,0 +1,315 @@
+
+
+
+
+
+
+
+ {{indexList[touchmoveIndex]}}
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-input/u-input.vue b/uni_modules/vk-uview-ui/components/u-input/u-input.vue
new file mode 100644
index 0000000..df0a12f
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-input/u-input.vue
@@ -0,0 +1,460 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-keyboard/u-keyboard.vue b/uni_modules/vk-uview-ui/components/u-keyboard/u-keyboard.vue
new file mode 100644
index 0000000..d5aee71
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-keyboard/u-keyboard.vue
@@ -0,0 +1,285 @@
+
+
+
+
+
+ {{ cancelBtn ? cancelText : "" }}
+
+
+ {{
+ tips ? tips : mode == "number" ? "数字键盘" : mode == "card" ? "身份证键盘" : "车牌号键盘"
+ }}
+
+
+ {{ confirmBtn ? confirmText : "" }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-lazy-load/u-lazy-load.vue b/uni_modules/vk-uview-ui/components/u-lazy-load/u-lazy-load.vue
new file mode 100644
index 0000000..f872922
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-lazy-load/u-lazy-load.vue
@@ -0,0 +1,254 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-line-progress/u-line-progress.vue b/uni_modules/vk-uview-ui/components/u-line-progress/u-line-progress.vue
new file mode 100644
index 0000000..77e2da2
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-line-progress/u-line-progress.vue
@@ -0,0 +1,147 @@
+
+
+
+
+
+ {{percent + '%'}}
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-line/u-line.vue b/uni_modules/vk-uview-ui/components/u-line/u-line.vue
new file mode 100644
index 0000000..c56fbc3
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-line/u-line.vue
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-link/u-link.vue b/uni_modules/vk-uview-ui/components/u-link/u-link.vue
new file mode 100644
index 0000000..2dd2a73
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-link/u-link.vue
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-loading-page/u-loading-page.vue b/uni_modules/vk-uview-ui/components/u-loading-page/u-loading-page.vue
new file mode 100644
index 0000000..7e04401
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-loading-page/u-loading-page.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-loading/u-loading.vue b/uni_modules/vk-uview-ui/components/u-loading/u-loading.vue
new file mode 100644
index 0000000..3175c8c
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-loading/u-loading.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-loadmore/u-loadmore.vue b/uni_modules/vk-uview-ui/components/u-loadmore/u-loadmore.vue
new file mode 100644
index 0000000..e7cbbea
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-loadmore/u-loadmore.vue
@@ -0,0 +1,204 @@
+
+
+
+
+
+
+
+
+
+
+ {{ showText }}
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-mask/u-mask.vue b/uni_modules/vk-uview-ui/components/u-mask/u-mask.vue
new file mode 100644
index 0000000..cd33923
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-mask/u-mask.vue
@@ -0,0 +1,137 @@
+
+ {}" :class="{
+ 'u-mask-zoom': zoom,
+ 'u-mask-show': show
+ }">
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-message-input/u-message-input.vue b/uni_modules/vk-uview-ui/components/u-message-input/u-message-input.vue
new file mode 100644
index 0000000..f4b1568
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-message-input/u-message-input.vue
@@ -0,0 +1,327 @@
+
+
+
+
+
+
+
+
+
+ {{ charArr[index] ? charArr[index] : ''}}
+
+ {{ charArr[index] ? '●' : ''}}
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-modal/u-modal.vue b/uni_modules/vk-uview-ui/components/u-modal/u-modal.vue
new file mode 100644
index 0000000..bf8b4fc
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-modal/u-modal.vue
@@ -0,0 +1,339 @@
+
+
+
+
+
+ {{ title }}
+
+
+
+
+ {{ content }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-navbar/u-navbar.vue b/uni_modules/vk-uview-ui/components/u-navbar/u-navbar.vue
new file mode 100644
index 0000000..450242e
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-navbar/u-navbar.vue
@@ -0,0 +1,315 @@
+
+
+
+
+
+
+
+
+
+ {{ backText }}
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-no-network/u-no-network.vue b/uni_modules/vk-uview-ui/components/u-no-network/u-no-network.vue
new file mode 100644
index 0000000..51d9f4f
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-no-network/u-no-network.vue
@@ -0,0 +1,233 @@
+
+ {}">
+
+
+
+ {{tips}}
+
+
+
+
+ 请检查网络,或前往设置
+
+
+
+ 重试
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-notice-bar/u-notice-bar.vue b/uni_modules/vk-uview-ui/components/u-notice-bar/u-notice-bar.vue
new file mode 100644
index 0000000..f5a05a2
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-notice-bar/u-notice-bar.vue
@@ -0,0 +1,273 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-number-box/u-number-box.vue b/uni_modules/vk-uview-ui/components/u-number-box/u-number-box.vue
new file mode 100644
index 0000000..6ceecfc
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-number-box/u-number-box.vue
@@ -0,0 +1,476 @@
+
+
+
+
+ -
+
+
+
+ +
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-number-keyboard/u-number-keyboard.vue b/uni_modules/vk-uview-ui/components/u-number-keyboard/u-number-keyboard.vue
new file mode 100644
index 0000000..f2d90f2
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-number-keyboard/u-number-keyboard.vue
@@ -0,0 +1,170 @@
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/vk-uview-ui/components/u-parse/libs/CssHandler.js b/uni_modules/vk-uview-ui/components/u-parse/libs/CssHandler.js
new file mode 100644
index 0000000..ad3add0
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-parse/libs/CssHandler.js
@@ -0,0 +1,100 @@
+import cfg from './config.js'
+var isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+
+function CssHandler(tagStyle) {
+ var styles = Object.assign(Object.create(null), cfg.userAgentStyles);
+ for (var item in tagStyle)
+ styles[item] = (styles[item] ? styles[item] + ';' : '') + tagStyle[item];
+ this.styles = styles;
+}
+CssHandler.prototype.getStyle = function(data) {
+ this.styles = new parser(data, this.styles).parse();
+}
+CssHandler.prototype.match = function(name, attrs) {
+ var tmp, matched = (tmp = this.styles[name]) ? tmp + ';' : '';
+ if (attrs.class) {
+ var items = attrs.class.split(' ');
+ for (var i = 0, item; item = items[i]; i++)
+ if (tmp = this.styles['.' + item])
+ matched += tmp + ';';
+ }
+ if (tmp = this.styles['#' + attrs.id])
+ matched += tmp + ';';
+ return matched;
+}
+export default CssHandler;
+
+function parser(data, init) {
+ this.data = data;
+ this.floor = 0;
+ this.i = 0;
+ this.list = [];
+ this.res = init;
+ this.state = this.Space;
+}
+parser.prototype.parse = function() {
+ for (var c; c = this.data[this.i]; this.i++)
+ this.state(c);
+ return this.res;
+}
+parser.prototype.section = function() {
+ return this.data.substring(this.start, this.i);
+}
+// 状态机
+parser.prototype.Space = function(c) {
+ if (c == '.' || c == '#' || isLetter(c)) {
+ this.start = this.i;
+ this.state = this.Name;
+ } else if (c == '/' && this.data[this.i + 1] == '*')
+ this.Comment();
+ else if (!cfg.blankChar[c] && c != ';')
+ this.state = this.Ignore;
+}
+parser.prototype.Comment = function() {
+ this.i = this.data.indexOf('*/', this.i) + 1;
+ if (!this.i) this.i = this.data.length;
+ this.state = this.Space;
+}
+parser.prototype.Ignore = function(c) {
+ if (c == '{') this.floor++;
+ else if (c == '}' && !--this.floor) {
+ this.list = [];
+ this.state = this.Space;
+ }
+}
+parser.prototype.Name = function(c) {
+ if (cfg.blankChar[c]) {
+ this.list.push(this.section());
+ this.state = this.NameSpace;
+ } else if (c == '{') {
+ this.list.push(this.section());
+ this.Content();
+ } else if (c == ',') {
+ this.list.push(this.section());
+ this.Comma();
+ } else if (!isLetter(c) && (c < '0' || c > '9') && c != '-' && c != '_')
+ this.state = this.Ignore;
+}
+parser.prototype.NameSpace = function(c) {
+ if (c == '{') this.Content();
+ else if (c == ',') this.Comma();
+ else if (!cfg.blankChar[c]) this.state = this.Ignore;
+}
+parser.prototype.Comma = function() {
+ while (cfg.blankChar[this.data[++this.i]]);
+ if (this.data[this.i] == '{') this.Content();
+ else {
+ this.start = this.i--;
+ this.state = this.Name;
+ }
+}
+parser.prototype.Content = function() {
+ this.start = ++this.i;
+ if ((this.i = this.data.indexOf('}', this.i)) == -1) this.i = this.data.length;
+ var content = this.section();
+ for (var i = 0, item; item = this.list[i++];)
+ if (this.res[item]) this.res[item] += ';' + content;
+ else this.res[item] = content;
+ this.list = [];
+ this.state = this.Space;
+}
diff --git a/uni_modules/vk-uview-ui/components/u-parse/libs/MpHtmlParser.js b/uni_modules/vk-uview-ui/components/u-parse/libs/MpHtmlParser.js
new file mode 100644
index 0000000..a829fab
--- /dev/null
+++ b/uni_modules/vk-uview-ui/components/u-parse/libs/MpHtmlParser.js
@@ -0,0 +1,581 @@
+/**
+ * html 解析器
+ * @tutorial https://github.com/jin-yufeng/Parser
+ * @version 20201029
+ * @author JinYufeng
+ * @listens MIT
+ */
+import cfg from './config.js'
+import CssHandler from './CssHandler.js'
+
+var blankChar = cfg.blankChar
+var windowWidth = uni.getSystemInfoSync().windowWidth;
+var emoji;
+
+function MpHtmlParser(data, options = {}) {
+ this.attrs = {};
+ this.CssHandler = new CssHandler(options.tagStyle, windowWidth);
+ this.data = data;
+ this.domain = options.domain;
+ this.DOM = [];
+ this.i = this.start = this.audioNum = this.imgNum = this.videoNum = 0;
+ options.prot = (this.domain || '').includes('://') ? this.domain.split('://')[0] : 'http';
+ this.options = options;
+ this.state = this.Text;
+ this.STACK = [];
+ // 工具函数
+ this.bubble = () => {
+ for (var i = this.STACK.length, item; item = this.STACK[--i];) {
+ if (cfg.richOnlyTags[item.name]) return false;
+ item.c = 1;
+ }
+ return true;
+ }
+ this.decode = (val, amp) => {
+ var i = -1,
+ j, en;
+ while (1) {
+ if ((i = val.indexOf('&', i + 1)) == -1) break;
+ if ((j = val.indexOf(';', i + 2)) == -1) break;
+ if (val[i + 1] == '#') {
+ en = parseInt((val[i + 2] == 'x' ? '0' : '') + val.substring(i + 2, j));
+ if (!isNaN(en)) val = val.substr(0, i) + String.fromCharCode(en) + val.substr(j + 1);
+ } else {
+ en = val.substring(i + 1, j);
+ if (cfg.entities[en] || en == amp)
+ val = val.substr(0, i) + (cfg.entities[en] || '&') + val.substr(j + 1);
+ }
+ }
+ return val;
+ }
+ this.getUrl = url => {
+ if (url[0] == '/') {
+ if (url[1] == '/') url = this.options.prot + ':' + url;
+ else if (this.domain) url = this.domain + url;
+ } else if (this.domain && url.indexOf('data:') != 0 && !url.includes('://'))
+ url = this.domain + '/' + url;
+ return url;
+ }
+ this.isClose = () => this.data[this.i] == '>' || (this.data[this.i] == '/' && this.data[this.i + 1] == '>');
+ this.section = () => this.data.substring(this.start, this.i);
+ this.parent = () => this.STACK[this.STACK.length - 1];
+ this.siblings = () => this.STACK.length ? this.parent().children : this.DOM;
+}
+MpHtmlParser.prototype.parse = function() {
+ if (emoji) this.data = emoji.parseEmoji(this.data);
+ for (var c; c = this.data[this.i]; this.i++)
+ this.state(c);
+ if (this.state == this.Text) this.setText();
+ while (this.STACK.length) this.popNode(this.STACK.pop());
+ return this.DOM;
+}
+// 设置属性
+MpHtmlParser.prototype.setAttr = function() {
+ var name = this.attrName.toLowerCase(),
+ val = this.attrVal;
+ if (cfg.boolAttrs[name]) this.attrs[name] = 'T';
+ else if (val) {
+ if (name == 'src' || (name == 'data-src' && !this.attrs.src)) this.attrs.src = this.getUrl(this.decode(val, 'amp'));
+ else if (name == 'href' || name == 'style') this.attrs[name] = this.decode(val, 'amp');
+ else if (name.substr(0, 5) != 'data-') this.attrs[name] = val;
+ }
+ this.attrVal = '';
+ while (blankChar[this.data[this.i]]) this.i++;
+ if (this.isClose()) this.setNode();
+ else {
+ this.start = this.i;
+ this.state = this.AttrName;
+ }
+}
+// 设置文本节点
+MpHtmlParser.prototype.setText = function() {
+ var back, text = this.section();
+ if (!text) return;
+ text = (cfg.onText && cfg.onText(text, () => back = true)) || text;
+ if (back) {
+ this.data = this.data.substr(0, this.start) + text + this.data.substr(this.i);
+ let j = this.start + text.length;
+ for (this.i = this.start; this.i < j; this.i++) this.state(this.data[this.i]);
+ return;
+ }
+ if (!this.pre) {
+ // 合并空白符
+ var flag, tmp = [];
+ for (let i = text.length, c; c = text[--i];)
+ if (!blankChar[c]) {
+ tmp.unshift(c);
+ if (!flag) flag = 1;
+ } else {
+ if (tmp[0] != ' ') tmp.unshift(' ');
+ if (c == '\n' && flag == void 0) flag = 0;
+ }
+ if (flag == 0) return;
+ text = tmp.join('');
+ }
+ this.siblings().push({
+ type: 'text',
+ text: this.decode(text)
+ });
+}
+// 设置元素节点
+MpHtmlParser.prototype.setNode = function() {
+ var node = {
+ name: this.tagName.toLowerCase(),
+ attrs: this.attrs
+ },
+ close = cfg.selfClosingTags[node.name];
+ if (this.options.nodes.length) node.type = 'node';
+ this.attrs = {};
+ if (!cfg.ignoreTags[node.name]) {
+ // 处理属性
+ var attrs = node.attrs,
+ style = this.CssHandler.match(node.name, attrs, node) + (attrs.style || ''),
+ styleObj = {};
+ if (attrs.id) {
+ if (this.options.compress & 1) attrs.id = void 0;
+ else if (this.options.useAnchor) this.bubble();
+ }
+ if ((this.options.compress & 2) && attrs.class) attrs.class = void 0;
+ switch (node.name) {
+ case 'a':
+ case 'ad': // #ifdef APP-PLUS
+ case 'iframe':
+ // #endif
+ this.bubble();
+ break;
+ case 'font':
+ if (attrs.color) {
+ styleObj['color'] = attrs.color;
+ attrs.color = void 0;
+ }
+ if (attrs.face) {
+ styleObj['font-family'] = attrs.face;
+ attrs.face = void 0;
+ }
+ if (attrs.size) {
+ var size = parseInt(attrs.size);
+ if (size < 1) size = 1;
+ else if (size > 7) size = 7;
+ var map = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'];
+ styleObj['font-size'] = map[size - 1];
+ attrs.size = void 0;
+ }
+ break;
+ case 'embed':
+ // #ifndef APP-PLUS
+ var src = node.attrs.src || '',
+ type = node.attrs.type || '';
+ if (type.includes('video') || src.includes('.mp4') || src.includes('.3gp') || src.includes('.m3u8'))
+ node.name = 'video';
+ else if (type.includes('audio') || src.includes('.m4a') || src.includes('.wav') || src.includes('.mp3') || src.includes(
+ '.aac'))
+ node.name = 'audio';
+ else break;
+ if (node.attrs.autostart)
+ node.attrs.autoplay = 'T';
+ node.attrs.controls = 'T';
+ // #endif
+ // #ifdef APP-PLUS
+ this.bubble();
+ break;
+ // #endif
+ case 'video':
+ case 'audio':
+ if (!attrs.id) attrs.id = node.name + (++this[`${node.name}Num`]);
+ else this[`${node.name}Num`]++;
+ if (node.name == 'video') {
+ if (this.videoNum > 3)
+ node.lazyLoad = 1;
+ if (attrs.width) {
+ styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px');
+ attrs.width = void 0;
+ }
+ if (attrs.height) {
+ styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px');
+ attrs.height = void 0;
+ }
+ }
+ if (!attrs.controls && !attrs.autoplay) attrs.controls = 'T';
+ attrs.source = [];
+ if (attrs.src) {
+ attrs.source.push(attrs.src);
+ attrs.src = void 0;
+ }
+ this.bubble();
+ break;
+ case 'td':
+ case 'th':
+ if (attrs.colspan || attrs.rowspan)
+ for (var k = this.STACK.length, item; item = this.STACK[--k];)
+ if (item.name == 'table') {
+ item.flag = 1;
+ break;
+ }
+ }
+ if (attrs.align) {
+ if (node.name == 'table') {
+ if (attrs.align == 'center') styleObj['margin-inline-start'] = styleObj['margin-inline-end'] = 'auto';
+ else styleObj['float'] = attrs.align;
+ } else styleObj['text-align'] = attrs.align;
+ attrs.align = void 0;
+ }
+ // 压缩 style
+ var styles = style.split(';');
+ style = '';
+ for (var i = 0, len = styles.length; i < len; i++) {
+ var info = styles[i].split(':');
+ if (info.length < 2) continue;
+ let key = info[0].trim().toLowerCase(),
+ value = info.slice(1).join(':').trim();
+ if (value[0] == '-' || value.includes('safe'))
+ style += `;${key}:${value}`;
+ else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import'))
+ styleObj[key] = value;
+ }
+ if (node.name == 'img') {
+ if (attrs.src && !attrs.ignore) {
+ if (this.bubble())
+ attrs.i = (this.imgNum++).toString();
+ else attrs.ignore = 'T';
+ }
+ if (attrs.ignore) {
+ style += ';-webkit-touch-callout:none';
+ styleObj['max-width'] = '100%';
+ }
+ var width;
+ if (styleObj.width) width = styleObj.width;
+ else if (attrs.width) width = attrs.width.includes('%') ? attrs.width : parseFloat(attrs.width) + 'px';
+ if (width) {
+ styleObj.width = width;
+ attrs.width = '100%';
+ if (parseInt(width) > windowWidth) {
+ styleObj.height = '';
+ if (attrs.height) attrs.height = void 0;
+ }
+ }
+ if (styleObj.height) {
+ attrs.height = styleObj.height;
+ styleObj.height = '';
+ } else if (attrs.height && !attrs.height.includes('%'))
+ attrs.height = parseFloat(attrs.height) + 'px';
+ }
+ for (var key in styleObj) {
+ var value = styleObj[key];
+ if (!value) continue;
+ if (key.includes('flex') || key == 'order' || key == 'self-align') node.c = 1;
+ // 填充链接
+ if (value.includes('url')) {
+ var j = value.indexOf('(');
+ if (j++ != -1) {
+ while (value[j] == '"' || value[j] == "'" || blankChar[value[j]]) j++;
+ value = value.substr(0, j) + this.getUrl(value.substr(j));
+ }
+ }
+ // 转换 rpx
+ else if (value.includes('rpx'))
+ value = value.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * windowWidth / 750 + 'px');
+ else if (key == 'white-space' && value.includes('pre') && !close)
+ this.pre = node.pre = true;
+ style += `;${key}:${value}`;
+ }
+ style = style.substr(1);
+ if (style) attrs.style = style;
+ if (!close) {
+ node.children = [];
+ if (node.name == 'pre' && cfg.highlight) {
+ this.remove(node);
+ this.pre = node.pre = true;
+ }
+ this.siblings().push(node);
+ this.STACK.push(node);
+ } else if (!cfg.filter || cfg.filter(node, this) != false)
+ this.siblings().push(node);
+ } else {
+ if (!close) this.remove(node);
+ else if (node.name == 'source') {
+ var parent = this.parent();
+ if (parent && (parent.name == 'video' || parent.name == 'audio') && node.attrs.src)
+ parent.attrs.source.push(node.attrs.src);
+ } else if (node.name == 'base' && !this.domain) this.domain = node.attrs.href;
+ }
+ if (this.data[this.i] == '/') this.i++;
+ this.start = this.i + 1;
+ this.state = this.Text;
+}
+// 移除标签
+MpHtmlParser.prototype.remove = function(node) {
+ var name = node.name,
+ j = this.i;
+ // 处理 svg
+ var handleSvg = () => {
+ var src = this.data.substring(j, this.i + 1);
+ node.attrs.xmlns = 'http://www.w3.org/2000/svg';
+ for (var key in node.attrs) {
+ if (key == 'viewbox') src = ` viewBox="${node.attrs.viewbox}"` + src;
+ else if (key != 'style') src = ` ${key}="${node.attrs[key]}"` + src;
+ }
+ src = '