├── pages
├── my
│ ├── my.json
│ ├── myPost
│ │ ├── myPost.json
│ │ ├── myPost.wxss
│ │ ├── myPost.wxml
│ │ └── myPost.js
│ ├── contactUs
│ │ ├── contactUs.json
│ │ ├── contactUs.wxss
│ │ ├── contactUs.wxml
│ │ └── contactUs.js
│ ├── mySetting
│ │ ├── mySetting.json
│ │ ├── mySetting.wxss
│ │ ├── mySetting.wxml
│ │ └── mySetting.js
│ ├── myUserFollow
│ │ ├── myUserFollow.json
│ │ ├── myUserFollow.wxss
│ │ ├── myUserFollow.wxml
│ │ └── myUserFollow.js
│ ├── myUserFollower
│ │ ├── myUserFollower.json
│ │ ├── myUserFollower.wxss
│ │ ├── myUserFollower.wxml
│ │ └── myUserFollower.js
│ ├── my.js
│ ├── my.wxss
│ └── my.wxml
├── post
│ ├── post.json
│ ├── post.wxss
│ ├── post.wxml
│ └── post.js
├── index
│ ├── index.json
│ ├── index.wxss
│ ├── index.wxml
│ └── index.js
├── postDetail
│ ├── postDetail.json
│ ├── postDetail.wxss
│ ├── postDetail.wxml
│ └── postDetail.js
└── userHomepage
│ ├── userHomepage.json
│ ├── userHomepage.wxml
│ ├── userHomepage.js
│ └── userHomepage.wxss
├── images
├── wx.png
├── scan.png
├── demo1.png
├── demo2.png
├── demo3.png
├── scan-1.png
├── icon_add.png
├── postLike.png
├── bookCollect.png
├── icon_add_b.png
├── postUnlike.png
├── userFollow.png
├── userUnfollow.png
├── bookUncollect.png
├── footer-icon-01.png
├── footer-icon-02.png
├── footer-icon-03.png
├── footer-icon-04.png
├── footer-icon-05.png
├── qrcode-kalnon.jpg
├── wx_app_message.png
├── iconfont-dingdan.png
├── footer-icon-01-active.png
├── footer-icon-02-active.png
├── footer-icon-03-active.png
├── footer-icon-04-active.png
└── footer-icon-05-active.png
├── screenshots
├── QQ截图20170820162313.png
├── QQ截图20170820162335.png
├── QQ截图20170820162353.png
└── QQ截图20170820162407.png
├── README.md
├── utils
├── common.js
├── util.js
└── underscore.js
├── app.json
├── app.wxss
├── app.js
└── style
└── weui.wxss
/pages/my/my.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/pages/post/post.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/pages/my/myPost/myPost.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/pages/my/contactUs/contactUs.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/pages/my/mySetting/mySetting.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/pages/postDetail/postDetail.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/pages/userHomepage/userHomepage.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/pages/my/myUserFollow/myUserFollow.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/pages/my/myUserFollower/myUserFollower.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/pages/my/contactUs/contactUs.wxss:
--------------------------------------------------------------------------------
1 | /* contactUs.wxss */
--------------------------------------------------------------------------------
/pages/my/mySetting/mySetting.wxss:
--------------------------------------------------------------------------------
1 | /* pages/my/mySetting/mySetting.wxss */
--------------------------------------------------------------------------------
/images/wx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/wx.png
--------------------------------------------------------------------------------
/images/scan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/scan.png
--------------------------------------------------------------------------------
/images/demo1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/demo1.png
--------------------------------------------------------------------------------
/images/demo2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/demo2.png
--------------------------------------------------------------------------------
/images/demo3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/demo3.png
--------------------------------------------------------------------------------
/images/scan-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/scan-1.png
--------------------------------------------------------------------------------
/pages/my/myUserFollow/myUserFollow.wxss:
--------------------------------------------------------------------------------
1 | /* pages/my/myUserFollow/myUserFollow.wxss */
--------------------------------------------------------------------------------
/images/icon_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/icon_add.png
--------------------------------------------------------------------------------
/images/postLike.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/postLike.png
--------------------------------------------------------------------------------
/pages/my/myUserFollower/myUserFollower.wxss:
--------------------------------------------------------------------------------
1 | /* pages/my/myUserFollower/myUserFollower.wxss */
--------------------------------------------------------------------------------
/images/bookCollect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/bookCollect.png
--------------------------------------------------------------------------------
/images/icon_add_b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/icon_add_b.png
--------------------------------------------------------------------------------
/images/postUnlike.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/postUnlike.png
--------------------------------------------------------------------------------
/images/userFollow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/userFollow.png
--------------------------------------------------------------------------------
/images/userUnfollow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/userUnfollow.png
--------------------------------------------------------------------------------
/images/bookUncollect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/bookUncollect.png
--------------------------------------------------------------------------------
/images/footer-icon-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/footer-icon-01.png
--------------------------------------------------------------------------------
/images/footer-icon-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/footer-icon-02.png
--------------------------------------------------------------------------------
/images/footer-icon-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/footer-icon-03.png
--------------------------------------------------------------------------------
/images/footer-icon-04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/footer-icon-04.png
--------------------------------------------------------------------------------
/images/footer-icon-05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/footer-icon-05.png
--------------------------------------------------------------------------------
/images/qrcode-kalnon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/qrcode-kalnon.jpg
--------------------------------------------------------------------------------
/images/wx_app_message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/wx_app_message.png
--------------------------------------------------------------------------------
/images/iconfont-dingdan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/iconfont-dingdan.png
--------------------------------------------------------------------------------
/images/footer-icon-01-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/footer-icon-01-active.png
--------------------------------------------------------------------------------
/images/footer-icon-02-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/footer-icon-02-active.png
--------------------------------------------------------------------------------
/images/footer-icon-03-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/footer-icon-03-active.png
--------------------------------------------------------------------------------
/images/footer-icon-04-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/footer-icon-04-active.png
--------------------------------------------------------------------------------
/images/footer-icon-05-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/images/footer-icon-05-active.png
--------------------------------------------------------------------------------
/screenshots/QQ截图20170820162313.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/screenshots/QQ截图20170820162313.png
--------------------------------------------------------------------------------
/screenshots/QQ截图20170820162335.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/screenshots/QQ截图20170820162335.png
--------------------------------------------------------------------------------
/screenshots/QQ截图20170820162353.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/screenshots/QQ截图20170820162353.png
--------------------------------------------------------------------------------
/screenshots/QQ截图20170820162407.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zas023/ershoushu/HEAD/screenshots/QQ截图20170820162407.png
--------------------------------------------------------------------------------
/pages/my/myUserFollow/myUserFollow.wxml:
--------------------------------------------------------------------------------
1 |
2 | pages/my/myUserFollow/myUserFollow.wxml
3 |
--------------------------------------------------------------------------------
/pages/my/myUserFollower/myUserFollower.wxml:
--------------------------------------------------------------------------------
1 |
2 | pages/my/myUserFollower/myUserFollower.wxml
3 |
--------------------------------------------------------------------------------
/pages/post/post.wxss:
--------------------------------------------------------------------------------
1 | /* post.wxss */
2 | .title{
3 | display: flex;
4 | flex-direction: row;
5 | }
6 |
7 | .title_right{
8 | display: flex;
9 | flex-direction: column;
10 | }
11 |
--------------------------------------------------------------------------------
/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | /* pages/index/index.wxss */
2 | .item_content{
3 | display: flex;
4 | flex-direction: cow;
5 | }
6 |
7 | .item_content_left{
8 | margin-left: 40rpx;
9 | display: flex;
10 | flex-direction: column;
11 | justify-content: space-around;
12 | }
--------------------------------------------------------------------------------
/pages/userHomepage/userHomepage.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 关注TA
9 |
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 二手书交易平台微信小程序
2 | ##效果图如下:
3 |
4 | 
5 | 
6 | 
7 | 
8 |
--------------------------------------------------------------------------------
/pages/my/contactUs/contactUs.wxml:
--------------------------------------------------------------------------------
1 |
2 | 文本域
3 |
4 |
5 |
6 |
7 | 0/200
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/utils/common.js:
--------------------------------------------------------------------------------
1 | function showTip(sms, icon, fun, t) {
2 | if (!t) {
3 | t = 1000;
4 | }
5 | wx.showToast({
6 | title: sms,
7 | icon: icon,
8 | duration: t,
9 | success: fun
10 | })
11 | }
12 |
13 | function showModal(c,t,fun) {
14 | if(!t)
15 | t='提示'
16 | wx.showModal({
17 | title: t,
18 | content: c,
19 | showCancel:false,
20 | success: fun
21 | })
22 | }
23 |
24 |
25 | module.exports.showTip = showTip;
26 | module.exports.showModal = showModal;
--------------------------------------------------------------------------------
/utils/util.js:
--------------------------------------------------------------------------------
1 | function formatTime(date) {
2 | var year = date.getFullYear()
3 | var month = date.getMonth() + 1
4 | var day = date.getDate()
5 |
6 | var hour = date.getHours()
7 | var minute = date.getMinutes()
8 | var second = date.getSeconds()
9 |
10 |
11 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
12 | }
13 |
14 | function formatNumber(n) {
15 | n = n.toString()
16 | return n[1] ? n : '0' + n
17 | }
18 |
19 | module.exports = {
20 | formatTime: formatTime
21 | }
22 |
--------------------------------------------------------------------------------
/pages/my/my.js:
--------------------------------------------------------------------------------
1 | //my.js
2 | var app = getApp()
3 | Page({
4 |
5 | /**
6 | * 页面的初始数据
7 | */
8 | data: {
9 | userInfo: {},
10 | },
11 |
12 | /**
13 | * 生命周期函数--监听页面加载
14 | */
15 | onLoad: function (options) {
16 | var that = this
17 | //调用应用实例的方法获取全局数据
18 | app.getUserInfo(function (userInfo) {
19 | //更新数据
20 | that.setData({
21 | userInfo: userInfo
22 | })
23 | });
24 | },
25 |
26 | /**
27 | * 生命周期函数--监听页面初次渲染完成
28 | */
29 | onReady: function () {
30 |
31 | },
32 |
33 | /**
34 | * 生命周期函数--监听页面显示
35 | */
36 | onShow: function () {
37 |
38 | },
39 |
40 | /**
41 | * 生命周期函数--监听页面隐藏
42 | */
43 | onHide: function () {
44 |
45 | },
46 |
47 | /**
48 | * 生命周期函数--监听页面卸载
49 | */
50 | onUnload: function () {
51 |
52 | },
53 |
54 |
55 | })
--------------------------------------------------------------------------------
/pages/my/contactUs/contactUs.js:
--------------------------------------------------------------------------------
1 | // contactUs.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 |
9 | },
10 |
11 | /**
12 | * 生命周期函数--监听页面加载
13 | */
14 | onLoad: function (options) {
15 |
16 | },
17 |
18 | /**
19 | * 生命周期函数--监听页面初次渲染完成
20 | */
21 | onReady: function () {
22 |
23 | },
24 |
25 | /**
26 | * 生命周期函数--监听页面显示
27 | */
28 | onShow: function () {
29 |
30 | },
31 |
32 | /**
33 | * 生命周期函数--监听页面隐藏
34 | */
35 | onHide: function () {
36 |
37 | },
38 |
39 | /**
40 | * 生命周期函数--监听页面卸载
41 | */
42 | onUnload: function () {
43 |
44 | },
45 |
46 | /**
47 | * 页面相关事件处理函数--监听用户下拉动作
48 | */
49 | onPullDownRefresh: function () {
50 |
51 | },
52 |
53 | /**
54 | * 页面上拉触底事件的处理函数
55 | */
56 | onReachBottom: function () {
57 |
58 | },
59 |
60 | /**
61 | * 用户点击右上角分享
62 | */
63 | onShareAppMessage: function () {
64 |
65 | }
66 | })
--------------------------------------------------------------------------------
/pages/userHomepage/userHomepage.js:
--------------------------------------------------------------------------------
1 | // pages/userHomepage/userHomepage.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 |
9 | },
10 |
11 | /**
12 | * 生命周期函数--监听页面加载
13 | */
14 | onLoad: function (options) {
15 |
16 | },
17 |
18 | /**
19 | * 生命周期函数--监听页面初次渲染完成
20 | */
21 | onReady: function () {
22 |
23 | },
24 |
25 | /**
26 | * 生命周期函数--监听页面显示
27 | */
28 | onShow: function () {
29 |
30 | },
31 |
32 | /**
33 | * 生命周期函数--监听页面隐藏
34 | */
35 | onHide: function () {
36 |
37 | },
38 |
39 | /**
40 | * 生命周期函数--监听页面卸载
41 | */
42 | onUnload: function () {
43 |
44 | },
45 |
46 | /**
47 | * 页面相关事件处理函数--监听用户下拉动作
48 | */
49 | onPullDownRefresh: function () {
50 |
51 | },
52 |
53 | /**
54 | * 页面上拉触底事件的处理函数
55 | */
56 | onReachBottom: function () {
57 |
58 | },
59 |
60 | /**
61 | * 用户点击右上角分享
62 | */
63 | onShareAppMessage: function () {
64 |
65 | }
66 | })
--------------------------------------------------------------------------------
/pages/my/myUserFollow/myUserFollow.js:
--------------------------------------------------------------------------------
1 | // pages/my/myUserFollow/myUserFollow.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 |
9 | },
10 |
11 | /**
12 | * 生命周期函数--监听页面加载
13 | */
14 | onLoad: function (options) {
15 |
16 | },
17 |
18 | /**
19 | * 生命周期函数--监听页面初次渲染完成
20 | */
21 | onReady: function () {
22 |
23 | },
24 |
25 | /**
26 | * 生命周期函数--监听页面显示
27 | */
28 | onShow: function () {
29 |
30 | },
31 |
32 | /**
33 | * 生命周期函数--监听页面隐藏
34 | */
35 | onHide: function () {
36 |
37 | },
38 |
39 | /**
40 | * 生命周期函数--监听页面卸载
41 | */
42 | onUnload: function () {
43 |
44 | },
45 |
46 | /**
47 | * 页面相关事件处理函数--监听用户下拉动作
48 | */
49 | onPullDownRefresh: function () {
50 |
51 | },
52 |
53 | /**
54 | * 页面上拉触底事件的处理函数
55 | */
56 | onReachBottom: function () {
57 |
58 | },
59 |
60 | /**
61 | * 用户点击右上角分享
62 | */
63 | onShareAppMessage: function () {
64 |
65 | }
66 | })
--------------------------------------------------------------------------------
/pages/my/myUserFollower/myUserFollower.js:
--------------------------------------------------------------------------------
1 | // pages/my/myUserFollower/myUserFollower.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 |
9 | },
10 |
11 | /**
12 | * 生命周期函数--监听页面加载
13 | */
14 | onLoad: function (options) {
15 |
16 | },
17 |
18 | /**
19 | * 生命周期函数--监听页面初次渲染完成
20 | */
21 | onReady: function () {
22 |
23 | },
24 |
25 | /**
26 | * 生命周期函数--监听页面显示
27 | */
28 | onShow: function () {
29 |
30 | },
31 |
32 | /**
33 | * 生命周期函数--监听页面隐藏
34 | */
35 | onHide: function () {
36 |
37 | },
38 |
39 | /**
40 | * 生命周期函数--监听页面卸载
41 | */
42 | onUnload: function () {
43 |
44 | },
45 |
46 | /**
47 | * 页面相关事件处理函数--监听用户下拉动作
48 | */
49 | onPullDownRefresh: function () {
50 |
51 | },
52 |
53 | /**
54 | * 页面上拉触底事件的处理函数
55 | */
56 | onReachBottom: function () {
57 |
58 | },
59 |
60 | /**
61 | * 用户点击右上角分享
62 | */
63 | onShareAppMessage: function () {
64 |
65 | }
66 | })
--------------------------------------------------------------------------------
/pages/my/my.wxss:
--------------------------------------------------------------------------------
1 | /* pages/my/my.wxss */
2 | /*@import "../../style/weui.wxss";*/
3 |
4 | page {
5 | background-color: #f0eff4;
6 | }
7 |
8 | .top {
9 | background-color: #fff;
10 | padding: 20rpx;
11 | border-bottom: 2rpx solid #d0d0d0;
12 | position: relative;
13 | display: flex;
14 | height: 178rpx;
15 | box-sizing: border-box;
16 | }
17 |
18 | .top image {
19 | height: 138rpx;
20 | width: 138rpx;
21 | margin-right: 40rpx;
22 | border-radius: 10rpx;
23 | border: 2rpx solid #d0d0d0;
24 | }
25 |
26 | .top .namebox {
27 | display: inline-flex;
28 | flex-direction: column;
29 | justify-content: space-around;
30 | }
31 |
32 | .top .namebox .name {
33 | font-size: 38rpx;
34 | color: #333;
35 | }
36 |
37 | .top .namebox .more {
38 | font-size: 32rpx;
39 | color: #999;
40 | }
41 |
42 | .top:after {
43 | content: "";
44 | height: 16rpx;
45 | display: inline-block;
46 | width: 16rpx;
47 | border-right: 6rpx solid #c9c8cd;
48 | border-bottom: 6rpx solid #c9c8cd;
49 | transform: translateY(-50%) rotate(-45deg);
50 | margin-top: 6rpx;
51 | position: absolute;
52 | top: 50%;
53 | right: 50rpx;
54 | }
55 |
--------------------------------------------------------------------------------
/pages/postDetail/postDetail.wxss:
--------------------------------------------------------------------------------
1 | /* postDetail.wxss */
2 |
3 |
4 | .top {
5 | background-color: #fff;
6 | padding: 20rpx;
7 | border-bottom: 2rpx solid #d0d0d0;
8 | position: relative;
9 | display: flex;
10 | height: 178rpx;
11 | box-sizing: border-box;
12 | }
13 |
14 | .top image {
15 | height: 138rpx;
16 | width: 138rpx;
17 | margin-right: 40rpx;
18 | border-radius: 10rpx;
19 | border: 2rpx solid #d0d0d0;
20 | }
21 |
22 | .top .namebox {
23 | display: inline-flex;
24 | flex-direction: column;
25 | justify-content: space-around;
26 | }
27 |
28 | .top .namebox .name {
29 | font-size: 38rpx;
30 | color: #333;
31 | }
32 |
33 | .top .namebox .more {
34 | font-size: 32rpx;
35 | color: #999;
36 | }
37 |
38 | .top:after {
39 | content: "";
40 | height: 16rpx;
41 | display: inline-block;
42 | width: 16rpx;
43 | border-right: 6rpx solid #c9c8cd;
44 | border-bottom: 6rpx solid #c9c8cd;
45 | transform: translateY(-50%) rotate(-45deg);
46 | margin-top: 6rpx;
47 | position: absolute;
48 | top: 50%;
49 | right: 50rpx;
50 | }
51 |
52 | .item_content{
53 | display: flex;
54 | flex-direction: cow;
55 | }
56 |
57 | .item_content_left{
58 | margin-left: 40rpx;
59 | display: flex;
60 | flex-direction: column;
61 | justify-content: space-around;
62 | }
--------------------------------------------------------------------------------
/pages/my/my.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{userInfo.nickName}}
4 |
5 |
6 |
7 |
8 |
9 | 我的发布
10 |
11 |
12 |
13 |
14 | 我的关注
15 |
16 |
17 |
18 |
19 | 我的粉丝
20 |
21 |
22 |
23 |
24 | 交流反馈
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/index/index",
4 | "pages/post/post",
5 | "pages/postDetail/postDetail",
6 | "pages/userHomepage/userHomepage",
7 | "pages/my/my",
8 | "pages/my/myUserFollow/myUserFollow",
9 | "pages/my/myUserFollower/myUserFollower",
10 | "pages/my/myPost/myPost",
11 | "pages/my/mySetting/mySetting",
12 | "pages/my/contactUs/contactUs"
13 | ],
14 | "window": {
15 | "backgroundTextStyle": "light",
16 | "navigationBarBackgroundColor": "#444a5a",
17 | "navigationBarTitleText": "书享圈",
18 | "navigationBarTextStyle": "#fff"
19 | },
20 | "tabBar": {
21 | "color": "#6e6d6b",
22 | "selectedColor": "#2ea4fe",
23 | "borderStyle": "white",
24 | "backgroundColor": "#f7f7fa",
25 | "list": [
26 | {
27 | "pagePath": "pages/index/index",
28 | "iconPath": "images/footer-icon-01.png",
29 | "selectedIconPath": "images/footer-icon-01-active.png",
30 | "text": "首页"
31 | },
32 | {
33 | "pagePath": "pages/post/post",
34 | "iconPath": "images/footer-icon-03.png",
35 | "selectedIconPath": "images/footer-icon-03-active.png",
36 | "text": "发布"
37 | },
38 | {
39 | "pagePath": "pages/my/my",
40 | "iconPath": "images/footer-icon-05.png",
41 | "selectedIconPath": "images/footer-icon-05-active.png",
42 | "text": "我的"
43 | }
44 | ]
45 | }
46 | }
--------------------------------------------------------------------------------
/pages/my/myPost/myPost.wxss:
--------------------------------------------------------------------------------
1 | /* pages/my/myPost/myPost.wxss */
2 |
3 | .add_layer{width:100%;height:100%;background:rgba(66, 69, 72, 0.74);position:fixed;left:0;top:0;}
4 | .add_layer input,.add_layer textarea,.add_layer button{width:80%;margin:0 auto;margin:15px auto;font-size:14px;padding:10rpx;}
5 | .add_layer input,.add_layer textarea{
6 | background:#fff;
7 | }
8 | .diary_list{border-bottom:1px solid #ccc;margin:0px 0;padding:10px;position:relative;}
9 | .diary_list text{font-size:16px;color:#1e1e1e;}
10 | .diary_list view{font-size:14px;padding:5px 0}
11 | .diary_list button{
12 | position:absolute;
13 | right:15px;
14 | top:12px;
15 | }
16 | .diary_list button.modify{right:90px;}
17 |
18 |
19 | .weui-media-box__info__operate{
20 | float:right;
21 | color:#1e1e1e;
22 | padding-right:0em;
23 |
24 | }
25 | .weui-media-box__info__operate .del{
26 | margin-right: 15px;
27 | }
28 |
29 | .weui-media-box{
30 | padding-bottom: 0px;
31 | }
32 |
33 |
34 | .weui-cells__title{
35 | text-align: left;
36 | }
37 | textarea,input{
38 | text-align: left;
39 | color:#1e1e1e;
40 | }
41 | .weui-cells {
42 | border:1px solid #3891f8;
43 | }
44 | .weui-cells__title{
45 | padding-left: 0px;
46 | color:#1e1e1e;
47 | }
48 | .weui-dialog__ft button{
49 | background: none;
50 | padding: 0px;
51 | margin: 0px;
52 | }
53 | form .weui-dialog__bd:first-child {
54 | padding:0px 30rpx 1.7em;
55 |
56 | }
57 | .page__ft{
58 | padding-top: 40px;
59 | padding-bottom: 10px;
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/pages/userHomepage/userHomepage.wxss:
--------------------------------------------------------------------------------
1 | /* pages/userHomepage/userHomepage.wxss */
2 | .tool{
3 | height: 64rpx;
4 | margin: 20rpx 28rpx 20rpx 0;
5 | display: flex;
6 | justify-content: center;
7 | }
8 | .tool-item{
9 | align-items: center;
10 | margin-right: 30rpx;
11 | display: flex;
12 | }
13 |
14 | .tool-item:last-child{
15 | margin-right: 0rpx;
16 | }
17 |
18 | .tool-item image{
19 | height: 30rpx;
20 | width:30rpx;
21 | margin-right: 10rpx;
22 | }
23 |
24 | .comment image{
25 | transform: scale(.85);
26 | }
27 |
28 | .top {
29 | background-color: #fff;
30 | padding: 20rpx;
31 | border-bottom: 2rpx solid #d0d0d0;
32 | position: relative;
33 | display: flex;
34 | height: 178rpx;
35 | box-sizing: border-box;
36 | }
37 |
38 | .top image {
39 | height: 138rpx;
40 | width: 138rpx;
41 | margin-right: 40rpx;
42 | border-radius: 10rpx;
43 | border: 2rpx solid #d0d0d0;
44 | }
45 |
46 | .top .namebox {
47 | display: inline-flex;
48 | flex-direction: column;
49 | justify-content: space-around;
50 | }
51 |
52 | .top .namebox .name {
53 | font-size: 38rpx;
54 | color: #333;
55 | }
56 |
57 | .top .namebox .more {
58 | font-size: 32rpx;
59 | color: #999;
60 | }
61 |
62 | .top:after {
63 | content: "";
64 | height: 16rpx;
65 | display: inline-block;
66 | width: 16rpx;
67 | border-right: 6rpx solid #c9c8cd;
68 | border-bottom: 6rpx solid #c9c8cd;
69 | transform: translateY(-50%) rotate(-45deg);
70 | margin-top: 6rpx;
71 | position: absolute;
72 | top: 50%;
73 | right: 50rpx;
74 | }
--------------------------------------------------------------------------------
/pages/my/myPost/myPost.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{item.bookName}}
8 | 课程:{{item.courseName}}
9 | ISBN:{{item.bookISBN}}
10 | 作者:{{item.bookAuthor}}
11 | 出版社:{{item.bookPress}}
12 | 成色:{{item.condition}}
13 | 原价:{{item.bookPrice}}
14 | 售价:{{item.currentPrice}}元
15 |
16 |
17 | {{item.updatedAt}}
18 |
19 |
20 | 删除
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | 暂无发布
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 | @import "./style/weui.wxss";
3 | .container {
4 | height: 100%;
5 | display: flex;
6 | flex-direction: column;
7 | align-items: center;
8 | justify-content: space-between;
9 | padding: 200rpx 0;
10 | box-sizing: border-box;
11 | }
12 | page{background-color: #f3f3f3;padding-bottom: 20rpx; font-family: "微软雅黑","宋体";}
13 | .logo{background-color: #f0eff4;height: 90rpx;line-height: 88rpx;display: flex;justify-content: space-between;padding: 0 20rpx;color: #fff;font-size: 40rpx;}
14 | .logo image{width: 90rpx;height: 90rpx;}
15 | .logo .input{width: 710rpx;height: 50rpx;border: 0;border-radius: 10rpx;background-color: #fff;color: #999999;text-align: center;margin-top: 20rpx;}
16 | .head{display: flex;justify-content: space-between;text-align: center;line-height: 100rpx;font-size: 32rpx;background-color: #fff;}
17 | .head view{flex: 1;}
18 | .head navigator{display: inline-block;line-height: 100rpx;}
19 | .head navigator.on{border-bottom: 1px solid #363636;}
20 | .modular{background-color: #fff;padding: 20rpx 0 0;margin-top: 20rpx;}
21 | .modular .h1{font-size: 40rpx;line-height: 90rpx;}
22 | .modular .h1 .span{border-left: 10rpx solid #cda663;padding-left: 10rpx;display: inline;}
23 | .modular .content{column-count: 4;column-gap: 32rpx;border-bottom: 2rpx solid #f1f1f1;overflow: hidden;padding: 0 20rpx;}
24 | .modular .content image{width: 100%;height: 190rpx;}
25 | .modular .content view{padding: 14rpx 0;line-height: 34rpx;font-size: 28rpx;text-align: center;}
26 | .modular .more{line-height: 90rpx;text-align: center;color: #727ba6;font-size: 32rpx;}
27 | .modular .more .next{height: 16rpx;display: inline-block;width: 16rpx;border-right: 6rpx solid #c9c8cd;border-bottom: 6rpx solid #c9c8cd;transform: rotate(-45deg);margin-top: 6rpx;}
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | //app.js
2 | var Bmob = require('utils/bmob.js');
3 | Bmob.initialize("59c6af950c7ae5ae07df0e5291cdf708", "1be7b1ea080e159e483a330dba10cd07");
4 |
5 | App({
6 | onLaunch: function () {
7 | var user = new Bmob.User();//开始注册用户
8 |
9 | var newOpenid = wx.getStorageSync('openid')
10 | if (!newOpenid) {
11 |
12 |
13 | wx.login({
14 | success: function (res) {
15 | user.loginWithWeapp(res.code).then(function (user) {
16 | var openid = user.get("authData").weapp.openid;
17 | console.log(user, 'user', user.id, res);
18 |
19 | if (user.get("nickName")) {
20 | // 第二次访问
21 | console.log(user.get("nickName"), 'res.get("nickName")');
22 |
23 | wx.setStorageSync('openid', openid)
24 | } else {
25 |
26 | //保存用户其他信息
27 | wx.getUserInfo({
28 | success: function (result) {
29 |
30 | var userInfo = result.userInfo;
31 | var nickName = userInfo.nickName;
32 | var avatarUrl = userInfo.avatarUrl;
33 | var gender = userInfo.gender;
34 | var u = Bmob.Object.extend("_User");
35 | var query = new Bmob.Query(u);
36 | // 这个 id 是要修改条目的 id,你在生成这个存储并成功时可以获取到,请看前面的文档
37 | query.get(user.id, {
38 | success: function (result) {
39 | // 自动绑定之前的账号
40 | result.set('nickName', nickName);
41 | result.set("userPic", avatarUrl);
42 | result.set("openid", openid);
43 | result.set("gender", gender);
44 | result.save();
45 |
46 | }
47 | });
48 |
49 | }
50 | });
51 |
52 |
53 | }
54 |
55 | }, function (err) {
56 | console.log(err, 'errr');
57 | });
58 |
59 | }
60 | });
61 | }
62 |
63 |
64 |
65 | },
66 | getUserInfo: function (cb) {
67 | var that = this
68 | if (this.globalData.userInfo) {
69 | typeof cb == "function" && cb(this.globalData.userInfo)
70 | } else {
71 | //调用登录接口
72 | wx.login({
73 | success: function () {
74 |
75 | wx.getUserInfo({
76 | success: function (res) {
77 | that.globalData.userInfo = res.userInfo
78 | typeof cb == "function" && cb(that.globalData.userInfo)
79 | }
80 | })
81 | }
82 | })
83 | }
84 | },
85 | globalData: {
86 | userInfo: null
87 | }
88 | })
--------------------------------------------------------------------------------
/pages/postDetail/postDetail.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 图书详情
4 |
5 | {{bookName}}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 课程:{{courseName}}
14 | ISBN:{{bookISBN}}
15 | 作者:{{bookAuthor}}
16 | 出版社:{{bookPress}}
17 | 成色:{{condition}}
18 | 原价:{{bookPrice}}
19 | 售价:{{currentPrice}}元
20 | 备注:{{postRemark}}
21 |
22 |
23 |
24 |
25 |
26 | 更新时间:{{updatedAt}}
27 |
28 |
29 | 它的主人(点击查看TA的所有发布)
30 |
31 |
32 |
33 |
34 |
35 |
36 | {{ownerPostCount}}
37 |
38 |
39 | {{ownerNickname}}
40 | {{ownerCollege}}{{ownerEntryYear}}级{{ownerEducation}}
41 |
42 |
43 |
44 |
45 |
46 |
47 | 联系方式(长按选择复制)
48 |
49 |
50 | {{ownerPhone}}
51 | 手机
52 |
53 |
54 | {{ownerWechat}}
55 | 微信
56 |
57 |
58 | {{ownerQQ}}
59 | QQ
60 |
61 |
--------------------------------------------------------------------------------
/pages/my/myPost/myPost.js:
--------------------------------------------------------------------------------
1 | // pages/my/myPost/myPost.js
2 | var Bmob = require('../../../utils/bmob.js')
3 | var util = require('../../../utils/util.js')
4 | var util = require('../../../utils/common.js')
5 | var that
6 | Page({
7 | data: {
8 | limit: 10,
9 | skip: 0,
10 | postList: []
11 | },
12 |
13 | onLoad: function () {
14 | that = this;
15 | var Post = Bmob.Object.extend("post");
16 | var query = new Bmob.Query(Post);
17 | query.equalTo("ownerId", Bmob.User.current().id);
18 | query.descending('updatedAt');
19 | query.limit(this.data.limit);
20 | query.find({
21 | success: function (results) {
22 | that.setData({
23 | postList: results,
24 | skip: results.length
25 | })
26 | },
27 | error: function (error) {
28 | console.log("onLoad查询post失败: " + error.code + " " + error.message);
29 | }
30 | })
31 |
32 | },
33 | onShow:function(){
34 | var Post = Bmob.Object.extend("post");
35 | var query = new Bmob.Query(Post);
36 | query.equalTo("ownerId", Bmob.User.current().id);
37 | query.descending('updatedAt');
38 | query.limit(this.data.limit);
39 | query.find({
40 | success: function (results) {
41 | that.setData({
42 | postList: results,
43 | skip: results.length
44 | })
45 | },
46 | error: function (error) {
47 | console.log("onShow查询post失败: " + error.code + " " + error.message);
48 | }
49 | })
50 | },
51 |
52 | onPullDownRefresh: function () {
53 | this.onShow();
54 |
55 | },
56 |
57 | onReachBottom: function () {
58 | var Post = Bmob.Object.extend("post");
59 | var query = new Bmob.Query(Post);
60 | query.equalTo("ownerId", Bmob.User.current().id);
61 | query.descending('updatedAt');
62 | query.skip(this.data.skip);
63 | query.limit(this.data.limit);
64 | query.find({
65 | success: function (results) {
66 | if (results.length > 0) {
67 | var nl = that.data.postList.concat(results);
68 | that.setData({
69 | skip: that.data.skip + results.length,
70 | postList: nl
71 | })
72 | }
73 | else {
74 | wx.showToast({
75 | title: '已全部加载',
76 | icon: 'success',
77 | duration: 3000
78 | })
79 | }
80 | },
81 | error: function (error) {
82 | console.log("onReachBottom查询post失败: " + error.code + " " + error.message);
83 | }
84 | })
85 | },
86 |
87 | deletePost: function (event) {
88 | var objectId = event.target.dataset.id;
89 | wx.showModal({
90 | title: '操作提示',
91 | content: '确定要删除该发布?',
92 | success: function (res) {
93 | if (res.confirm) {
94 | //删除日记
95 | var Post = Bmob.Object.extend("post");
96 | //创建查询对象,入口参数是对象类的实例
97 | var query = new Bmob.Query(Post);
98 | query.equalTo("objectId", objectId);
99 | query.destroyAll({
100 | success: function () {
101 | common.showTip('删除成功');
102 | that.onShow();
103 | },
104 | error: function (err) {
105 | common.showTip('删除失败', 'loading');
106 | }
107 | });
108 | }
109 | }
110 | })
111 | },
112 |
113 | })
114 |
--------------------------------------------------------------------------------
/pages/my/mySetting/mySetting.wxml:
--------------------------------------------------------------------------------
1 |
2 | 以下信息必填哦
3 |
4 |
5 |
6 |
7 |
8 | 学校
9 |
10 |
11 |
12 | {{university[universityIndex]}}
13 |
14 |
15 |
16 |
17 |
18 |
19 | 学院
20 |
21 |
22 |
23 | {{college[collegeIndex]}}
24 |
25 |
26 |
27 |
28 |
29 |
30 | 学历
31 |
32 |
33 |
34 | {{education[educationIndex]}}
35 |
36 |
37 |
38 |
39 |
40 |
41 | 入学年份
42 |
43 |
44 |
45 | {{entryYear[entryYearIndex]}}
46 |
47 |
48 |
49 |
50 |
51 | 请注意:以下联系方式将展示给该小程序的其他用户
52 | 为保证意向买家能与你取得联系,至少需要填一项
53 |
54 |
55 |
56 | 微信号
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | QQ号
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | 手机号
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/pages/postDetail/postDetail.js:
--------------------------------------------------------------------------------
1 | // postDetail.js
2 | var Bmob = require('../../utils/bmob.js');
3 | var that
4 | Page({
5 |
6 | data: {
7 | bookISBN: '',
8 | bookImg: '',
9 | bookName: '',
10 | bookAuthor: '',
11 | bookPress: '',
12 | bookPrice: '',
13 |
14 | isTextbook: false,
15 | courseName: '',
16 | currentPrice: '',
17 | condition: '',
18 | updatedAt: '',
19 | campus: '',
20 | postRemark: '',
21 |
22 | ownerId: '',
23 | ownerNickname: '',
24 | ownerGender: '',
25 | ownerWechat: '',
26 | ownerQQ: '',
27 | ownerPhone: '',
28 | ownerCollege: '',
29 | ownerPostCount:0
30 |
31 | },
32 |
33 | onLoad: function (options) {
34 | that = this
35 | this.setData({
36 | bookISBN: options.bookISBN,
37 | bookName: options.bookName,
38 | bookAuthor: options.bookAuthor,
39 | bookPress: options.bookPress,
40 | bookPrice: options.bookPrice,
41 | bookImg: options.bookImg,
42 | isTextbook: options.isTextbook,
43 | courseName: options.courseName,
44 | currentPrice: options.currentPrice,
45 | condition: options.condition,
46 | updatedAt: options.updatedAt,
47 | campus: options.campus,
48 | postRemark: options.postRemark,
49 | ownerId: options.ownerId
50 | });
51 | var User = Bmob.Object.extend("_User");
52 | var query = new Bmob.Query(User);
53 | query.get(that.data.ownerId, {
54 | success: function (result) {
55 | that.setData({
56 | ownerPic: result.get("userPic"),
57 | ownerNickname: result.get("nickName"),
58 | ownerGender: result.get("gender"),
59 | ownerWechat: result.get("wechatId"),
60 | ownerQQ: result.get("QQ"),
61 | ownerPhone: result.get("mobliePhoneNumber"),
62 | ownerCollege: result.get("college"),
63 | ownerEntryYear: result.get("entryYear"),
64 | ownerEducation:result.get("education")
65 | })
66 | },
67 | error: function (object, error) {
68 | console.log('获取发布者失败', error)
69 | }
70 | });
71 | var Post = Bmob.Object.extend("post");
72 | var query = new Bmob.Query(Post);
73 | query.equalTo("ownerId", this.data.ownerId);
74 | query.count({
75 | success: function (count) {
76 | that.setData({
77 | ownerPostCount: count
78 | })
79 | },
80 | error: function (error) {
81 | // 查询失败
82 | }
83 | });
84 |
85 | },
86 |
87 | /**
88 | * 生命周期函数--监听页面初次渲染完成
89 | */
90 | onReady: function () {
91 | },
92 |
93 | /**
94 | * 生命周期函数--监听页面显示
95 | */
96 | onShow: function () {
97 |
98 | },
99 |
100 | /**
101 | * 生命周期函数--监听页面隐藏
102 | */
103 | onHide: function () {
104 |
105 | },
106 |
107 | /**
108 | * 生命周期函数--监听页面卸载
109 | */
110 | onUnload: function () {
111 |
112 | },
113 |
114 | /**
115 | * 页面相关事件处理函数--监听用户下拉动作
116 | */
117 | onPullDownRefresh: function () {
118 |
119 | },
120 |
121 | /**
122 | * 页面上拉触底事件的处理函数
123 | */
124 | onReachBottom: function () {
125 |
126 | },
127 |
128 | /**
129 | * 用户点击右上角分享
130 | */
131 | onShareAppMessage: function () {
132 |
133 | },
134 |
135 | navToUserHomePage:function(){
136 | wx.navigateTo({
137 | url: '../userHomepage/userHomepage?ownerId={{ownerId}}'
138 | })
139 | }
140 | })
--------------------------------------------------------------------------------
/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 校区
6 |
7 |
8 |
9 | {{campus[campusIndex]}}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
30 |
31 | 取消
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | {{item.bookName}}
41 |
42 |
43 |
44 |
45 |
46 |
47 | ISBN:{{item.bookISBN}}
48 | 课程:{{item.courseName}}
49 | 成色:{{item.condition}}
50 | 原价:{{item.bookPrice}}
51 | 售价:{{item.currentPrice}}元
52 |
53 |
54 |
55 |
56 |
57 | {{item.updatedAt}}
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | 暂无内容
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/pages/post/post.wxml:
--------------------------------------------------------------------------------
1 |
2 | 请先在“我的”里点击自己的头像设置联系方式哦~
3 |
4 |
5 |
6 | ISBN
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
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 |
52 |
53 | 定价
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | 是否为教材教辅
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | 课程名称
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | 校区
85 |
86 |
87 |
88 | {{campus[campusIndex]}}
89 |
90 |
91 |
92 |
93 |
94 |
95 | 成色
96 |
97 |
98 |
99 | {{conditions[conditionIndex]}}
100 |
101 |
102 |
103 |
104 |
105 |
106 | 售价
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | 备注
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/pages/index/index.js:
--------------------------------------------------------------------------------
1 | //index.js
2 | var Bmob = require('../../utils/bmob.js')
3 | var util = require('../../utils/util.js')
4 | var common = require('../../utils/common.js')
5 | var that
6 | Page({
7 | data: {
8 | campus: ["重庆大学A区", "重庆大学B区", "重庆大学C区", "重庆大学虎溪校区"],
9 | campusIndex: 3,
10 | limit: 2,
11 | skip: 0,
12 | postList: []
13 | },
14 |
15 | onLoad: function () {
16 | that = this;
17 | var Post = Bmob.Object.extend("post");
18 | var query = new Bmob.Query(Post);
19 | query.equalTo("campus", this.data.campus[this.data.campusIndex]);
20 | query.descending('updatedAt');
21 | query.limit(this.data.limit);
22 | query.find({
23 | success: function (results) {
24 | that.setData({
25 | postList: results,
26 | skip: results.length
27 | })
28 | },
29 | error: function (error) {
30 | console.log("onLoad查询post失败: " + error.code + " " + error.message);
31 | }
32 | })
33 |
34 | },
35 |
36 | onPullDownRefresh: function () {
37 | var Post = Bmob.Object.extend("post");
38 | var query = new Bmob.Query(Post);
39 | query.equalTo("campus", that.data.campus[this.data.campusIndex]);
40 | query.descending('updatedAt');
41 | query.limit(this.data.limit);
42 | query.find({
43 | success: function (results) {
44 | that.setData({
45 | postList: results,
46 | skip: results.length
47 | })
48 | },
49 | error: function (error) {
50 | console.log("onLoad查询post失败: " + error.code + " " + error.message);
51 | }
52 | })
53 |
54 | },
55 |
56 | onReachBottom: function () {
57 | var Post = Bmob.Object.extend("post");
58 | var query = new Bmob.Query(Post);
59 | query.equalTo("campus", that.data.campus[this.data.campusIndex]);
60 | query.descending('updatedAt');
61 | query.skip(this.data.skip);
62 | query.limit(this.data.limit);
63 | query.find({
64 | success: function (results) {
65 | if (results.length > 0) {
66 | var nl = that.data.postList.concat(results);
67 | that.setData({
68 | skip: that.data.skip + results.length,
69 | postList: nl
70 | })
71 | }
72 | else {
73 | wx.showToast({
74 | title: '已全部加载',
75 | icon: 'success',
76 | duration: 3000
77 | })
78 | }
79 | wx.stopPullDownRefresh()
80 | },
81 | error: function (error) {
82 | console.log("onReachBottom查询post失败: " + error.code + " " + error.message);
83 | }
84 | })
85 | },
86 |
87 | bindCampusChange: function (e) {
88 | this.setData({
89 | campusIndex: e.detail.value
90 | })
91 | },
92 |
93 | showInput: function () {
94 | this.setData({
95 | inputShowed: true
96 | });
97 | },
98 | hideInput: function () {
99 | this.setData({
100 | inputVal: "",
101 | inputShowed: false
102 | });
103 | var Post = Bmob.Object.extend("post");
104 | var query = new Bmob.Query(Post);
105 | query.equalTo("campus", this.data.campus[this.data.campusIndex]);
106 | query.descending('updatedAt');
107 | query.limit(this.data.limit);
108 | query.find({
109 | success: function (results) {
110 | that.setData({
111 | postList: results,
112 | skip: results.length
113 | })
114 | },
115 | error: function (error) {
116 | console.log("hideInput查询post失败: " + error.code + " " + error.message);
117 | }
118 | })
119 | },
120 |
121 | clearInput: function () {
122 | this.setData({
123 | inputVal: ""
124 | });
125 | var Post = Bmob.Object.extend("post");
126 | var query = new Bmob.Query(Post);
127 | query.equalTo("campus", this.data.campus[this.data.campusIndex]);
128 | query.descending('updatedAt');
129 | query.limit(this.data.limit);
130 | query.find({
131 | success: function (results) {
132 | that.setData({
133 | postList: results,
134 | skip: results.length
135 | })
136 | },
137 | error: function (error) {
138 | console.log("clearInput查询post失败: " + error.code + " " + error.message);
139 | }
140 | })
141 | },
142 |
143 | bindSearch: function (e) {
144 | this.getList(e.detail.value);
145 | console.log(e.detail.value)
146 | this.setData({
147 | inputVal: e.detail.value
148 | });
149 | },
150 |
151 | getList: function (k) {
152 | var Post = Bmob.Object.extend("post");
153 | var queryBookName = new Bmob.Query(Post);
154 | var queryISBN = new Bmob.Query(Post);
155 | var queryCourseName = new Bmob.Query(Post);
156 | queryBookName.equalTo("bookName", k);
157 | queryISBN.equalTo("bookISBN",k)
158 | queryCourseName.equalTo("courseName", k)
159 | var mainQuery = Bmob.Query.or(queryBookName, queryISBN,queryCourseName);
160 | mainQuery.equalTo("campus", that.data.campus[this.data.campusIndex]);
161 | mainQuery.descending('updatedAt');
162 | //mainQuery.limit(this.data.limit);
163 | mainQuery.find({
164 | success: function (results) {
165 | console.log(results)
166 | that.setData({
167 | postList: results
168 | })
169 | },
170 | error: function (error) {
171 | console.log("getList查询pos失败: " + error.code + " " + error.message);
172 | }
173 | });
174 | }
175 |
176 | })
177 |
--------------------------------------------------------------------------------
/pages/my/mySetting/mySetting.js:
--------------------------------------------------------------------------------
1 | // pages/my/mySetting/mySetting.js
2 | var Bmob = require('../../../utils/bmob.js');
3 | Page({
4 | data: {
5 | userWechat: '',
6 | userQQ: '',
7 | userPhone: '',
8 | userUniversity: '',
9 | userCollege: '',
10 | userEducation: '',
11 | userEntryYear: '',
12 | buttonLoading: false,
13 | university: ["重庆大学"],
14 | universityIndex: 0,
15 | college: ["公共管理学院", "经济与工商管理学院", "建设管理与房地产学院", "外国语学院", "艺术学院", "美视电影学院", "新闻学院", "法学院", "软件工程学院", "数学与统计学院", "机械工程学院", "光电工程学院", "材料科学与工程学院", "动力工程学院", "电气工程学院", "通信工程学院", "自动化学院", "计算机学院", "建筑城规学院", "土木工程学院", "城市建设与环境工程学院", "化学化工学院", "生物工程学院", "资源及环境科学学院", "体育学院", "生命科学学院", "物理学院", "博雅学院", "重庆大学—辛辛那提大学联合学院", "航空航天学院", "汽车工程学院", "弘深学院"],
16 | collegeIndex: 0,
17 | education: ["本科生", "硕士研究生", "博士研究生"],
18 | educationIndex: 0,
19 | entryYear: ["2012", "2013", "2014", "2015", "2016"],
20 | entryYearIndex: 3
21 | },
22 |
23 | /**
24 | * 生命周期函数--监听页面加载
25 | */
26 | onLoad: function () {
27 | var that = this
28 | this.setData({
29 | userUniversity: this.data.university[0],
30 | userCollege: this.data.college[0],
31 | userEducation: this.data.education[0],
32 | userEntryYear: this.data.entryYear[3],
33 | userWechat: '',
34 | userQQ: '',
35 | userPhone: ''
36 | })
37 | var User = Bmob.Object.extend("_User");
38 | var query = new Bmob.Query(User);
39 | query.get(Bmob.User.current().id, {
40 | success: function (result) {
41 | console.log('修改前',result)
42 | if (result.get("university")) {
43 | console.log('haha')
44 | that.setData({
45 | userUniversity: result.get("university"),
46 | universityIndex: that.data.university.indexOf(that.data.userUniversity)
47 | })
48 | }
49 | if (result.get("college")) {
50 | that.setData({
51 | userCollege: result.get("college"),
52 | collegeIndex: that.data.college.indexOf(that.data.userCollege)
53 | })
54 | }
55 | if (result.get("education")) {
56 | that.setData({
57 | userEducation: result.get("education"),
58 | educationIndex: that.data.education.indexOf(that.data.userEducation)
59 | })
60 | }
61 | if (result.get("entryYear")) {
62 | that.setData({
63 | userEntryYear: result.get("entryYear"),
64 | entryYearIndex: that.data.entryYear.indexOf(that.data.userEntryYear)
65 | })
66 | }
67 | if (result.get("wechatId")) {
68 | that.setData({
69 | userWechat: result.get("wechatId")
70 | })
71 | }
72 | if (result.get("QQ")) {
73 | that.setData({
74 | userQQ: result.get("QQ")
75 | })
76 | }
77 | if (result.get("mobilePhoneNumber")) {
78 | that.setData({
79 | userPhone: result.get("mobilePhoneNumber")
80 | })
81 | }
82 |
83 | console.log(that.data)
84 | },
85 | error: function (object, error) {
86 | console.log('查询失败', error)
87 | }
88 | });
89 | },
90 |
91 | /**
92 | * 生命周期函数--监听页面初次渲染完成
93 | */
94 | onReady: function () {
95 |
96 | },
97 |
98 | /**
99 | * 生命周期函数--监听页面显示
100 | */
101 | onShow: function () {
102 |
103 | },
104 |
105 | /**
106 | * 生命周期函数--监听页面隐藏
107 | */
108 | onHide: function () {
109 |
110 | },
111 |
112 | /**
113 | * 生命周期函数--监听页面卸载
114 | */
115 | onUnload: function () {
116 |
117 | },
118 |
119 | /**
120 | * 页面相关事件处理函数--监听用户下拉动作
121 | */
122 | onPullDownRefresh: function () {
123 |
124 | },
125 |
126 | /**
127 | * 页面上拉触底事件的处理函数
128 | */
129 | onReachBottom: function () {
130 |
131 | },
132 |
133 | bindUniversityChange: function (e) {
134 | this.setData({
135 | universityIndex: e.detail.value,
136 | userUniversity: this.data.university[this.data.universityIndex]
137 | })
138 | },
139 |
140 | bindCollegeChange: function (e) {
141 | this.setData({
142 | collegeIndex: e.detail.value,
143 | userCollege: this.data.college[this.data.collegeIndex]
144 | })
145 | },
146 | bindEducationChange: function (e) {
147 | this.setData({
148 | educationIndex: e.detail.value,
149 | userEducation: this.data.education[this.data.educationIndex]
150 | })
151 | },
152 | bindEntryYearChange: function (e) {
153 | this.setData({
154 | entryYearIndex: e.detail.value,
155 | userEntryYear: this.data.entryYear[this.data.entryYearIndex]
156 | })
157 | },
158 | bindWechatInput: function (e) {
159 | this.setData({
160 | userWechat: e.detail.value
161 | })
162 | },
163 | bindQQInput: function (e) {
164 | this.setData({
165 | userQQ: e.detail.value
166 | })
167 | },
168 | bindPhoneInput: function (e) {
169 | this.setData({
170 | userPhone: e.detail.value
171 | })
172 | },
173 | bindSubmit: function () {
174 | var that = this;
175 | this.setData({
176 | buttonLoading: true
177 | })
178 | var User = Bmob.Object.extend("_User");
179 | var query = new Bmob.Query(User);
180 | query.get(Bmob.User.current().id, {
181 | success: function (result) {
182 | console.log('点击按钮',result)
183 | result.set("wechatId", that.data.userWechat);
184 | result.set("QQ", that.data.userQQ);
185 | result.set("mobilePhoneNumber", that.data.userPhone);
186 | result.set("university", that.data.userUniversity);
187 | result.set("college", that.data.userCollege);
188 | result.set("education", that.data.userEducation);
189 | result.set("entryYear", that.data.userEntryYear);
190 | result.save();
191 | that.setData({
192 | buttonLoading: false
193 | });
194 | wx.showToast({
195 | title: '修改成功',
196 | icon: 'success',
197 | duration: 3000
198 | })
199 | },
200 | error: function (object, error) {
201 | console.log('失败', object, error)
202 | }
203 | })
204 | }
205 | })
--------------------------------------------------------------------------------
/pages/post/post.js:
--------------------------------------------------------------------------------
1 | // post.js
2 | var Bmob = require('../../utils/bmob.js');
3 | var basicURL = 'https://api.douban.com/v2/book/isbn/:';
4 | var app = getApp()
5 | Page({
6 | /**
7 | * 页面的初始数据
8 | */
9 | data: {
10 | ownerId: '',
11 | ownerNickname: '',
12 | ownerGender: '',
13 | bookFound: false,
14 |
15 | bookISBN: '',
16 | bookImg: '',
17 | bookName: '',
18 | bookAuthor: '',
19 | bookPress: '',
20 | bookPrice: '',
21 |
22 | isTextbook: false,
23 | courseName: '',
24 | conditions: ["全新","几乎全新", "少量笔记", "较多笔记", "不影响阅读"],
25 | conditionIndex: 2,
26 | campus: ["重庆大学A区", "重庆大学B区", "重庆大学C区", "重庆大学虎溪校区"],
27 | campusIndex: 3,
28 | currentPrice: '',
29 | postRemark: '',
30 | buttonLoading: false
31 | },
32 |
33 | /**
34 | * 生命周期函数--监听页面加载
35 | */
36 | onLoad: function () {
37 | var that = this
38 | app.getUserInfo(function (userInfo) {
39 | that.setData({
40 | ownerNickname: userInfo.nickName,
41 | ownerGender: userInfo.gender
42 | }),
43 | console.log('ownerNickname:', that.data.ownerNickname)
44 | console.log('ownerGender:', that.data.ownerGender)
45 | }),
46 | this.setData({
47 | ownerId: Bmob.User.current().id
48 | })
49 | console.log('ownerId:', this.data.ownerId)
50 | },
51 |
52 | /**
53 | * 生命周期函数--监听页面初次渲染完成
54 | */
55 | onReady: function () {
56 |
57 | },
58 |
59 | /**
60 | * 生命周期函数--监听页面显示
61 | */
62 | onShow: function () {
63 |
64 | },
65 |
66 | /**
67 | * 生命周期函数--监听页面隐藏
68 | */
69 | onHide: function () {
70 |
71 | },
72 |
73 | /**
74 | * 生命周期函数--监听页面卸载
75 | */
76 | onUnload: function () {
77 |
78 | },
79 |
80 | /**
81 | * 页面相关事件处理函数--监听用户下拉动作
82 | */
83 | onPullDownRefresh: function () {
84 |
85 | },
86 |
87 | /**
88 | * 页面上拉触底事件的处理函数
89 | */
90 | onReachBottom: function () {
91 |
92 | },
93 |
94 | //响应事件
95 | //扫码
96 | scanBookISBN: function () {
97 | var that = this;
98 | wx.scanCode({
99 | success: (res) => {
100 | that.setData({
101 | bookISBN: res.result
102 | })
103 | that.searchBookISBN()
104 | }
105 | })
106 | },
107 | //输入
108 | inputBookISBN: function (e) {
109 | var that = this;
110 | if (e.detail.value != '') {
111 | that.setData({
112 | bookISBN: e.detail.value
113 | })
114 | that.searchBookISBN();
115 | }
116 | },
117 |
118 | searchBookISBN: function () {
119 | var that = this;
120 | // req(this.data.bookISBN);
121 | wx.request({
122 | url: basicURL + that.data.bookISBN,
123 | // url: basicURL + this.data.bookISBN,
124 | // data: data,
125 | method: 'post',
126 | header: { 'Content-Type': 'json' },
127 | success: function (res) {
128 | if (res.statusCode != '404') {
129 |
130 | console.log(res)
131 | that.setData({
132 | bookFound: true,
133 | bookName: res.data.title,
134 | bookAuthor: res.data.author[0],
135 | bookPress: res.data.publisher,
136 | bookPrice: res.data.price,
137 | bookImg: res.data.image,
138 | })
139 | }
140 | else {
141 | var book = Bmob.Object.extend("book");
142 | var query = new Bmob.Query(book);
143 | query.equalTo("bookISBN", that.data.bookISBN);
144 | // 查询所有数据
145 | query.find({
146 | success: function (results) {
147 | console.log('查找book表成功')
148 | if (results.length != 0) {
149 | console.log('book表中有该书')
150 | var object = results[0];
151 | that.setData({
152 | bookFound: true,
153 | bookName: res.data.title,
154 | bookAuthor: res.data.author[0],
155 | bookPress: res.data.publisher,
156 | bookPrice: res.data.price,
157 | bookImg: res.data.image,
158 | })
159 | }
160 | else {
161 | console.log('book表中无该书')
162 | wx.showToast({
163 | title: '抱歉未找到该书',
164 | icon: 'success',
165 | duration: 3000
166 | })
167 | }
168 |
169 | },
170 | error: function (error) {
171 | console.log("查询book表失败: " + error.code + " " + error.message);
172 | }
173 | });
174 | }
175 | }
176 | })
177 | },
178 |
179 | bindBookNameInput: function (e) {
180 | this.setData({
181 | bookName: e.detail.value
182 | })
183 | },
184 | bindBookAuthorInput: function (e) {
185 | this.setData({
186 | bookAuthor: e.detail.value
187 | })
188 | },
189 | bindBookPressInput: function (e) {
190 | this.setData({
191 | bookPress: e.detail.value
192 | })
193 | },
194 | bindBookPriceInput: function (e) {
195 | this.setData({
196 | bookPrice: e.detail.value
197 | })
198 | },
199 |
200 | bindNeedCourse: function (e) {
201 | this.setData({
202 | isTextbook: e.detail.value
203 | })
204 | if (!this.data.isTextbook) {
205 | this.setData({
206 | courseName: ''
207 | })
208 | }
209 | },
210 | bindCourseInput: function (e) {
211 | this.setData({
212 | courseName: e.detail.value
213 | })
214 | },
215 |
216 | bindConditionChange: function (e) {
217 | this.setData({
218 | conditionIndex: e.detail.value
219 | })
220 | },
221 |
222 | bindCampusChange: function (e) {
223 | this.setData({
224 | campusIndex: e.detail.value
225 | })
226 | },
227 |
228 | bindCurrentPriceInput: function (e) {
229 | this.setData({
230 | currentPrice: e.detail.value
231 | })
232 | },
233 |
234 | bindPostRemarkInput: function (e) {
235 | this.setData({
236 | postRemark: e.detail.value
237 | })
238 | },
239 |
240 | bindSubmit: function () {
241 | var that = this;
242 | this.setData({
243 | buttonLoading: true
244 | })
245 |
246 | var Post = Bmob.Object.extend("post");
247 | var post = new Post();
248 | post.set("ownerId", this.data.ownerId);
249 | post.set("ownerNickname", this.data.ownerNickname);
250 | post.set("ownerGender", this.data.ownerGender);
251 | post.set("bookISBN", this.data.bookISBN);
252 | post.set("bookImg", this.data.bookImg);
253 | post.set("bookName", this.data.bookName);
254 | post.set("bookAuthor", this.data.bookAuthor);
255 | post.set("bookPress", this.data.bookPress);
256 | post.set("bookPrice", this.data.bookPrice);
257 | post.set("isTextbook", this.data.isTextbook);
258 | post.set("courseName", this.data.courseName);
259 | post.set("condition", this.data.conditions[this.data.conditionIndex]);
260 | post.set("campus", this.data.campus[this.data.campusIndex]);
261 | post.set("currentPrice", parseInt(this.data.currentPrice));
262 | post.set("bookRemark", this.data.bookRemark);
263 | //添加数据,第一个入口参数是null
264 | post.save(null, {
265 | success: function (result) {
266 | // 添加成功,返回成功之后的objectId(注意:返回的属性名字是id,不是objectId),你还可以在Bmob的Web管理后台看到对应的数据
267 | console.log("创建post成功, objectId:" + result.id);
268 | that.setData({
269 | buttonLoading: false
270 | });
271 | wx.showToast({
272 | title: '发布成功',
273 | icon: 'success',
274 | duration: 3000
275 | })
276 | },
277 | error: function (result, error) {
278 | // 添加失败
279 | console.log('创建post失败',result,error);
280 | that.setData({
281 | buttonLoading: false
282 | })
283 | }
284 | });
285 | }
286 | })
--------------------------------------------------------------------------------
/style/weui.wxss:
--------------------------------------------------------------------------------
1 | page {
2 | line-height: 1.6;
3 | font-family: -apple-system-font, "Helvetica Neue", sans-serif;
4 | }
5 | icon {
6 | vertical-align: middle;
7 | }
8 | .weui-cells {
9 | position: relative;
10 | margin-top: 1.17647059em;
11 | background-color: #FFFFFF;
12 | line-height: 1.41176471;
13 | font-size: 17px;
14 | }
15 | .weui-cells:before {
16 | content: " ";
17 | position: absolute;
18 | left: 0;
19 | top: 0;
20 | right: 0;
21 | height: 1px;
22 | border-top: 1rpx solid #D9D9D9;
23 | color: #D9D9D9;
24 | }
25 | .weui-cells:after {
26 | content: " ";
27 | position: absolute;
28 | left: 0;
29 | bottom: 0;
30 | right: 0;
31 | height: 1px;
32 | border-bottom: 1rpx solid #D9D9D9;
33 | color: #D9D9D9;
34 | }
35 | .weui-cells__title {
36 | margin-top: .77em;
37 | margin-bottom: .3em;
38 | padding-left: 15px;
39 | padding-right: 15px;
40 | color: #999999;
41 | font-size: 14px;
42 | }
43 | .weui-cells_after-title {
44 | margin-top: 0;
45 | }
46 | .weui-cells__tips {
47 | margin-top: .3em;
48 | color: #999999;
49 | padding-left: 15px;
50 | padding-right: 15px;
51 | font-size: 14px;
52 | }
53 | .weui-cell {
54 | padding: 10px 15px;
55 | position: relative;
56 | display: -webkit-box;
57 | display: -webkit-flex;
58 | display: flex;
59 | -webkit-box-align: center;
60 | -webkit-align-items: center;
61 | align-items: center;
62 | }
63 | .weui-cell:before {
64 | content: " ";
65 | position: absolute;
66 | left: 0;
67 | top: 0;
68 | right: 0;
69 | height: 1px;
70 | border-top: 1rpx solid #D9D9D9;
71 | color: #D9D9D9;
72 | left: 15px;
73 | }
74 | .weui-cell:first-child:before {
75 | display: none;
76 | }
77 | .weui-cell_active {
78 | background-color: #ECECEC;
79 | }
80 | .weui-cell_primary {
81 | -webkit-box-align: start;
82 | -webkit-align-items: flex-start;
83 | align-items: flex-start;
84 | }
85 | .weui-cell__bd {
86 | -webkit-box-flex: 1;
87 | -webkit-flex: 1;
88 | flex: 1;
89 | }
90 | .weui-cell__ft {
91 | text-align: right;
92 | color: #999999;
93 | }
94 | .weui-cell_access {
95 | color: inherit;
96 | }
97 | .weui-cell__ft_in-access {
98 | padding-right: 13px;
99 | position: relative;
100 | }
101 | .weui-cell__ft_in-access:after {
102 | content: " ";
103 | display: inline-block;
104 | height: 6px;
105 | width: 6px;
106 | border-width: 2px 2px 0 0;
107 | border-color: #C8C8CD;
108 | border-style: solid;
109 | -webkit-transform: matrix(0.71, 0.71, -0.71, 0.71, 0, 0);
110 | transform: matrix(0.71, 0.71, -0.71, 0.71, 0, 0);
111 | position: relative;
112 | top: -2px;
113 | position: absolute;
114 | top: 50%;
115 | margin-top: -4px;
116 | right: 2px;
117 | }
118 | .weui-cell_link {
119 | color: #586C94;
120 | font-size: 14px;
121 | }
122 | .weui-cell_link:active {
123 | background-color: #ECECEC;
124 | }
125 | .weui-cell_link:first-child:before {
126 | display: block;
127 | }
128 | .weui-icon-radio {
129 | margin-left: 3.2px;
130 | margin-right: 3.2px;
131 | }
132 | .weui-icon-checkbox_circle,
133 | .weui-icon-checkbox_success {
134 | margin-left: 4.6px;
135 | margin-right: 4.6px;
136 | }
137 | .weui-check__label:active {
138 | background-color: #ECECEC;
139 | }
140 | .weui-check {
141 | position: absolute;
142 | left: -9999px;
143 | }
144 | .weui-check__hd_in-checkbox {
145 | padding-right: 0.35em;
146 | }
147 | .weui-cell__ft_in-radio {
148 | padding-left: 0.35em;
149 | }
150 | .weui-cell_input {
151 | padding-top: 0;
152 | padding-bottom: 0;
153 | }
154 | .weui-label {
155 | width: 105px;
156 | word-wrap: break-word;
157 | word-break: break-all;
158 | }
159 | .weui-input {
160 | height: 2.58823529em;
161 | min-height: 2.58823529em;
162 | line-height: 2.58823529em;
163 | }
164 | .weui-toptips {
165 | position: fixed;
166 | -webkit-transform: translateZ(0);
167 | transform: translateZ(0);
168 | top: 0;
169 | left: 0;
170 | right: 0;
171 | padding: 5px;
172 | font-size: 14px;
173 | text-align: center;
174 | color: #FFFFFF;
175 | z-index: 5000;
176 | word-wrap: break-word;
177 | word-break: break-all;
178 | }
179 | .weui-toptips_warn {
180 | background-color: #E64340;
181 | }
182 | .weui-textarea {
183 | display: block;
184 | width: 100%;
185 | }
186 | .weui-textarea-counter {
187 | color: #B2B2B2;
188 | text-align: right;
189 | }
190 | .weui-textarea-counter_warn {
191 | color: #E64340;
192 | }
193 | .weui-cell_warn {
194 | color: #E64340;
195 | }
196 | .weui-form-preview {
197 | position: relative;
198 | background-color: #FFFFFF;
199 | }
200 | .weui-form-preview:before {
201 | content: " ";
202 | position: absolute;
203 | left: 0;
204 | top: 0;
205 | right: 0;
206 | height: 1px;
207 | border-top: 1rpx solid #D9D9D9;
208 | color: #D9D9D9;
209 | }
210 | .weui-form-preview:after {
211 | content: " ";
212 | position: absolute;
213 | left: 0;
214 | bottom: 0;
215 | right: 0;
216 | height: 1px;
217 | border-bottom: 1rpx solid #D9D9D9;
218 | color: #D9D9D9;
219 | }
220 | .weui-form-preview__value {
221 | font-size: 14px;
222 | }
223 | .weui-form-preview__value_in-hd {
224 | font-size: 26px;
225 | }
226 | .weui-form-preview__hd {
227 | position: relative;
228 | padding: 10px 15px;
229 | text-align: right;
230 | line-height: 2.5em;
231 | }
232 | .weui-form-preview__hd:after {
233 | content: " ";
234 | position: absolute;
235 | left: 0;
236 | bottom: 0;
237 | right: 0;
238 | height: 1px;
239 | border-bottom: 1rpx solid #D9D9D9;
240 | color: #D9D9D9;
241 | left: 15px;
242 | }
243 | .weui-form-preview__bd {
244 | padding: 10px 15px;
245 | font-size: .9em;
246 | text-align: right;
247 | color: #999999;
248 | line-height: 2;
249 | }
250 | .weui-form-preview__ft {
251 | position: relative;
252 | line-height: 50px;
253 | display: -webkit-box;
254 | display: -webkit-flex;
255 | display: flex;
256 | }
257 | .weui-form-preview__ft:after {
258 | content: " ";
259 | position: absolute;
260 | left: 0;
261 | top: 0;
262 | right: 0;
263 | height: 1px;
264 | border-top: 1rpx solid #D5D5D6;
265 | color: #D5D5D6;
266 | }
267 | .weui-form-preview__item {
268 | overflow: hidden;
269 | }
270 | .weui-form-preview__label {
271 | float: left;
272 | margin-right: 1em;
273 | min-width: 4em;
274 | color: #999999;
275 | text-align: justify;
276 | text-align-last: justify;
277 | }
278 | .weui-form-preview__value {
279 | display: block;
280 | overflow: hidden;
281 | word-break: normal;
282 | word-wrap: break-word;
283 | }
284 | .weui-form-preview__btn {
285 | position: relative;
286 | display: block;
287 | -webkit-box-flex: 1;
288 | -webkit-flex: 1;
289 | flex: 1;
290 | color: #3CC51F;
291 | text-align: center;
292 | }
293 | .weui-form-preview__btn:after {
294 | content: " ";
295 | position: absolute;
296 | left: 0;
297 | top: 0;
298 | width: 1px;
299 | bottom: 0;
300 | border-left: 1rpx solid #D5D5D6;
301 | color: #D5D5D6;
302 | }
303 | .weui-form-preview__btn:first-child:after {
304 | display: none;
305 | }
306 | .weui-form-preview__btn_active {
307 | background-color: #EEEEEE;
308 | }
309 | .weui-form-preview__btn_default {
310 | color: #999999;
311 | }
312 | .weui-form-preview__btn_primary {
313 | color: #0BB20C;
314 | }
315 | .weui-cell_select {
316 | padding: 0;
317 | }
318 | .weui-select {
319 | position: relative;
320 | padding-left: 15px;
321 | padding-right: 30px;
322 | height: 2.58823529em;
323 | min-height: 2.58823529em;
324 | line-height: 2.58823529em;
325 | border-right: 1rpx solid #D9D9D9;
326 | }
327 | .weui-select:before {
328 | content: " ";
329 | display: inline-block;
330 | height: 6px;
331 | width: 6px;
332 | border-width: 2px 2px 0 0;
333 | border-color: #C8C8CD;
334 | border-style: solid;
335 | -webkit-transform: matrix(0.71, 0.71, -0.71, 0.71, 0, 0);
336 | transform: matrix(0.71, 0.71, -0.71, 0.71, 0, 0);
337 | position: relative;
338 | top: -2px;
339 | position: absolute;
340 | top: 50%;
341 | right: 15px;
342 | margin-top: -4px;
343 | }
344 | .weui-select_in-select-after {
345 | padding-left: 0;
346 | }
347 | .weui-cell__hd_in-select-after,
348 | .weui-cell__bd_in-select-before {
349 | padding-left: 15px;
350 | }
351 | .weui-cell_vcode {
352 | padding-right: 0;
353 | }
354 | .weui-vcode-img {
355 | margin-left: 5px;
356 | height: 2.58823529em;
357 | vertical-align: middle;
358 | }
359 | .weui-vcode-btn {
360 | display: inline-block;
361 | height: 2.58823529em;
362 | margin-left: 5px;
363 | padding: 0 0.6em 0 0.7em;
364 | border-left: 1px solid #E5E5E5;
365 | line-height: 2.58823529em;
366 | vertical-align: middle;
367 | font-size: 17px;
368 | color: #3CC51F;
369 | white-space: nowrap;
370 | }
371 | .weui-vcode-btn:active {
372 | color: #52a341;
373 | }
374 | .weui-cell_switch {
375 | padding-top: 6px;
376 | padding-bottom: 6px;
377 | }
378 | .weui-uploader__hd {
379 | display: -webkit-box;
380 | display: -webkit-flex;
381 | display: flex;
382 | padding-bottom: 10px;
383 | -webkit-box-align: center;
384 | -webkit-align-items: center;
385 | align-items: center;
386 | }
387 | .weui-uploader__title {
388 | -webkit-box-flex: 1;
389 | -webkit-flex: 1;
390 | flex: 1;
391 | }
392 | .weui-uploader__info {
393 | color: #B2B2B2;
394 | }
395 | .weui-uploader__bd {
396 | margin-bottom: -4px;
397 | margin-right: -9px;
398 | overflow: hidden;
399 | }
400 | .weui-uploader__file {
401 | float: left;
402 | margin-right: 9px;
403 | margin-bottom: 9px;
404 | }
405 | .weui-uploader__img {
406 | display: block;
407 | width: 79px;
408 | height: 79px;
409 | }
410 | .weui-uploader__file_status {
411 | position: relative;
412 | }
413 | .weui-uploader__file_status:before {
414 | content: " ";
415 | position: absolute;
416 | top: 0;
417 | right: 0;
418 | bottom: 0;
419 | left: 0;
420 | background-color: rgba(0, 0, 0, 0.5);
421 | }
422 | .weui-uploader__file-content {
423 | position: absolute;
424 | top: 50%;
425 | left: 50%;
426 | -webkit-transform: translate(-50%, -50%);
427 | transform: translate(-50%, -50%);
428 | color: #FFFFFF;
429 | }
430 | .weui-uploader__input-box {
431 | float: left;
432 | position: relative;
433 | margin-right: 9px;
434 | margin-bottom: 9px;
435 | width: 77px;
436 | height: 77px;
437 | border: 1px solid #D9D9D9;
438 | }
439 | .weui-uploader__input-box:before,
440 | .weui-uploader__input-box:after {
441 | content: " ";
442 | position: absolute;
443 | top: 50%;
444 | left: 50%;
445 | -webkit-transform: translate(-50%, -50%);
446 | transform: translate(-50%, -50%);
447 | background-color: #D9D9D9;
448 | }
449 | .weui-uploader__input-box:before {
450 | width: 2px;
451 | height: 39.5px;
452 | }
453 | .weui-uploader__input-box:after {
454 | width: 39.5px;
455 | height: 2px;
456 | }
457 | .weui-uploader__input-box:active {
458 | border-color: #999999;
459 | }
460 | .weui-uploader__input-box:active:before,
461 | .weui-uploader__input-box:active:after {
462 | background-color: #999999;
463 | }
464 | .weui-uploader__input {
465 | position: absolute;
466 | z-index: 1;
467 | top: 0;
468 | left: 0;
469 | width: 100%;
470 | height: 100%;
471 | opacity: 0;
472 | }
473 | .weui-article {
474 | padding: 20px 15px;
475 | font-size: 15px;
476 | }
477 | .weui-article__section {
478 | margin-bottom: 1.5em;
479 | }
480 | .weui-article__h1 {
481 | font-size: 18px;
482 | font-weight: 400;
483 | margin-bottom: .9em;
484 | }
485 | .weui-article__h2 {
486 | font-size: 16px;
487 | font-weight: 400;
488 | margin-bottom: .34em;
489 | }
490 | .weui-article__h3 {
491 | font-weight: 400;
492 | font-size: 15px;
493 | margin-bottom: .34em;
494 | }
495 | .weui-article__p {
496 | margin: 0 0 .8em;
497 | }
498 | .weui-msg {
499 | padding-top: 36px;
500 | text-align: center;
501 | }
502 | .weui-msg__link {
503 | display: inline;
504 | color: #586C94;
505 | }
506 | .weui-msg__icon-area {
507 | margin-bottom: 30px;
508 | }
509 | .weui-msg__text-area {
510 | margin-bottom: 25px;
511 | padding: 0 20px;
512 | }
513 | .weui-msg__title {
514 | margin-bottom: 5px;
515 | font-weight: 400;
516 | font-size: 20px;
517 | }
518 | .weui-msg__desc {
519 | font-size: 14px;
520 | color: #999999;
521 | }
522 | .weui-msg__opr-area {
523 | margin-bottom: 25px;
524 | }
525 | .weui-msg__extra-area {
526 | margin-bottom: 15px;
527 | font-size: 14px;
528 | color: #999999;
529 | }
530 | @media screen and (min-height: 438px) {
531 | .weui-msg__extra-area {
532 | position: fixed;
533 | left: 0;
534 | bottom: 0;
535 | width: 100%;
536 | text-align: center;
537 | }
538 | }
539 | .weui-flex {
540 | display: -webkit-box;
541 | display: -webkit-flex;
542 | display: flex;
543 | }
544 | .weui-flex__item {
545 | -webkit-box-flex: 1;
546 | -webkit-flex: 1;
547 | flex: 1;
548 | }
549 | .weui-btn {
550 | margin-top: 15px;
551 | }
552 | .weui-btn:first-child {
553 | margin-top: 0;
554 | }
555 | .weui-btn-area {
556 | margin: 1.17647059em 15px 0.3em;
557 | }
558 | .weui-agree {
559 | display: block;
560 | padding: .5em 15px;
561 | font-size: 13px;
562 | }
563 | .weui-agree__text {
564 | color: #999999;
565 | }
566 | .weui-agree__link {
567 | display: inline;
568 | color: #586C94;
569 | }
570 | .weui-agree__checkbox {
571 | position: absolute;
572 | left: -9999px;
573 | }
574 | .weui-agree__checkbox-icon {
575 | position: relative;
576 | top: 2px;
577 | display: inline-block;
578 | border: 1px solid #D1D1D1;
579 | background-color: #FFFFFF;
580 | border-radius: 3px;
581 | width: 11px;
582 | height: 11px;
583 | }
584 | .weui-agree__checkbox-icon-check {
585 | position: absolute;
586 | top: 1px;
587 | left: 1px;
588 | }
589 | .weui-footer {
590 | color: #999999;
591 | font-size: 14px;
592 | text-align: center;
593 | }
594 | .weui-footer_fixed-bottom {
595 | position: fixed;
596 | bottom: .52em;
597 | left: 0;
598 | right: 0;
599 | }
600 | .weui-footer__links {
601 | font-size: 0;
602 | }
603 | .weui-footer__link {
604 | display: inline-block;
605 | vertical-align: top;
606 | margin: 0 .62em;
607 | position: relative;
608 | font-size: 14px;
609 | color: #586C94;
610 | }
611 | .weui-footer__link:before {
612 | content: " ";
613 | position: absolute;
614 | left: 0;
615 | top: 0;
616 | width: 1px;
617 | bottom: 0;
618 | border-left: 1rpx solid #C7C7C7;
619 | color: #C7C7C7;
620 | left: -0.65em;
621 | top: .36em;
622 | bottom: .36em;
623 | }
624 | .weui-footer__link:first-child:before {
625 | display: none;
626 | }
627 | .weui-footer__text {
628 | padding: 0 .34em;
629 | font-size: 12px;
630 | }
631 | .weui-grids {
632 | border-top: 1rpx solid #D9D9D9;
633 | border-left: 1rpx solid #D9D9D9;
634 | overflow: hidden;
635 | }
636 | .weui-grid {
637 | position: relative;
638 | float: left;
639 | padding: 20px 10px;
640 | width: 33.33333333%;
641 | box-sizing: border-box;
642 | border-right: 1rpx solid #D9D9D9;
643 | border-bottom: 1rpx solid #D9D9D9;
644 | }
645 | .weui-grid_active {
646 | background-color: #ECECEC;
647 | }
648 | .weui-grid__icon {
649 | display: block;
650 | width: 28px;
651 | height: 28px;
652 | margin: 0 auto;
653 | }
654 | .weui-grid__label {
655 | margin-top: 5px;
656 | display: block;
657 | text-align: center;
658 | color: #000000;
659 | font-size: 14px;
660 | white-space: nowrap;
661 | text-overflow: ellipsis;
662 | overflow: hidden;
663 | }
664 | .weui-loading {
665 | margin: 0 5px;
666 | width: 20px;
667 | height: 20px;
668 | display: inline-block;
669 | vertical-align: middle;
670 | -webkit-animation: weuiLoading 1s steps(12, end) infinite;
671 | animation: weuiLoading 1s steps(12, end) infinite;
672 | background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat;
673 | background-size: 100%;
674 | }
675 | .weui-loading.weui-loading_transparent {
676 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 100 100'%3E%3Cpath fill='none' d='M0 0h100v100H0z'/%3E%3Crect xmlns='http://www.w3.org/2000/svg' width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.56)' rx='5' ry='5' transform='translate(0 -30)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.5)' rx='5' ry='5' transform='rotate(30 105.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.43)' rx='5' ry='5' transform='rotate(60 75.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.38)' rx='5' ry='5' transform='rotate(90 65 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.32)' rx='5' ry='5' transform='rotate(120 58.66 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.28)' rx='5' ry='5' transform='rotate(150 54.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.25)' rx='5' ry='5' transform='rotate(180 50 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.2)' rx='5' ry='5' transform='rotate(-150 45.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.17)' rx='5' ry='5' transform='rotate(-120 41.34 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.14)' rx='5' ry='5' transform='rotate(-90 35 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.1)' rx='5' ry='5' transform='rotate(-60 24.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.03)' rx='5' ry='5' transform='rotate(-30 -5.98 65)'/%3E%3C/svg%3E");
677 | }
678 | @-webkit-keyframes weuiLoading {
679 | 0% {
680 | -webkit-transform: rotate3d(0, 0, 1, 0deg);
681 | transform: rotate3d(0, 0, 1, 0deg);
682 | }
683 | 100% {
684 | -webkit-transform: rotate3d(0, 0, 1, 360deg);
685 | transform: rotate3d(0, 0, 1, 360deg);
686 | }
687 | }
688 | @keyframes weuiLoading {
689 | 0% {
690 | -webkit-transform: rotate3d(0, 0, 1, 0deg);
691 | transform: rotate3d(0, 0, 1, 0deg);
692 | }
693 | 100% {
694 | -webkit-transform: rotate3d(0, 0, 1, 360deg);
695 | transform: rotate3d(0, 0, 1, 360deg);
696 | }
697 | }
698 | .weui-badge {
699 | display: inline-block;
700 | padding: .15em .4em;
701 | min-width: 8px;
702 | border-radius: 18px;
703 | background-color: #E64340;
704 | color: #FFFFFF;
705 | line-height: 1.2;
706 | text-align: center;
707 | font-size: 12px;
708 | vertical-align: middle;
709 | }
710 | .weui-badge_dot {
711 | padding: .4em;
712 | min-width: 0;
713 | }
714 | .weui-loadmore {
715 | width: 65%;
716 | margin: 1.5em auto;
717 | line-height: 1.6em;
718 | font-size: 14px;
719 | text-align: center;
720 | }
721 | .weui-loadmore__tips {
722 | display: inline-block;
723 | vertical-align: middle;
724 | }
725 | .weui-loadmore_line {
726 | border-top: 1px solid #E5E5E5;
727 | margin-top: 2.4em;
728 | }
729 | .weui-loadmore__tips_in-line {
730 | position: relative;
731 | top: -0.9em;
732 | padding: 0 .55em;
733 | background-color: #FFFFFF;
734 | color: #999999;
735 | }
736 | .weui-loadmore__tips_in-dot {
737 | position: relative;
738 | padding: 0 .16em;
739 | width: 4px;
740 | height: 1.6em;
741 | }
742 | .weui-loadmore__tips_in-dot:before {
743 | content: " ";
744 | position: absolute;
745 | top: 50%;
746 | left: 50%;
747 | margin-top: -1px;
748 | margin-left: -2px;
749 | width: 4px;
750 | height: 4px;
751 | border-radius: 50%;
752 | background-color: #E5E5E5;
753 | }
754 | .weui-panel {
755 | background-color: #FFFFFF;
756 | margin-top: 10px;
757 | position: relative;
758 | overflow: hidden;
759 | }
760 | .weui-panel:first-child {
761 | margin-top: 0;
762 | }
763 | .weui-panel:before {
764 | content: " ";
765 | position: absolute;
766 | left: 0;
767 | top: 0;
768 | right: 0;
769 | height: 1px;
770 | border-top: 1rpx solid #E5E5E5;
771 | color: #E5E5E5;
772 | }
773 | .weui-panel:after {
774 | content: " ";
775 | position: absolute;
776 | left: 0;
777 | bottom: 0;
778 | right: 0;
779 | height: 1px;
780 | border-bottom: 1rpx solid #E5E5E5;
781 | color: #E5E5E5;
782 | }
783 | .weui-panel__hd {
784 | padding: 14px 15px 10px;
785 | color: #999999;
786 | font-size: 13px;
787 | position: relative;
788 | }
789 | .weui-panel__hd:after {
790 | content: " ";
791 | position: absolute;
792 | left: 0;
793 | bottom: 0;
794 | right: 0;
795 | height: 1px;
796 | border-bottom: 1rpx solid #E5E5E5;
797 | color: #E5E5E5;
798 | left: 15px;
799 | }
800 | .weui-media-box {
801 | padding: 15px;
802 | position: relative;
803 | }
804 | .weui-media-box:before {
805 | content: " ";
806 | position: absolute;
807 | left: 0;
808 | top: 0;
809 | right: 0;
810 | height: 1px;
811 | border-top: 1rpx solid #E5E5E5;
812 | color: #E5E5E5;
813 | left: 15px;
814 | }
815 | .weui-media-box:first-child:before {
816 | display: none;
817 | }
818 | .weui-media-box__title {
819 | font-weight: 400;
820 | font-size: 17px;
821 | width: auto;
822 | overflow: hidden;
823 | text-overflow: ellipsis;
824 | white-space: nowrap;
825 | word-wrap: normal;
826 | word-wrap: break-word;
827 | word-break: break-all;
828 | }
829 | .weui-media-box__desc {
830 | color: #999999;
831 | font-size: 13px;
832 | line-height: 1.2;
833 | overflow: hidden;
834 | text-overflow: ellipsis;
835 | display: -webkit-box;
836 | -webkit-box-orient: vertical;
837 | -webkit-line-clamp: 2;
838 | }
839 | .weui-media-box__info {
840 | margin-top: 15px;
841 | padding-bottom: 5px;
842 | font-size: 13px;
843 | color: #CECECE;
844 | line-height: 1em;
845 | list-style: none;
846 | overflow: hidden;
847 | }
848 | .weui-media-box__info__meta {
849 | float: left;
850 | padding-right: 1em;
851 | }
852 | .weui-media-box__info__meta_extra {
853 | padding-left: 1em;
854 | border-left: 1px solid #CECECE;
855 | }
856 | .weui-media-box__title_in-text {
857 | margin-bottom: 8px;
858 | }
859 | .weui-media-box_appmsg {
860 | display: -webkit-box;
861 | display: -webkit-flex;
862 | display: flex;
863 | -webkit-box-align: center;
864 | -webkit-align-items: center;
865 | align-items: center;
866 | }
867 | .weui-media-box__thumb {
868 | width: 100%;
869 | height: 100%;
870 | vertical-align: top;
871 | }
872 | .weui-media-box__hd_in-appmsg {
873 | margin-right: .8em;
874 | width: 60px;
875 | height: 60px;
876 | line-height: 60px;
877 | text-align: center;
878 | }
879 | .weui-media-box__bd_in-appmsg {
880 | -webkit-box-flex: 1;
881 | -webkit-flex: 1;
882 | flex: 1;
883 | min-width: 0;
884 | }
885 | .weui-media-box_small-appmsg {
886 | padding: 0;
887 | }
888 | .weui-cells_in-small-appmsg {
889 | margin-top: 0;
890 | }
891 | .weui-cells_in-small-appmsg:before {
892 | display: none;
893 | }
894 | .weui-progress {
895 | display: -webkit-box;
896 | display: -webkit-flex;
897 | display: flex;
898 | -webkit-box-align: center;
899 | -webkit-align-items: center;
900 | align-items: center;
901 | }
902 | .weui-progress__bar {
903 | -webkit-box-flex: 1;
904 | -webkit-flex: 1;
905 | flex: 1;
906 | }
907 | .weui-progress__opr {
908 | margin-left: 15px;
909 | font-size: 0;
910 | }
911 | .weui-navbar {
912 | display: -webkit-box;
913 | display: -webkit-flex;
914 | display: flex;
915 | position: absolute;
916 | z-index: 500;
917 | top: 0;
918 | width: 100%;
919 | border-bottom: 1rpx solid #CCCCCC;
920 | }
921 | .weui-navbar__item {
922 | position: relative;
923 | display: block;
924 | -webkit-box-flex: 1;
925 | -webkit-flex: 1;
926 | flex: 1;
927 | padding: 13px 0;
928 | text-align: center;
929 | font-size: 0;
930 | }
931 | .weui-navbar__item.weui-bar__item_on {
932 | color: #1AAD19;
933 | }
934 | .weui-navbar__slider {
935 | position: absolute;
936 | content: " ";
937 | left: 0;
938 | bottom: 0;
939 | width: 6em;
940 | height: 3px;
941 | background-color: #1AAD19;
942 | -webkit-transition: -webkit-transform .3s;
943 | transition: -webkit-transform .3s;
944 | transition: transform .3s;
945 | transition: transform .3s, -webkit-transform .3s;
946 | }
947 | .weui-navbar__title {
948 | display: inline-block;
949 | font-size: 15px;
950 | max-width: 8em;
951 | width: auto;
952 | overflow: hidden;
953 | text-overflow: ellipsis;
954 | white-space: nowrap;
955 | word-wrap: normal;
956 | }
957 | .weui-tab {
958 | position: relative;
959 | height: 100%;
960 | }
961 | .weui-tab__panel {
962 | box-sizing: border-box;
963 | height: 100%;
964 | padding-top: 50px;
965 | overflow: auto;
966 | -webkit-overflow-scrolling: touch;
967 | }
968 | .weui-search-bar {
969 | position: relative;
970 | padding: 8px 10px;
971 | display: -webkit-box;
972 | display: -webkit-flex;
973 | display: flex;
974 | box-sizing: border-box;
975 | background-color: #EFEFF4;
976 | border-top: 1rpx solid #D7D6DC;
977 | border-bottom: 1rpx solid #D7D6DC;
978 | }
979 | .weui-icon-search {
980 | margin-right: 8px;
981 | font-size: inherit;
982 | }
983 | .weui-icon-search_in-box {
984 | position: absolute;
985 | left: 10px;
986 | top: 7px;
987 | }
988 | .weui-search-bar__text {
989 | display: inline-block;
990 | font-size: 14px;
991 | vertical-align: middle;
992 | }
993 | .weui-search-bar__form {
994 | position: relative;
995 | -webkit-box-flex: 1;
996 | -webkit-flex: auto;
997 | flex: auto;
998 | border-radius: 5px;
999 | background: #FFFFFF;
1000 | border: 1rpx solid #E6E6EA;
1001 | }
1002 | .weui-search-bar__box {
1003 | position: relative;
1004 | padding-left: 30px;
1005 | padding-right: 30px;
1006 | width: 100%;
1007 | box-sizing: border-box;
1008 | z-index: 1;
1009 | }
1010 | .weui-search-bar__input {
1011 | height: 28px;
1012 | line-height: 28px;
1013 | font-size: 14px;
1014 | }
1015 | .weui-icon-clear {
1016 | position: absolute;
1017 | top: 0;
1018 | right: 0;
1019 | padding: 7px 8px;
1020 | font-size: 0;
1021 | }
1022 | .weui-search-bar__label {
1023 | position: absolute;
1024 | top: 0;
1025 | right: 0;
1026 | bottom: 0;
1027 | left: 0;
1028 | z-index: 2;
1029 | border-radius: 3px;
1030 | text-align: center;
1031 | color: #9B9B9B;
1032 | background: #FFFFFF;
1033 | line-height: 28px;
1034 | }
1035 | .weui-search-bar__cancel-btn {
1036 | margin-left: 10px;
1037 | line-height: 28px;
1038 | color: #09BB07;
1039 | white-space: nowrap;
1040 | }
1041 |
--------------------------------------------------------------------------------
/utils/underscore.js:
--------------------------------------------------------------------------------
1 | // Underscore.js 1.8.3
2 | // http://underscorejs.org
3 | // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
4 | // Underscore may be freely distributed under the MIT license.
5 |
6 | (function() {
7 |
8 | // Baseline setup
9 | // --------------
10 |
11 | // Establish the root object, `window` in the browser, or `exports` on the server.
12 | //var root = this;
13 |
14 | // Save the previous value of the `_` variable.
15 | //var previousUnderscore = root._;
16 |
17 | // Save bytes in the minified (but not gzipped) version:
18 | var ArrayProto = Array.prototype,
19 | ObjProto = Object.prototype,
20 | FuncProto = Function.prototype;
21 |
22 | // Create quick reference variables for speed access to core prototypes.
23 | var
24 | push = ArrayProto.push,
25 | slice = ArrayProto.slice,
26 | toString = ObjProto.toString,
27 | hasOwnProperty = ObjProto.hasOwnProperty;
28 |
29 | // All **ECMAScript 5** native function implementations that we hope to use
30 | // are declared here.
31 | var
32 | nativeIsArray = Array.isArray,
33 | nativeKeys = Object.keys,
34 | nativeBind = FuncProto.bind,
35 | nativeCreate = Object.create;
36 |
37 | // Naked function reference for surrogate-prototype-swapping.
38 | var Ctor = function() {};
39 |
40 | // Create a safe reference to the Underscore object for use below.
41 | var _ = function(obj) {
42 | if (obj instanceof _) return obj;
43 | if (!(this instanceof _)) return new _(obj);
44 | this._wrapped = obj;
45 | };
46 |
47 | // Export the Underscore object for **Node.js**, with
48 | // backwards-compatibility for the old `require()` API. If we're in
49 | // the browser, add `_` as a global object.
50 | if (typeof exports !== 'undefined') {
51 | if (typeof module !== 'undefined' && module.exports) {
52 | exports = module.exports = _;
53 | }
54 | exports._ = _;
55 | } else {
56 | root._ = _;
57 | }
58 |
59 | // Current version.
60 | _.VERSION = '1.8.3';
61 |
62 | // Internal function that returns an efficient (for current engines) version
63 | // of the passed-in callback, to be repeatedly applied in other Underscore
64 | // functions.
65 | var optimizeCb = function(func, context, argCount) {
66 | if (context === void 0) return func;
67 | switch (argCount == null ? 3 : argCount) {
68 | case 1:
69 | return function(value) {
70 | return func.call(context, value);
71 | };
72 | case 2:
73 | return function(value, other) {
74 | return func.call(context, value, other);
75 | };
76 | case 3:
77 | return function(value, index, collection) {
78 | return func.call(context, value, index, collection);
79 | };
80 | case 4:
81 | return function(accumulator, value, index, collection) {
82 | return func.call(context, accumulator, value, index, collection);
83 | };
84 | }
85 | return function() {
86 | return func.apply(context, arguments);
87 | };
88 | };
89 |
90 | // A mostly-internal function to generate callbacks that can be applied
91 | // to each element in a collection, returning the desired result — either
92 | // identity, an arbitrary callback, a property matcher, or a property accessor.
93 | var cb = function(value, context, argCount) {
94 | if (value == null) return _.identity;
95 | if (_.isFunction(value)) return optimizeCb(value, context, argCount);
96 | if (_.isObject(value)) return _.matcher(value);
97 | return _.property(value);
98 | };
99 | _.iteratee = function(value, context) {
100 | return cb(value, context, Infinity);
101 | };
102 |
103 | // An internal function for creating assigner functions.
104 | var createAssigner = function(keysFunc, undefinedOnly) {
105 | return function(obj) {
106 | var length = arguments.length;
107 | if (length < 2 || obj == null) return obj;
108 | for (var index = 1; index < length; index++) {
109 | var source = arguments[index],
110 | keys = keysFunc(source),
111 | l = keys.length;
112 | for (var i = 0; i < l; i++) {
113 | var key = keys[i];
114 | if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
115 | }
116 | }
117 | return obj;
118 | };
119 | };
120 |
121 | // An internal function for creating a new object that inherits from another.
122 | var baseCreate = function(prototype) {
123 | if (!_.isObject(prototype)) return {};
124 | if (nativeCreate) return nativeCreate(prototype);
125 | Ctor.prototype = prototype;
126 | var result = new Ctor;
127 | Ctor.prototype = null;
128 | return result;
129 | };
130 |
131 | var property = function(key) {
132 | return function(obj) {
133 | return obj == null ? void 0 : obj[key];
134 | };
135 | };
136 |
137 | // Helper for collection methods to determine whether a collection
138 | // should be iterated as an array or as an object
139 | // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
140 | // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
141 | var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
142 | var getLength = property('length');
143 | var isArrayLike = function(collection) {
144 | var length = getLength(collection);
145 | return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
146 | };
147 |
148 | // Collection Functions
149 | // --------------------
150 |
151 | // The cornerstone, an `each` implementation, aka `forEach`.
152 | // Handles raw objects in addition to array-likes. Treats all
153 | // sparse array-likes as if they were dense.
154 | _.each = _.forEach = function(obj, iteratee, context) {
155 | iteratee = optimizeCb(iteratee, context);
156 | var i, length;
157 | if (isArrayLike(obj)) {
158 | for (i = 0, length = obj.length; i < length; i++) {
159 | iteratee(obj[i], i, obj);
160 | }
161 | } else {
162 | var keys = _.keys(obj);
163 | for (i = 0, length = keys.length; i < length; i++) {
164 | iteratee(obj[keys[i]], keys[i], obj);
165 | }
166 | }
167 | return obj;
168 | };
169 |
170 | // Return the results of applying the iteratee to each element.
171 | _.map = _.collect = function(obj, iteratee, context) {
172 | iteratee = cb(iteratee, context);
173 | var keys = !isArrayLike(obj) && _.keys(obj),
174 | length = (keys || obj).length,
175 | results = Array(length);
176 | for (var index = 0; index < length; index++) {
177 | var currentKey = keys ? keys[index] : index;
178 | results[index] = iteratee(obj[currentKey], currentKey, obj);
179 | }
180 | return results;
181 | };
182 |
183 | // Create a reducing function iterating left or right.
184 | function createReduce(dir) {
185 | // Optimized iterator function as using arguments.length
186 | // in the main function will deoptimize the, see #1991.
187 | function iterator(obj, iteratee, memo, keys, index, length) {
188 | for (; index >= 0 && index < length; index += dir) {
189 | var currentKey = keys ? keys[index] : index;
190 | memo = iteratee(memo, obj[currentKey], currentKey, obj);
191 | }
192 | return memo;
193 | }
194 |
195 | return function(obj, iteratee, memo, context) {
196 | iteratee = optimizeCb(iteratee, context, 4);
197 | var keys = !isArrayLike(obj) && _.keys(obj),
198 | length = (keys || obj).length,
199 | index = dir > 0 ? 0 : length - 1;
200 | // Determine the initial value if none is provided.
201 | if (arguments.length < 3) {
202 | memo = obj[keys ? keys[index] : index];
203 | index += dir;
204 | }
205 | return iterator(obj, iteratee, memo, keys, index, length);
206 | };
207 | }
208 |
209 | // **Reduce** builds up a single result from a list of values, aka `inject`,
210 | // or `foldl`.
211 | _.reduce = _.foldl = _.inject = createReduce(1);
212 |
213 | // The right-associative version of reduce, also known as `foldr`.
214 | _.reduceRight = _.foldr = createReduce(-1);
215 |
216 | // Return the first value which passes a truth test. Aliased as `detect`.
217 | _.find = _.detect = function(obj, predicate, context) {
218 | var key;
219 | if (isArrayLike(obj)) {
220 | key = _.findIndex(obj, predicate, context);
221 | } else {
222 | key = _.findKey(obj, predicate, context);
223 | }
224 | if (key !== void 0 && key !== -1) return obj[key];
225 | };
226 |
227 | // Return all the elements that pass a truth test.
228 | // Aliased as `select`.
229 | _.filter = _.select = function(obj, predicate, context) {
230 | var results = [];
231 | predicate = cb(predicate, context);
232 | _.each(obj, function(value, index, list) {
233 | if (predicate(value, index, list)) results.push(value);
234 | });
235 | return results;
236 | };
237 |
238 | // Return all the elements for which a truth test fails.
239 | _.reject = function(obj, predicate, context) {
240 | return _.filter(obj, _.negate(cb(predicate)), context);
241 | };
242 |
243 | // Determine whether all of the elements match a truth test.
244 | // Aliased as `all`.
245 | _.every = _.all = function(obj, predicate, context) {
246 | predicate = cb(predicate, context);
247 | var keys = !isArrayLike(obj) && _.keys(obj),
248 | length = (keys || obj).length;
249 | for (var index = 0; index < length; index++) {
250 | var currentKey = keys ? keys[index] : index;
251 | if (!predicate(obj[currentKey], currentKey, obj)) return false;
252 | }
253 | return true;
254 | };
255 |
256 | // Determine if at least one element in the object matches a truth test.
257 | // Aliased as `any`.
258 | _.some = _.any = function(obj, predicate, context) {
259 | predicate = cb(predicate, context);
260 | var keys = !isArrayLike(obj) && _.keys(obj),
261 | length = (keys || obj).length;
262 | for (var index = 0; index < length; index++) {
263 | var currentKey = keys ? keys[index] : index;
264 | if (predicate(obj[currentKey], currentKey, obj)) return true;
265 | }
266 | return false;
267 | };
268 |
269 | // Determine if the array or object contains a given item (using `===`).
270 | // Aliased as `includes` and `include`.
271 | _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
272 | if (!isArrayLike(obj)) obj = _.values(obj);
273 | if (typeof fromIndex != 'number' || guard) fromIndex = 0;
274 | return _.indexOf(obj, item, fromIndex) >= 0;
275 | };
276 |
277 | // Invoke a method (with arguments) on every item in a collection.
278 | _.invoke = function(obj, method) {
279 | var args = slice.call(arguments, 2);
280 | var isFunc = _.isFunction(method);
281 | return _.map(obj, function(value) {
282 | var func = isFunc ? method : value[method];
283 | return func == null ? func : func.apply(value, args);
284 | });
285 | };
286 |
287 | // Convenience version of a common use case of `map`: fetching a property.
288 | _.pluck = function(obj, key) {
289 | return _.map(obj, _.property(key));
290 | };
291 |
292 | // Convenience version of a common use case of `filter`: selecting only objects
293 | // containing specific `key:value` pairs.
294 | _.where = function(obj, attrs) {
295 | return _.filter(obj, _.matcher(attrs));
296 | };
297 |
298 | // Convenience version of a common use case of `find`: getting the first object
299 | // containing specific `key:value` pairs.
300 | _.findWhere = function(obj, attrs) {
301 | return _.find(obj, _.matcher(attrs));
302 | };
303 |
304 | // Return the maximum element (or element-based computation).
305 | _.max = function(obj, iteratee, context) {
306 | var result = -Infinity,
307 | lastComputed = -Infinity,
308 | value, computed;
309 | if (iteratee == null && obj != null) {
310 | obj = isArrayLike(obj) ? obj : _.values(obj);
311 | for (var i = 0, length = obj.length; i < length; i++) {
312 | value = obj[i];
313 | if (value > result) {
314 | result = value;
315 | }
316 | }
317 | } else {
318 | iteratee = cb(iteratee, context);
319 | _.each(obj, function(value, index, list) {
320 | computed = iteratee(value, index, list);
321 | if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
322 | result = value;
323 | lastComputed = computed;
324 | }
325 | });
326 | }
327 | return result;
328 | };
329 |
330 | // Return the minimum element (or element-based computation).
331 | _.min = function(obj, iteratee, context) {
332 | var result = Infinity,
333 | lastComputed = Infinity,
334 | value, computed;
335 | if (iteratee == null && obj != null) {
336 | obj = isArrayLike(obj) ? obj : _.values(obj);
337 | for (var i = 0, length = obj.length; i < length; i++) {
338 | value = obj[i];
339 | if (value < result) {
340 | result = value;
341 | }
342 | }
343 | } else {
344 | iteratee = cb(iteratee, context);
345 | _.each(obj, function(value, index, list) {
346 | computed = iteratee(value, index, list);
347 | if (computed < lastComputed || computed === Infinity && result === Infinity) {
348 | result = value;
349 | lastComputed = computed;
350 | }
351 | });
352 | }
353 | return result;
354 | };
355 |
356 | // Shuffle a collection, using the modern version of the
357 | // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
358 | _.shuffle = function(obj) {
359 | var set = isArrayLike(obj) ? obj : _.values(obj);
360 | var length = set.length;
361 | var shuffled = Array(length);
362 | for (var index = 0, rand; index < length; index++) {
363 | rand = _.random(0, index);
364 | if (rand !== index) shuffled[index] = shuffled[rand];
365 | shuffled[rand] = set[index];
366 | }
367 | return shuffled;
368 | };
369 |
370 | // Sample **n** random values from a collection.
371 | // If **n** is not specified, returns a single random element.
372 | // The internal `guard` argument allows it to work with `map`.
373 | _.sample = function(obj, n, guard) {
374 | if (n == null || guard) {
375 | if (!isArrayLike(obj)) obj = _.values(obj);
376 | return obj[_.random(obj.length - 1)];
377 | }
378 | return _.shuffle(obj).slice(0, Math.max(0, n));
379 | };
380 |
381 | // Sort the object's values by a criterion produced by an iteratee.
382 | _.sortBy = function(obj, iteratee, context) {
383 | iteratee = cb(iteratee, context);
384 | return _.pluck(_.map(obj, function(value, index, list) {
385 | return {
386 | value: value,
387 | index: index,
388 | criteria: iteratee(value, index, list)
389 | };
390 | }).sort(function(left, right) {
391 | var a = left.criteria;
392 | var b = right.criteria;
393 | if (a !== b) {
394 | if (a > b || a === void 0) return 1;
395 | if (a < b || b === void 0) return -1;
396 | }
397 | return left.index - right.index;
398 | }), 'value');
399 | };
400 |
401 | // An internal function used for aggregate "group by" operations.
402 | var group = function(behavior) {
403 | return function(obj, iteratee, context) {
404 | var result = {};
405 | iteratee = cb(iteratee, context);
406 | _.each(obj, function(value, index) {
407 | var key = iteratee(value, index, obj);
408 | behavior(result, value, key);
409 | });
410 | return result;
411 | };
412 | };
413 |
414 | // Groups the object's values by a criterion. Pass either a string attribute
415 | // to group by, or a function that returns the criterion.
416 | _.groupBy = group(function(result, value, key) {
417 | if (_.has(result, key)) result[key].push(value);
418 | else result[key] = [value];
419 | });
420 |
421 | // Indexes the object's values by a criterion, similar to `groupBy`, but for
422 | // when you know that your index values will be unique.
423 | _.indexBy = group(function(result, value, key) {
424 | result[key] = value;
425 | });
426 |
427 | // Counts instances of an object that group by a certain criterion. Pass
428 | // either a string attribute to count by, or a function that returns the
429 | // criterion.
430 | _.countBy = group(function(result, value, key) {
431 | if (_.has(result, key)) result[key]++;
432 | else result[key] = 1;
433 | });
434 |
435 | // Safely create a real, live array from anything iterable.
436 | _.toArray = function(obj) {
437 | if (!obj) return [];
438 | if (_.isArray(obj)) return slice.call(obj);
439 | if (isArrayLike(obj)) return _.map(obj, _.identity);
440 | return _.values(obj);
441 | };
442 |
443 | // Return the number of elements in an object.
444 | _.size = function(obj) {
445 | if (obj == null) return 0;
446 | return isArrayLike(obj) ? obj.length : _.keys(obj).length;
447 | };
448 |
449 | // Split a collection into two arrays: one whose elements all satisfy the given
450 | // predicate, and one whose elements all do not satisfy the predicate.
451 | _.partition = function(obj, predicate, context) {
452 | predicate = cb(predicate, context);
453 | var pass = [],
454 | fail = [];
455 | _.each(obj, function(value, key, obj) {
456 | (predicate(value, key, obj) ? pass : fail).push(value);
457 | });
458 | return [pass, fail];
459 | };
460 |
461 | // Array Functions
462 | // ---------------
463 |
464 | // Get the first element of an array. Passing **n** will return the first N
465 | // values in the array. Aliased as `head` and `take`. The **guard** check
466 | // allows it to work with `_.map`.
467 | _.first = _.head = _.take = function(array, n, guard) {
468 | if (array == null) return void 0;
469 | if (n == null || guard) return array[0];
470 | return _.initial(array, array.length - n);
471 | };
472 |
473 | // Returns everything but the last entry of the array. Especially useful on
474 | // the arguments object. Passing **n** will return all the values in
475 | // the array, excluding the last N.
476 | _.initial = function(array, n, guard) {
477 | return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
478 | };
479 |
480 | // Get the last element of an array. Passing **n** will return the last N
481 | // values in the array.
482 | _.last = function(array, n, guard) {
483 | if (array == null) return void 0;
484 | if (n == null || guard) return array[array.length - 1];
485 | return _.rest(array, Math.max(0, array.length - n));
486 | };
487 |
488 | // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
489 | // Especially useful on the arguments object. Passing an **n** will return
490 | // the rest N values in the array.
491 | _.rest = _.tail = _.drop = function(array, n, guard) {
492 | return slice.call(array, n == null || guard ? 1 : n);
493 | };
494 |
495 | // Trim out all falsy values from an array.
496 | _.compact = function(array) {
497 | return _.filter(array, _.identity);
498 | };
499 |
500 | // Internal implementation of a recursive `flatten` function.
501 | var flatten = function(input, shallow, strict, startIndex) {
502 | var output = [],
503 | idx = 0;
504 | for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
505 | var value = input[i];
506 | if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
507 | //flatten current level of array or arguments object
508 | if (!shallow) value = flatten(value, shallow, strict);
509 | var j = 0,
510 | len = value.length;
511 | output.length += len;
512 | while (j < len) {
513 | output[idx++] = value[j++];
514 | }
515 | } else if (!strict) {
516 | output[idx++] = value;
517 | }
518 | }
519 | return output;
520 | };
521 |
522 | // Flatten out an array, either recursively (by default), or just one level.
523 | _.flatten = function(array, shallow) {
524 | return flatten(array, shallow, false);
525 | };
526 |
527 | // Return a version of the array that does not contain the specified value(s).
528 | _.without = function(array) {
529 | return _.difference(array, slice.call(arguments, 1));
530 | };
531 |
532 | // Produce a duplicate-free version of the array. If the array has already
533 | // been sorted, you have the option of using a faster algorithm.
534 | // Aliased as `unique`.
535 | _.uniq = _.unique = function(array, isSorted, iteratee, context) {
536 | if (!_.isBoolean(isSorted)) {
537 | context = iteratee;
538 | iteratee = isSorted;
539 | isSorted = false;
540 | }
541 | if (iteratee != null) iteratee = cb(iteratee, context);
542 | var result = [];
543 | var seen = [];
544 | for (var i = 0, length = getLength(array); i < length; i++) {
545 | var value = array[i],
546 | computed = iteratee ? iteratee(value, i, array) : value;
547 | if (isSorted) {
548 | if (!i || seen !== computed) result.push(value);
549 | seen = computed;
550 | } else if (iteratee) {
551 | if (!_.contains(seen, computed)) {
552 | seen.push(computed);
553 | result.push(value);
554 | }
555 | } else if (!_.contains(result, value)) {
556 | result.push(value);
557 | }
558 | }
559 | return result;
560 | };
561 |
562 | // Produce an array that contains the union: each distinct element from all of
563 | // the passed-in arrays.
564 | _.union = function() {
565 | return _.uniq(flatten(arguments, true, true));
566 | };
567 |
568 | // Produce an array that contains every item shared between all the
569 | // passed-in arrays.
570 | _.intersection = function(array) {
571 | var result = [];
572 | var argsLength = arguments.length;
573 | for (var i = 0, length = getLength(array); i < length; i++) {
574 | var item = array[i];
575 | if (_.contains(result, item)) continue;
576 | for (var j = 1; j < argsLength; j++) {
577 | if (!_.contains(arguments[j], item)) break;
578 | }
579 | if (j === argsLength) result.push(item);
580 | }
581 | return result;
582 | };
583 |
584 | // Take the difference between one array and a number of other arrays.
585 | // Only the elements present in just the first array will remain.
586 | _.difference = function(array) {
587 | var rest = flatten(arguments, true, true, 1);
588 | return _.filter(array, function(value) {
589 | return !_.contains(rest, value);
590 | });
591 | };
592 |
593 | // Zip together multiple lists into a single array -- elements that share
594 | // an index go together.
595 | _.zip = function() {
596 | return _.unzip(arguments);
597 | };
598 |
599 | // Complement of _.zip. Unzip accepts an array of arrays and groups
600 | // each array's elements on shared indices
601 | _.unzip = function(array) {
602 | var length = array && _.max(array, getLength).length || 0;
603 | var result = Array(length);
604 |
605 | for (var index = 0; index < length; index++) {
606 | result[index] = _.pluck(array, index);
607 | }
608 | return result;
609 | };
610 |
611 | // Converts lists into objects. Pass either a single array of `[key, value]`
612 | // pairs, or two parallel arrays of the same length -- one of keys, and one of
613 | // the corresponding values.
614 | _.object = function(list, values) {
615 | var result = {};
616 | for (var i = 0, length = getLength(list); i < length; i++) {
617 | if (values) {
618 | result[list[i]] = values[i];
619 | } else {
620 | result[list[i][0]] = list[i][1];
621 | }
622 | }
623 | return result;
624 | };
625 |
626 | // Generator function to create the findIndex and findLastIndex functions
627 | function createPredicateIndexFinder(dir) {
628 | return function(array, predicate, context) {
629 | predicate = cb(predicate, context);
630 | var length = getLength(array);
631 | var index = dir > 0 ? 0 : length - 1;
632 | for (; index >= 0 && index < length; index += dir) {
633 | if (predicate(array[index], index, array)) return index;
634 | }
635 | return -1;
636 | };
637 | }
638 |
639 | // Returns the first index on an array-like that passes a predicate test
640 | _.findIndex = createPredicateIndexFinder(1);
641 | _.findLastIndex = createPredicateIndexFinder(-1);
642 |
643 | // Use a comparator function to figure out the smallest index at which
644 | // an object should be inserted so as to maintain order. Uses binary search.
645 | _.sortedIndex = function(array, obj, iteratee, context) {
646 | iteratee = cb(iteratee, context, 1);
647 | var value = iteratee(obj);
648 | var low = 0,
649 | high = getLength(array);
650 | while (low < high) {
651 | var mid = Math.floor((low + high) / 2);
652 | if (iteratee(array[mid]) < value) low = mid + 1;
653 | else high = mid;
654 | }
655 | return low;
656 | };
657 |
658 | // Generator function to create the indexOf and lastIndexOf functions
659 | function createIndexFinder(dir, predicateFind, sortedIndex) {
660 | return function(array, item, idx) {
661 | var i = 0,
662 | length = getLength(array);
663 | if (typeof idx == 'number') {
664 | if (dir > 0) {
665 | i = idx >= 0 ? idx : Math.max(idx + length, i);
666 | } else {
667 | length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
668 | }
669 | } else if (sortedIndex && idx && length) {
670 | idx = sortedIndex(array, item);
671 | return array[idx] === item ? idx : -1;
672 | }
673 | if (item !== item) {
674 | idx = predicateFind(slice.call(array, i, length), _.isNaN);
675 | return idx >= 0 ? idx + i : -1;
676 | }
677 | for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
678 | if (array[idx] === item) return idx;
679 | }
680 | return -1;
681 | };
682 | }
683 |
684 | // Return the position of the first occurrence of an item in an array,
685 | // or -1 if the item is not included in the array.
686 | // If the array is large and already in sort order, pass `true`
687 | // for **isSorted** to use binary search.
688 | _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
689 | _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
690 |
691 | // Generate an integer Array containing an arithmetic progression. A port of
692 | // the native Python `range()` function. See
693 | // [the Python documentation](http://docs.python.org/library/functions.html#range).
694 | _.range = function(start, stop, step) {
695 | if (stop == null) {
696 | stop = start || 0;
697 | start = 0;
698 | }
699 | step = step || 1;
700 |
701 | var length = Math.max(Math.ceil((stop - start) / step), 0);
702 | var range = Array(length);
703 |
704 | for (var idx = 0; idx < length; idx++, start += step) {
705 | range[idx] = start;
706 | }
707 |
708 | return range;
709 | };
710 |
711 | // Function (ahem) Functions
712 | // ------------------
713 |
714 | // Determines whether to execute a function as a constructor
715 | // or a normal function with the provided arguments
716 | var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
717 | if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
718 | var self = baseCreate(sourceFunc.prototype);
719 | var result = sourceFunc.apply(self, args);
720 | if (_.isObject(result)) return result;
721 | return self;
722 | };
723 |
724 | // Create a function bound to a given object (assigning `this`, and arguments,
725 | // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
726 | // available.
727 | _.bind = function(func, context) {
728 | if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
729 | if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
730 | var args = slice.call(arguments, 2);
731 | var bound = function() {
732 | return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
733 | };
734 | return bound;
735 | };
736 |
737 | // Partially apply a function by creating a version that has had some of its
738 | // arguments pre-filled, without changing its dynamic `this` context. _ acts
739 | // as a placeholder, allowing any combination of arguments to be pre-filled.
740 | _.partial = function(func) {
741 | var boundArgs = slice.call(arguments, 1);
742 | var bound = function() {
743 | var position = 0,
744 | length = boundArgs.length;
745 | var args = Array(length);
746 | for (var i = 0; i < length; i++) {
747 | args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
748 | }
749 | while (position < arguments.length) args.push(arguments[position++]);
750 | return executeBound(func, bound, this, this, args);
751 | };
752 | return bound;
753 | };
754 |
755 | // Bind a number of an object's methods to that object. Remaining arguments
756 | // are the method names to be bound. Useful for ensuring that all callbacks
757 | // defined on an object belong to it.
758 | _.bindAll = function(obj) {
759 | var i, length = arguments.length,
760 | key;
761 | if (length <= 1) throw new Error('bindAll must be passed function names');
762 | for (i = 1; i < length; i++) {
763 | key = arguments[i];
764 | obj[key] = _.bind(obj[key], obj);
765 | }
766 | return obj;
767 | };
768 |
769 | // Memoize an expensive function by storing its results.
770 | _.memoize = function(func, hasher) {
771 | var memoize = function(key) {
772 | var cache = memoize.cache;
773 | var address = '' + (hasher ? hasher.apply(this, arguments) : key);
774 | if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
775 | return cache[address];
776 | };
777 | memoize.cache = {};
778 | return memoize;
779 | };
780 |
781 | // Delays a function for the given number of milliseconds, and then calls
782 | // it with the arguments supplied.
783 | _.delay = function(func, wait) {
784 | var args = slice.call(arguments, 2);
785 | return setTimeout(function() {
786 | return func.apply(null, args);
787 | }, wait);
788 | };
789 |
790 | // Defers a function, scheduling it to run after the current call stack has
791 | // cleared.
792 | _.defer = _.partial(_.delay, _, 1);
793 |
794 | // Returns a function, that, when invoked, will only be triggered at most once
795 | // during a given window of time. Normally, the throttled function will run
796 | // as much as it can, without ever going more than once per `wait` duration;
797 | // but if you'd like to disable the execution on the leading edge, pass
798 | // `{leading: false}`. To disable execution on the trailing edge, ditto.
799 | _.throttle = function(func, wait, options) {
800 | var context, args, result;
801 | var timeout = null;
802 | var previous = 0;
803 | if (!options) options = {};
804 | var later = function() {
805 | previous = options.leading === false ? 0 : _.now();
806 | timeout = null;
807 | result = func.apply(context, args);
808 | if (!timeout) context = args = null;
809 | };
810 | return function() {
811 | var now = _.now();
812 | if (!previous && options.leading === false) previous = now;
813 | var remaining = wait - (now - previous);
814 | context = this;
815 | args = arguments;
816 | if (remaining <= 0 || remaining > wait) {
817 | if (timeout) {
818 | clearTimeout(timeout);
819 | timeout = null;
820 | }
821 | previous = now;
822 | result = func.apply(context, args);
823 | if (!timeout) context = args = null;
824 | } else if (!timeout && options.trailing !== false) {
825 | timeout = setTimeout(later, remaining);
826 | }
827 | return result;
828 | };
829 | };
830 |
831 | // Returns a function, that, as long as it continues to be invoked, will not
832 | // be triggered. The function will be called after it stops being called for
833 | // N milliseconds. If `immediate` is passed, trigger the function on the
834 | // leading edge, instead of the trailing.
835 | _.debounce = function(func, wait, immediate) {
836 | var timeout, args, context, timestamp, result;
837 |
838 | var later = function() {
839 | var last = _.now() - timestamp;
840 |
841 | if (last < wait && last >= 0) {
842 | timeout = setTimeout(later, wait - last);
843 | } else {
844 | timeout = null;
845 | if (!immediate) {
846 | result = func.apply(context, args);
847 | if (!timeout) context = args = null;
848 | }
849 | }
850 | };
851 |
852 | return function() {
853 | context = this;
854 | args = arguments;
855 | timestamp = _.now();
856 | var callNow = immediate && !timeout;
857 | if (!timeout) timeout = setTimeout(later, wait);
858 | if (callNow) {
859 | result = func.apply(context, args);
860 | context = args = null;
861 | }
862 |
863 | return result;
864 | };
865 | };
866 |
867 | // Returns the first function passed as an argument to the second,
868 | // allowing you to adjust arguments, run code before and after, and
869 | // conditionally execute the original function.
870 | _.wrap = function(func, wrapper) {
871 | return _.partial(wrapper, func);
872 | };
873 |
874 | // Returns a negated version of the passed-in predicate.
875 | _.negate = function(predicate) {
876 | return function() {
877 | return !predicate.apply(this, arguments);
878 | };
879 | };
880 |
881 | // Returns a function that is the composition of a list of functions, each
882 | // consuming the return value of the function that follows.
883 | _.compose = function() {
884 | var args = arguments;
885 | var start = args.length - 1;
886 | return function() {
887 | var i = start;
888 | var result = args[start].apply(this, arguments);
889 | while (i--) result = args[i].call(this, result);
890 | return result;
891 | };
892 | };
893 |
894 | // Returns a function that will only be executed on and after the Nth call.
895 | _.after = function(times, func) {
896 | return function() {
897 | if (--times < 1) {
898 | return func.apply(this, arguments);
899 | }
900 | };
901 | };
902 |
903 | // Returns a function that will only be executed up to (but not including) the Nth call.
904 | _.before = function(times, func) {
905 | var memo;
906 | return function() {
907 | if (--times > 0) {
908 | memo = func.apply(this, arguments);
909 | }
910 | if (times <= 1) func = null;
911 | return memo;
912 | };
913 | };
914 |
915 | // Returns a function that will be executed at most one time, no matter how
916 | // often you call it. Useful for lazy initialization.
917 | _.once = _.partial(_.before, 2);
918 |
919 | // Object Functions
920 | // ----------------
921 |
922 | // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
923 | var hasEnumBug = !{ toString: null }.propertyIsEnumerable('toString');
924 | var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
925 | 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'
926 | ];
927 |
928 | function collectNonEnumProps(obj, keys) {
929 | var nonEnumIdx = nonEnumerableProps.length;
930 | var constructor = obj.constructor;
931 | var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
932 |
933 | // Constructor is a special case.
934 | var prop = 'constructor';
935 | if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
936 |
937 | while (nonEnumIdx--) {
938 | prop = nonEnumerableProps[nonEnumIdx];
939 | if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
940 | keys.push(prop);
941 | }
942 | }
943 | }
944 |
945 | // Retrieve the names of an object's own properties.
946 | // Delegates to **ECMAScript 5**'s native `Object.keys`
947 | _.keys = function(obj) {
948 | if (!_.isObject(obj)) return [];
949 | if (nativeKeys) return nativeKeys(obj);
950 | var keys = [];
951 | for (var key in obj)
952 | if (_.has(obj, key)) keys.push(key);
953 | // Ahem, IE < 9.
954 | if (hasEnumBug) collectNonEnumProps(obj, keys);
955 | return keys;
956 | };
957 |
958 | // Retrieve all the property names of an object.
959 | _.allKeys = function(obj) {
960 | if (!_.isObject(obj)) return [];
961 | var keys = [];
962 | for (var key in obj) keys.push(key);
963 | // Ahem, IE < 9.
964 | if (hasEnumBug) collectNonEnumProps(obj, keys);
965 | return keys;
966 | };
967 |
968 | // Retrieve the values of an object's properties.
969 | _.values = function(obj) {
970 | var keys = _.keys(obj);
971 | var length = keys.length;
972 | var values = Array(length);
973 | for (var i = 0; i < length; i++) {
974 | values[i] = obj[keys[i]];
975 | }
976 | return values;
977 | };
978 |
979 | // Returns the results of applying the iteratee to each element of the object
980 | // In contrast to _.map it returns an object
981 | _.mapObject = function(obj, iteratee, context) {
982 | iteratee = cb(iteratee, context);
983 | var keys = _.keys(obj),
984 | length = keys.length,
985 | results = {},
986 | currentKey;
987 | for (var index = 0; index < length; index++) {
988 | currentKey = keys[index];
989 | results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
990 | }
991 | return results;
992 | };
993 |
994 | // Convert an object into a list of `[key, value]` pairs.
995 | _.pairs = function(obj) {
996 | var keys = _.keys(obj);
997 | var length = keys.length;
998 | var pairs = Array(length);
999 | for (var i = 0; i < length; i++) {
1000 | pairs[i] = [keys[i], obj[keys[i]]];
1001 | }
1002 | return pairs;
1003 | };
1004 |
1005 | // Invert the keys and values of an object. The values must be serializable.
1006 | _.invert = function(obj) {
1007 | var result = {};
1008 | var keys = _.keys(obj);
1009 | for (var i = 0, length = keys.length; i < length; i++) {
1010 | result[obj[keys[i]]] = keys[i];
1011 | }
1012 | return result;
1013 | };
1014 |
1015 | // Return a sorted list of the function names available on the object.
1016 | // Aliased as `methods`
1017 | _.functions = _.methods = function(obj) {
1018 | var names = [];
1019 | for (var key in obj) {
1020 | if (_.isFunction(obj[key])) names.push(key);
1021 | }
1022 | return names.sort();
1023 | };
1024 |
1025 | // Extend a given object with all the properties in passed-in object(s).
1026 | _.extend = createAssigner(_.allKeys);
1027 |
1028 | // Assigns a given object with all the own properties in the passed-in object(s)
1029 | // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
1030 | _.extendOwn = _.assign = createAssigner(_.keys);
1031 |
1032 | // Returns the first key on an object that passes a predicate test
1033 | _.findKey = function(obj, predicate, context) {
1034 | predicate = cb(predicate, context);
1035 | var keys = _.keys(obj),
1036 | key;
1037 | for (var i = 0, length = keys.length; i < length; i++) {
1038 | key = keys[i];
1039 | if (predicate(obj[key], key, obj)) return key;
1040 | }
1041 | };
1042 |
1043 | // Return a copy of the object only containing the whitelisted properties.
1044 | _.pick = function(object, oiteratee, context) {
1045 | var result = {},
1046 | obj = object,
1047 | iteratee, keys;
1048 | if (obj == null) return result;
1049 | if (_.isFunction(oiteratee)) {
1050 | keys = _.allKeys(obj);
1051 | iteratee = optimizeCb(oiteratee, context);
1052 | } else {
1053 | keys = flatten(arguments, false, false, 1);
1054 | iteratee = function(value, key, obj) { return key in obj; };
1055 | obj = Object(obj);
1056 | }
1057 | for (var i = 0, length = keys.length; i < length; i++) {
1058 | var key = keys[i];
1059 | var value = obj[key];
1060 | if (iteratee(value, key, obj)) result[key] = value;
1061 | }
1062 | return result;
1063 | };
1064 |
1065 | // Return a copy of the object without the blacklisted properties.
1066 | _.omit = function(obj, iteratee, context) {
1067 | if (_.isFunction(iteratee)) {
1068 | iteratee = _.negate(iteratee);
1069 | } else {
1070 | var keys = _.map(flatten(arguments, false, false, 1), String);
1071 | iteratee = function(value, key) {
1072 | return !_.contains(keys, key);
1073 | };
1074 | }
1075 | return _.pick(obj, iteratee, context);
1076 | };
1077 |
1078 | // Fill in a given object with default properties.
1079 | _.defaults = createAssigner(_.allKeys, true);
1080 |
1081 | // Creates an object that inherits from the given prototype object.
1082 | // If additional properties are provided then they will be added to the
1083 | // created object.
1084 | _.create = function(prototype, props) {
1085 | var result = baseCreate(prototype);
1086 | if (props) _.extendOwn(result, props);
1087 | return result;
1088 | };
1089 |
1090 | // Create a (shallow-cloned) duplicate of an object.
1091 | _.clone = function(obj) {
1092 | if (!_.isObject(obj)) return obj;
1093 | return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
1094 | };
1095 |
1096 | // Invokes interceptor with the obj, and then returns obj.
1097 | // The primary purpose of this method is to "tap into" a method chain, in
1098 | // order to perform operations on intermediate results within the chain.
1099 | _.tap = function(obj, interceptor) {
1100 | interceptor(obj);
1101 | return obj;
1102 | };
1103 |
1104 | // Returns whether an object has a given set of `key:value` pairs.
1105 | _.isMatch = function(object, attrs) {
1106 | var keys = _.keys(attrs),
1107 | length = keys.length;
1108 | if (object == null) return !length;
1109 | var obj = Object(object);
1110 | for (var i = 0; i < length; i++) {
1111 | var key = keys[i];
1112 | if (attrs[key] !== obj[key] || !(key in obj)) return false;
1113 | }
1114 | return true;
1115 | };
1116 |
1117 |
1118 | // Internal recursive comparison function for `isEqual`.
1119 | var eq = function(a, b, aStack, bStack) {
1120 | // Identical objects are equal. `0 === -0`, but they aren't identical.
1121 | // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
1122 | if (a === b) return a !== 0 || 1 / a === 1 / b;
1123 | // A strict comparison is necessary because `null == undefined`.
1124 | if (a == null || b == null) return a === b;
1125 | // Unwrap any wrapped objects.
1126 | if (a instanceof _) a = a._wrapped;
1127 | if (b instanceof _) b = b._wrapped;
1128 | // Compare `[[Class]]` names.
1129 | var className = toString.call(a);
1130 | if (className !== toString.call(b)) return false;
1131 | switch (className) {
1132 | // Strings, numbers, regular expressions, dates, and booleans are compared by value.
1133 | case '[object RegExp]':
1134 | // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
1135 | case '[object String]':
1136 | // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
1137 | // equivalent to `new String("5")`.
1138 | return '' + a === '' + b;
1139 | case '[object Number]':
1140 | // `NaN`s are equivalent, but non-reflexive.
1141 | // Object(NaN) is equivalent to NaN
1142 | if (+a !== +a) return +b !== +b;
1143 | // An `egal` comparison is performed for other numeric values.
1144 | return +a === 0 ? 1 / +a === 1 / b : +a === +b;
1145 | case '[object Date]':
1146 | case '[object Boolean]':
1147 | // Coerce dates and booleans to numeric primitive values. Dates are compared by their
1148 | // millisecond representations. Note that invalid dates with millisecond representations
1149 | // of `NaN` are not equivalent.
1150 | return +a === +b;
1151 | }
1152 |
1153 | var areArrays = className === '[object Array]';
1154 | if (!areArrays) {
1155 | if (typeof a != 'object' || typeof b != 'object') return false;
1156 |
1157 | // Objects with different constructors are not equivalent, but `Object`s or `Array`s
1158 | // from different frames are.
1159 | var aCtor = a.constructor,
1160 | bCtor = b.constructor;
1161 | if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
1162 | _.isFunction(bCtor) && bCtor instanceof bCtor) &&
1163 | ('constructor' in a && 'constructor' in b)) {
1164 | return false;
1165 | }
1166 | }
1167 | // Assume equality for cyclic structures. The algorithm for detecting cyclic
1168 | // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
1169 |
1170 | // Initializing stack of traversed objects.
1171 | // It's done here since we only need them for objects and arrays comparison.
1172 | aStack = aStack || [];
1173 | bStack = bStack || [];
1174 | var length = aStack.length;
1175 | while (length--) {
1176 | // Linear search. Performance is inversely proportional to the number of
1177 | // unique nested structures.
1178 | if (aStack[length] === a) return bStack[length] === b;
1179 | }
1180 |
1181 | // Add the first object to the stack of traversed objects.
1182 | aStack.push(a);
1183 | bStack.push(b);
1184 |
1185 | // Recursively compare objects and arrays.
1186 | if (areArrays) {
1187 | // Compare array lengths to determine if a deep comparison is necessary.
1188 | length = a.length;
1189 | if (length !== b.length) return false;
1190 | // Deep compare the contents, ignoring non-numeric properties.
1191 | while (length--) {
1192 | if (!eq(a[length], b[length], aStack, bStack)) return false;
1193 | }
1194 | } else {
1195 | // Deep compare objects.
1196 | var keys = _.keys(a),
1197 | key;
1198 | length = keys.length;
1199 | // Ensure that both objects contain the same number of properties before comparing deep equality.
1200 | if (_.keys(b).length !== length) return false;
1201 | while (length--) {
1202 | // Deep compare each member
1203 | key = keys[length];
1204 | if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
1205 | }
1206 | }
1207 | // Remove the first object from the stack of traversed objects.
1208 | aStack.pop();
1209 | bStack.pop();
1210 | return true;
1211 | };
1212 |
1213 | // Perform a deep comparison to check if two objects are equal.
1214 | _.isEqual = function(a, b) {
1215 | return eq(a, b);
1216 | };
1217 |
1218 | // Is a given array, string, or object empty?
1219 | // An "empty" object has no enumerable own-properties.
1220 | _.isEmpty = function(obj) {
1221 | if (obj == null) return true;
1222 | if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
1223 | return _.keys(obj).length === 0;
1224 | };
1225 |
1226 | // Is a given value a DOM element?
1227 | _.isElement = function(obj) {
1228 | return !!(obj && obj.nodeType === 1);
1229 | };
1230 |
1231 | // Is a given value an array?
1232 | // Delegates to ECMA5's native Array.isArray
1233 | _.isArray = nativeIsArray || function(obj) {
1234 | return toString.call(obj) === '[object Array]';
1235 | };
1236 |
1237 | // Is a given variable an object?
1238 | _.isObject = function(obj) {
1239 | var type = typeof obj;
1240 | return type === 'function' || type === 'object' && !!obj;
1241 | };
1242 |
1243 | // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
1244 | _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
1245 | _['is' + name] = function(obj) {
1246 | return toString.call(obj) === '[object ' + name + ']';
1247 | };
1248 | });
1249 |
1250 | // Define a fallback version of the method in browsers (ahem, IE < 9), where
1251 | // there isn't any inspectable "Arguments" type.
1252 | if (!_.isArguments(arguments)) {
1253 | _.isArguments = function(obj) {
1254 | return _.has(obj, 'callee');
1255 | };
1256 | }
1257 |
1258 | // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
1259 | // IE 11 (#1621), and in Safari 8 (#1929).
1260 | if (typeof /./ != 'function' && typeof Int8Array != 'object') {
1261 | _.isFunction = function(obj) {
1262 | return typeof obj == 'function' || false;
1263 | };
1264 | }
1265 |
1266 | // Is a given object a finite number?
1267 | _.isFinite = function(obj) {
1268 | return isFinite(obj) && !isNaN(parseFloat(obj));
1269 | };
1270 |
1271 | // Is the given value `NaN`? (NaN is the only number which does not equal itself).
1272 | _.isNaN = function(obj) {
1273 | return _.isNumber(obj) && obj !== +obj;
1274 | };
1275 |
1276 | // Is a given value a boolean?
1277 | _.isBoolean = function(obj) {
1278 | return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
1279 | };
1280 |
1281 | // Is a given value equal to null?
1282 | _.isNull = function(obj) {
1283 | return obj === null;
1284 | };
1285 |
1286 | // Is a given variable undefined?
1287 | _.isUndefined = function(obj) {
1288 | return obj === void 0;
1289 | };
1290 |
1291 | // Shortcut function for checking if an object has a given property directly
1292 | // on itself (in other words, not on a prototype).
1293 | _.has = function(obj, key) {
1294 | return obj != null && hasOwnProperty.call(obj, key);
1295 | };
1296 |
1297 | // Utility Functions
1298 | // -----------------
1299 |
1300 | // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
1301 | // previous owner. Returns a reference to the Underscore object.
1302 | _.noConflict = function() {
1303 | root._ = previousUnderscore;
1304 | return this;
1305 | };
1306 |
1307 | // Keep the identity function around for default iteratees.
1308 | _.identity = function(value) {
1309 | return value;
1310 | };
1311 |
1312 | // Predicate-generating functions. Often useful outside of Underscore.
1313 | _.constant = function(value) {
1314 | return function() {
1315 | return value;
1316 | };
1317 | };
1318 |
1319 | _.noop = function() {};
1320 |
1321 | _.property = property;
1322 |
1323 | // Generates a function for a given object that returns a given property.
1324 | _.propertyOf = function(obj) {
1325 | return obj == null ? function() {} : function(key) {
1326 | return obj[key];
1327 | };
1328 | };
1329 |
1330 | // Returns a predicate for checking whether an object has a given set of
1331 | // `key:value` pairs.
1332 | _.matcher = _.matches = function(attrs) {
1333 | attrs = _.extendOwn({}, attrs);
1334 | return function(obj) {
1335 | return _.isMatch(obj, attrs);
1336 | };
1337 | };
1338 |
1339 | // Run a function **n** times.
1340 | _.times = function(n, iteratee, context) {
1341 | var accum = Array(Math.max(0, n));
1342 | iteratee = optimizeCb(iteratee, context, 1);
1343 | for (var i = 0; i < n; i++) accum[i] = iteratee(i);
1344 | return accum;
1345 | };
1346 |
1347 | // Return a random integer between min and max (inclusive).
1348 | _.random = function(min, max) {
1349 | if (max == null) {
1350 | max = min;
1351 | min = 0;
1352 | }
1353 | return min + Math.floor(Math.random() * (max - min + 1));
1354 | };
1355 |
1356 | // A (possibly faster) way to get the current timestamp as an integer.
1357 | _.now = Date.now || function() {
1358 | return new Date().getTime();
1359 | };
1360 |
1361 | // List of HTML entities for escaping.
1362 | var escapeMap = {
1363 | '&': '&',
1364 | '<': '<',
1365 | '>': '>',
1366 | '"': '"',
1367 | "'": ''',
1368 | '`': '`'
1369 | };
1370 | var unescapeMap = _.invert(escapeMap);
1371 |
1372 | // Functions for escaping and unescaping strings to/from HTML interpolation.
1373 | var createEscaper = function(map) {
1374 | var escaper = function(match) {
1375 | return map[match];
1376 | };
1377 | // Regexes for identifying a key that needs to be escaped
1378 | var source = '(?:' + _.keys(map).join('|') + ')';
1379 | var testRegexp = RegExp(source);
1380 | var replaceRegexp = RegExp(source, 'g');
1381 | return function(string) {
1382 | string = string == null ? '' : '' + string;
1383 | return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
1384 | };
1385 | };
1386 | _.escape = createEscaper(escapeMap);
1387 | _.unescape = createEscaper(unescapeMap);
1388 |
1389 | // If the value of the named `property` is a function then invoke it with the
1390 | // `object` as context; otherwise, return it.
1391 | _.result = function(object, property, fallback) {
1392 | var value = object == null ? void 0 : object[property];
1393 | if (value === void 0) {
1394 | value = fallback;
1395 | }
1396 | return _.isFunction(value) ? value.call(object) : value;
1397 | };
1398 |
1399 | // Generate a unique integer id (unique within the entire client session).
1400 | // Useful for temporary DOM ids.
1401 | var idCounter = 0;
1402 | _.uniqueId = function(prefix) {
1403 | var id = ++idCounter + '';
1404 | return prefix ? prefix + id : id;
1405 | };
1406 |
1407 | // By default, Underscore uses ERB-style template delimiters, change the
1408 | // following template settings to use alternative delimiters.
1409 | _.templateSettings = {
1410 | evaluate: /<%([\s\S]+?)%>/g,
1411 | interpolate: /<%=([\s\S]+?)%>/g,
1412 | escape: /<%-([\s\S]+?)%>/g
1413 | };
1414 |
1415 | // When customizing `templateSettings`, if you don't want to define an
1416 | // interpolation, evaluation or escaping regex, we need one that is
1417 | // guaranteed not to match.
1418 | var noMatch = /(.)^/;
1419 |
1420 | // Certain characters need to be escaped so that they can be put into a
1421 | // string literal.
1422 | var escapes = {
1423 | "'": "'",
1424 | '\\': '\\',
1425 | '\r': 'r',
1426 | '\n': 'n',
1427 | '\u2028': 'u2028',
1428 | '\u2029': 'u2029'
1429 | };
1430 |
1431 | var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
1432 |
1433 | var escapeChar = function(match) {
1434 | return '\\' + escapes[match];
1435 | };
1436 |
1437 | // JavaScript micro-templating, similar to John Resig's implementation.
1438 | // Underscore templating handles arbitrary delimiters, preserves whitespace,
1439 | // and correctly escapes quotes within interpolated code.
1440 | // NB: `oldSettings` only exists for backwards compatibility.
1441 | _.template = function(text, settings, oldSettings) {
1442 | if (!settings && oldSettings) settings = oldSettings;
1443 | settings = _.defaults({}, settings, _.templateSettings);
1444 |
1445 | // Combine delimiters into one regular expression via alternation.
1446 | var matcher = RegExp([
1447 | (settings.escape || noMatch).source,
1448 | (settings.interpolate || noMatch).source,
1449 | (settings.evaluate || noMatch).source
1450 | ].join('|') + '|$', 'g');
1451 |
1452 | // Compile the template source, escaping string literals appropriately.
1453 | var index = 0;
1454 | var source = "__p+='";
1455 | text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
1456 | source += text.slice(index, offset).replace(escaper, escapeChar);
1457 | index = offset + match.length;
1458 |
1459 | if (escape) {
1460 | source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
1461 | } else if (interpolate) {
1462 | source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
1463 | } else if (evaluate) {
1464 | source += "';\n" + evaluate + "\n__p+='";
1465 | }
1466 |
1467 | // Adobe VMs need the match returned to produce the correct offest.
1468 | return match;
1469 | });
1470 | source += "';\n";
1471 |
1472 | // If a variable is not specified, place data values in local scope.
1473 | if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
1474 |
1475 | source = "var __t,__p='',__j=Array.prototype.join," +
1476 | "print=function(){__p+=__j.call(arguments,'');};\n" +
1477 | source + 'return __p;\n';
1478 |
1479 | try {
1480 | var render = new Function(settings.variable || 'obj', '_', source);
1481 | } catch (e) {
1482 | e.source = source;
1483 | throw e;
1484 | }
1485 |
1486 | var template = function(data) {
1487 | return render.call(this, data, _);
1488 | };
1489 |
1490 | // Provide the compiled source as a convenience for precompilation.
1491 | var argument = settings.variable || 'obj';
1492 | template.source = 'function(' + argument + '){\n' + source + '}';
1493 |
1494 | return template;
1495 | };
1496 |
1497 | // Add a "chain" function. Start chaining a wrapped Underscore object.
1498 | _.chain = function(obj) {
1499 | var instance = _(obj);
1500 | instance._chain = true;
1501 | return instance;
1502 | };
1503 |
1504 | // OOP
1505 | // ---------------
1506 | // If Underscore is called as a function, it returns a wrapped object that
1507 | // can be used OO-style. This wrapper holds altered versions of all the
1508 | // underscore functions. Wrapped objects may be chained.
1509 |
1510 | // Helper function to continue chaining intermediate results.
1511 | var result = function(instance, obj) {
1512 | return instance._chain ? _(obj).chain() : obj;
1513 | };
1514 |
1515 | // Add your own custom functions to the Underscore object.
1516 | _.mixin = function(obj) {
1517 | _.each(_.functions(obj), function(name) {
1518 | var func = _[name] = obj[name];
1519 | _.prototype[name] = function() {
1520 | var args = [this._wrapped];
1521 | push.apply(args, arguments);
1522 | return result(this, func.apply(_, args));
1523 | };
1524 | });
1525 | };
1526 |
1527 | // Add all of the Underscore functions to the wrapper object.
1528 | _.mixin(_);
1529 |
1530 | // Add all mutator Array functions to the wrapper.
1531 | _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
1532 | var method = ArrayProto[name];
1533 | _.prototype[name] = function() {
1534 | var obj = this._wrapped;
1535 | method.apply(obj, arguments);
1536 | if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
1537 | return result(this, obj);
1538 | };
1539 | });
1540 |
1541 | // Add all accessor Array functions to the wrapper.
1542 | _.each(['concat', 'join', 'slice'], function(name) {
1543 | var method = ArrayProto[name];
1544 | _.prototype[name] = function() {
1545 | return result(this, method.apply(this._wrapped, arguments));
1546 | };
1547 | });
1548 |
1549 | // Extracts the result from a wrapped and chained object.
1550 | _.prototype.value = function() {
1551 | return this._wrapped;
1552 | };
1553 |
1554 | // Provide unwrapping proxy for some methods used in engine operations
1555 | // such as arithmetic and JSON stringification.
1556 | _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
1557 |
1558 | _.prototype.toString = function() {
1559 | return '' + this._wrapped;
1560 | };
1561 |
1562 | // AMD registration happens at the end for compatibility with AMD loaders
1563 | // that may not enforce next-turn semantics on modules. Even though general
1564 | // practice for AMD registration is to be anonymous, underscore registers
1565 | // as a named module because, like jQuery, it is a base library that is
1566 | // popular enough to be bundled in a third party lib, but not be part of
1567 | // an AMD load request. Those cases could generate an error when an
1568 | // anonymous define() is called outside of a loader request.
1569 | if (typeof define === 'function' && define.amd) {
1570 | define('underscore', [], function() {
1571 | return _;
1572 | });
1573 | }
1574 | }.call(this));
--------------------------------------------------------------------------------