diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/app.js b/app.js new file mode 100644 index 0000000..b5d2324 --- /dev/null +++ b/app.js @@ -0,0 +1,143 @@ +var util = require('lib/util.js'); +var timeQueue = require('eaterplanet_ecommerce/utils/timeQueue'); +var mta = require('lib/mta_analysis.js'); +require('eaterplanet_ecommerce/utils//mixins.js'); +require('/lib/SPage.js') + +App({ + onLaunch: async function (options) { + let scene = options.scene || ''; + this.globalData.scene = scene; + console.log('scene:' + scene); + var userInfo = wx.getStorageSync("userInfo"); + this.globalData.userInfo = userInfo; + wx.setStorageSync("isparse_formdata", 0); + var currentCommunity = wx.getStorageSync("community"); + this.globalData.hasDefaultCommunity = !!currentCommunity; + this.globalData.community = currentCommunity; + this.globalData.systemInfo = wx.getSystemInfoSync(); + var model = this.globalData.systemInfo.model; + this.globalData.isIpx = model.indexOf("iPhone X") > -1 || model.indexOf("unknown -1; + this.globalData.timer = new timeQueue.default(); + mta.App.init({ + "appID": "", + "eventID": "", + "autoReport": true, + "statParam": true, + "ignoreParams": ['test_adt'], + "lauchOpts": true, + "statPullDownFresh": true, + "statShareApp": true, + "statReachBottom": true + }); + }, + $mixinP:{ + onLoad(options){ + console.log("options", options) + } + }, + onShow: function () { + if(this.globalData.scene!=1154) this.getUpdate(); + }, + onHide: function () { + }, + + util: util, + userInfo: { + sessionid: null, + }, + globalData: { + systemInfo: {}, + isIpx: false, + userInfo: {}, + canGetGPS: true, + city: {}, + community: {}, + location: {}, + hasDefaultCommunity: true, + historyCommunity: [], + changedCommunity: false, + disUserInfo: {}, + changeCity: "", + timer: 0, + formIds: [], + community_id: '', + placeholdeImg: '', + cartNum: 0, + cartNumStamp: 0, + common_header_backgroundimage: '', + appLoadStatus: 1, // 1 正常 0 未登录 2 未选择社区 + goodsListCarCount: [], + typeCateId: 0, + navBackUrl: '', + isblack: 0, + statusBarHeight: wx.getSystemInfoSync()['statusBarHeight'], + skin: { + color: '#ff5344', + subColor: '#ed7b3a', + lighter: '#fff9f4' + }, + goods_sale_unit: '件', + scene: '', + indexCateId: '', + }, + getUpdate: function(){ + if (wx.canIUse("getUpdateManager")) { + const updateManager = wx.getUpdateManager(); + updateManager.onCheckForUpdate(function (res) { + res.hasUpdate && (updateManager.onUpdateReady(function () { + wx.showModal({ + title: "更新提示", + content: "新版本已经准备好,是否马上重启小程序?", + success: function (t) { + t.confirm && updateManager.applyUpdate(); + } + }); + }), updateManager.onUpdateFailed(function () { + wx.showModal({ + title: "已经有新版本了哟~", + content: "新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~" + }); + })); + }); + } else wx.showModal({ + title: "提示", + content: "当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。" + }); + }, + getConfig: function() { + var token = wx.getStorageSync('token'); + return new Promise((resolve, reject)=>{ + util.request({ + url: 'entry/wxapp/user', + data: { + controller: 'index.get_firstload_msg', + token, + m: 'eaterplanet_ecommerce' + }, + method: 'post', + dataType: 'json', + success: function(res) { + if(res.data.code==0) { + let { new_head_id, default_head_info, isparse_formdata } = res.data; + if(!token) isparse_formdata = 0; + wx.setStorageSync('isparse_formdata', isparse_formdata); + + if(new_head_id>0&&Object.keys(default_head_info).length) { + wx.setStorageSync('community', default_head_info); + } + resolve(res) + } else { + reject() + } + } + }) + }) + }, + setShareConfig: function(){ + wx.showShareMenu({ + menus: ['shareAppMessage', 'shareTimeline'] + }) + }, + siteInfo: require('siteinfo.js') +}); diff --git a/app.json b/app.json new file mode 100644 index 0000000..c252632 --- /dev/null +++ b/app.json @@ -0,0 +1,231 @@ +{ + "pages": [ + "eaterplanet_ecommerce/pages/index/advert", + "eaterplanet_ecommerce/pages/index/index", + "eaterplanet_ecommerce/pages/goods/goodsDetail", + "eaterplanet_ecommerce/pages/order/shopCart", + "eaterplanet_ecommerce/pages/user/me", + "eaterplanet_ecommerce/pages/position/community", + "eaterplanet_ecommerce/pages/position/search", + "eaterplanet_ecommerce/pages/order/index", + "eaterplanet_ecommerce/pages/order/order", + "eaterplanet_ecommerce/pages/order/refunddetail", + "eaterplanet_ecommerce/pages/user/protocol", + "eaterplanet_ecommerce/pages/user/articleProtocol", + "eaterplanet_ecommerce/pages/order/refund", + "eaterplanet_ecommerce/pages/order/evaluate", + "eaterplanet_ecommerce/pages/position/cities", + "eaterplanet_ecommerce/pages/order/placeOrder", + "eaterplanet_ecommerce/pages/goods/buyRecords", + "eaterplanet_ecommerce/pages/goods/comment", + "eaterplanet_ecommerce/pages/supply/recruit", + "eaterplanet_ecommerce/pages/supply/apply", + "eaterplanet_ecommerce/pages/web-view", + "eaterplanet_ecommerce/pages/order/goods_express", + "eaterplanet_ecommerce/pages/order/shareOrderInfo", + "eaterplanet_ecommerce/pages/user/coupon", + "eaterplanet_ecommerce/pages/index/share", + "eaterplanet_ecommerce/pages/type/index", + "eaterplanet_ecommerce/pages/user/rechargeDetails", + "eaterplanet_ecommerce/pages/user/charge", + "eaterplanet_ecommerce/pages/type/search", + "eaterplanet_ecommerce/pages/type/result", + "eaterplanet_ecommerce/pages/goods/industrial", + "eaterplanet_ecommerce/pages/supply/index", + "eaterplanet_ecommerce/pages/supply/home", + "eaterplanet_ecommerce/pages/refund/refundList", + "eaterplanet_ecommerce/pages/type/details", + "eaterplanet_ecommerce/pages/user/rule" + ], + "window": { + "navigationStyle": "custom", + "navigationBarTextStyle": "black", + "navigationBarTitleText": "", + "navigationBarBackgroundColor": "#007FAF", + "backgroundColor": "#fff" + }, + "tabBar": { + "list": [ + { + "pagePath": "eaterplanet_ecommerce/pages/index/index", + "text": "首页" + }, + { + "pagePath": "eaterplanet_ecommerce/pages/type/index", + "text": "分类" + }, + { + "pagePath": "eaterplanet_ecommerce/pages/order/shopCart", + "text": "购物车" + }, + { + "pagePath": "eaterplanet_ecommerce/pages/user/me", + "text": "我的" + } + ], + "color": "#fff", + "selectedColor": "#fff", + "backgroundColor": "#fff", + "borderStyle": "white" + }, + "networkTimeout": { + "request": 20000 + }, + "permission": { + "scope.userLocation": { + "desc": "为了更好的服务您,请授权允许" + } + }, + "subPackages": [ + { + "name": "distributionCenter", + "root": "eaterplanet_ecommerce/distributionCenter", + "pages": [ + "pages/share", + "pages/member", + "pages/memberInfo", + "pages/details", + "pages/me", + "pages/recruit", + "pages/apply", + "pages/excharge", + "pages/exchargeRecord", + "pages/goodsDetails", + "pages/fans" + ] + }, + { + "name": "moduleA", + "root": "eaterplanet_ecommerce/moduleA", + "pages": [ + "special/index", + "special/list", + "pin/goodsDetail", + "pin/share", + "pin/me", + "pin/rule", + "pin/index", + "pin/income", + "pin/excharge", + "pin/exchargeRecord", + "vip/upgrade", + "vip/notice", + "score/signin", + "score/scoreDetails", + "menu/index", + "menu/fav", + "menu/subcate", + "menu/list", + "menu/details", + "seckill/list", + "solitaire/pub", + "solitaire/index", + "solitaire/details", + "video/index", + "video/detail", + "solitaire/me", + "solitaire/groupIndex", + "solitaire/addGood", + "solitaire/groupDetails", + "solitaire/order", + "solitaire/share", + "solitaire/shareDetails", + "groupCenter/index", + "groupCenter/recruit", + "groupCenter/apply", + "groupCenter/communityMembers", + "groupCenter/distributionList", + "groupCenter/distributionInstruct", + "groupCenter/settlementList", + "groupCenter/settlementDetail", + "groupCenter/editInfo", + "groupCenter/groupList", + "groupCenter/groupDetail", + "groupCenter/buyHistory", + "groupCenter/pendingDeliveryOrders", + "groupCenter/wallet", + "groupCenter/cashList", + "groupCenter/detailsList", + "groupCenter/list", + "groupCenter/listDetails", + "groupCenter/memberList", + "groupCenter/setting", + "groupCenter/closure", + "groupCenter/addHexiao", + "groupCenter/bind_member_hexiao", + "groupCenter/goodsManage", + "groupCenter/gruopInfo", + "groupCenter/headlist", + "groupCenter/recommend", + "groupCenter/ranking", + "coupon/getCoupon", + "editUser/index" + ] + }, + { + "name": "moduleB", + "root": "eaterplanet_ecommerce/moduleB", + "pages": [ + "index/index", + "writeoff/index", + "index/auth", + "live/index", + "writeoff/member", + "rider/index", + "rider/order", + "rider/grab", + "supply/index", + "live/replay", + "supply/goodsManage", + "supply/orderManage", + "generalmall/index", + "supply/moneyManage", + "supply/excharge", + "supply/exchargeRecord", + "supply/orderDetails", + "supply/editSku", + "rider/census", + "rider/me", + "rider/excharge", + "rider/exchargeRecord", + "rider/accountRecord", + "writeoff/details", + "supply/changePrice", + "order/share", + "presale/index", + "invite/index", + "invite/reward", + "invite/scoreList", + "invite/record", + "invite/share", + "virtualcard/index", + "virtualcard/exchange", + "manage/index", + "offlineCode/index" + ] + } + ], + "preloadRule": { + "eaterplanet_ecommerce/pages/user/me": { + "network": "all", + "packages": [ + "moduleA", + "distributionCenter", + "moduleB" + ] + } + }, + "sitemapLocation": "sitemap.json", + "usingComponents": { + "i-vip-modal": "/eaterplanet_ecommerce/components/vipModal/index" + }, + "requiredBackgroundModes": [ + "audio" + ], + "usingShopPlugin": true, + "requiredPrivateInfos": [ + "chooseAddress", + "chooseLocation", + "getLocation" + ] +} diff --git a/app.wxss b/app.wxss new file mode 100644 index 0000000..335077e --- /dev/null +++ b/app.wxss @@ -0,0 +1,404 @@ +@import "/icon.wxss"; +@import "/common.wxss"; +page { + background-color: #f6f6f6; + font-size: 28rpx; + font-weight: 400; + color: #333; +} + +.i-load-more { + width: 65%; + font-size: 24rpx; + display: flex; + align-items: center; + justify-content: center; + margin: 60rpx auto; +} + +.i-load-more-loading { + display: inline-block; + margin-right: 24rpx; + vertical-align: middle; + width: 28rpx; + height: 28rpx; + background: 0 0; + border-radius: 50%; + border: 4rpx solid #e9eaec; + border-color: #e9eaec #e9eaec #e9eaec #2d8cf0; + animation: btn-spin 0.6s linear; + animation-iteration-count: infinite; +} + +.i-load-more-tip { + display: inline-block; + vertical-align: middle; + color: #999; +} + +.i-load-more-line { + display: flex; + border-top: 0; +} + +.i-load-more-line .i-load-more-tip { + position: relative; + top: -.1em; + padding: 0 0.55em; +} + +.i-load-more-empty { + width: 8rpx; + height: 8rpx; + border-radius: 50%; + background-color: #e5e5e5; + display: inline-block; + position: relative; + vertical-align: 0; + top: -.16em; +} + +@-webkit-keyframes btn-spin { + 0% { + transform: rotate(0); + } + + 100% { + transform: rotate(360deg); + } +} + +@keyframes btn-spin { + 0% { + transform: rotate(0); + } + + 100% { + transform: rotate(360deg); + } +} + +/**首页规格弹窗begin ***/ +.sku-content { + position: fixed; + bottom: 0px; + z-index: 9999; +} + +.sku-card { + width: 750rpx; + box-sizing: border-box; + border-radius: 30rpx 30rpx 0 0; + background: #fff; + overflow: hidden; + padding-bottom: constant(safe-area-inset-bottom); + +} + +.sku-card .close { + position: absolute; + right: 28rpx; + top: 28rpx; + width: 40rpx; + height: 40rpx; + display: flex; + align-items: center; + justify-content: center; +} + +.sku-card .close image { + width: 26rpx; + height: 26rpx; +} + +.sku-card .sku-header { + display: flex; + align-items: flex-start; + margin: 40rpx; +} + +.sku-card .sku-header .sku-img { + width: 180rpx; + height: 180rpx; + border-radius: 20rpx; + margin-right: 30rpx; + box-shadow: 0 0 15rpx rgba(0,0,0,0.1); + +} + +.sku-card .sku-header .sku-img image { + border: none; +} + +.sku-card .sku-header .sku-desc { + display: flex; + flex-direction: column; +} + +.sku-card .sku-header .sku-desc .sku-title { + width: 390rpx; + min-height: 60rpx; + margin-bottom: 16rpx; + color: #444; + font-weight: bold; + position: relative; +} + +.sku-card .sku-header .sku-desc .sku-title span { + position: absolute; + width: 390rpx; + height: 60rpx; + left: 0; + top: 0; + font-size: 26rpx; + line-height: 31rpx; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + text-overflow: initial; + white-space: normal; +} + +.sku-card .sku-header .sku-price { + display: flex; + align-items: flex-end; + margin-bottom: 12rpx; + font-size: 24rpx; + line-height: 24rpx; +} + +.sku-card .sku-header .sku-price .sale-price { + color: #ff758c; + font-family: DIN; + margin-right: 12rpx; + margin-bottom: -4rpx; +} + +.sku-card .sku-header .sku-price .sale-price span { + font-size: 56rpx; + line-height: 56rpx; + margin-left: 8rpx; + font-weight: bold; +} + +.sku-card .sku-header .sku-price .market-price { + font-family: DIN; + text-decoration: line-through; + color: #999; + margin-right: 30rpx; +} + +.sku-card .sku-header .sku-switch-on { + font-size: 24rpx; + color: #444; +} + +.sku-card .sku-msg { + width: 670rpx; + margin: 0 auto 60rpx; + border-radius: 16rpx; + background: linear-gradient(to right,#fff7f0,#fff4ec); + display: flex; + align-items: flex-start; + padding: 20rpx; + color: #4facfe; + box-sizing: border-box; +} + +.sku-card .sku-msg .tag { + border-radius: 16rpx; + border: 1rpx solid #4facfe; + font-size: 20rpx; + line-height: 28rpx; + font-weight: 500; + padding: 0 8rpx; + margin-right: 8rpx; + color: #4facfe; + white-space: nowrap; + vertical-align: middle; +} + +.sku-card .sku-msg .sku-activity-msg { + color: #ca7e57; + font-size: 24rpx; + line-height: 32rpx; + width: 540rpx; + font-weight: 500; +} + +.sku-card .sku-spec { + width: 670rpx; + margin: 0 auto 40rpx; + display: flex; + align-items: flex-start; +} + +.sku-card .sku-spec .title { + font-size: 26rpx; + line-height: 50rpx; + margin-right: 8rpx; +} + +.sku-card .sku-spec .spec-list { + width: 600rpx; + display: flex; + flex: 1; + flex-wrap: wrap; +} + +.sku-card .sku-spec .spec-list span { + position: relative; + height: 46rpx; + background: #f6f6f6; + border: 2rpx solid #f6f6f6; + text-align: center; + line-height: 46rpx; + font-size: 26rpx; + margin: 0 8rpx 20rpx 0; + color: #666; + border-radius: 46rpx; + padding: 0 30rpx; + display: block; + white-space: nowrap; +} + +.sku-card .sku-spec .spec-list .on { + border-color: #00f2fe; + color: #4facfe; + background: #fff; +} + +.sku-card .sku-spec .spec-list .disabled { + color: #ccc; +} + +.sku-card .sku-num-content { + width: 670rpx; + margin: 0 auto 26rpx; + display: flex; + align-items: center; +} + +.sku-card .sku-num-content .title { + width: 80rpx; + font-size: 26rpx; + line-height: 50rpx; +} + +.sku-card .sku-num-content .msg { + width: 420rpx; + color: #aaa; + font-size: 26rpx; + line-height: 50rpx; + text-align: right; +} + +.sku-card .sku-num-content .even-num { + width: 420rpx; + color: #4facfe; + font-size: 26rpx; + line-height: 50rpx; + white-space: nowrap; + text-align: right; +} + +.sku-card .sku-confirm { + width: 750rpx; + background: linear-gradient(90deg, #e7614d 0%, #e68475 100%); + line-height: 96rpx; + text-align: center; + color: #fff; + font-size: 30rpx; + margin: 0; + padding: 0; + border-radius: 0; + font-weight: bold; + border-radius: 20px 20px 0px 0px; + padding-bottom: calc(env(safe-area-inset-bottom) - 30rpx); +} + +.sku-card button.sku-confirm::after{ + border: 0; +} + +.sku-card button[disabled].sku-confirm{ + background: #f6f6f6; +} + +.i-input-number { + color: #495060; + display: flex; + align-items: center; + position: relative; +} + +.i-input-number view { + width: 48rpx; + height: 48rpx; + display: inline-block; + vertical-align: middle; +} + +.i-input-number view image { + width: 48rpx; + height: 48rpx; +} + +.i-input-number-minus { + border-right: none; + border-radius: 4rpx 0 0 4rpx; +} + +.i-input-number-plus { + border-left: none; + border-radius: 0 4rpx 4rpx 0; +} + +.i-input-number-text { + text-align: center; + height: 48rpx; + width: 66rpx; + font-size: 24rpx; + line-height: 48rpx; + color: #495060; + z-index: 0; +} + +/**首页规格弹出end***/ + +.mask { + width: 100%; + height: 100%; + background: #000; + position: fixed; + left: 0; + top: 0; + z-index: 99; + line-height: 80rpx; + opacity: 0.5; +} + +/* 订单提醒begin */ +.order-notify { + position: fixed; + left: 0; + top: calc(env(safe-area-inset-top) + 200rpx); + z-index: 200; +} + +/* 订单提醒end */ + +image { + will-change: transform; +} + +.bgDisabled { + background: #ccc!important; +} + +/* 安全区域 */ +.safebottom { + padding-bottom: env(safe-area-inset-bottom) !important; + /* padding-bottom: 20rpx!important; */ +} \ No newline at end of file diff --git a/common.wxss b/common.wxss new file mode 100644 index 0000000..3965cb0 --- /dev/null +++ b/common.wxss @@ -0,0 +1,411 @@ +/* flex */ +.i-flex { + display: flex; +} + +.i-flex-wrap { + flex-wrap: wrap; +} + +.i-flex-nowrap { + flex-wrap: nowrap; +} + +.i-flex-col { + display: flex; + flex-direction: column; +} + +.i-flex-item { + flex: 1; +} + +.i-flex-alc { + justify-content: center; + align-items: center; +} + +.i-flex-spb { + justify-content: space-between; + align-items: center; +} + +.i-aic { + align-items: center!important; +} + +.jcontent-c { + justify-content: center; +} + +.jcontent-sb { + justify-content: space-between; +} + +.jcontent-sa { + justify-content: space-around; +} + +.weight { + font-weight: bold; +} + +.text-overflow1 { + overflow: hidden; + text-overflow:ellipsis; + white-space: nowrap; +} + +.text-overflow2 { + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; +} + +.text-center { + text-align: center; +} + +.text-right { + text-align: right; +} + +/* 字体大小 */ +.fsz-16 { + font-size: 16rpx!important; +} + +.fsz-22 { + font-size: 22rpx; +} + +.fsz-24 { + font-size: 24rpx; +} + +.fsz-26 { + font-size: 26rpx; +} + +.fsz-28 { + font-size: 28rpx; +} + +.fsz-30 { + font-size: 30rpx; +} + +.fsz-32 { + font-size: 32rpx; +} + +.fsz-34 { + font-size: 34rpx; +} + +.fsz-36 { + font-size: 36rpx; +} + +.fsz-38 { + font-size: 38rpx; +} + +.fsz-60 { + font-size: 60rpx; +} + +/* 字体颜色 */ +.text-3 { + color: #333!important; +} + +.text-6 { + color: #666; +} + +.text-gray { + color: #999; +} + +.text-white { + color: #fff!important; +} + +.text-dark { + color: #000!important; +} + +.text-sucess { + color: #5cb85c!important; +} + +.text-warning { + color: #f0ad4e!important; +} + +.red { + color: #ff5344; +} + +.bule { + color: #4facfe; +} + +/* 背景 */ +.bg-f { + background-color: #fff; +} + +.bg-blue { + background-color: #4facfe; +} + +.bg-primary { + background-color: #ff5344; +} + +.bg-lighter { + background-color: #f8f8f8; +} + +.bg-ccc { + background: #ccc!important; +} + +.bg-sucess { + background: #5cb85c!important; +} + +.bg-warning { + background: #f0ad4e!important; +} + +/* 边距 */ +.ml5 { + margin-left: 10rpx; +} + +.ml10 { + margin-left: 20rpx; +} + +.mb5 { + margin-bottom: 10rpx; +} + +.mt-auto { + margin-top: auto; +} + +.mt5 { + margin-top: 10rpx; +} + +.mx5 { + margin-left: 10rpx; + margin-right: 10rpx; +} + +.m10 { + margin: 20rpx; +} + +.mt10 { + margin-top: 20rpx; +} + +.my10 { + margin-top: 10rpx; + margin-bottom: 10rpx; +} + +.mx10 { + margin-left: 20rpx; + margin-right: 20rpx; +} + +.mx15 { + margin-left: 30rpx; + margin-right: 30rpx; +} + +.mb10 { + margin-bottom: 20rpx; +} + +.mb20 { + margin-bottom: 40rpx; +} + +.m15 { + margin: 30rpx; +} + +.p5 { + padding: 10rpx; +} + +.p10 { + padding: 20rpx; +} + +.p15 { + padding: 30rpx; +} + +.pt10 { + padding-top: 20rpx; +} + +.pb10 { + padding-bottom: 20rpx!important; +} + +.py10 { + padding-top: 20rpx!important; + padding-bottom: 20rpx!important; +} + +.pb15 { + padding-bottom: 30rpx; +} + +.px15 { + padding-left: 30rpx; + padding-right: 30rpx; +} + +.py15 { + padding-top: 30rpx!important; + padding-bottom: 30rpx!important; +} + +.pb20 { + padding-bottom: 40rpx; +} + +.p30 { + padding: 30rpx; +} + +.ml30 { + margin-left: 30rpx; +} + +.pb100 { + padding-bottom: 100rpx; +} + +.w0 { + width: 0; +} + +.w90p { + width: 90%; +} + +.maxH { + max-height: 75vh; +} + +.rounded-mini { + border-radius: 5rpx; +} + +.rounded { + border-radius: 10rpx; +} + +.border-bottom, +.border-top { + position: relative; +} + +.border-bottom::after { + content: ""; + position: absolute; + left: 0; + bottom: 0; + right: 0; + border-bottom: 1px solid #e5e5e5; + transform-origin: 0 0; + transform: scaleY(0.5); +} + +.border-top::before { + content: ""; + position: absolute; + left: 0; + top: 0; + right: 0; + border-bottom: 1px solid #e5e5e5; + transform-origin: 0 0; + transform: scaleY(0.5); +} + +.btn-hollow { + border: 1rpx solid #e5e5e5; + padding: 12rpx 20rpx; + border-radius: 30rpx; + font-size: 22rpx; + color: #666; + line-height: 1; +} + +.line-through { + text-decoration: line-through; +} + +.line-height { + line-height: 1.5; +} + +/* 定位 */ +.pos-r { + position: relative; +} + +.pos-a { + position: absolute; +} + +.pos-f { + position: fixed; +} + +.avatar { + width: 80rpx; + height: 80rpx; + border-radius: 50%; +} + +.shadow { + box-shadow: 1px 2px 5px #ccc; +} + +.shadow-top { + box-shadow: 0px -3px 5px -2px #ccc; +} + +.avatar-md { + width: 100rpx; + height: 100rpx; + border-radius: 50%; + overflow: hidden; +} + +/* 边距 字体 */ +.u-m-l-5{margin-left:5rpx !important}.u-m-l-10{margin-left:10rpx !important}.u-m-l-15{margin-left:15rpx !important}.u-m-l-20{margin-left:20rpx !important}.u-m-l-25{margin-left:25rpx !important}.u-m-l-30{margin-left:30rpx !important}.u-m-l-35{margin-left:35rpx !important}.u-m-l-40{margin-left:40rpx !important}.u-m-l-45{margin-left:45rpx !important}.u-m-l-50{margin-left:50rpx !important}.u-m-l-55{margin-left:55rpx !important}.u-m-l-60{margin-left:60rpx !important}.u-m-t-5{margin-top:5rpx !important}.u-m-t-10{margin-top:10rpx !important}.u-m-t-15{margin-top:15rpx !important}.u-m-t-20{margin-top:20rpx !important}.u-m-t-25{margin-top:25rpx !important}.u-m-t-30{margin-top:30rpx !important}.u-m-t-35{margin-top:35rpx !important}.u-m-t-40{margin-top:40rpx !important}.u-m-t-45{margin-top:45rpx !important}.u-m-t-50{margin-top:50rpx !important}.u-m-t-55{margin-top:55rpx !important}.u-m-t-60{margin-top:60rpx !important}.u-m-r-5{margin-right:5rpx !important}.u-m-r-10{margin-right:10rpx !important}.u-m-r-15{margin-right:15rpx !important}.u-m-r-20{margin-right:20rpx !important}.u-m-r-25{margin-right:25rpx !important}.u-m-r-30{margin-right:30rpx !important}.u-m-r-35{margin-right:35rpx !important}.u-m-r-40{margin-right:40rpx !important}.u-m-r-45{margin-right:45rpx !important}.u-m-r-50{margin-right:50rpx !important}.u-m-r-55{margin-right:55rpx !important}.u-m-r-60{margin-right:60rpx !important}.u-m-b-5{margin-bottom:5rpx !important}.u-m-b-10{margin-bottom:10rpx !important}.u-m-b-15{margin-bottom:15rpx !important}.u-m-b-20{margin-bottom:20rpx !important}.u-m-b-25{margin-bottom:25rpx !important}.u-m-b-30{margin-bottom:30rpx !important}.u-m-b-35{margin-bottom:35rpx !important}.u-m-b-40{margin-bottom:40rpx !important}.u-m-b-45{margin-bottom:45rpx !important}.u-m-b-50{margin-bottom:50rpx !important}.u-m-b-55{margin-bottom:55rpx !important}.u-m-b-60{margin-bottom:60rpx !important}.u-p-l-5{padding-left:5rpx !important}.u-p-l-10{padding-left:10rpx !important}.u-p-l-15{padding-left:15rpx !important}.u-p-l-20{padding-left:20rpx !important}.u-p-l-25{padding-left:25rpx !important}.u-p-l-30{padding-left:30rpx !important}.u-p-l-35{padding-left:35rpx !important}.u-p-l-40{padding-left:40rpx !important}.u-p-l-45{padding-left:45rpx !important}.u-p-l-50{padding-left:50rpx !important}.u-p-l-55{padding-left:55rpx !important}.u-p-l-60{padding-left:60rpx !important}.u-p-t-5{padding-top:5rpx !important}.u-p-t-10{padding-top:10rpx !important}.u-p-t-15{padding-top:15rpx !important}.u-p-t-20{padding-top:20rpx !important}.u-p-t-25{padding-top:25rpx !important}.u-p-t-30{padding-top:30rpx !important}.u-p-t-35{padding-top:35rpx !important}.u-p-t-40{padding-top:40rpx !important}.u-p-t-45{padding-top:45rpx !important}.u-p-t-50{padding-top:50rpx !important}.u-p-t-55{padding-top:55rpx !important}.u-p-t-60{padding-top:60rpx !important}.u-p-r-5{padding-right:5rpx !important}.u-p-r-10{padding-right:10rpx !important}.u-p-r-15{padding-right:15rpx !important}.u-p-r-20{padding-right:20rpx !important}.u-p-r-25{padding-right:25rpx !important}.u-p-r-30{padding-right:30rpx !important}.u-p-r-35{padding-right:35rpx !important}.u-p-r-40{padding-right:40rpx !important}.u-p-r-45{padding-right:45rpx !important}.u-p-r-50{padding-right:50rpx !important}.u-p-r-55{padding-right:55rpx !important}.u-p-r-60{padding-right:60rpx !important}.u-p-b-5{padding-bottom:5rpx !important}.u-p-b-10{padding-bottom:10rpx !important}.u-p-b-15{padding-bottom:15rpx !important}.u-p-b-20{padding-bottom:20rpx !important}.u-p-b-25{padding-bottom:25rpx !important}.u-p-b-30{padding-bottom:30rpx !important}.u-p-b-35{padding-bottom:35rpx !important}.u-p-b-40{padding-bottom:40rpx !important}.u-p-b-45{padding-bottom:45rpx !important}.u-p-b-50{padding-bottom:50rpx !important}.u-p-b-55{padding-bottom:55rpx !important}.u-p-b-60{padding-bottom:60rpx !important}.u-m-5{margin:5rpx !important}.u-m-10{margin:10rpx !important}.u-m-15{margin:15rpx !important}.u-m-20{margin:20rpx !important}.u-m-25{margin:25rpx !important}.u-m-30{margin:30rpx !important}.u-m-35{margin:35rpx !important}.u-m-40{margin:40rpx !important}.u-p-5{padding:5rpx !important}.u-p-10{padding:10rpx !important}.u-p-15{padding:15rpx !important}.u-p-20{padding:20rpx !important}.u-p-25{padding:25rpx !important}.u-p-30{padding:30rpx !important}.u-p-35{padding:35rpx !important}.u-p-40{padding:40rpx !important}.u-font-12{font-size:12rpx !important}.u-font-14{font-size:14rpx !important}.u-font-16{font-size:16rpx !important}.u-font-18{font-size:18rpx !important}.u-font-20{font-size:20rpx !important}.u-font-22{font-size:22rpx !important}.u-font-24{font-size:24rpx !important}.u-font-26{font-size:26rpx !important}.u-font-28{font-size:28rpx !important}.u-font-30{font-size:30rpx !important}.u-font-32{font-size:32rpx !important}.u-font-34{font-size:34rpx !important}.u-font-36{font-size:36rpx !important}.u-font-38{font-size:38rpx !important}.u-font-40{font-size:40rpx !important} +/* 边框 */ +.u-border-bottom, +.u-border-left, +.u-border-right, +.u-border-top, +.u-border-top-bottom{position:relative}.u-border-bottom:after, +.u-border-left:after, +.u-border-right:after, +.u-border-top-bottom:after, +.u-border-top:after, +.u-border:after{content:" ";position:absolute;left:0;top:0;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:0 0;transform-origin:0 0;width:199.8%;height:199.7%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #e4e7ed;z-index:2}.u-border-top:after{border-top-width:1px}.u-border-left:after{border-left-width:1px}.u-border-right:after{border-right-width:1px}.u-border-bottom:after{border-bottom-width:1px}.u-border-top-bottom:after{border-width:1px 0}.u-border:after{border-width:1px} \ No newline at end of file diff --git a/icon.wxss b/icon.wxss new file mode 100644 index 0000000..6f46e0d --- /dev/null +++ b/icon.wxss @@ -0,0 +1,394 @@ +@font-face { + font-family: 'iconfont'; /* Project id 1377061 */ + src: url('data:application/octet-stream;base64,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') format('woff2'), + url('data:application/font-woff;base64,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') format('woff'), + url('//at.alicdn.com/t/font_1377061_61msjf6mslj.ttf?t=1623144740367') format('truetype'); +} + +@font-face { + font-family: 'DIN'; + src: url('data:font/woff2;charset=utf-8;base64,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') format('woff2'), + url('data:font/woff;charset=utf-8;base64,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') format('woff'); + font-weight: 500; + font-style: normal; +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-time:before { + content: "\e669"; +} + +.icon-calendar:before { + content: "\e62f"; +} + +.icon-daifahuo:before { + content: "\e663"; +} + +.icon-tuihuotubiao-01:before { + content: "\e64d"; +} + +.icon-peisongzhong:before { + content: "\e75e"; +} + +.icon-huodaofukuan:before { + content: "\e632"; +} + +.icon-pintuan:before { + content: "\e635"; +} + +.icon-rules:before { + content: "\e734"; +} + +.icon-luxian:before { + content: "\e627"; +} + +.icon-zhuye1:before { + content: "\e654"; +} + +.icon-fenxiang1:before { + content: "\e62d"; +} + +.icon-fenxiang3:before { + content: "\e62e"; +} + +.icon-gouwudai:before { + content: "\e6d8"; +} + +.icon-fanhui:before { + content: "\e624"; +} + +.icon-more:before { + content: "\e626"; +} + +.icon-off-stock:before { + content: "\e621"; +} + +.icon-add:before { + content: "\e694"; +} + +.icon-edit-stock:before { + content: "\e622"; +} + +.icon-sceen:before { + content: "\e645"; +} + +.icon-bianji:before { + content: "\e658"; +} + +.icon-goods-manage:before { + content: "\e618"; +} + +.icon-money-manage:before { + content: "\e619"; +} + +.icon-order-manage:before { + content: "\e620"; +} + +.icon-refund-manage:before { + content: "\e668"; +} + +.icon-qu:before { + content: "\e67d"; +} + +.icon-song:before { + content: "\e67e"; +} + +.icon-ditu1:before { + content: "\e610"; +} + +.icon-selected:before { + content: "\e7a0"; +} + +.icon-jian:before { + content: "\e666"; +} + +.icon-jia:before { + content: "\e617"; +} + +.icon-laba:before { + content: "\e616"; +} + +.icon-live:before { + content: "\e8ce"; +} + +.icon-jielongguanli:before { + content: "\e628"; +} + +.icon-icon_shoufukuanhexiaoguanli:before { + content: "\e874"; +} + +.icon-notice:before { + content: "\e60d"; +} + +.icon-good:before { + content: "\e753"; +} + +.icon-good-fill:before { + content: "\e780"; +} + +.icon-pengyouquan1:before { + content: "\e60e"; +} + +.icon-fenxiang2:before { + content: "\e623"; +} + +.icon-zhankai:before { + content: "\e60a"; +} + +.icon-fabu:before { + content: "\e9b1"; +} + +.icon-shuru:before { + content: "\e60b"; +} + +.icon-fanhuidingbu:before { + content: "\e657"; +} + +.icon-goTop:before { + content: "\e6de"; +} + +.icon-icon-test1:before { + content: "\e608"; +} + +.icon-gengduo:before { + content: "\e607"; +} + +.icon-tubiaozhizuomoban:before { + content: "\e606"; +} + +.icon-xinaixin:before { + content: "\e612"; +} + +.icon-gouwuche:before { + content: "\e604"; +} + +.icon-shicai:before { + content: "\e677"; +} + +.icon-shoucang:before { + content: "\e8e0"; +} + +.icon-fenlei_:before { + content: "\e605"; +} + +.icon-wanchenggouxuan2:before { + content: "\e63e"; +} + +.icon-gou1:before { + content: "\e650"; +} + +.icon-qiandao:before { + content: "\e609"; +} + +.icon-huiyuan:before { + content: "\e603"; +} + +.icon-pintuanzhong:before { + content: "\e615"; +} + +.icon-pintuanchenggong:before { + content: "\e613"; +} + +.icon-pintuanshibai:before { + content: "\e614"; +} + +.icon-wenhao:before { + content: "\e6d7"; +} + +.icon-gou:before { + content: "\e611"; +} + +.icon-jiaru:before { + content: "\e62c"; +} + +.icon-huangguan:before { + content: "\e629"; +} + +.icon-erweima1:before { + content: "\e61f"; +} + +.icon-weixinzhifu:before { + content: "\e62a"; +} + +.icon-guanbi:before { + content: "\e601"; +} + +.icon-youjiantou:before { + content: "\e61e"; +} + +.icon-xia:before { + content: "\e60f"; +} + +.icon-shang:before { + content: "\e74c"; +} + +.icon-erweima:before { + content: "\e61a"; +} + +.icon-weizhi-tianchong:before { + content: "\e653"; +} + +.icon-sousuo:before { + content: "\e68f"; +} + +.icon-pengyouquan:before { + content: "\e61b"; +} + +.icon-shouye:before { + content: "\e67a"; +} + +.icon-xiangceshanchutubiao:before { + content: "\e600"; +} + +.icon-balance:before { + content: "\e696"; +} + +.icon-weixin1:before { + content: "\e63c"; +} + +.icon-sousuo1:before { + content: "\e665"; +} + +.icon-fenxiang:before { + content: "\e667"; +} + +.icon-ziyuan:before { + content: "\e62b"; +} + +.icon-weixin2:before { + content: "\e637"; +} + +.icon-bofang:before { + content: "\e60c"; +} + +.icon-rili:before { + content: "\e6b6"; +} + +.icon-shuoming:before { + content: "\e75d"; +} + +.icon-kefu:before { + content: "\e6a7"; +} + +.icon-zhaopian:before { + content: "\e66b"; +} + +.icon-xiatiao:before { + content: "\e625"; +} + +.icon-shanchu1:before { + content: "\e649"; +} + +.icon-wsdzb_zzgzt_dwgl_zbjfgl:before { + content: "\e602"; +} + +.icon-edit:before { + content: "\e61c"; +} + +.icon-shuaxin:before { + content: "\e70e"; +} + +.icon-question:before { + content: "\e675"; +} + +.icon-xiangce:before { + content: "\e61d"; +} diff --git a/lib/SEvent.js b/lib/SEvent.js new file mode 100644 index 0000000..c9c6927 --- /dev/null +++ b/lib/SEvent.js @@ -0,0 +1,91 @@ +class SEvent { + constructor(eventName, isGetEvent) { + if (!isGetEvent) { + throw 'SEventError:get SEvent instance from SEvent.getEvent!' + } + this.handlers = [] + SEvent.events[eventName] = this + } + + static getEvent(eventName) { + SEvent.events = SEvent.events || {}; + const keys = Object.keys(SEvent.events) + for (const key of keys) { + if (key === eventName) { + return SEvent.events[key] + } + + } + return new SEvent(eventName, true) + } + + static removeEvent(eventName) { + const keys = Object.keys(SEvent.events) + for (const key of keys) { + if (key === eventName) { + SEvent.events[key].handlers = null + delete SEvent.events[key] + } + } + } + + static off(listenerId){ + for(const key of Object.keys(SEvent.events)){ + for(let i=0; i { + originHandler(args) + this.off(handler) + } + this.on(handler) + } + + emit(args) { + if (!(this.handlers && this.handlers.length)) return + let l = this.handlers.length + let i = 0 + while(i < this.handlers.length){ + this.handlers[i++].handler(...arguments) + // 防止删除某些once事件的handler导致length改变 + if (this.handlers.length == l - 1) { + i-- + l-- + } + } + } + + off(handler) { + if (!(this.handlers && this.handlers.length)) return + for (let i = 0; i < this.handlers.length; i++) { + if (this.handlers[i].handler === handler) { + this.handlers.splice(i, 1) + break + } + } + } +} +SEvent.listenerId = 1 + +module.exports = SEvent + + diff --git a/lib/SPage.js b/lib/SPage.js new file mode 100644 index 0000000..7b20c62 --- /dev/null +++ b/lib/SPage.js @@ -0,0 +1,345 @@ +// 引入事件模块 https://github.com/GravityC/SPage +const SEvent = require('SEvent.js') +wx.$event = { + on(eventName, handler) { + return SEvent.getEvent(eventName).on(handler) + }, + once(eventName, handler) { + SEvent.getEvent(eventName).once(handler) + }, + emit(eventName) { + const args = Array.from(arguments).slice(1) + SEvent.getEvent(eventName).emit(...args) + }, + off(nameOrId, handler) { + if(handler && typeof (handler) === 'function'){ + SEvent.getEvent(nameOrId).off(handler) + }else{ + SEvent.off(nameOrId) + } + }, + remove(eventName) { + SEvent.removeEvent(eventName) + } +} + +// 引入request模块 +const SRequest = require('SRequest.js') +const $http = new SRequest() +wx.$http = $http +wx.$request = $http.request.bind($http) +wx.$get = $http.get.bind($http) +wx.$post = $http.post.bind($http) +wx.$put = $http.put.bind($http) +wx.$delete = $http.delete.bind($http) + + +/* ----------------------------------------------------------------------------- */ +wx.$pages = {} +// 获取当前页面实例 +wx.$getCurPage = function() { + return getCurrentPages()[getCurrentPages().length - 1] +} + +// 获取当前页面实例对应的页面名 +wx.$getCurPageName = function() { + return wx.$getCurPage().$name +} + +// $place与$take,$take调用完即删除引用 +let channel = {} +wx.$place = function(id, value) { + channel[id] = value +} + +wx.$take = function(id) { + const v = channel[id] + channel[id] = null + return v +} + +/** + * 封装wx.navigateTo + * @url {string} - 跳转路径 + * @query {object} - 携带参数 + */ +wx.$route = function(url, query) { + const page = getPage(url) + query = query || {} + query.from = wx.$getCurPageName() // Page || Component + // 若page已加载可调用onNavigate方法 + if (page && page.onNavigate) { + page.onNavigate(query) + } + url = url + '?' + parseQuery(query) + wx.navigateTo({ + url + }) +} + +// -----------------------------以下是工具函数---------------------- + +//装饰器 +//@afterOrigin {Boolean} - true:装饰函数在原函数之后触发 +const decorator = function(originFn, decorateFn, afterOrigin) { + const origin = originFn + originFn = function(args) { + if (afterOrigin) { + if (origin) origin.call(this, args) + decorateFn.call(this, args) + } else { + decorateFn.call(this, args) + if (origin) origin.call(this, args) + } + } + return originFn +} + +// 解析query对象成string +const parseQuery = function(query) { + return Object.keys(query).map(k => `${k}=${query[k]}`).join('&') +} + +// 从url中得到pageName +const getPageName = function(url) { + url = url.includes('?') ? url.split('?')[0] : url + const arr = url.split('/') + return arr[arr.length - 1] +} + +/** + * @str - pageName或者url + */ +const getPage = function(str) { + const name = str.includes('/') ? getPageName(str) : str + return wx.$pages[name] +} + +// 判断是否是空对象 +const isEmpty = function(obj) { + return !Object.keys(obj).length +} + +/** + * 扩展computed计算属性 + */ +const extendComputed = function(option) { + let page + // 为$setData方法响应computed + option.$setData = function(obj) { + this.setData(obj) + page = this // 绑定page实例 + const needUpdate = calcComputed() // 将需要改变的computed属性添加到接下来要setData的对象中 + if (!isEmpty(needUpdate)) { + this.setData(needUpdate) + } + } + + const computed = option.computed || {} + const computedKeys = Object.keys(computed) + let computedCache = {} + + // 计算需更改的计算属性 + const calcComputed = function(isInit) { + const needUpdate = {} + const that = isInit ? option : page + for (const key of computedKeys) { + const value = computed[key].call(that) + if (value !== computedCache[key]) needUpdate[key] = computedCache[key] = value + if (isInit) option.data[key] = needUpdate[key] // 初始化操作 + } + return needUpdate + } + + // 页面unload时清空computedCache + option.onUnload = decorator(option.onUnload, function() { + computedCache = {} + }) + + calcComputed(true); +} + +/** + * 为所有Page和Component扩展方法 + */ +const extendFunctions = function(option) { + option.$route = wx.$route + option.$place = wx.$place + option.$take = wx.$take + // 封装wx.request + option.$request = wx.$request + option.$get = wx.$get + option.$post = wx.$post + option.$put = wx.$put + option.$delete = wx.$delete + // 事件机制 + option.$on = function(eventName, handler){ + this.$listeners = this.$listeners || [] + this.$listeners.push(wx.$event.on(eventName, handler)) + } + option.$once = wx.$event.once + option.$emit = wx.$event.emit + option.$off = wx.$event.off + option.$remove = wx.$event.remove +} + +/** + * -------------扩展App------------------- + */ +let initPageObject +let initCompObject +const extendApp = function() { + const originApp = App + App = function(option) { + if (option.$mixinP) { + initPageObject = option.$mixinP + } + + if (option.$mixinC) { + initCompObject = option.$mixinC + } + + originApp(option) + } +} + +/** + * -------------扩展Page---------------- + */ +const extendPage = function() { + const originPage = Page + Page = function(option) { + // 混合app.$mixinP + if (initPageObject) { + const hooks = ['onLoad', 'onShow', 'onReady', 'onHide', 'onUnload', 'onPullDownRefresh', 'onReachBottom', 'onShareAppMessage', 'onPageScroll', 'onResize', 'onTabItemTap'] + for (const k in initPageObject) { + if (hooks.includes(k)) { + option[k] = decorator(option[k], initPageObject[k]) + } else if (k === 'data') { + option.data = Object.assign({}, initPageObject.data, option.data) + } else if (!option.hasOwnProperty(k)) { + option[k] = initPageObject[k] + } + } + } + + // 若定义了$name, 则添加到wx.$pages中 + if (option.$name) { + wx.$pages[option.$name] = option + } else { + option.$name = 'unKnow' //此处强行给$name赋值,为了后续区分是Page还是Component + } + + // 添加$status属性 + option.$status = { + isFirstShow: true + } + // 是否已执行过onNavigate函数 + option.$$isNavigated = false + + // 扩展computed属性 + extendComputed(option) + // 扩展方法 + extendFunctions(option) + + // 装饰onNavigate + option.onNavigate = decorator(option.onNavigate, function(query) { + option.$$isNavigated = true + }) + + // 装饰onLoad + option.onLoad = decorator(option.onLoad, function(query) { + // 若页面有onNavigate方法但还没运行,则运行onNavigate方法 + if (option.onNavigate && !option.$$isNavigated) { + option.onNavigate(query) + } + }) + + // 装饰onShow + option.onShow = decorator(option.onShow, function() { + this.$status.isFirstShow = false + }, true) + + // 隐藏页面时隐藏标题栏加载动画(坑爹的微信官方bug) + option.onHide = decorator(option.onHide, function() { + wx.hideNavigationBarLoading() + }) + + // 装饰onUnload + option.onUnload = decorator(option.onUnload, function(){ + // 卸载本页面的监听器 + if (this.$listeners && this.$listeners.length) { + for (const id of this.$listeners) { + wx.$event.off(id) + } + } + }) + + //原生Page构造 + originPage(option) + } +} + +/** + * --------------------------------------------扩展Component + */ +const extendComponent = function() { + const originComponent = Component + Component = function(option) { + option.methods = option.methods || {} + // 混合app.$mixinC + if (initCompObject) { + const mixinObj = ['properties', 'data', 'observers', 'methods', 'options'] + for (const k in initCompObject) { + if (k === 'lifetimes' || k === 'pageLifetimes') { + if (!option[k]) { + option[k] = initCompObject[k] + } else { + for (const h in initCompObject[k]) { + option[k][h] = decorator(option[k][h], initCompObject[k][h]) + } + } + } else if (mixinObj.includes(k)) { + option[k] = Object.assign({}, initCompObject[k], option[k]) + } else if (!option.hasOwnProperty(k)) { + option[k] = initCompObject[k] + } + } + } + // 扩展computed属性 + extendComputed(option) + // 扩展方法 + extendFunctions(option.methods) + + option.lifetimes = option.lifetimes || {} + // 装饰detached + option.lifetimes.detached = decorator(option.lifetimes.detached, function () { + // 卸载本组件的监听器 + if (this.$listeners && this.$listeners.length) { + for (const id of this.$listeners) { + wx.$event.off(id) + } + } + }) + + // 获取当前页面实例 + option.methods.$getCurPage = wx.$getCurPage + + // 获取当前页面实例对应的页面名 + option.methods.$getCurPageName = wx.$getCurPageName + + // 重新定义$setData,便于扩展其他功能 + const originData = option.$setData + option.methods.$setData = function(obj) { + return originData.call(this, obj) + } + //原生Component构造 + originComponent(option) + } +} + +module.exports = (function() { + extendApp() + extendPage() + extendComponent() +}()) \ No newline at end of file diff --git a/lib/SRequest.js b/lib/SRequest.js new file mode 100644 index 0000000..ef06f01 --- /dev/null +++ b/lib/SRequest.js @@ -0,0 +1,124 @@ +class Interceptor { + handlerId = 1 + + constructor() { + this.id = Interceptor.id++ + this.handlers = [] + } + + use(success, fail) { + this.handlers.push({ + id: this.handlerId, + success, + fail + }) + return this.handlerId++ + } + + eject(handlerId) { + for (let i = 0; i < this.handlers.length; i++) { + if (this.handlers[i].id === handlerId) { + return this.handlers.splice(i, 1) + } + } + } + + go(config, isSuccess) { + if(!isSuccess){ + return this.handlers[0].fail(config) + }else{ + for (const v of this.handlers) { + config = v.success(config) + } + return config + } + } +} +Interceptor.id = 1 + +function isHttpSuccess(status){ + return status >= 200 && status < 300 || status === 304 +} + +class SRequest { + config = { + baseUrl:'', + dataType: 'json', + responseType: 'text', + header: {}, + } + + constructor(config) { + this.config = Object.assign(this.config, config) + this.interceptors = { + request: new Interceptor(), + response: new Interceptor() + } + } + + request(config) { + config = config ? Object.assign({}, this.config, config) : this.config + config = this.interceptReq(config, true) + + let { url, method, data, header, dataType, responseType } = config + if (!url.startsWith('https://')) { + url = config.baseUrl + url + } + return new Promise((resolve, reject) => { + wx.request({ + url, + data, + header: header || this.header, + method, + dataType, + responseType, + success: res => { + if(isHttpSuccess(res.statusCode)){ + res = this.interceptRes(res, true) + resolve(res.data) + }else{ + res = this.interceptRes(res, false) + reject(res) + } + }, + fail: res => { + res = this.interceptRes(res, false) + reject(res) + }, + }) + }) + } + // 遍历请求拦截器 + interceptReq(config, isSuccess) { + return this.interceptors.request.go(config, isSuccess) + } + + // 遍历响应拦截器 + interceptRes(response, isSuccess) { + return this.interceptors.response.go(response, isSuccess) + } + + get(url, config) { + const options = { url, method: 'GET' } + Object.assign(options, config || null) + return this.request(options) + } + + post(url, data, config) { + const options = { url, method: 'POST' } + Object.assign(options, data ? { data } : null, config || null) + return this.request(options) + } + put(url, data, config) { + const options = { url, method: 'PUT' } + Object.assign(options, data ? { data } : null, config || null) + return this.request(options) + } + delete(url, config) { + const options = { url, method: 'DELETE' } + Object.assign(options, config || null) + return this.request(options) + } +} + +module.exports = SRequest \ No newline at end of file diff --git a/lib/base64.js b/lib/base64.js new file mode 100644 index 0000000..a2d9411 --- /dev/null +++ b/lib/base64.js @@ -0,0 +1,93 @@ +function base64_encode(str) { + var c1, c2, c3; + var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var i = 0, len = str.length, string = ''; + + while (i < len) { + c1 = str.charCodeAt(i++) & 0xff; + if (i == len) { + string += base64EncodeChars.charAt(c1 >> 2); + string += base64EncodeChars.charAt((c1 & 0x3) << 4); + string += "=="; + break; + } + c2 = str.charCodeAt(i++); + if (i == len) { + string += base64EncodeChars.charAt(c1 >> 2); + string += base64EncodeChars.charAt(((c1 & 0x3) << 4) + | ((c2 & 0xF0) >> 4)); + string += base64EncodeChars.charAt((c2 & 0xF) << 2); + string += "="; + break; + } + c3 = str.charCodeAt(i++); + string += base64EncodeChars.charAt(c1 >> 2); + string += base64EncodeChars.charAt(((c1 & 0x3) << 4) + | ((c2 & 0xF0) >> 4)); + string += base64EncodeChars.charAt(((c2 & 0xF) << 2) + | ((c3 & 0xC0) >> 6)); + string += base64EncodeChars.charAt(c3 & 0x3F) + } + return string +} + +function base64_decode(str) { + var c1, c2, c3, c4; + var base64DecodeChars = new Array(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, + -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, + -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1); + var i = 0, len = str.length, string = ''; + + while (i < len) { + do { + c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff] + } while (i < len && c1 == -1); + + if (c1 == -1) + break; + + do { + c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff] + } while (i < len && c2 == -1); + + if (c2 == -1) + break; + + string += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4)); + + do { + c3 = str.charCodeAt(i++) & 0xff; + if (c3 == 61) + return string; + + c3 = base64DecodeChars[c3] + } while (i < len && c3 == -1); + + if (c3 == -1) + break; + + string += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2)); + + do { + c4 = str.charCodeAt(i++) & 0xff; + if (c4 == 61) + return string; + c4 = base64DecodeChars[c4] + } while (i < len && c4 == -1); + + if (c4 == -1) + break; + + string += String.fromCharCode(((c3 & 0x03) << 6) | c4) + } + return string; +} +module.exports = { + 'base64_encode': base64_encode, + 'base64_decode': base64_decode +}; \ No newline at end of file diff --git a/lib/md5.js b/lib/md5.js new file mode 100644 index 0000000..83108ff --- /dev/null +++ b/lib/md5.js @@ -0,0 +1,273 @@ +/* + * JavaScript MD5 + * https://github.com/blueimp/JavaScript-MD5 + * + * Copyright 2011, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + * + * Based on + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for more info. + */ + +/*global unescape, define, module */ + +; (function ($) { + 'use strict' + + /* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ + function safe_add(x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF) + var msw = (x >> 16) + (y >> 16) + (lsw >> 16) + return (msw << 16) | (lsw & 0xFFFF) + } + + /* + * Bitwise rotate a 32-bit number to the left. + */ + function bit_rol(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)) + } + + /* + * These functions implement the four basic operations the algorithm uses. + */ + function md5_cmn(q, a, b, x, s, t) { + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b) + } + function md5_ff(a, b, c, d, x, s, t) { + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t) + } + function md5_gg(a, b, c, d, x, s, t) { + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t) + } + function md5_hh(a, b, c, d, x, s, t) { + return md5_cmn(b ^ c ^ d, a, b, x, s, t) + } + function md5_ii(a, b, c, d, x, s, t) { + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t) + } + + /* + * Calculate the MD5 of an array of little-endian words, and a bit length. + */ + function binl_md5(x, len) { + /* append padding */ + x[len >> 5] |= 0x80 << (len % 32) + x[(((len + 64) >>> 9) << 4) + 14] = len + + var i + var olda + var oldb + var oldc + var oldd + var a = 1732584193 + var b = -271733879 + var c = -1732584194 + var d = 271733878 + + for (i = 0; i < x.length; i += 16) { + olda = a + oldb = b + oldc = c + oldd = d + + a = md5_ff(a, b, c, d, x[i], 7, -680876936) + d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586) + c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819) + b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330) + a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897) + d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426) + c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341) + b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983) + a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416) + d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417) + c = md5_ff(c, d, a, b, x[i + 10], 17, -42063) + b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162) + a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682) + d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101) + c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290) + b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329) + + a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510) + d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632) + c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713) + b = md5_gg(b, c, d, a, x[i], 20, -373897302) + a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691) + d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083) + c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335) + b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848) + a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438) + d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690) + c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961) + b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501) + a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467) + d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784) + c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473) + b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734) + + a = md5_hh(a, b, c, d, x[i + 5], 4, -378558) + d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463) + c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562) + b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556) + a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060) + d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353) + c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632) + b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640) + a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174) + d = md5_hh(d, a, b, c, x[i], 11, -358537222) + c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979) + b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189) + a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487) + d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835) + c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520) + b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651) + + a = md5_ii(a, b, c, d, x[i], 6, -198630844) + d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415) + c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905) + b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055) + a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571) + d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606) + c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523) + b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799) + a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359) + d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744) + c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380) + b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649) + a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070) + d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379) + c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259) + b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551) + + a = safe_add(a, olda) + b = safe_add(b, oldb) + c = safe_add(c, oldc) + d = safe_add(d, oldd) + } + return [a, b, c, d] + } + + /* + * Convert an array of little-endian words to a string + */ + function binl2rstr(input) { + var i + var output = '' + var length32 = input.length * 32 + for (i = 0; i < length32; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF) + } + return output + } + + /* + * Convert a raw string to an array of little-endian words + * Characters >255 have their high-byte silently ignored. + */ + function rstr2binl(input) { + var i + var output = [] + output[(input.length >> 2) - 1] = undefined + for (i = 0; i < output.length; i += 1) { + output[i] = 0 + } + var length8 = input.length * 8 + for (i = 0; i < length8; i += 8) { + output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32) + } + return output + } + + /* + * Calculate the MD5 of a raw string + */ + function rstr_md5(s) { + return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)) + } + + /* + * Calculate the HMAC-MD5, of a key and some data (raw strings) + */ + function rstr_hmac_md5(key, data) { + var i + var bkey = rstr2binl(key) + var ipad = [] + var opad = [] + var hash + ipad[15] = opad[15] = undefined + if (bkey.length > 16) { + bkey = binl_md5(bkey, key.length * 8) + } + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636 + opad[i] = bkey[i] ^ 0x5C5C5C5C + } + hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8) + return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)) + } + + /* + * Convert a raw string to a hex string + */ + function rstr2hex(input) { + var hex_tab = '0123456789abcdef' + var output = '' + var x + var i + for (i = 0; i < input.length; i += 1) { + x = input.charCodeAt(i) + output += hex_tab.charAt((x >>> 4) & 0x0F) + + hex_tab.charAt(x & 0x0F) + } + return output + } + + /* + * Encode a string as utf-8 + */ + function str2rstr_utf8(input) { + return unescape(encodeURIComponent(input)) + } + + /* + * Take string arguments and return either raw or hex encoded strings + */ + function raw_md5(s) { + return rstr_md5(str2rstr_utf8(s)) + } + function hex_md5(s) { + return rstr2hex(raw_md5(s)) + } + function raw_hmac_md5(k, d) { + return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)) + } + function hex_hmac_md5(k, d) { + return rstr2hex(raw_hmac_md5(k, d)) + } + + function md5(string, key, raw) { + if (!key) { + if (!raw) { + return hex_md5(string) + } + return raw_md5(string) + } + if (!raw) { + return hex_hmac_md5(key, string) + } + return raw_hmac_md5(key, string) + } + + module.exports = md5; +}(this)) diff --git a/lib/mta_analysis.js b/lib/mta_analysis.js new file mode 100644 index 0000000..01d59c7 --- /dev/null +++ b/lib/mta_analysis.js @@ -0,0 +1,14 @@ +var MTA_CONFIG={app_id:"",event_id:"",api_base:"https://pingtas.qq.com/pingd",prefix:"_mta_",version:"1.3.10",stat_share_app:!1,stat_pull_down_fresh:!1,stat_reach_bottom:!1,stat_param:!0};function getNetworkType(a){wx.getNetworkType({success:function(b){a(b.networkType)}})} +function getSystemInfo(){var a=wx.getSystemInfoSync();return{adt:encodeURIComponent(a.model),scl:a.pixelRatio,scr:a.windowWidth+"x"+a.windowHeight,lg:a.language,fl:a.version,jv:encodeURIComponent(a.system),tz:encodeURIComponent(a.platform)}}function getUID(){try{return wx.getStorageSync(MTA_CONFIG.prefix+"auid")}catch(a){}}function setUID(){try{var a=getRandom();wx.setStorageSync(MTA_CONFIG.prefix+"auid",a);return a}catch(b){}} +function getSID(){try{return wx.getStorageSync(MTA_CONFIG.prefix+"ssid")}catch(a){}}function setSID(){try{var a="s"+getRandom();wx.setStorageSync(MTA_CONFIG.prefix+"ssid",a);return a}catch(b){}}function getRandom(a){for(var b=[0,1,2,3,4,5,6,7,8,9],c=10;1c;c++)d=10*d+b[c];return(a||"")+(d+""+ +new Date)} +function getPagePath(){try{var a=getCurrentPages(),b="/";0MTA_CONFIG.ignore_params.length)return a;var b={},c;for(c in a)0<=MTA_CONFIG.ignore_params.indexOf(c)||(b[c]=a[c]);return b} +function initOnload(){var a=Page;Page=function(b){var c=b.onLoad;b.onLoad=function(a){c&&c.call(this,a);MTA.Data.lastPageQuery=MTA.Data.pageQuery;MTA.Data.pageQuery=a;MTA.Data.lastPageUrl=MTA.Data.pageUrl;MTA.Data.pageUrl=getPagePath();MTA.Data.show=!1;MTA.Page.init()};a(b)}} +var MTA={App:{init:function(a){"appID"in a&&(MTA_CONFIG.app_id=a.appID);"eventID"in a&&(MTA_CONFIG.event_id=a.eventID);"statShareApp"in a&&(MTA_CONFIG.stat_share_app=a.statShareApp);"statPullDownFresh"in a&&(MTA_CONFIG.stat_pull_down_fresh=a.statPullDownFresh);"statReachBottom"in a&&(MTA_CONFIG.stat_reach_bottom=a.statReachBottom);"ignoreParams"in a&&(MTA_CONFIG.ignore_params=a.ignoreParams);"statParam"in a&&(MTA_CONFIG.stat_param=a.statParam);setSID();try{"lauchOpts"in a&&(MTA.Data.lanchInfo=a.lauchOpts, + MTA.Data.lanchInfo.landing=1)}catch(b){}"autoReport"in a&&a.autoReport&&initOnload()}},Page:{init:function(){var a=getCurrentPages()[getCurrentPages().length-1];a.onShow&&!function(){var b=a.onShow;a.onShow=function(){if(!0===MTA.Data.show){var a=MTA.Data.lastPageQuery;MTA.Data.lastPageQuery=MTA.Data.pageQuery;MTA.Data.pageQuery=a;MTA.Data.lastPageUrl=MTA.Data.pageUrl;MTA.Data.pageUrl=getPagePath()}MTA.Data.show=!0;MTA.Page.stat();b.apply(this,arguments)}}();MTA_CONFIG.stat_pull_down_fresh&&a.onPullDownRefresh&& +!function(){var b=a.onPullDownRefresh;a.onPullDownRefresh=function(){MTA.Event.stat(MTA_CONFIG.prefix+"pulldownfresh",{url:a.__route__});b.apply(this,arguments)}}();MTA_CONFIG.stat_reach_bottom&&a.onReachBottom&&!function(){var b=a.onReachBottom;a.onReachBottom=function(){MTA.Event.stat(MTA_CONFIG.prefix+"reachbottom",{url:a.__route__});b.apply(this,arguments)}}();MTA_CONFIG.stat_share_app&&a.onShareAppMessage&&!function(){var b=a.onShareAppMessage;a.onShareAppMessage=function(){MTA.Event.stat(MTA_CONFIG.prefix+ + "shareapp",{url:a.__route__});return b.apply(this,arguments)}}()},multiStat:function(a,b){if(1==b)MTA.Page.stat(a),!0;else{var c=getCurrentPages()[getCurrentPages().length-1];c.onShow&&!function(){var b=c.onShow;c.onShow=function(){MTA.Page.stat(a);b.call(this,arguments)}}()}},stat:function(a){if(""!=MTA_CONFIG.app_id){var b=[],c=getExtentInfo();a&&(c.r2=a);a=[getMainInfo(),c,getBasicInfo()];if(MTA.Data.lanchInfo){a.push({ht:MTA.Data.lanchInfo.scene});MTA.Data.pageQuery&&MTA.Data.pageQuery._mta_ref_id&& +a.push({rarg:MTA.Data.pageQuery._mta_ref_id});try{1==MTA.Data.lanchInfo.landing&&(c.ext+=";lp=1",MTA.Data.lanchInfo.landing=0)}catch(e){}}a.push({rdm:"/",rurl:0>=MTA.Data.lastPageUrl.length?MTA.Data.pageUrl+getQuery(MTA.Data.lastPageQuery):encodeURIComponent(MTA.Data.lastPageUrl+getQuery(MTA.Data.lastPageQuery))});a.push({rand:+new Date});c=0;for(var d=a.length;c= 0 && length <= MAX_ARRAY_INDEX; + }; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles raw objects in addition to array-likes. Treats all + // sparse array-likes as if they were dense. + _.each = _.forEach = function (obj, iteratee, context) { + iteratee = optimizeCb(iteratee, context); + var i, length; + if (isArrayLike(obj)) { + for (i = 0, length = obj.length; i < length; i++) { + iteratee(obj[i], i, obj); + } + } else { + var keys = _.keys(obj); + for (i = 0, length = keys.length; i < length; i++) { + iteratee(obj[keys[i]], keys[i], obj); + } + } + return obj; + }; + + // Return the results of applying the iteratee to each element. + _.map = _.collect = function (obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + results = Array(length); + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + results[index] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + + // Create a reducing function iterating left or right. + function createReduce(dir) { + // Optimized iterator function as using arguments.length + // in the main function will deoptimize the, see #1991. + function iterator(obj, iteratee, memo, keys, index, length) { + for (; index >= 0 && index < length; index += dir) { + var currentKey = keys ? keys[index] : index; + memo = iteratee(memo, obj[currentKey], currentKey, obj); + } + return memo; + } + + return function (obj, iteratee, memo, context) { + iteratee = optimizeCb(iteratee, context, 4); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + index = dir > 0 ? 0 : length - 1; + // Determine the initial value if none is provided. + if (arguments.length < 3) { + memo = obj[keys ? keys[index] : index]; + index += dir; + } + return iterator(obj, iteratee, memo, keys, index, length); + }; + } + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. + _.reduce = _.foldl = _.inject = createReduce(1); + + // The right-associative version of reduce, also known as `foldr`. + _.reduceRight = _.foldr = createReduce(-1); + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function (obj, predicate, context) { + var key; + if (isArrayLike(obj)) { + key = _.findIndex(obj, predicate, context); + } else { + key = _.findKey(obj, predicate, context); + } + if (key !== void 0 && key !== -1) return obj[key]; + }; + + // Return all the elements that pass a truth test. + // Aliased as `select`. + _.filter = _.select = function (obj, predicate, context) { + var results = []; + predicate = cb(predicate, context); + _.each(obj, function (value, index, list) { + if (predicate(value, index, list)) results.push(value); + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function (obj, predicate, context) { + return _.filter(obj, _.negate(cb(predicate)), context); + }; + + // Determine whether all of the elements match a truth test. + // Aliased as `all`. + _.every = _.all = function (obj, predicate, context) { + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + if (!predicate(obj[currentKey], currentKey, obj)) return false; + } + return true; + }; + + // Determine if at least one element in the object matches a truth test. + // Aliased as `any`. + _.some = _.any = function (obj, predicate, context) { + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + if (predicate(obj[currentKey], currentKey, obj)) return true; + } + return false; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `includes` and `include`. + _.contains = _.includes = _.include = function (obj, target, fromIndex) { + if (!isArrayLike(obj)) obj = _.values(obj); + return _.indexOf(obj, target, typeof fromIndex == 'number' && fromIndex) >= 0; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function (obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function (value) { + var func = isFunc ? method : value[method]; + return func == null ? func : func.apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function (obj, key) { + return _.map(obj, _.property(key)); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function (obj, attrs) { + return _.filter(obj, _.matcher(attrs)); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function (obj, attrs) { + return _.find(obj, _.matcher(attrs)); + }; + + // Return the maximum element (or element-based computation). + _.max = function (obj, iteratee, context) { + var result = -Infinity, lastComputed = -Infinity, + value, computed; + if (iteratee == null && obj != null) { + obj = isArrayLike(obj) ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value > result) { + result = value; + } + } + } else { + iteratee = cb(iteratee, context); + _.each(obj, function (value, index, list) { + computed = iteratee(value, index, list); + if (computed > lastComputed || computed === -Infinity && result === -Infinity) { + result = value; + lastComputed = computed; + } + }); + } + return result; + }; + + // Return the minimum element (or element-based computation). + _.min = function (obj, iteratee, context) { + var result = Infinity, lastComputed = Infinity, + value, computed; + if (iteratee == null && obj != null) { + obj = isArrayLike(obj) ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value < result) { + result = value; + } + } + } else { + iteratee = cb(iteratee, context); + _.each(obj, function (value, index, list) { + computed = iteratee(value, index, list); + if (computed < lastComputed || computed === Infinity && result === Infinity) { + result = value; + lastComputed = computed; + } + }); + } + return result; + }; + + // Shuffle a collection, using the modern version of the + // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher鈥揧ates_shuffle). + _.shuffle = function (obj) { + var set = isArrayLike(obj) ? obj : _.values(obj); + var length = set.length; + var shuffled = Array(length); + for (var index = 0, rand; index < length; index++) { + rand = _.random(0, index); + if (rand !== index) shuffled[index] = shuffled[rand]; + shuffled[rand] = set[index]; + } + return shuffled; + }; + + // Sample **n** random values from a collection. + // If **n** is not specified, returns a single random element. + // The internal `guard` argument allows it to work with `map`. + _.sample = function (obj, n, guard) { + if (n == null || guard) { + if (!isArrayLike(obj)) obj = _.values(obj); + return obj[_.random(obj.length - 1)]; + } + return _.shuffle(obj).slice(0, Math.max(0, n)); + }; + + // Sort the object's values by a criterion produced by an iteratee. + _.sortBy = function (obj, iteratee, context) { + iteratee = cb(iteratee, context); + return _.pluck(_.map(obj, function (value, index, list) { + return { + value: value, + index: index, + criteria: iteratee(value, index, list) + }; + }).sort(function (left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function (behavior) { + return function (obj, iteratee, context) { + var result = {}; + iteratee = cb(iteratee, context); + _.each(obj, function (value, index) { + var key = iteratee(value, index, obj); + behavior(result, value, key); + }); + return result; + }; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = group(function (result, value, key) { + if (_.has(result, key)) result[key].push(value); else result[key] = [value]; + }); + + // Indexes the object's values by a criterion, similar to `groupBy`, but for + // when you know that your index values will be unique. + _.indexBy = group(function (result, value, key) { + result[key] = value; + }); + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = group(function (result, value, key) { + if (_.has(result, key)) result[key]++; else result[key] = 1; + }); + + // Safely create a real, live array from anything iterable. + _.toArray = function (obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (isArrayLike(obj)) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function (obj) { + if (obj == null) return 0; + return isArrayLike(obj) ? obj.length : _.keys(obj).length; + }; + + // Split a collection into two arrays: one whose elements all satisfy the given + // predicate, and one whose elements all do not satisfy the predicate. + _.partition = function (obj, predicate, context) { + predicate = cb(predicate, context); + var pass = [], fail = []; + _.each(obj, function (value, key, obj) { + (predicate(value, key, obj) ? pass : fail).push(value); + }); + return [pass, fail]; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function (array, n, guard) { + if (array == null) return void 0; + if (n == null || guard) return array[0]; + return _.initial(array, array.length - n); + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. + _.initial = function (array, n, guard) { + return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. + _.last = function (array, n, guard) { + if (array == null) return void 0; + if (n == null || guard) return array[array.length - 1]; + return _.rest(array, Math.max(0, array.length - n)); + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. + _.rest = _.tail = _.drop = function (array, n, guard) { + return slice.call(array, n == null || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function (array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function (input, shallow, strict, startIndex) { + var output = [], idx = 0; + for (var i = startIndex || 0, length = input && input.length; i < length; i++) { + var value = input[i]; + if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { + //flatten current level of array or arguments object + if (!shallow) value = flatten(value, shallow, strict); + var j = 0, len = value.length; + output.length += len; + while (j < len) { + output[idx++] = value[j++]; + } + } else if (!strict) { + output[idx++] = value; + } + } + return output; + }; + + // Flatten out an array, either recursively (by default), or just one level. + _.flatten = function (array, shallow) { + return flatten(array, shallow, false); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function (array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function (array, isSorted, iteratee, context) { + if (array == null) return []; + if (!_.isBoolean(isSorted)) { + context = iteratee; + iteratee = isSorted; + isSorted = false; + } + if (iteratee != null) iteratee = cb(iteratee, context); + var result = []; + var seen = []; + for (var i = 0, length = array.length; i < length; i++) { + var value = array[i], + computed = iteratee ? iteratee(value, i, array) : value; + if (isSorted) { + if (!i || seen !== computed) result.push(value); + seen = computed; + } else if (iteratee) { + if (!_.contains(seen, computed)) { + seen.push(computed); + result.push(value); + } + } else if (!_.contains(result, value)) { + result.push(value); + } + } + return result; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function () { + return _.uniq(flatten(arguments, true, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function (array) { + if (array == null) return []; + var result = []; + var argsLength = arguments.length; + for (var i = 0, length = array.length; i < length; i++) { + var item = array[i]; + if (_.contains(result, item)) continue; + for (var j = 1; j < argsLength; j++) { + if (!_.contains(arguments[j], item)) break; + } + if (j === argsLength) result.push(item); + } + return result; + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function (array) { + var rest = flatten(arguments, true, true, 1); + return _.filter(array, function (value) { + return !_.contains(rest, value); + }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function () { + return _.unzip(arguments); + }; + + // Complement of _.zip. Unzip accepts an array of arrays and groups + // each array's elements on shared indices + _.unzip = function (array) { + var length = array && _.max(array, 'length').length || 0; + var result = Array(length); + + for (var index = 0; index < length; index++) { + result[index] = _.pluck(array, index); + } + return result; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function (list, values) { + var result = {}; + for (var i = 0, length = list && list.length; i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // Return the position of the first occurrence of an item in an array, + // or -1 if the item is not included in the array. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function (array, item, isSorted) { + var i = 0, length = array && array.length; + if (typeof isSorted == 'number') { + i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted; + } else if (isSorted && length) { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + if (item !== item) { + return _.findIndex(slice.call(array, i), _.isNaN); + } + for (; i < length; i++) if (array[i] === item) return i; + return -1; + }; + + _.lastIndexOf = function (array, item, from) { + var idx = array ? array.length : 0; + if (typeof from == 'number') { + idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1); + } + if (item !== item) { + return _.findLastIndex(slice.call(array, 0, idx), _.isNaN); + } + while (--idx >= 0) if (array[idx] === item) return idx; + return -1; + }; + + // Generator function to create the findIndex and findLastIndex functions + function createIndexFinder(dir) { + return function (array, predicate, context) { + predicate = cb(predicate, context); + var length = array != null && array.length; + var index = dir > 0 ? 0 : length - 1; + for (; index >= 0 && index < length; index += dir) { + if (predicate(array[index], index, array)) return index; + } + return -1; + }; + } + + // Returns the first index on an array-like that passes a predicate test + _.findIndex = createIndexFinder(1); + + _.findLastIndex = createIndexFinder(-1); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function (array, obj, iteratee, context) { + iteratee = cb(iteratee, context, 1); + var value = iteratee(obj); + var low = 0, high = array.length; + while (low < high) { + var mid = Math.floor((low + high) / 2); + if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; + } + return low; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function (start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = step || 1; + + var length = Math.max(Math.ceil((stop - start) / step), 0); + var range = Array(length); + + for (var idx = 0; idx < length; idx++ , start += step) { + range[idx] = start; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Determines whether to execute a function as a constructor + // or a normal function with the provided arguments + var executeBound = function (sourceFunc, boundFunc, context, callingContext, args) { + if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); + var self = baseCreate(sourceFunc.prototype); + var result = sourceFunc.apply(self, args); + if (_.isObject(result)) return result; + return self; + }; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function (func, context) { + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); + var args = slice.call(arguments, 2); + var bound = function () { + return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); + }; + return bound; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. _ acts + // as a placeholder, allowing any combination of arguments to be pre-filled. + _.partial = function (func) { + var boundArgs = slice.call(arguments, 1); + var bound = function () { + var position = 0, length = boundArgs.length; + var args = Array(length); + for (var i = 0; i < length; i++) { + args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i]; + } + while (position < arguments.length) args.push(arguments[position++]); + return executeBound(func, bound, this, this, args); + }; + return bound; + }; + + // Bind a number of an object's methods to that object. Remaining arguments + // are the method names to be bound. Useful for ensuring that all callbacks + // defined on an object belong to it. + _.bindAll = function (obj) { + var i, length = arguments.length, key; + if (length <= 1) throw new Error('bindAll must be passed function names'); + for (i = 1; i < length; i++) { + key = arguments[i]; + obj[key] = _.bind(obj[key], obj); + } + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function (func, hasher) { + var memoize = function (key) { + var cache = memoize.cache; + var address = '' + (hasher ? hasher.apply(this, arguments) : key); + if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); + return cache[address]; + }; + memoize.cache = {}; + return memoize; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function (func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function () { + return func.apply(null, args); + }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = _.partial(_.delay, _, 1); + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function (func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + if (!options) options = {}; + var later = function () { + previous = options.leading === false ? 0 : _.now(); + timeout = null; + result = func.apply(context, args); + if (!timeout) context = args = null; + }; + return function () { + var now = _.now(); + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0 || remaining > wait) { + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + previous = now; + result = func.apply(context, args); + if (!timeout) context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function (func, wait, immediate) { + var timeout, args, context, timestamp, result; + + var later = function () { + var last = _.now() - timestamp; + + if (last < wait && last >= 0) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + if (!timeout) context = args = null; + } + } + }; + + return function () { + context = this; + args = arguments; + timestamp = _.now(); + var callNow = immediate && !timeout; + if (!timeout) timeout = setTimeout(later, wait); + if (callNow) { + result = func.apply(context, args); + context = args = null; + } + + return result; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function (func, wrapper) { + return _.partial(wrapper, func); + }; + + // Returns a negated version of the passed-in predicate. + _.negate = function (predicate) { + return function () { + return !predicate.apply(this, arguments); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function () { + var args = arguments; + var start = args.length - 1; + return function () { + var i = start; + var result = args[start].apply(this, arguments); + while (i--) result = args[i].call(this, result); + return result; + }; + }; + + // Returns a function that will only be executed on and after the Nth call. + _.after = function (times, func) { + return function () { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Returns a function that will only be executed up to (but not including) the Nth call. + _.before = function (times, func) { + var memo; + return function () { + if (--times > 0) { + memo = func.apply(this, arguments); + } + if (times <= 1) func = null; + return memo; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = _.partial(_.before, 2); + + // Object Functions + // ---------------- + + // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. + var hasEnumBug = !{ toString: null }.propertyIsEnumerable('toString'); + var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', + 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; + + function collectNonEnumProps(obj, keys) { + var nonEnumIdx = nonEnumerableProps.length; + var constructor = obj.constructor; + var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto; + + // Constructor is a special case. + var prop = 'constructor'; + if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); + + while (nonEnumIdx--) { + prop = nonEnumerableProps[nonEnumIdx]; + if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { + keys.push(prop); + } + } + } + + // Retrieve the names of an object's own properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = function (obj) { + if (!_.isObject(obj)) return []; + if (nativeKeys) return nativeKeys(obj); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; + + // Retrieve all the property names of an object. + _.allKeys = function (obj) { + if (!_.isObject(obj)) return []; + var keys = []; + for (var key in obj) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function (obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; + } + return values; + }; + + // Returns the results of applying the iteratee to each element of the object + // In contrast to _.map it returns an object + _.mapObject = function (obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = _.keys(obj), + length = keys.length, + results = {}, + currentKey; + for (var index = 0; index < length; index++) { + currentKey = keys[index]; + results[currentKey] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function (obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function (obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; + } + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function (obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = createAssigner(_.allKeys); + + // Assigns a given object with all the own properties in the passed-in object(s) + // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) + _.extendOwn = _.assign = createAssigner(_.keys); + + // Returns the first key on an object that passes a predicate test + _.findKey = function (obj, predicate, context) { + predicate = cb(predicate, context); + var keys = _.keys(obj), key; + for (var i = 0, length = keys.length; i < length; i++) { + key = keys[i]; + if (predicate(obj[key], key, obj)) return key; + } + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function (object, oiteratee, context) { + var result = {}, obj = object, iteratee, keys; + if (obj == null) return result; + if (_.isFunction(oiteratee)) { + keys = _.allKeys(obj); + iteratee = optimizeCb(oiteratee, context); + } else { + keys = flatten(arguments, false, false, 1); + iteratee = function (value, key, obj) { return key in obj; }; + obj = Object(obj); + } + for (var i = 0, length = keys.length; i < length; i++) { + var key = keys[i]; + var value = obj[key]; + if (iteratee(value, key, obj)) result[key] = value; + } + return result; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function (obj, iteratee, context) { + if (_.isFunction(iteratee)) { + iteratee = _.negate(iteratee); + } else { + var keys = _.map(flatten(arguments, false, false, 1), String); + iteratee = function (value, key) { + return !_.contains(keys, key); + }; + } + return _.pick(obj, iteratee, context); + }; + + // Fill in a given object with default properties. + _.defaults = createAssigner(_.allKeys, true); + + // Creates an object that inherits from the given prototype object. + // If additional properties are provided then they will be added to the + // created object. + _.create = function (prototype, props) { + var result = baseCreate(prototype); + if (props) _.extendOwn(result, props); + return result; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function (obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function (obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Returns whether an object has a given set of `key:value` pairs. + _.isMatch = function (object, attrs) { + var keys = _.keys(attrs), length = keys.length; + if (object == null) return !length; + var obj = Object(object); + for (var i = 0; i < length; i++) { + var key = keys[i]; + if (attrs[key] !== obj[key] || !(key in obj)) return false; + } + return true; + }; + + + // Internal recursive comparison function for `isEqual`. + var eq = function (a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a === 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className !== toString.call(b)) return false; + switch (className) { + // Strings, numbers, regular expressions, dates, and booleans are compared by value. + case '[object RegExp]': + // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return '' + a === '' + b; + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. + // Object(NaN) is equivalent to NaN + if (+a !== +a) return +b !== +b; + // An `egal` comparison is performed for other numeric values. + return +a === 0 ? 1 / +a === 1 / b : +a === +b; + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a === +b; + } + + var areArrays = className === '[object Array]'; + if (!areArrays) { + if (typeof a != 'object' || typeof b != 'object') return false; + + // Objects with different constructors are not equivalent, but `Object`s or `Array`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && + _.isFunction(bCtor) && bCtor instanceof bCtor) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + } + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + + // Initializing stack of traversed objects. + // It's done here since we only need them for objects and arrays comparison. + aStack = aStack || []; + bStack = bStack || []; + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] === a) return bStack[length] === b; + } + + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + + // Recursively compare objects and arrays. + if (areArrays) { + // Compare array lengths to determine if a deep comparison is necessary. + length = a.length; + if (length !== b.length) return false; + // Deep compare the contents, ignoring non-numeric properties. + while (length--) { + if (!eq(a[length], b[length], aStack, bStack)) return false; + } + } else { + // Deep compare objects. + var keys = _.keys(a), key; + length = keys.length; + // Ensure that both objects contain the same number of properties before comparing deep equality. + if (_.keys(b).length !== length) return false; + while (length--) { + // Deep compare each member + key = keys[length]; + if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return true; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function (a, b) { + return eq(a, b); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function (obj) { + if (obj == null) return true; + if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; + return _.keys(obj).length === 0; + }; + + // Is a given value a DOM element? + _.isElement = function (obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function (obj) { + return toString.call(obj) === '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function (obj) { + var type = typeof obj; + return type === 'function' || type === 'object' && !!obj; + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. + _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function (name) { + _['is' + name] = function (obj) { + return toString.call(obj) === '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE < 9), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function (obj) { + return _.has(obj, 'callee'); + }; + } + + // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, + // IE 11 (#1621), and in Safari 8 (#1929). + if (typeof /./ != 'function' && typeof Int8Array != 'object') { + _.isFunction = function (obj) { + return typeof obj == 'function' || false; + }; + } + + // Is a given object a finite number? + _.isFinite = function (obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function (obj) { + return _.isNumber(obj) && obj !== +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function (obj) { + return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function (obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function (obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function (obj, key) { + return obj != null && hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function () { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iteratees. + _.identity = function (value) { + return value; + }; + + // Predicate-generating functions. Often useful outside of Underscore. + _.constant = function (value) { + return function () { + return value; + }; + }; + + _.noop = function () { }; + + _.property = function (key) { + return function (obj) { + return obj == null ? void 0 : obj[key]; + }; + }; + + // Generates a function for a given object that returns a given property. + _.propertyOf = function (obj) { + return obj == null ? function () { } : function (key) { + return obj[key]; + }; + }; + + // Returns a predicate for checking whether an object has a given set of + // `key:value` pairs. + _.matcher = _.matches = function (attrs) { + attrs = _.extendOwn({}, attrs); + return function (obj) { + return _.isMatch(obj, attrs); + }; + }; + + // Run a function **n** times. + _.times = function (n, iteratee, context) { + var accum = Array(Math.max(0, n)); + iteratee = optimizeCb(iteratee, context, 1); + for (var i = 0; i < n; i++) accum[i] = iteratee(i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function (min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // A (possibly faster) way to get the current timestamp as an integer. + _.now = Date.now || function () { + return new Date().getTime(); + }; + + // List of HTML entities for escaping. + var escapeMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`' + }; + var unescapeMap = _.invert(escapeMap); + + // Functions for escaping and unescaping strings to/from HTML interpolation. + var createEscaper = function (map) { + var escaper = function (match) { + return map[match]; + }; + // Regexes for identifying a key that needs to be escaped + var source = '(?:' + _.keys(map).join('|') + ')'; + var testRegexp = RegExp(source); + var replaceRegexp = RegExp(source, 'g'); + return function (string) { + string = string == null ? '' : '' + string; + return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; + }; + }; + _.escape = createEscaper(escapeMap); + _.unescape = createEscaper(unescapeMap); + + // If the value of the named `property` is a function then invoke it with the + // `object` as context; otherwise, return it. + _.result = function (object, property, fallback) { + var value = object == null ? void 0 : object[property]; + if (value === void 0) { + value = fallback; + } + return _.isFunction(value) ? value.call(object) : value; + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function (prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate: /<%([\s\S]+?)%>/g, + interpolate: /<%=([\s\S]+?)%>/g, + escape: /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\u2028|\u2029/g; + + var escapeChar = function (match) { + return '\\' + escapes[match]; + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + // NB: `oldSettings` only exists for backwards compatibility. + _.template = function (text, settings, oldSettings) { + if (!settings && oldSettings) settings = oldSettings; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function (match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset).replace(escaper, escapeChar); + index = offset + match.length; + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } else if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } else if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + + // Adobe VMs need the match returned to produce the correct offest. + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + 'return __p;\n'; + + try { + var render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + var template = function (data) { + return render.call(this, data, _); + }; + + // Provide the compiled source as a convenience for precompilation. + var argument = settings.variable || 'obj'; + template.source = 'function(' + argument + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function. Start chaining a wrapped Underscore object. + _.chain = function (obj) { + var instance = _(obj); + instance._chain = true; + return instance; + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function (instance, obj) { + return instance._chain ? _(obj).chain() : obj; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function (obj) { + _.each(_.functions(obj), function (name) { + var func = _[name] = obj[name]; + _.prototype[name] = function () { + var args = [this._wrapped]; + push.apply(args, arguments); + return result(this, func.apply(_, args)); + }; + }); + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function (name) { + var method = ArrayProto[name]; + _.prototype[name] = function () { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; + return result(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + _.each(['concat', 'join', 'slice'], function (name) { + var method = ArrayProto[name]; + _.prototype[name] = function () { + return result(this, method.apply(this._wrapped, arguments)); + }; + }); + + // Extracts the result from a wrapped and chained object. + _.prototype.value = function () { + return this._wrapped; + }; + + // Provide unwrapping proxy for some methods used in engine operations + // such as arithmetic and JSON stringification. + _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; + + _.prototype.toString = function () { + return '' + this._wrapped; + }; + + // AMD registration happens at the end for compatibility with AMD loaders + // that may not enforce next-turn semantics on modules. Even though general + // practice for AMD registration is to be anonymous, underscore registers + // as a named module because, like jQuery, it is a base library that is + // popular enough to be bundled in a third party lib, but not be part of + // an AMD load request. Those cases could generate an error when an + // anonymous define() is called outside of a loader request. + // if (typeof define === 'function' && define.amd) { + // define('underscore', [], function() { + // return _; + // }); + // } +}.call(this)); diff --git a/lib/util.js b/lib/util.js new file mode 100644 index 0000000..65be5b6 --- /dev/null +++ b/lib/util.js @@ -0,0 +1,883 @@ +import { + base64_encode, + base64_decode +} from 'base64'; +import md5 from 'md5'; + +var siteInfo = require('../siteinfo.js') + +var util = {}; +var app = getApp() || {siteInfo: siteInfo}; + +util.base64_encode = function(str) { + return base64_encode(str) +}; + +util.base64_decode = function(str) { + return base64_decode(str) +}; + +util.md5 = function(str) { + return md5(str) +}; + +/** + 构造微擎地址, + @params action 微擎系统中的controller, action, do,格式为 'wxapp/home/navs' + @params querystring 格式为 {参数名1 : 值1, 参数名2 : 值2} +*/ +util.url = function(action, querystring) { + var url = app.siteInfo.siteroot + '?i=' + app.siteInfo.uniacid + '&t=' + app.siteInfo.multiid + '&v=' + app.siteInfo.version + '&from=wxapp&'; + + if (action) { + action = action.split('/'); + if (action[0]) { + url += 'c=' + action[0] + '&'; + } + if (action[1]) { + url += 'a=' + action[1] + '&'; + } + if (action[2]) { + url += 'do=' + action[2] + '&'; + } + } + + if (querystring && typeof querystring === 'object') { + for (let param in querystring) { + if (param && querystring.hasOwnProperty(param) && querystring[param]) { + url += param + '=' + querystring[param] + '&'; + } + } + } + return url; +} + +function getQuery(url) { + var theRequest = []; + if (url.indexOf("?") != -1) { + var str = url.split('?')[1]; + var strs = str.split("&"); + for (var i = 0; i < strs.length; i++) { + if (strs[i].split("=")[0] && unescape(strs[i].split("=")[1])) { + theRequest[i] = { + 'name': strs[i].split("=")[0], + 'value': unescape(strs[i].split("=")[1]) + } + } + } + } + return theRequest; +} +/* + * 获取链接某个参数 + * url 链接地址 + * name 参数名称 + */ +function getUrlParam(url, name) { + var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象 + var r = url.split('?')[1].match(reg); //匹配目标参数 + if (r != null) return unescape(r[2]); + return null; //返回参数值 +} +/** + * 获取签名 将链接地址的所有参数按字母排序后拼接加上token进行md5 + * url 链接地址 + * date 参数{参数名1 : 值1, 参数名2 : 值2} * + * token 签名token 非必须 + */ +function getSign(url, data, token) { + var _ = require('underscore.js'); + var md5 = require('md5.js'); + var querystring = ''; + var sign = getUrlParam(url, 'sign'); + if (sign || (data && data.sign)) { + return false; + } else { + if (url) { + querystring = getQuery(url); + } + if (data) { + var theRequest = []; + for (let param in data) { + if (param && data[param]) { + theRequest = theRequest.concat({ + 'name': param, + 'value': data[param] + }) + } + } + querystring = querystring.concat(theRequest); + } + //排序 + querystring = _.sortBy(querystring, 'name'); + //去重 + querystring = _.uniq(querystring, true, 'name'); + var urlData = ''; + for (let i = 0; i < querystring.length; i++) { + if (querystring[i] && querystring[i].name && querystring[i].value) { + urlData += querystring[i].name + '=' + querystring[i].value; + if (i < (querystring.length - 1)) { + urlData += '&'; + } + } + } + token = token ? token : app.siteInfo.token; + sign = md5(urlData + token); + return sign; + } +} +util.getSign = function(url, data, token) { + return getSign(url, data, token); +}; +/** + 二次封装微信wx.request函数、增加交互体全、配置缓存、以及配合微擎格式化返回数据 + @params option 弹出参数表, + { + url : 同微信, + data : 同微信, + header : 同微信, + method : 同微信, + success : 同微信, + fail : 同微信, + complete : 同微信, + cachetime : 缓存周期,在此周期内不重复请求http,默认不缓存 + } +*/ +util.request = function(option) { + var _ = require('underscore.js'); + var md5 = require('md5.js'); + var option = option ? option : {}; + option.cachetime = option.cachetime ? option.cachetime : 0; + option.showLoading = typeof option.showLoading != 'undefined' ? option.showLoading : true; + + var sessionid = wx.getStorageSync('userInfo').sessionid; + var url = option.url; + if (url.indexOf('http://') == -1 && url.indexOf('https://') == -1) { + url = util.url(url); + } + var state = getUrlParam(url, 'state'); + if (!state && !(option.data && option.data.state) && sessionid) { + url = url + '&state=we7sid-' + sessionid + } + if (!option.data || !option.data.m) { + var nowPage = getCurrentPages(); + if (nowPage.length) { + nowPage = nowPage[getCurrentPages().length - 1]; + if (nowPage && nowPage.__route__) { + url = url + '&m=' + nowPage.__route__.split('/')[0]; + } + } + } + + var sign = getSign(url, option.data); + if (sign) { + url = url + "&sign=" + sign; + } + if (!url) { + return false; + } + //wx.showNavigationBarLoading(); + if (option.showLoading) { + //util.showLoading(); + } + if (option.cachetime) { + var cachekey = md5(url); + var cachedata = wx.getStorageSync(cachekey); + var timestamp = Date.parse(new Date()); + + if (cachedata && cachedata.data) { + if (cachedata.expire > timestamp) { + if (option.complete && typeof option.complete == 'function') { + option.complete(cachedata); + } + if (option.success && typeof option.success == 'function') { + option.success(cachedata); + } + console.log('cache:' + url); + // wx.hideLoading(); + //wx.hideNavigationBarLoading(); + return true; + } else { + wx.removeStorageSync(cachekey) + } + } + } + wx.request({ + 'url': url, + 'data': option.data ? option.data : {}, + 'header': option.header ? option.header : {}, + 'method': option.method ? option.method : 'GET', + 'header': { + 'content-type': 'application/x-www-form-urlencoded' + }, + 'success': function(response) { + //wx.hideNavigationBarLoading(); + //wx.hideLoading(); + if (response.data.errno) { + if (response.data.errno == '41009') { + wx.setStorageSync('userInfo', ''); + util.getUserInfo(function() { + util.request(option) + }); + return; + } else { + if (option.fail && typeof option.fail == 'function') { + option.fail(response); + } else { + if (response.data.message) { + if (response.data.data != null && response.data.data.redirect) { + var redirect = response.data.data.redirect; + } else { + var redirect = ''; + } + app.util.message(response.data.message, redirect, 'error'); + } + } + return; + } + } else { + if (option.success && typeof option.success == 'function') { + option.success(response); + } + //写入缓存,减少HTTP请求,并且如果网络异常可以读取缓存数据 + if (option.cachetime) { + var cachedata = { + 'data': response.data, + 'expire': timestamp + option.cachetime * 1000 + }; + wx.setStorageSync(cachekey, cachedata); + } + } + }, + 'fail': function(response) { + wx.hideNavigationBarLoading(); + wx.hideLoading(); + + //如果请求失败,尝试从缓存中读取数据 + var md5 = require('md5.js'); + var cachekey = md5(url); + var cachedata = wx.getStorageSync(cachekey); + if (cachedata && cachedata.data) { + if (option.success && typeof option.success == 'function') { + option.success(cachedata); + } + console.log('failreadcache:' + url); + return true; + } else { + if (option.fail && typeof option.fail == 'function') { + option.fail(response); + } + } + }, + 'complete': function(response) { + // wx.hideNavigationBarLoading(); + // wx.hideLoading(); + if (option.complete && typeof option.complete == 'function') { + option.complete(response); + } + } + }); +} +/* + * 获取用户信息 + */ +util.getUserInfo = function(cb) { + var login = function() { + console.log('start login'); + var userInfo = { + 'sessionid': '', + 'wxInfo': '', + 'memberInfo': '', + }; + wx.login({ + success: function(res) { + util.request({ + url: 'auth/session/openid', + data: { + code: res.code + }, + cachetime: 0, + success: function(session) { + if (!session.data.errno) { + userInfo.sessionid = session.data.data.sessionid + wx.setStorageSync('userInfo', userInfo); + wx.getUserInfo({ + success: function(wxInfo) { + userInfo.wxInfo = wxInfo.userInfo + wx.setStorageSync('userInfo', userInfo); + util.request({ + url: 'auth/session/userinfo', + data: { + signature: wxInfo.signature, + rawData: wxInfo.rawData, + iv: wxInfo.iv, + encryptedData: wxInfo.encryptedData + }, + method: 'POST', + header: { + 'content-type': 'application/x-www-form-urlencoded' + }, + cachetime: 0, + success: function(res) { + if (!res.data.errno) { + userInfo.memberInfo = res.data.data; + wx.setStorageSync('userInfo', userInfo); + } + typeof cb == "function" && cb(userInfo); + } + }); + }, + fail: function() { + typeof cb == "function" && cb(userInfo); + }, + complete: function() {} + }) + } + } + }); + }, + fail: function() { + wx.showModal({ + title: '获取信息失败', + content: '请允许授权以便为您提供给服务', + success: function(res) { + if (res.confirm) { + util.getUserInfo(); + } + } + }) + } + }); + }; + + var app = wx.getStorageSync('userInfo'); + if (app.sessionid) { + wx.checkSession({ + success: function() { + typeof cb == "function" && cb(app); + }, + fail: function() { + app.sessionid = ''; + console.log('relogin'); + wx.removeStorageSync('userInfo'); + login(); + } + }) + } else { + //调用登录接口 + login(); + } +} + +util.navigateBack = function(obj) { + let delta = obj.delta ? obj.delta : 1; + if (obj.data) { + let pages = getCurrentPages() + let curPage = pages[pages.length - (delta + 1)]; + if (curPage.pageForResult) { + curPage.pageForResult(obj.data); + } else { + curPage.setData(obj.data); + } + } + wx.navigateBack({ + delta: delta, // 回退前 delta(默认为1) 页面 + success: function(res) { + // success + typeof obj.success == "function" && obj.success(res); + }, + fail: function(err) { + // fail + typeof obj.fail == "function" && obj.fail(err); + }, + complete: function() { + // complete + typeof obj.complete == "function" && obj.complete(); + } + }) +}; + +util.footer = function($this) { + let that = $this; + let tabBar = app.tabBar; + for (let i in tabBar['list']) { + tabBar['list'][i]['pageUrl'] = tabBar['list'][i]['pagePath'].replace(/(\?|#)[^"]*/g, '') + } + that.setData({ + tabBar: tabBar, + 'tabBar.thisurl': that.__route__ + }) +}; +/* + * 提示信息 + * type 为 success, error 当为 success, 时,为toast方式,否则为模态框的方式 + * redirect 为提示后的跳转地址, 跳转的时候可以加上 协议名称 + * navigate:/we7/pages/detail/detail 以 navigateTo 的方法跳转, + * redirect:/we7/pages/detail/detail 以 redirectTo 的方式跳转,默认为 redirect + */ +util.message = function (title, redirect, type, confirmText="确定") { + if (!title) { + return true; + } + if (typeof title == 'object') { + redirect = title.redirect; + type = title.type; + title = title.title; + } + if (redirect) { + var redirectType = redirect.substring(0, 9), + url = '', + redirectFunction = ''; + if (redirectType == 'navigate:') { + redirectFunction = 'navigateTo'; + url = redirect.substring(9); + } else if (redirectType == 'redirect:') { + redirectFunction = 'redirectTo'; + url = redirect.substring(9); + } else if (redirectType == 'switchTo:') { + redirectFunction = 'switchTab'; + url = redirect.substring(9); + } else { + url = redirect; + redirectFunction = 'redirectTo'; + } + } + if (!type) { + type = 'success'; + } + + if (type == 'success') { + wx.showToast({ + title: title, + icon: 'success', + duration: 2000, + mask: url ? true : false, + complete: function() { + if (url) { + setTimeout(function() { + wx[redirectFunction]({ + url: url, + }); + }, 1800); + } + + } + }); + } else if (type == 'error') { + wx.showModal({ + title: '提示', + content: title, + showCancel: false, + confirmColor: '#ff5041', + confirmText, + complete: function() { + if (url) { + wx[redirectFunction]({ + url: url, + }); + } + } + }); + } +} + +util.navTo = function (redirect){ + if (redirect) { + var redirectType = redirect.substring(0, 9), + url = '', + redirectFunction = ''; + if (redirectType == 'navigate:') { + redirectFunction = 'navigateTo'; + url = redirect.substring(9); + } else if (redirectType == 'redirect:') { + redirectFunction = 'redirectTo'; + url = redirect.substring(9); + } else if (redirectType == 'switchTo:') { + redirectFunction = 'switchTab'; + url = redirect.substring(9); + } else { + url = redirect; + redirectFunction = 'redirectTo'; + } + url && wx[redirectFunction]({ url }); + } +} + +util.user = util.getUserInfo; + +//封装微信等待提示,防止ajax过多时,show多次 +util.showLoading = function() { + var isShowLoading = wx.getStorageSync('isShowLoading'); + if (isShowLoading) { + wx.hideLoading(); + wx.setStorageSync('isShowLoading', false); + } + + wx.showLoading({ + title: '加载中', + complete: function() { + wx.setStorageSync('isShowLoading', true); + }, + fail: function() { + wx.setStorageSync('isShowLoading', false); + } + }); +} + +util.showImage = function(event) { + var url = event ? event.currentTarget.dataset.preview : ''; + if (!url) { + return false; + } + wx.previewImage({ + urls: [url] + }); +} + +/** + * 转换内容中的emoji表情为 unicode 码点,在Php中使用utf8_bytes来转换输出 + */ +util.parseContent = function(string) { + if (!string) { + return string; + } + + var ranges = [ + '\ud83c[\udf00-\udfff]', // U+1F300 to U+1F3FF + '\ud83d[\udc00-\ude4f]', // U+1F400 to U+1F64F + '\ud83d[\ude80-\udeff]' // U+1F680 to U+1F6FF + ]; + var emoji = string.match( + new RegExp(ranges.join('|'), 'g')); + + if (emoji) { + for (var i in emoji) { + string = string.replace(emoji[i], '[U+' + emoji[i].codePointAt(0).toString(16).toUpperCase() + ']'); + } + } + return string; +} + +util.date = function() { + /** + * 判断闰年 + * @param date Date日期对象 + * @return boolean true 或false + */ + this.isLeapYear = function(date) { + return (0 == date.getYear() % 4 && ((date.getYear() % 100 != 0) || (date.getYear() % 400 == 0))); + } + + /** + * 日期对象转换为指定格式的字符串 + * @param f 日期格式,格式定义如下 yyyy-MM-dd HH:mm:ss + * @param date Date日期对象, 如果缺省,则为当前时间 + * + * YYYY/yyyy/YY/yy 表示年份 + * MM/M 月份 + * W/w 星期 + * dd/DD/d/D 日期 + * hh/HH/h/H 时间 + * mm/m 分钟 + * ss/SS/s/S 秒 + * @return string 指定格式的时间字符串 + */ + this.dateToStr = function(formatStr, date) { + formatStr = arguments[0] || "yyyy-MM-dd HH:mm:ss"; + date = arguments[1] || new Date(); + var str = formatStr; + var Week = ['日', '一', '二', '三', '四', '五', '六']; + str = str.replace(/yyyy|YYYY/, date.getFullYear()); + str = str.replace(/yy|YY/, (date.getYear() % 100) > 9 ? (date.getYear() % 100).toString() : '0' + (date.getYear() % 100)); + str = str.replace(/MM/, date.getMonth() > 9 ? (date.getMonth() + 1) : '0' + (date.getMonth() + 1)); + str = str.replace(/M/g, date.getMonth()); + str = str.replace(/w|W/g, Week[date.getDay()]); + + str = str.replace(/dd|DD/, date.getDate() > 9 ? date.getDate().toString() : '0' + date.getDate()); + str = str.replace(/d|D/g, date.getDate()); + + str = str.replace(/hh|HH/, date.getHours() > 9 ? date.getHours().toString() : '0' + date.getHours()); + str = str.replace(/h|H/g, date.getHours()); + str = str.replace(/mm/, date.getMinutes() > 9 ? date.getMinutes().toString() : '0' + date.getMinutes()); + str = str.replace(/m/g, date.getMinutes()); + + str = str.replace(/ss|SS/, date.getSeconds() > 9 ? date.getSeconds().toString() : '0' + date.getSeconds()); + str = str.replace(/s|S/g, date.getSeconds()); + + return str; + } + + + /** + * 日期计算 + * @param strInterval string 可选值 y 年 m月 d日 w星期 ww周 h时 n分 s秒 + * @param num int + * @param date Date 日期对象 + * @return Date 返回日期对象 + */ + this.dateAdd = function(strInterval, num, date) { + date = arguments[2] || new Date(); + switch (strInterval) { + case 's': + return new Date(date.getTime() + (1000 * num)); + case 'n': + return new Date(date.getTime() + (60000 * num)); + case 'h': + return new Date(date.getTime() + (3600000 * num)); + case 'd': + return new Date(date.getTime() + (86400000 * num)); + case 'w': + return new Date(date.getTime() + ((86400000 * 7) * num)); + case 'm': + return new Date(date.getFullYear(), (date.getMonth()) + num, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()); + case 'y': + return new Date((date.getFullYear() + num), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()); + } + } + + /** + * 比较日期差 dtEnd 格式为日期型或者有效日期格式字符串 + * @param strInterval string 可选值 y 年 m月 d日 w星期 ww周 h时 n分 s秒 + * @param dtStart Date 可选值 y 年 m月 d日 w星期 ww周 h时 n分 s秒 + * @param dtEnd Date 可选值 y 年 m月 d日 w星期 ww周 h时 n分 s秒 + */ + this.dateDiff = function(strInterval, dtStart, dtEnd) { + switch (strInterval) { + case 's': + return parseInt((dtEnd - dtStart) / 1000); + case 'n': + return parseInt((dtEnd - dtStart) / 60000); + case 'h': + return parseInt((dtEnd - dtStart) / 3600000); + case 'd': + return parseInt((dtEnd - dtStart) / 86400000); + case 'w': + return parseInt((dtEnd - dtStart) / (86400000 * 7)); + case 'm': + return (dtEnd.getMonth() + 1) + ((dtEnd.getFullYear() - dtStart.getFullYear()) * 12) - (dtStart.getMonth() + 1); + case 'y': + return dtEnd.getFullYear() - dtStart.getFullYear(); + } + } + + /** + * 字符串转换为日期对象 // eval 不可用 + * @param date Date 格式为yyyy-MM-dd HH:mm:ss,必须按年月日时分秒的顺序,中间分隔符不限制 + */ + this.strToDate = function(dateStr) { + var data = dateStr; + var reCat = /(\d{1,4})/gm; + var t = data.match(reCat); + t[1] = t[1] - 1; + eval('var d = new Date(' + t.join(',') + ');'); + return d; + } + + /** + * 把指定格式的字符串转换为日期对象yyyy-MM-dd HH:mm:ss + * + */ + this.strFormatToDate = function(formatStr, dateStr) { + var year = 0; + var start = -1; + var len = dateStr.length; + if ((start = formatStr.indexOf('yyyy')) > -1 && start < len) { + year = dateStr.substr(start, 4); + } + var month = 0; + if ((start = formatStr.indexOf('MM')) > -1 && start < len) { + month = parseInt(dateStr.substr(start, 2)) - 1; + } + var day = 0; + if ((start = formatStr.indexOf('dd')) > -1 && start < len) { + day = parseInt(dateStr.substr(start, 2)); + } + var hour = 0; + if (((start = formatStr.indexOf('HH')) > -1 || (start = formatStr.indexOf('hh')) > 1) && start < len) { + hour = parseInt(dateStr.substr(start, 2)); + } + var minute = 0; + if ((start = formatStr.indexOf('mm')) > -1 && start < len) { + minute = dateStr.substr(start, 2); + } + var second = 0; + if ((start = formatStr.indexOf('ss')) > -1 && start < len) { + second = dateStr.substr(start, 2); + } + return new Date(year, month, day, hour, minute, second); + } + + + /** + * 日期对象转换为毫秒数 + */ + this.dateToLong = function(date) { + return date.getTime(); + } + + /** + * 毫秒转换为日期对象 + * @param dateVal number 日期的毫秒数 + */ + this.longToDate = function(dateVal) { + return new Date(dateVal); + } + + /** + * 判断字符串是否为日期格式 + * @param str string 字符串 + * @param formatStr string 日期格式, 如下 yyyy-MM-dd + */ + this.isDate = function(str, formatStr) { + if (formatStr == null) { + formatStr = "yyyyMMdd"; + } + var yIndex = formatStr.indexOf("yyyy"); + if (yIndex == -1) { + return false; + } + var year = str.substring(yIndex, yIndex + 4); + var mIndex = formatStr.indexOf("MM"); + if (mIndex == -1) { + return false; + } + var month = str.substring(mIndex, mIndex + 2); + var dIndex = formatStr.indexOf("dd"); + if (dIndex == -1) { + return false; + } + var day = str.substring(dIndex, dIndex + 2); + if (!isNumber(year) || year > "2100" || year < "1900") { + return false; + } + if (!isNumber(month) || month > "12" || month < "01") { + return false; + } + if (day > getMaxDay(year, month) || day < "01") { + return false; + } + return true; + } + + this.getMaxDay = function(year, month) { + if (month == 4 || month == 6 || month == 9 || month == 11) + return "30"; + if (month == 2) + if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) + return "29"; + else + return "28"; + return "31"; + } + /** + * 变量是否为数字 + */ + this.isNumber = function(str) { + var regExp = /^\d+$/g; + return regExp.test(str); + } + + /** + * 把日期分割成数组 [年、月、日、时、分、秒] + */ + this.toArray = function(myDate) { + myDate = arguments[0] || new Date(); + var myArray = Array(); + myArray[0] = myDate.getFullYear(); + myArray[1] = myDate.getMonth(); + myArray[2] = myDate.getDate(); + myArray[3] = myDate.getHours(); + myArray[4] = myDate.getMinutes(); + myArray[5] = myDate.getSeconds(); + return myArray; + } + + /** + * 取得日期数据信息 + * 参数 interval 表示数据类型 + * y 年 M月 d日 w星期 ww周 h时 n分 s秒 + */ + this.datePart = function(interval, myDate) { + myDate = arguments[1] || new Date(); + var partStr = ''; + var Week = ['日', '一', '二', '三', '四', '五', '六']; + switch (interval) { + case 'y': + partStr = myDate.getFullYear(); + break; + case 'M': + partStr = myDate.getMonth() + 1; + break; + case 'd': + partStr = myDate.getDate(); + break; + case 'w': + partStr = Week[myDate.getDay()]; + break; + case 'ww': + partStr = myDate.WeekNumOfYear(); + break; + case 'h': + partStr = myDate.getHours(); + break; + case 'm': + partStr = myDate.getMinutes(); + break; + case 's': + partStr = myDate.getSeconds(); + break; + } + return partStr; + } + + /** + * 取得当前日期所在月的最大天数 + */ + this.maxDayOfDate = function(date) { + date = arguments[0] || new Date(); + date.setDate(1); + date.setMonth(date.getMonth() + 1); + var time = date.getTime() - 24 * 60 * 60 * 1000; + var newDate = new Date(time); + return newDate.getDate(); + } +}; + +util.getLightColor = function(color, level) { + color = color ? color.toUpperCase() : color; + var r = /^\#?[0-9A-F]{6}$/; + if (!r.test(color)) return color; + color = color.replace("#", ""); + var hxs = color.match(/../g); + for (var i = 0; i < 3; i++) { + var col = parseInt(hxs[i], 16); + hxs[i] = Math.floor((255 - col) * level + col); + } + return `rgb(${hxs[0]}, ${hxs[1]}, ${hxs[2]})`; +} + +util.ProReq = function(controller, params) { + return new Promise((resolve, reject)=>{ + util.request({ + url: 'entry/wxapp/index', + data: { + controller, + ...params + }, + dataType: 'json', + success: function (res) { + wx.hideLoading(); + if (res.data.code == 0) { + resolve(res.data) + } else { + reject(res.data) + } + }, + fail: err=>{ + console.log(err) + } + }) + }) +} + +module.exports = util; \ No newline at end of file diff --git a/project.config.json b/project.config.json new file mode 100644 index 0000000..38e771f --- /dev/null +++ b/project.config.json @@ -0,0 +1,57 @@ +{ + "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", + "packOptions": { + "ignore": [], + "include": [] + }, + "setting": { + "urlCheck": true, + "es6": false, + "enhance": true, + "postcss": true, + "preloadBackgroundData": false, + "minified": true, + "newFeature": false, + "coverView": true, + "nodeModules": true, + "autoAudits": false, + "showShadowRootInWxmlPanel": true, + "scopeDataCheck": false, + "uglifyFileName": true, + "checkInvalidKey": true, + "checkSiteMap": true, + "uploadWithSourceMap": true, + "compileHotReLoad": false, + "lazyloadPlaceholderEnable": false, + "useMultiFrameRuntime": true, + "useApiHook": true, + "useApiHostProcess": true, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "enableEngineNative": false, + "useIsolateContext": false, + "userConfirmedBundleSwitch": false, + "packNpmManually": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "disableUseStrict": false, + "minifyWXML": true, + "showES6CompileOption": false, + "useCompilerPlugins": false, + "useStaticServer": true, + "ignoreUploadUnusedFiles": false, + "condition": false + }, + "compileType": "miniprogram", + "libVersion": "2.30.1", + "appid": "wx95e000d520e78bdc", + "projectname": "EP-WeChatApp-5.2.1", + "condition": {}, + "editorSetting": { + "tabIndent": "insertSpaces", + "tabSize": 4 + } +} \ No newline at end of file diff --git a/project.private.config.json b/project.private.config.json new file mode 100644 index 0000000..0ca6240 --- /dev/null +++ b/project.private.config.json @@ -0,0 +1,37 @@ +{ + "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", + "libVersion": "2.17.0", + "setting": { + "autoAudits": true, + "compileHotReLoad": true, + "urlCheck": false + }, + "condition": { + "miniprogram": { + "list": [ + { + "name": "", + "pathName": "eaterplanet_ecommerce/moduleA/groupCenter/pendingDeliveryOrders", + "query": "memberId=49", + "launchMode": "default", + "scene": null + }, + { + "name": "", + "pathName": "eaterplanet_ecommerce/pages/order/shopCart", + "query": "", + "launchMode": "default", + "scene": null + }, + { + "name": "", + "pathName": "eaterplanet_ecommerce/pages/user/me", + "query": "", + "launchMode": "default", + "scene": null + } + ] + } + }, + "projectname": "EP-WeChatApp-5.2.1" +} \ No newline at end of file diff --git a/siteinfo.js b/siteinfo.js new file mode 100644 index 0000000..b432354 --- /dev/null +++ b/siteinfo.js @@ -0,0 +1,2 @@ +var siteinfo = { "siteroot": "https://shop.ofme.cn/wxapp.php"} +module.exports = siteinfo \ No newline at end of file diff --git a/sitemap.json b/sitemap.json new file mode 100644 index 0000000..ca02add --- /dev/null +++ b/sitemap.json @@ -0,0 +1,7 @@ +{ + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", + "rules": [{ + "action": "allow", + "page": "*" + }] +} \ No newline at end of file