806d3c4a by simon

版本提交

1 parent 5f588c45
Showing 367 changed files with 6367 additions and 110 deletions
...@@ -20,6 +20,8 @@ App({ ...@@ -20,6 +20,8 @@ App({
20 onLaunch: function () {}, 20 onLaunch: function () {},
21 globalData: { 21 globalData: {
22 indexInfo: null, 22 indexInfo: null,
23 userInfo: null 23 userInfo: null,
24 wxcode: store.getItem("wxcode"),
25 tlMemberCode: ""
24 } 26 }
25 }) 27 })
......
1 { 1 {
2 "pages": [ 2 "pages": [
3 "pages/index/index", 3 "pages/index/index",
4 "pages/authorize/authorize",
5 "pages/wish/wish",
6 "pages/create-wish/create-wish",
7 "pages/new-welfare/new-welfare",
8 "pages/user-table/user-table",
9 "pages/rank/rank",
10 "pages/poster/poster",
11 "pages/coop/coop",
4 "pages/example/example", 12 "pages/example/example",
5 "pages/more/more" 13 "pages/more/more"
6 ], 14 ],
...@@ -9,24 +17,5 @@ ...@@ -9,24 +17,5 @@
9 "navigationBarBackgroundColor": "#fff", 17 "navigationBarBackgroundColor": "#fff",
10 "navigationBarTitleText": "心愿单", 18 "navigationBarTitleText": "心愿单",
11 "navigationBarTextStyle": "black" 19 "navigationBarTextStyle": "black"
12 },
13 "tabBar": {
14 "color": "#7A7E83",
15 "selectedColor": "#CF4646",
16 "borderStyle": "black",
17 "backgroundColor": "#ffffff",
18 "list": [{
19 "pagePath": "pages/index/index",
20 "iconPath": "image/tabbar/home_D.png",
21 "selectedIconPath": "image/tabbar/home.png",
22 "text": "介绍"
23 },
24 {
25 "pagePath": "pages/more/more",
26 "iconPath": "image/tabbar/set_D.png",
27 "selectedIconPath": "image/tabbar/set.png",
28 "text": "更多"
29 }
30 ]
31 } 20 }
32 } 21 }
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
27 justify-content: space-between; 27 justify-content: space-between;
28 // text-align: center; 28 // text-align: center;
29 box-sizing: border-box; 29 box-sizing: border-box;
30 font-family: -apple-system-font, Helvetica Neue, Helvetica, sans-serif, FZY3JW-GB1-0; 30 font-family: SourceHanSansCN, -apple-system-font, Helvetica Neue, Helvetica, sans-serif, FZY3JW-GB1-0;
31 } 31 }
32 32
33 .app__width { 33 .app__width {
...@@ -89,7 +89,7 @@ ...@@ -89,7 +89,7 @@
89 89
90 @font-face { 90 @font-face {
91 font-family: "iconfont"; 91 font-family: "iconfont";
92 src:url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAOsAAsAAAAAB6gAAANdAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgqDDIJmATYCJAMMCwgABCAFhG0HORuvBsgOJUHBwIABAAlgPHyN/f7c3UVEk0mi+3QSQxJNJCoexUrxUhhKIyT4UsKbL89+kizTNWb3wyt7UkR96ayA4xev1q04fZzIa32ey/Gt5wc26luWy5iT9qKFAcYBBbQ3RgEFWiAJesPYlRdxn0C9YccRqxl5ZcBCYSwLxJFS3gwsUk6lpj7UCtUle4t4Yqo2XaeXAHj0vx//QUhYkFRlxtq1w/Q2kPRz+iOmhipDoM51Gx7PD3aIjBlAITZLgxuoMDODUq8YTerLqxUhjRU3GgFfqeqrzT88kiCqGbWNYAJlEz+nbQmJP1h91rUZVMPcGeAZM51XhqohJw97O/vO23paqy3T6coNhsqQ1esr3nVWF19mTZ3YnOwtWwPk5bvMfvYCQV11V+xUzZx02tPO6H02TtP0y4dn5a7M9ravfPvs/poNl43TTmVrW87O66dcKzd3myo2Tjo5rW07l6+fcXXd3KmUDdBKXH240GtvAAw49qfa2BeatkTevUsumTJX5pzRRVy781FXe+YP15YALi0+kkDHQRm8OLz2sP/U1NGjIPxKdyVpafxHpKWvbajtddvnaxmZHLP0XGY1d2wvLarJWrd3LMD6Q1DiSPHusrPgvOxtlAKDyt7bk32nH3emP+npcwo2dKU/Vj040Jn2+HTvAU5VFtOf5vZDf683NVrpbEvIO7N3IX421A40MRbmdVIPQGXQhMi7/+o3vjanTBtt4/7Vygr4/p/GIHW7aqBWorXqz7QVQMVYCK4xXLnISlup57Ntpvcth3Ju8j8aod2b/tauu8+FWl0xkhpDyGqNEIWZQZUG86hWawH1pmUebtBBQolShynjAKHVFSTNPpG1ekUU5jWqdPuGaq1Bod56OJ7ZYCyUdKqEmjFqgy3dUNkqCozlwXRQX4Lk7VyzlNT4XAWSNMo4DA4IyuYzkYCkMTZoOuQhGDOQkUQeZoDHEMeJUC2JKtSKAxQYq2MCA5myFwW0ijygrZAgzTCkDdSiG6TUSiRg3MEYnft8CUSuHaeZVNNTka6ASDSUo0PBAgS1IDKNQquea3lGo4NcCAxjQAyJiAdlgFkIhyOC1OWzVJBWWABFj5RajECzH9PWGDC/mX++Q1DPGJsjRY6i5hgx1hSNwhTxatwNAAAAAA==') format('woff2'), 92 src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAOsAAsAAAAAB6gAAANdAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgqDDIJmATYCJAMMCwgABCAFhG0HORuvBsgOJUHBwIABAAlgPHyN/f7c3UVEk0mi+3QSQxJNJCoexUrxUhhKIyT4UsKbL89+kizTNWb3wyt7UkR96ayA4xev1q04fZzIa32ey/Gt5wc26luWy5iT9qKFAcYBBbQ3RgEFWiAJesPYlRdxn0C9YccRqxl5ZcBCYSwLxJFS3gwsUk6lpj7UCtUle4t4Yqo2XaeXAHj0vx//QUhYkFRlxtq1w/Q2kPRz+iOmhipDoM51Gx7PD3aIjBlAITZLgxuoMDODUq8YTerLqxUhjRU3GgFfqeqrzT88kiCqGbWNYAJlEz+nbQmJP1h91rUZVMPcGeAZM51XhqohJw97O/vO23paqy3T6coNhsqQ1esr3nVWF19mTZ3YnOwtWwPk5bvMfvYCQV11V+xUzZx02tPO6H02TtP0y4dn5a7M9ravfPvs/poNl43TTmVrW87O66dcKzd3myo2Tjo5rW07l6+fcXXd3KmUDdBKXH240GtvAAw49qfa2BeatkTevUsumTJX5pzRRVy781FXe+YP15YALi0+kkDHQRm8OLz2sP/U1NGjIPxKdyVpafxHpKWvbajtddvnaxmZHLP0XGY1d2wvLarJWrd3LMD6Q1DiSPHusrPgvOxtlAKDyt7bk32nH3emP+npcwo2dKU/Vj040Jn2+HTvAU5VFtOf5vZDf683NVrpbEvIO7N3IX421A40MRbmdVIPQGXQhMi7/+o3vjanTBtt4/7Vygr4/p/GIHW7aqBWorXqz7QVQMVYCK4xXLnISlup57Ntpvcth3Ju8j8aod2b/tauu8+FWl0xkhpDyGqNEIWZQZUG86hWawH1pmUebtBBQolShynjAKHVFSTNPpG1ekUU5jWqdPuGaq1Bod56OJ7ZYCyUdKqEmjFqgy3dUNkqCozlwXRQX4Lk7VyzlNT4XAWSNMo4DA4IyuYzkYCkMTZoOuQhGDOQkUQeZoDHEMeJUC2JKtSKAxQYq2MCA5myFwW0ijygrZAgzTCkDdSiG6TUSiRg3MEYnft8CUSuHaeZVNNTka6ASDSUo0PBAgS1IDKNQquea3lGo4NcCAxjQAyJiAdlgFkIhyOC1OWzVJBWWABFj5RajECzH9PWGDC/mX++Q1DPGJsjRY6i5hgx1hSNwhTxatwNAAAAAA==') format('woff2'),
93 } 93 }
94 94
95 .iconfont { 95 .iconfont {
...@@ -98,7 +98,7 @@ ...@@ -98,7 +98,7 @@
98 font-style: normal; 98 font-style: normal;
99 -webkit-font-smoothing: antialiased; 99 -webkit-font-smoothing: antialiased;
100 -moz-osx-font-smoothing: grayscale; 100 -moz-osx-font-smoothing: grayscale;
101 } 101 }
102 102
103 .iconrefresh:before { 103 .iconrefresh:before {
104 content: "\e874"; 104 content: "\e874";
...@@ -111,3 +111,8 @@ ...@@ -111,3 +111,8 @@
111 .drop-down-item :last-child { 111 .drop-down-item :last-child {
112 border-bottom: none; 112 border-bottom: none;
113 } 113 }
114
115
116 .van-popup {
117 background-color: transparent !important;
118 }
......
...@@ -8,6 +8,24 @@ ...@@ -8,6 +8,24 @@
8 * 8 *
9 */ 9 */
10 10
11 // 居中按钮样式
12 @mixin btn-center($width, $height) {
13 width: $width;
14 height: $height;
15 line-height: $height;
16 text-align: center;
17 }
18
19 // 超过多少行自动省略 默认一行
20 @mixin ellipsis($line:1) {
21 display: -webkit-box;
22 word-break: break-all;
23 -webkit-box-orient: vertical;
24 -webkit-line-clamp: $line;
25 overflow: hidden;
26 text-overflow: ellipsis;
27 }
28
11 // 文字截取 29 // 文字截取
12 @mixin text-overflow() { 30 @mixin text-overflow() {
13 overflow: hidden; 31 overflow: hidden;
...@@ -32,11 +50,13 @@ ...@@ -32,11 +50,13 @@
32 50
33 // 清除浮动 51 // 清除浮动
34 @mixin clearfix() { 52 @mixin clearfix() {
53
35 &:before, 54 &:before,
36 &:after { 55 &:after {
37 content: " "; // 1 56 content: " "; // 1
38 display: table; // 2 57 display: table; // 2
39 } 58 }
59
40 &:after { 60 &:after {
41 clear: both; 61 clear: both;
42 } 62 }
......
...@@ -39,3 +39,5 @@ $fontSizeSmall: 28px; ...@@ -39,3 +39,5 @@ $fontSizeSmall: 28px;
39 $fontSizeSmaller: 24px; 39 $fontSizeSmaller: 24px;
40 $fontSizeLarge: 36px; 40 $fontSizeLarge: 36px;
41 $fontSizeLarger: 44px; 41 $fontSizeLarger: 44px;
42
43 $pageBottom:80px;
......
1 Component({
2 properties: {
3 // 这里定义了innerText属性,属性值可以在组件使用时指定
4 innerText: {
5 type: String,
6 value: 'default value',
7 }
8 },
9 data: {
10 // 这里是一些组件内部数据
11 someData: {}
12 },
13 methods: {
14 // 这里是一个自定义方法
15 customMethod() {
16 this.triggerEvent('evtcomp', {
17 name: "_evt_custom"
18 })
19 },
20 // 隐藏蒙层
21 hideMask() {
22 this.triggerEvent('evtcomp', {
23 name: "_evt_hide_authorize"
24 });
25 }
26 }
27 })
1 .comp-item{
2 width: 557px;
3 height: 505px;
4 border-radius: 10px;
5 background-color: #ffffff;
6 }
1 <view class="comp-item">
2
3 </view>
...@@ -12,6 +12,16 @@ Component({ ...@@ -12,6 +12,16 @@ Component({
12 }, 12 },
13 methods: { 13 methods: {
14 // 这里是一个自定义方法 14 // 这里是一个自定义方法
15 customMethod() {} 15 customMethod() {
16 this.triggerEvent('evtcomp', {
17 name: "_evt_custom"
18 })
19 },
20 // 隐藏蒙层
21 hideMask() {
22 this.triggerEvent('evtcomp', {
23 name: "_evt_hide_product_detail_mask"
24 });
25 }
16 } 26 }
17 }) 27 })
......
1 <view class="demo-item">demo-item</view> 1 <view class="comp-item">comp-item</view>
......
1 Component({
2 properties: {
3 // 这里定义了innerText属性,属性值可以在组件使用时指定
4 innerText: {
5 type: String,
6 value: 'default value',
7 }
8 },
9 data: {
10 // 这里是一些组件内部数据
11 someData: {}
12 },
13 methods: {
14 // 这里是一个自定义方法
15 customMethod() {
16 this.triggerEvent('evtcomp', {
17 name: "_evt_custom"
18 })
19 },
20 // 隐藏蒙层
21 hideMask() {
22 this.triggerEvent('evtcomp', {
23 name: "_evt_hide_product_detail_mask"
24 });
25 }
26 }
27 })
1 .comp-item {
2 .bg {
3 position: absolute;
4 width: 654px;
5 height: 911px;
6 }
7 }
1 <view class="comp-item">
2 <image class="bg" src="../../image/rule/rule_c1.png" mode="widthFix" />
3 </view>
1 module.exports = { 1 module.exports = {
2 mockApi: 'http://mock.simonfungc.com', 2 mockApi: 'http://mock.simonfungc.com',
3 Dev: { 3 Dev: {
4 baseApi: 'https://dev-api.xxx.com' 4 baseApi: 'https://ow.go.qudone.com'
5 }, 5 },
6 Test: { 6 Test: {
7 baseApi: 'https://test-api.xxx.com' 7 baseApi: 'https://test-api.xxx.com'
...@@ -10,6 +10,6 @@ module.exports = { ...@@ -10,6 +10,6 @@ module.exports = {
10 baseApi: 'https://slave-api.xxx.com' 10 baseApi: 'https://slave-api.xxx.com'
11 }, 11 },
12 Prod: { 12 Prod: {
13 baseApi: 'https://api.xxx.com' 13 baseApi: 'https://api.k.wxpai.cn/bizproxy'
14 } 14 }
15 } 15 }
......
1 module.exports = { 1 module.exports = {
2 index: '/xxx/index', // Index 接口 2 login: '/warubiEyeCreamApi/app/login', // 通过wxcode换取sessionId
3 decrypt: '/xxx/decrypt', // 解析用户信息 3 index: '/warubiEyeCreamApi/app/index', // Index 接口
4 register: '/warubiEyeCreamApi/app/register', // 注册(用户授权)
4 } 5 }
......
1 let config = require('./../config'); 1 let config = require('./../config');
2 let Store = require('./../utils/stroage'); 2 let Store = require('./../utils/stroage');
3 const reason = '服务异常,请稍后重试'; 3 let Router = require('./../router/index');
4 const errMsg = '服务异常,请稍后重试';
4 5
5 // 检查并获取sessionid sid:是否需要验证sessionId 6 // 检查并获取sessionid
6 function checkSessionId(sid) { 7 function checkSessionId() {
7 return new Promise((resolve, reject) => { 8 return new Promise((resolve, reject) => {
8 if (!sid) {
9 resolve();
10 return;
11 }
12 let sessionId = Store.getItem('sessionId'); 9 let sessionId = Store.getItem('sessionId');
13 if (sessionId) { 10 if (sessionId) {
14 resolve(sessionId); 11 resolve();
15 } else { 12 } else {
16 // 身份失效 13 // 没有sessionId则获取并埋值
17 //登陆失效的回调 14 wx.login({
18 // Store.clear("sessionId"); 15 success: function (res) {
19 // wx.reLaunch({ 16 console.log("wxlogin:", res);
20 // // url: '/pages/authorize/authorize' 17 Store.setItem('wxcode', res.code);
21 // url: '/pages/login/login', 18 let baseUrl = config.NET_CONFIG.baseApi;
22 // }) 19 wx.request({
20 url: baseUrl + '/warubiEyeCreamApi/app/login',
21 data: {
22 code: res.code
23 },
24 method: 'POST', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
25 // header: {}, // 设置请求的 header
26 success: function (res2) {
27 let {
28 code,
29 content
30 } = res2.data;
31 if (code == 200 && content.sessionId) {
32 Store.setItem('sessionId', content.sessionId);
33 resolve();
34 } else {
35 wx.showToast({
36 title: errMsg,
37 icon: 'none'
38 });
39 reject();
40 }
41 // console.log("sid:", Store.getItem('sessionId'));
42 // resolve();
43 }
44 })
45 }
46 });
23 } 47 }
24 }); 48 });
25 } 49 }
...@@ -28,6 +52,7 @@ const fetch = function ({ ...@@ -28,6 +52,7 @@ const fetch = function ({
28 loading = false, 52 loading = false,
29 toast = true, 53 toast = true,
30 sid = true, 54 sid = true,
55 auth = true,
31 mode, 56 mode,
32 isMock, 57 isMock,
33 url, 58 url,
...@@ -54,15 +79,18 @@ const fetch = function ({ ...@@ -54,15 +79,18 @@ const fetch = function ({
54 } 79 }
55 80
56 checkSessionId().then((result) => { 81 checkSessionId().then((result) => {
57 if (sid) { 82 // if (sid) {
58 url += "?sessionId=" + Store.getItem("sessionId") 83 // url += "?sessionId=" + Store.getItem("sessionId")
59 } 84 // }
85 // url += "?sessionId=" + Store.getItem("sessionId")
60 // console.log("url:", url); 86 // console.log("url:", url);
61 wx.request({ 87 wx.request({
62 url: baseUrl + url, //请求地址 88 url: baseUrl + url, //请求地址
63 data: data, //自定义参数 89 data: data, //自定义参数
64 method: method || 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT 90 method: method || 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
65 // header: {}, // 设置请求的 header的默认参数,根据项目需求添加 91 header: {
92 sessionId: Store.getItem("sessionId")
93 }, // 设置请求的 header的默认参数,根据项目需求添加
66 // header: { 94 // header: {
67 // 'clientInfo': JSON.stringify(clientInfo), 95 // 'clientInfo': JSON.stringify(clientInfo),
68 // 'Server-Token':'xxx' 96 // 'Server-Token':'xxx'
...@@ -86,6 +114,15 @@ const fetch = function ({ ...@@ -86,6 +114,15 @@ const fetch = function ({
86 wx.reLaunch({ 114 wx.reLaunch({
87 url: '/pages/authorize/authorize' 115 url: '/pages/authorize/authorize'
88 }) 116 })
117 return;
118
119 // Router.push({
120 // path: "authorize",
121 // openType: "reLaunch",
122 // query: {
123 // status: '404'
124 // }
125 // })
89 } 126 }
90 // 内部统一的成功code拦截码 127 // 内部统一的成功code拦截码
91 if (res.code === 200) { 128 if (res.code === 200) {
...@@ -129,8 +166,6 @@ const fetch = function ({ ...@@ -129,8 +166,6 @@ const fetch = function ({
129 } 166 }
130 }) 167 })
131 }) 168 })
132
133
134 }); 169 });
135 return promise; 170 return promise;
136 } 171 }
......
...@@ -3,37 +3,35 @@ let config = require('../../config'); ...@@ -3,37 +3,35 @@ let config = require('../../config');
3 3
4 Page({ 4 Page({
5 data: { 5 data: {
6 authorized: true, 6 authorized: false,
7 canIUse: wx.canIUse('button.open-type.getUserInfo') 7 canIUse: wx.canIUse('button.open-type.getUserInfo')
8 }, 8 },
9 onLoad(options) {}, 9 onShareAppMessage() {},
10 onReady() { 10 onReady() {
11 wx.showLoading(); 11 wx.showLoading();
12 this.autoAuth(); 12 this.autoAuth();
13 }, 13 },
14 onLoad(options) {},
15 onShow() {},
14 bindGetUserInfo(e) { 16 bindGetUserInfo(e) {
15 wx.showLoading(); 17 wx.showLoading();
16 this.getUserInfo(e.detail); 18 this.getUserInfo(e.detail);
17 }, 19 },
18 // 点openType==userInfo 手动登陆
19 getUserInfo(e) { 20 getUserInfo(e) {
20 let _this = this; 21 let _this = this;
21 // 直接就能拿到 userInfo
22 app.globalData.userInfo = e.userInfo; 22 app.globalData.userInfo = e.userInfo;
23 wx.login({
24 success: function (res) {
25 app.post({ 23 app.post({
26 url: app.api.decrypt, 24 url: app.api.register,
25 sid: false,
27 data: { 26 data: {
28 encryptedData: e.encryptedData, 27 encryptedData: e.encryptedData,
29 iv: e.iv, 28 iv: e.iv,
30 code: res.code 29 code: app.globalData.wxcode,
30 tlMemberCode: app.globalData.tlMemberCode
31 } 31 }
32 }).then((res2) => { 32 }).then((res2) => {
33 _this.autoAuth(); 33 _this.autoAuth();
34 }).catch((err) => {}) 34 }).catch((err) => {})
35 }
36 });
37 }, 35 },
38 // 刷新首页数据 36 // 刷新首页数据
39 refreshIndexData() { 37 refreshIndexData() {
...@@ -49,32 +47,37 @@ Page({ ...@@ -49,32 +47,37 @@ Page({
49 }); 47 });
50 }); 48 });
51 }, 49 },
52 // 判断结果去首页 50 // 自动授权
53 autoAuth() { 51 autoAuth() {
54 // 调用自动登陆方法
55 let _this = this; 52 let _this = this;
56 this.refreshIndexData().then((result) => { 53 this.refreshIndexData().then((result) => {
57 let indexInfo = app.globalData.indexInfo; 54 if (result.isNeedAuth == 1) {
58 // 自动登陆成功 55 // 未授权
59 let loginSuc = true; 56 wx.login({
60 if (loginSuc) { 57 success: function (res) {
61 // 登陆成功跳转到首页 58 app.store.setItem("wxcode", res.code);
62 setTimeout(() => { 59 }
63 app.router.push({ 60 });
64 path: 'index',
65 query: {},
66 duration: 0,
67 openType: "redirect"
68 })
69 wx.hideLoading();
70 }, 3000);
71 } else {
72 // 登陆失败,隐藏loading自动登陆
73 wx.hideLoading(); 61 wx.hideLoading();
74 this.setData({ 62 _this.setData({
75 authorized: false 63 authorized: false
76 }) 64 })
65 } else {
66 // 已经授权
67 // setTimeout(() => {
68 _this.toIndex();
69 wx.hideLoading();
70 // }, 2000);
77 } 71 }
78 }); 72 });
73 },
74 // 跳转到首页
75 toIndex() {
76 app.router.push({
77 path: "index",
78 openType: "redirect"
79 })
80 wx.hideLoading();
79 } 81 }
82
80 }) 83 })
......
...@@ -4,31 +4,74 @@ ...@@ -4,31 +4,74 @@
4 position: relative; 4 position: relative;
5 overflow: hidden; 5 overflow: hidden;
6 6
7 .bgc {} 7 .bgc {
8 8 // background-color: transparent;
9 .bg {} 9 // background-color: black;
10 background-color: #fafafc;
11 }
10 12
11 13
14 .main {
12 15
16 position: relative;
13 17
14 .main { 18 .top-space {
19 height: 60px;
20 }
15 21
16 .login-wrap {
17 padding-top: 946px;
18 22
19 .login-btn { 23 .login {
20 width: 340px; 24 position: relative;
21 height: 80px; 25 width: 650px;
22 line-height: 80px;
23 border-radius: 40px;
24 border: solid 3px #4bc2ed;
25 margin: 0 auto; 26 margin: 0 auto;
26 font-size: 36px;
27 color: #4bc2ed;
28 text-align: center; 27 text-align: center;
29 background-color: transparent; 28
29 &-logo {
30 width: 140px;
31 height: 140px;
30 } 32 }
33
34 &-name {
35 margin-top: 32px;
36 font-size: 32px;
37 color: #333333;
38 }
39
40 &-line {
41 margin-top: 70px;
42 width: 650px;
43 height: 2px;
44 background-color: #eaeaec;
31 } 45 }
46
47 &-title {
48 margin-top: 40px;
49 font-size: 32px;
50 text-align: left;
51 color: #333333;
52 }
53
54
55 &-tips {
56 margin-top: 28px;
57 font-size: 26px;
58 text-align: left;
59 color: #666666;
60 }
61
62 &-btn {
63 margin-top: 102px;
64 width: 650px;
65 height: 90px;
66 line-height: 90px;
67 border-radius: 8px;
68 background-color: #00c200;
69 font-size: 32px;
70 color: #ffffff;
71 }
72
73 }
74
32 } 75 }
33 76
34 } 77 }
......
1 <navbar navbar-data='{{navbarData}}'></navbar>
2 <view style='height: {{barHeight}}px'></view>
1 <view class="page-authorize page"> 3 <view class="page-authorize page">
2 <view class="app__bgc bgc"></view> 4 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view> 5 <view class="app__bg bg"></view>
4 <!-- <view class="app__top-shadow"></view> --> 6 <!-- <view class="app__top-shadow"></view> -->
5 <view class="app__content main"> 7 <view class="app__content main">
6 <view class="login-wrap"> 8 <view class="top-space"></view>
7 <button class="login-btn" wx:if="{{!authorized}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo"> 9 <view class="login">
8 同意微信授权 10 <image class="login-logo" src="../../image/logo.png" mode="aspectFit" />
11 <view class="login-name">丸美</view>
12 <view class="login-line"></view>
13 <view class="login-title">完整体验小程序功能,需要您的微信授权</view>
14 <view class="login-tips">· 获取您的公开信息(昵称、头像等)</view>
15 <button type="default" class="login-btn" wx:if="{{!authorized}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">
16 确认授权
9 </button> 17 </button>
10 </view> 18 </view>
11 </view> 19 </view>
......
1 let app = getApp();
2 Page({
3 data: {},
4 onShareAppMessage() {},
5 onLoad(options) {},
6 // 子组件事件
7 evtcomp(evt) {
8 let {
9 name,
10 data
11 } = evt.detail;
12 switch (name) {
13
14 case "_evt_hide":
15 break;
16
17 default:
18 break;
19 }
20 },
21 })
1 {
2 "navigationBarTitleText": "more"
3 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 .bgc {}
6
7 .bg {}
8
9 .main {
10 .top-space {
11 height: 0px;
12 }
13
14 .content {
15 position: relative;
16 }
17 }
18 }
1 <view class="page">
2 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view>
4 <!-- <view class="app__top-shadow"></view> -->
5 <view class="app__content main">
6 <view class="top-space"></view>
7 <view class="content"></view>
8 </view>
9 </view>
1 let app = getApp();
2 Page({
3 data: {
4 ruleVisible: true,
5 },
6 onShareAppMessage() {},
7 onLoad(options) {}
8 })
1 {
2 "navigationBarTitleText": "丸美心愿单",
3 "usingComponents": {
4 "rule-comp": "../../component/rule-comp/rule-comp",
5 "van-popup": "../../ui/vant-weapp/popup/index"
6 }
7 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 .bgc {}
6
7 .bg {}
8
9 .main {
10 .top-space {
11 height: 0px;
12 }
13
14 .content {
15 position: relative;
16 }
17 }
18 }
1 <view class="page">
2 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view>
4 <view class="app__content main">
5 <view class="top-space"></view>
6 <view class="content">create-wish</view>
7 </view>
8 </view>
9 <van-popup show="{{ ruleVisible }}">
10 <rule-comp bind:evtcomp="evtcomp"></rule-comp>
11 </van-popup>
1 let app = getApp(); 1 let app = getApp();
2 Page({ 2 Page({
3 data: {}, 3 data: {},
4 onLoad(options) {} 4 onShareAppMessage() {},
5 onLoad(options) {},
6 // 子组件事件
7 evtcomp(evt) {
8 let {
9 name,
10 data
11 } = evt.detail;
12 switch (name) {
13
14 case "_evt_hide":
15 break;
16
17 default:
18 break;
19 }
20 },
5 }) 21 })
......
1 let app = getApp(); 1 let app = getApp();
2 Page({ 2 Page({
3 data: {}, 3 data: {
4 onLoad(options) {} 4 authorized: true,
5 canIUse: wx.canIUse('button.open-type.getUserInfo')
6 },
7 onShareAppMessage() {},
8 onLoad(options) {},
9 // 子组件事件
10 evtcomp(evt) {
11 let {
12 name,
13 data
14 } = evt.detail;
15 switch (name) {
16
17 case "_evt_hide":
18 break;
19
20 default:
21 break;
22 }
23 },
24 // 开始互动游戏
25 onStartHandler() {
26 let path = "createWish";
27 app.router.push({
28 path: "createWish"
29 })
30 }
5 }) 31 })
......
1 { 1 {
2 "navigationBarTitleText": "index" 2 "navigationBarTitleText": "我的心愿单",
3 "usingComponents": {
4 "authorize-comp": "../../component/authorize-comp/authorize-comp",
5 "van-popup": "../../ui/vant-weapp/popup/index"
6 }
3 } 7 }
......
...@@ -2,17 +2,58 @@ ...@@ -2,17 +2,58 @@
2 @import '../../assets/scss/utils'; 2 @import '../../assets/scss/utils';
3 3
4 .page { 4 .page {
5 .bgc {} 5 .bgc {
6 image {
7 width: 100%;
8 height: 100%;
9 }
10 }
11
12 .bg {
13 image {
14 position: absolute;
15 width: 750px;
16 height: 1303px;
17 top: -130px;
18 }
19 }
20
21 .decoration {
22 position: relative;
23
24 .d1 {
25 position: absolute;
26 width: 160px;
27 height: 192px;
28 top: 0;
29 left: 0;
30 }
6 31
7 .bg {} 32 .d2 {
33 position: fixed;
34 width: 301px;
35 height: 195px;
36 left: 0;
37 bottom: 0;
38 }
39 }
8 40
9 .main { 41 .main {
10 .top-space { 42 .top-space {
11 height: 0px; 43 height: 1042px;
12 } 44 }
13 45
14 .content { 46 .content {
47 .btn {
15 position: relative; 48 position: relative;
49 margin: 0 auto;
50 @include btn-center(336px, 88px);
51 border-radius: 44px;
52 background-image: linear-gradient(to right, #b83138, #f2234a 51%, #b83138);
53 font-weight: 300;
54 font-size: 32px;
55 color: #fff;
56 }
16 } 57 }
17 } 58 }
18 } 59 }
......
1 <view class="page"> 1 <view class="page">
2 <view class="app__bgc bgc"></view> 2 <view class="app__bgc bgc">
3 <view class="app__bg bg"></view> 3 <image src="../../image/index/index_c1.png" mode="scaleToFill" />
4 <!-- <view class="app__top-shadow"></view> --> 4 </view>
5 <view class="app__bg bg">
6 <image src="../../image/index/index_c2.png" mode="scaleToFill" />
7 </view>
8 <view class="decoration">
9 <image class="d1" src="../../image/index/index_c4.png" mode="widthFix" />
10 <image class="d2" src="../../image/index/index_c3.png" mode="widthFix" />
11 </view>
5 <view class="app__content main"> 12 <view class="app__content main">
6 <view class="top-space"></view> 13 <view class="top-space"></view>
7 <view class="content"></view> 14 <view class="content">
15 <!-- 已授权 直接到下一步操作 -->
16 <button class="btn" wx:if="{{authorized}}" bindtap="onStartHandler">马上测弹力值</button>
17 <!-- 未授权 拉起授权弹窗 -->
18 <!-- <button class="btn" wx:else open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">马上测弹力值2</button> -->
19 </view>
8 </view> 20 </view>
21
9 </view> 22 </view>
23 <!-- <van-popup show="{{ authorizeVisible }}" >
24 <authorize-comp bind:evtcomp="evtcomp"></authorize-comp>
25 </van-popup> -->
......
1 let app = getApp();
2 Page({
3 data: {},
4 onShareAppMessage() {},
5 onLoad(options) {},
6 // 子组件事件
7 evtcomp(evt) {
8 let {
9 name,
10 data
11 } = evt.detail;
12 switch (name) {
13
14 case "_evt_hide":
15 break;
16
17 default:
18 break;
19 }
20 },
21 })
1 {
2 "navigationBarTitleText": "more"
3 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 .bgc {}
6
7 .bg {}
8
9 .main {
10 .top-space {
11 height: 0px;
12 }
13
14 .content {
15 position: relative;
16 }
17 }
18 }
1 <view class="page">
2 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view>
4 <!-- <view class="app__top-shadow"></view> -->
5 <view class="app__content main">
6 <view class="top-space"></view>
7 <view class="content"></view>
8 </view>
9 </view>
1 let app = getApp();
2 Page({
3 data: {},
4 onShareAppMessage() {},
5 onLoad(options) {},
6 // 子组件事件
7 evtcomp(evt) {
8 let {
9 name,
10 data
11 } = evt.detail;
12 switch (name) {
13
14 case "_evt_hide":
15 break;
16
17 default:
18 break;
19 }
20 },
21 })
1 {
2 "navigationBarTitleText": "more"
3 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 .bgc {}
6
7 .bg {}
8
9 .main {
10 .top-space {
11 height: 0px;
12 }
13
14 .content {
15 position: relative;
16 }
17 }
18 }
1 <view class="page">
2 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view>
4 <!-- <view class="app__top-shadow"></view> -->
5 <view class="app__content main">
6 <view class="top-space"></view>
7 <view class="content"></view>
8 </view>
9 </view>
1 let app = getApp();
2 Page({
3 data: {},
4 onShareAppMessage() {},
5 onLoad(options) {},
6 // 子组件事件
7 evtcomp(evt) {
8 let {
9 name,
10 data
11 } = evt.detail;
12 switch (name) {
13
14 case "_evt_hide":
15 break;
16
17 default:
18 break;
19 }
20 },
21 })
1 {
2 "navigationBarTitleText": "more"
3 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 .bgc {}
6
7 .bg {}
8
9 .main {
10 .top-space {
11 height: 0px;
12 }
13
14 .content {
15 position: relative;
16 }
17 }
18 }
1 <view class="page">
2 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view>
4 <!-- <view class="app__top-shadow"></view> -->
5 <view class="app__content main">
6 <view class="top-space"></view>
7 <view class="content"></view>
8 </view>
9 </view>
1 let app = getApp();
2 Page({
3 data: {},
4 onShareAppMessage() {},
5 onLoad(options) {},
6 // 子组件事件
7 evtcomp(evt) {
8 let {
9 name,
10 data
11 } = evt.detail;
12 switch (name) {
13
14 case "_evt_hide":
15 break;
16
17 default:
18 break;
19 }
20 },
21 })
1 {
2 "navigationBarTitleText": "more"
3 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 .bgc {}
6
7 .bg {}
8
9 .main {
10 .top-space {
11 height: 0px;
12 }
13
14 .content {
15 position: relative;
16 }
17 }
18 }
1 <view class="page">
2 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view>
4 <!-- <view class="app__top-shadow"></view> -->
5 <view class="app__content main">
6 <view class="top-space"></view>
7 <view class="content"></view>
8 </view>
9 </view>
1 let app = getApp();
2 Page({
3 data: {},
4 onShareAppMessage() {},
5 onLoad(options) {},
6 // 子组件事件
7 evtcomp(evt) {
8 let {
9 name,
10 data
11 } = evt.detail;
12 switch (name) {
13
14 case "_evt_hide":
15 break;
16
17 default:
18 break;
19 }
20 },
21 })
1 {
2 "navigationBarTitleText": "more"
3 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 .bgc {}
6
7 .bg {}
8
9 .main {
10 .top-space {
11 height: 0px;
12 }
13
14 .content {
15 position: relative;
16 }
17 }
18 }
1 <view class="page">
2 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view>
4 <!-- <view class="app__top-shadow"></view> -->
5 <view class="app__content main">
6 <view class="top-space"></view>
7 <view class="content"></view>
8 </view>
9 </view>
1 let app = getApp();
2 Page({
3 data: {},
4 onShareAppMessage() {},
5 onLoad(options) {},
6 // 子组件事件
7 evtcomp(evt) {
8 let {
9 name,
10 data
11 } = evt.detail;
12 switch (name) {
13
14 case "_evt_hide":
15 break;
16
17 default:
18 break;
19 }
20 },
21 })
1 {
2 "navigationBarTitleText": "more"
3 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 .bgc {}
6
7 .bg {}
8
9 .main {
10 .top-space {
11 height: 0px;
12 }
13
14 .content {
15 position: relative;
16 }
17 }
18 }
1 <view class="page">
2 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view>
4 <!-- <view class="app__top-shadow"></view> -->
5 <view class="app__content main">
6 <view class="top-space"></view>
7 <view class="content"></view>
8 </view>
9 </view>
1 const routerPath = { 1 const routerPath = {
2 index: '/pages/index/index', // 首页 2 index: '/pages/index/index', // 首页
3 wish: '/pages/wish/wish', // 创建心愿单 3 wish: '/pages/wish/wish', // 心愿单
4 createWish: '/pages/create-wish/create-wish', // 创建心愿单 4 createWish: '/pages/create-wish/create-wish', // 创建心愿单
5 newWelfare: '/pages/new-welfare/new-welfare', // 新人福利 5 newWelfare: '/pages/new-welfare/new-welfare', // 新人福利
6 userTable: '/pages/user-table/user-table', // 用户表单 6 userTable: '/pages/user-table/user-table', // 用户表单
7 rank: '/pages/rank/rank', // 排行榜 7 rank: '/pages/rank/rank', // 排行榜
8 index: '/pages/poster/poster', // 海报页 8 poster: '/pages/poster/poster', // 海报页
9 coop: '/pages/coop/coop', // 协作页/好友查看 9 coop: '/pages/coop/coop', // 协作页/好友查看
10 register: '/pages/register/register', // 注册 10 register: '/pages/register/register', // 注册
11 authorize: '/pages/authorize/authorize', // 授权 11 authorize: '/pages/authorize/authorize', // 授权
......
1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({
4 mixins: [safeArea()],
5 props: {
6 show: Boolean,
7 title: String,
8 cancelText: String,
9 zIndex: {
10 type: Number,
11 value: 100
12 },
13 actions: {
14 type: Array,
15 value: []
16 },
17 overlay: {
18 type: Boolean,
19 value: true
20 },
21 closeOnClickOverlay: {
22 type: Boolean,
23 value: true
24 }
25 },
26 methods: {
27 onSelect(event) {
28 const { index } = event.currentTarget.dataset;
29 const item = this.data.actions[index];
30 if (item && !item.disabled && !item.loading) {
31 this.$emit('select', item);
32 }
33 },
34 onCancel() {
35 this.$emit('cancel');
36 },
37 onClose() {
38 this.$emit('close');
39 }
40 }
41 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-popup": "../popup/index",
6 "van-loading": "../loading/index"
7 }
8 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <van-popup
4 show="{{ show }}"
5 position="bottom"
6 z-index="{{ zIndex }}"
7 overlay="{{ overlay }}"
8 custom-class="van-action-sheet"
9 safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
10 close-on-click-overlay="{{ closeOnClickOverlay }}"
11 bind:close="onClose"
12 >
13 <view wx:if="{{ title }}" class="van-hairline--bottom van-action-sheet__header">
14 {{ title }}
15 <van-icon
16 name="close"
17 custom-class="van-action-sheet__close"
18 bind:click="onClose"
19 />
20 </view>
21 <view wx:if="{{ actions && actions.length }}">
22 <!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
23 <button
24 wx:for="{{ actions }}"
25 wx:key="index"
26 open-type="{{ item.openType }}"
27 class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} van-hairline--top {{ item.className || '' }}"
28 hover-class="van-action-sheet__item--hover"
29 data-index="{{ index }}"
30 bind:tap="onSelect"
31 >
32 <block wx:if="{{ !item.loading }}">
33 {{ item.name }}
34 <text wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</text>
35 </block>
36 <van-loading wx:else size="20px" />
37 </button>
38 </view>
39 <slot />
40 <view
41 wx:if="{{ cancelText }}"
42 class="van-action-sheet__cancel"
43 hover-class="van-action-sheet__cancel--hover"
44 hover-stay-time="70"
45 bind:tap="onCancel"
46 >
47 {{ cancelText }}
48 </view>
49 </van-popup>
1 @import '../common/index.wxss';.van-action-sheet{max-height:90%!important;color:#333}.van-action-sheet__cancel,.van-action-sheet__item{height:50px;font-size:16px;line-height:50px;text-align:center;background-color:#fff}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5}.van-action-sheet__cancel{height:60px}.van-action-sheet__cancel:before{display:block;height:10px;background-color:#f8f8f8;content:" "}.van-action-sheet__item--disabled{color:#c9c9c9}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:#fff}.van-action-sheet__subname{margin-left:5px;font-size:12px;color:#7d7e80}.van-action-sheet__header{font-size:16px;font-weight:500;line-height:44px;text-align:center}.van-action-sheet__close{position:absolute!important;top:0;right:0;padding:0 15px;font-size:18px!important;line-height:inherit!important;color:#999}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 classes: ['active-class', 'toolbar-class', 'column-class'],
4 props: {
5 title: String,
6 value: String,
7 loading: Boolean,
8 cancelButtonText: String,
9 confirmButtonText: String,
10 itemHeight: {
11 type: Number,
12 value: 44
13 },
14 visibleItemCount: {
15 type: Number,
16 value: 5
17 },
18 columnsNum: {
19 type: [String, Number],
20 value: 3
21 },
22 areaList: {
23 type: Object,
24 value: {}
25 }
26 },
27 data: {
28 columns: [{ values: [] }, { values: [] }, { values: [] }],
29 displayColumns: [{ values: [] }, { values: [] }, { values: [] }]
30 },
31 watch: {
32 value(value) {
33 this.code = value;
34 this.setValues();
35 },
36 areaList: 'setValues',
37 columnsNum(value) {
38 this.set({
39 displayColumns: this.data.columns.slice(0, +value)
40 });
41 }
42 },
43 methods: {
44 getPicker() {
45 if (this.picker == null) {
46 this.picker = this.selectComponent('.van-area__picker');
47 }
48 return this.picker;
49 },
50 onCancel(event) {
51 this.emit('cancel', event.detail);
52 },
53 onConfirm(event) {
54 this.emit('confirm', event.detail);
55 },
56 emit(type, detail) {
57 detail.values = detail.value;
58 delete detail.value;
59 this.$emit(type, detail);
60 },
61 onChange(event) {
62 const { index, picker, value } = event.detail;
63 this.code = value[index].code;
64 this.setValues().then(() => {
65 this.$emit('change', {
66 picker,
67 values: picker.getValues(),
68 index
69 });
70 });
71 },
72 getConfig(type) {
73 const { areaList } = this.data;
74 return (areaList && areaList[`${type}_list`]) || {};
75 },
76 getList(type, code) {
77 let result = [];
78 if (type !== 'province' && !code) {
79 return result;
80 }
81 const list = this.getConfig(type);
82 result = Object.keys(list).map(code => ({
83 code,
84 name: list[code]
85 }));
86 if (code) {
87 // oversea code
88 if (code[0] === '9' && type === 'city') {
89 code = '9';
90 }
91 result = result.filter(item => item.code.indexOf(code) === 0);
92 }
93 return result;
94 },
95 getIndex(type, code) {
96 let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
97 const list = this.getList(type, code.slice(0, compareNum - 2));
98 // oversea code
99 if (code[0] === '9' && type === 'province') {
100 compareNum = 1;
101 }
102 code = code.slice(0, compareNum);
103 for (let i = 0; i < list.length; i++) {
104 if (list[i].code.slice(0, compareNum) === code) {
105 return i;
106 }
107 }
108 return 0;
109 },
110 setValues() {
111 const county = this.getConfig('county');
112 let code = this.code || Object.keys(county)[0] || '';
113 const province = this.getList('province');
114 const city = this.getList('city', code.slice(0, 2));
115 const picker = this.getPicker();
116 if (!picker) {
117 return;
118 }
119 const stack = [];
120 stack.push(picker.setColumnValues(0, province, false));
121 stack.push(picker.setColumnValues(1, city, false));
122 if (city.length && code.slice(2, 4) === '00') {
123 ;
124 [{ code }] = city;
125 }
126 stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
127 return Promise.all(stack)
128 .catch(() => { })
129 .then(() => picker.setIndexes([
130 this.getIndex('province', code),
131 this.getIndex('city', code),
132 this.getIndex('county', code)
133 ]))
134 .catch(() => { });
135 },
136 getValues() {
137 const picker = this.getPicker();
138 return picker ? picker.getValues().filter(value => !!value) : [];
139 },
140 getDetail() {
141 const values = this.getValues();
142 const area = {
143 code: '',
144 country: '',
145 province: '',
146 city: '',
147 county: ''
148 };
149 if (!values.length) {
150 return area;
151 }
152 const names = values.map((item) => item.name);
153 area.code = values[values.length - 1].code;
154 if (area.code[0] === '9') {
155 area.country = names[1] || '';
156 area.province = names[2] || '';
157 }
158 else {
159 area.province = names[0] || '';
160 area.city = names[1] || '';
161 area.county = names[2] || '';
162 }
163 return area;
164 },
165 reset() {
166 this.code = '';
167 return this.setValues();
168 }
169 }
170 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-picker": "../picker/index"
5 }
6 }
1 <van-picker
2 class="van-area__picker"
3 active-class="active-class"
4 toolbar-class="toolbar-class"
5 column-class="column-class"
6 show-toolbar
7 value-key="name"
8 title="{{ title }}"
9 loading="{{ loading }}"
10 columns="{{ displayColumns }}"
11 item-height="{{ itemHeight }}"
12 visible-item-count="{{ visibleItemCount }}"
13 cancel-button-text="{{ cancelButtonText }}"
14 confirm-button-text="{{ confirmButtonText }}"
15 bind:change="onChange"
16 bind:confirm="onConfirm"
17 bind:cancel="onCancel"
18 />
1 @import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { isNumber } from '../common/utils';
3 VantComponent({
4 relation: {
5 name: 'badge',
6 type: 'descendant',
7 linked(target) {
8 this.badges.push(target);
9 this.setActive();
10 },
11 unlinked(target) {
12 this.badges = this.badges.filter(item => item !== target);
13 this.setActive();
14 }
15 },
16 props: {
17 active: {
18 type: Number,
19 value: 0
20 }
21 },
22 watch: {
23 active: 'setActive'
24 },
25 beforeCreate() {
26 this.badges = [];
27 this.currentActive = -1;
28 },
29 methods: {
30 setActive(badge) {
31 let { active } = this.data;
32 const { badges } = this;
33 if (badge && !isNumber(badge)) {
34 active = badges.indexOf(badge);
35 }
36 if (active === this.currentActive) {
37 return;
38 }
39 if (this.currentActive !== -1 && badges[this.currentActive]) {
40 this.$emit('change', active);
41 badges[this.currentActive].setActive(false);
42 }
43 if (badges[active]) {
44 badges[active].setActive(true);
45 this.currentActive = active;
46 }
47 }
48 }
49 });
1 <view class="van-badge-group van-hairline--top-bottom custom-class">
2 <slot />
3 </view>
1 @import '../common/index.wxss';.van-badge-group{width:85px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 relation: {
4 type: 'ancestor',
5 name: 'badge-group'
6 },
7 props: {
8 info: null,
9 title: String
10 },
11 methods: {
12 onClick() {
13 const group = this.getRelationNodes('../badge-group/index')[0];
14 if (group) {
15 group.setActive(this);
16 }
17 },
18 setActive(active) {
19 this.set({ active });
20 }
21 }
22 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-info": "../info/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="{{ utils.bem('badge', { active }) }} van-hairline custom-class"
5 hover-class="van-badge--hover"
6 hover-stay-time="70"
7 bind:tap="onClick"
8 >
9 <view class="van-badge__text">
10 <van-info
11 wx:if="{{ info !== null }}"
12 info="{{ info }}"
13 custom-style="right: 4px"
14 />
15 {{ title }}
16 </view>
17 </view>
1 @import '../common/index.wxss';.van-badge{display:block;padding:20px 12px 20px 9px;overflow:hidden;font-size:14px;line-height:1.4;color:#7d7e80;word-break:break-all;background-color:#f8f8f8;border-left:3px solid transparent;box-sizing:border-box;-webkit-user-select:none;user-select:none}.van-badge--hover{background-color:#f2f3f5}.van-badge:after{border-bottom-width:1px}.van-badge--active{font-weight:700;color:#333;border-color:#f44}.van-badge--active:after{border-right-width:1px}.van-badge--active,.van-badge--active.van-badge--hover{background-color:#fff}.van-badge__text{position:relative}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { button } from '../mixins/button';
3 import { openType } from '../mixins/open-type';
4 VantComponent({
5 mixins: [button, openType],
6 classes: ['hover-class', 'loading-class'],
7 props: {
8 plain: Boolean,
9 block: Boolean,
10 round: Boolean,
11 square: Boolean,
12 loading: Boolean,
13 hairline: Boolean,
14 disabled: Boolean,
15 loadingText: String,
16 type: {
17 type: String,
18 value: 'default'
19 },
20 size: {
21 type: String,
22 value: 'normal'
23 },
24 loadingSize: {
25 type: String,
26 value: '20px'
27 }
28 },
29 methods: {
30 onClick() {
31 if (!this.data.disabled && !this.data.loading) {
32 this.$emit('click');
33 }
34 }
35 }
36 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-loading": "../loading/index"
5 }
6 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <button
4 id="{{ id }}"
5 class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
6 open-type="{{ openType }}"
7 hover-class="van-button--active hover-class"
8 lang="{{ lang }}"
9 business-id="{{ businessId }}"
10 session-from="{{ sessionFrom }}"
11 send-message-title="{{ sendMessageTitle }}"
12 send-message-path="{{ sendMessagePath }}"
13 send-message-img="{{ sendMessageImg }}"
14 show-message-card="{{ showMessageCard }}"
15 app-parameter="{{ appParameter }}"
16 aria-label="{{ ariaLabel }}"
17 bindtap="onClick"
18 bindgetuserinfo="bindGetUserInfo"
19 bindcontact="bindContact"
20 bindgetphonenumber="bindGetPhoneNumber"
21 binderror="bindError"
22 bindlaunchapp="bindLaunchApp"
23 bindopensetting="bindOpenSetting"
24 >
25 <block wx:if="{{ loading }}">
26 <van-loading
27 custom-class="loading-class"
28 size="{{ loadingSize }}"
29 color="{{ type === 'default' ? '#c9c9c9' : '' }}"
30 />
31 <view
32 wx:if="{{ loadingText }}"
33 class="van-button__loading-text"
34 >
35 {{ loadingText }}
36 </view>
37 </block>
38 <slot wx:else />
39 </button>
1 @import '../common/index.wxss';.van-button{position:relative;display:inline-block;height:44px;padding:0;font-size:16px;line-height:42px;text-align:center;vertical-align:middle;box-sizing:border-box;border-radius:2px;-webkit-appearance:none;-webkit-text-size-adjust:100%}.van-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;background-color:#000;border:inherit;border-color:#000;border-radius:inherit;content:" ";opacity:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{color:#333;background-color:#fff;border:1px solid #eee}.van-button--primary{color:#fff;background-color:#07c160;border:1px solid #07c160}.van-button--info{color:#fff;background-color:#1989fa;border:1px solid #1989fa}.van-button--danger{color:#fff;background-color:#f44;border:1px solid #f44}.van-button--warning{color:#fff;background-color:#ff976a;border:1px solid #ff976a}.van-button--plain{background-color:#fff}.van-button--plain.van-button--primary{color:#07c160}.van-button--plain.van-button--info{color:#1989fa}.van-button--plain.van-button--danger{color:#f44}.van-button--plain.van-button--warning{color:#ff976a}.van-button--large{width:100%;height:50px;line-height:48px}.van-button--normal{padding:0 15px;font-size:14px}.van-button--small{height:30px;min-width:60px;padding:0 8px;font-size:12px;line-height:28px}.van-button--mini{display:inline-block;width:50px;height:22px;font-size:10px;line-height:20px}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:block;width:100%}.van-button--round{border-radius:10em}.van-button--square{border-radius:0}.van-button--disabled{opacity:.5}.van-button__loading-text{margin-left:5px;display:inline-block;vertical-align:middle}.van-button--hairline{border-width:0;padding-top:1px}.van-button--hairline:after{border-width:1px;border-color:inherit;border-radius:4px}.van-button--hairline.van-button--round:after{border-radius:10em}.van-button--hairline.van-button--square:after{border-radius:0}
...\ No newline at end of file ...\ No newline at end of file
1 import { link } from '../mixins/link';
2 import { VantComponent } from '../common/component';
3 VantComponent({
4 classes: [
5 'num-class',
6 'desc-class',
7 'thumb-class',
8 'title-class',
9 'price-class',
10 'origin-price-class',
11 ],
12 mixins: [link],
13 props: {
14 tag: String,
15 num: String,
16 desc: String,
17 thumb: String,
18 title: String,
19 price: String,
20 centered: Boolean,
21 lazyLoad: Boolean,
22 thumbLink: String,
23 originPrice: String,
24 thumbMode: {
25 type: String,
26 value: 'aspectFit'
27 },
28 currency: {
29 type: String,
30 value: '¥'
31 }
32 },
33 methods: {
34 onClickThumb() {
35 this.jumpLink('thumbLink');
36 }
37 }
38 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-tag": "../tag/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="custom-class van-card">
4 <view class="{{ utils.bem('card__header', { center: centered }) }}">
5 <view class="van-card__thumb" bind:tap="onClickThumb">
6 <image
7 wx:if="{{ thumb }}"
8 src="{{ thumb }}"
9 mode="{{ thumbMode }}"
10 lazy-load="{{ lazyLoad }}"
11 class="van-card__img thumb-class"
12 />
13 <slot name="thumb" />
14 <van-tag
15 wx:if="{{ tag }}"
16 mark
17 type="danger"
18 custom-class="van-card__tag"
19 >
20 {{ tag }}
21 </van-tag>
22 </view>
23
24 <view class="van-card__content">
25 <view wx:if="{{ title }}" class="van-card__title title-class">{{ title }}</view>
26 <slot wx:else name="title" />
27
28 <view wx:if="{{ desc }}" class="van-card__desc desc-class">{{ desc }}</view>
29 <slot wx:else name="desc" />
30
31 <slot name="tags" />
32
33 <view class="van-card__bottom">
34 <view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">{{ currency }} {{ price }}</view>
35 <view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
36 <view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
37 </view>
38 </view>
39 </view>
40
41 <view class="van-card__footer">
42 <slot name="footer" />
43 </view>
44 </view>
1 @import '../common/index.wxss';.van-card{position:relative;padding:5px 15px;font-size:12px;color:#333;background-color:#fafafa;box-sizing:border-box}.van-card__header{display:-webkit-flex;display:flex}.van-card__header--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-card__thumb{position:relative;width:90px;height:90px;margin-right:10px;-webkit-flex:none;flex:none}.van-card__thumb:empty{display:none}.van-card__img{width:100%;height:100%}.van-card__content{position:relative;min-width:0;-webkit-flex:1;flex:1}.van-card__desc,.van-card__title{word-break:break-all}.van-card__title{font-weight:700;line-height:16px}.van-card__desc{color:#7d7e80}.van-card__bottom,.van-card__desc{line-height:20px}.van-card__price{display:inline-block;font-weight:700;color:#f44}.van-card__origin-price{display:inline-block;margin-left:5px;font-size:10px;color:#7d7e80;text-decoration:line-through}.van-card__num{float:right}.van-card__tag{position:absolute;top:2px;left:0}.van-card__footer{width:100%;text-align:right;-webkit-flex:none;flex:none}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 title: String,
5 border: {
6 type: Boolean,
7 value: true
8 }
9 }
10 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <view
2 wx:if="{{ title }}"
3 class="van-cell-group__title"
4 >
5 {{ title }}
6 </view>
7 <view class="custom-class van-cell-group {{ border ? 'van-hairline--top-bottom' : '' }}">
8 <slot />
9 </view>
1 @import '../common/index.wxss';.van-cell-group__title{font-size:14px;padding:15px 15px 5px;color:#999;line-height:16px}
...\ No newline at end of file ...\ No newline at end of file
1 import { link } from '../mixins/link';
2 import { VantComponent } from '../common/component';
3 VantComponent({
4 classes: [
5 'title-class',
6 'label-class',
7 'value-class',
8 'right-icon-class',
9 'hover-class'
10 ],
11 mixins: [link],
12 props: {
13 title: null,
14 value: null,
15 icon: String,
16 size: String,
17 label: String,
18 center: Boolean,
19 isLink: Boolean,
20 required: Boolean,
21 clickable: Boolean,
22 titleWidth: String,
23 customStyle: String,
24 arrowDirection: String,
25 border: {
26 type: Boolean,
27 value: true
28 }
29 },
30 methods: {
31 onClick(event) {
32 this.$emit('click', event.detail);
33 this.jumpLink();
34 }
35 }
36 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ utils.bem('cell', [size, { center, required, borderless: !border, clickable: isLink || clickable }]) }}"
5 hover-class="van-cell--hover hover-class"
6 hover-stay-time="70"
7 style="{{ customStyle }}"
8 bind:tap="onClick"
9 >
10 <van-icon
11 wx:if="{{ icon }}"
12 name="{{ icon }}"
13 class="van-cell__left-icon-wrap"
14 custom-class="van-cell__left-icon"
15 />
16 <slot wx:else name="icon" />
17
18 <view
19 style="{{ titleWidth ? 'max-width:' + titleWidth + ';min-width:' + titleWidth : '' }}"
20 class="van-cell__title title-class"
21 >
22 <block wx:if="{{ title }}">
23 {{ title }}
24 <view wx:if="{{ label }}" class="van-cell__label label-class">{{ label }}</view>
25 </block>
26 <slot wx:else name="title" />
27 </view>
28
29 <view class="van-cell__value value-class">
30 <block wx:if="{{ value || value === 0 }}">{{ value }}</block>
31 <slot wx:else />
32 </view>
33
34 <van-icon
35 wx:if="{{ isLink }}"
36 name="{{ arrowDirection ? 'arrow' + '-' + arrowDirection : 'arrow' }}"
37 class="van-cell__right-icon-wrap right-icon-class"
38 custom-class="van-cell__right-icon"
39 />
40 <slot wx:else name="right-icon" />
41
42 <slot name="extra" />
43 </view>
1 @import '../common/index.wxss';.van-cell{position:relative;display:-webkit-flex;display:flex;width:100%;padding:10px 15px;font-size:14px;line-height:24px;color:#333;background-color:#fff;box-sizing:border-box}.van-cell:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:auto;left:15px;right:0;bottom:0;-webkit-transform:scaleY(.5);transform:scaleY(.5);border-bottom:1px solid #eee}.van-cell--borderless:after{display:none}.van-cell-group{background-color:#fff}.van-cell__label{margin-top:3px;font-size:12px;line-height:18px;color:#999}.van-cell__value{overflow:hidden;color:#999;text-align:right;vertical-align:middle}.van-cell__title,.van-cell__value{-webkit-flex:1;flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{display:-webkit-flex;display:flex;height:24px;font-size:16px;-webkit-align-items:center;align-items:center}.van-cell__left-icon-wrap{margin-right:5px}.van-cell__right-icon-wrap{margin-left:5px;color:#999}.van-cell__left-icon{line-height:24px;vertical-align:middle}.van-cell__right-icon{line-height:24px}.van-cell--clickable.van-cell--hover{background-color:#f2f3f5}.van-cell--required{overflow:visible}.van-cell--required:before{position:absolute;left:7px;font-size:14px;color:#f44;content:"*"}.van-cell--center{-webkit-align-items:center;align-items:center}.van-cell--large{padding-top:12px;padding-bottom:12px}.van-cell--large .van-cell__title{font-size:16px}.van-cell--large .van-cell__label{font-size:14px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 relation: {
5 name: 'checkbox',
6 type: 'descendant',
7 linked(target) {
8 const { value, disabled } = this.data;
9 target.set({
10 value: value.indexOf(target.data.name) !== -1,
11 disabled: disabled || target.data.disabled
12 });
13 }
14 },
15 props: {
16 max: Number,
17 value: Array,
18 disabled: Boolean
19 },
20 watch: {
21 value(value) {
22 const children = this.getRelationNodes('../checkbox/index');
23 children.forEach(child => {
24 child.set({ value: value.indexOf(child.data.name) !== -1 });
25 });
26 },
27 disabled(disabled) {
28 const children = this.getRelationNodes('../checkbox/index');
29 children.forEach(child => {
30 child.set({ disabled: disabled || child.data.disabled });
31 });
32 }
33 }
34 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 @import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 relation: {
5 name: 'checkbox-group',
6 type: 'ancestor'
7 },
8 classes: ['icon-class', 'label-class'],
9 props: {
10 value: null,
11 disabled: Boolean,
12 useIconSlot: Boolean,
13 checkedColor: String,
14 labelPosition: String,
15 labelDisabled: Boolean,
16 shape: {
17 type: String,
18 value: 'round'
19 }
20 },
21 methods: {
22 emitChange(value) {
23 const parent = this.getRelationNodes('../checkbox-group/index')[0];
24 if (parent) {
25 this.setParentValue(parent, value);
26 }
27 else {
28 this.$emit('input', value);
29 this.$emit('change', value);
30 }
31 },
32 toggle() {
33 if (!this.data.disabled) {
34 this.emitChange(!this.data.value);
35 }
36 },
37 onClickLabel() {
38 if (!this.data.disabled && !this.data.labelDisabled) {
39 this.emitChange(!this.data.value);
40 }
41 },
42 setParentValue(parent, value) {
43 const parentValue = parent.data.value.slice();
44 const { name } = this.data;
45 if (value) {
46 if (parent.data.max && parentValue.length >= parent.data.max) {
47 return;
48 }
49 /* istanbul ignore else */
50 if (parentValue.indexOf(name) === -1) {
51 parentValue.push(name);
52 parent.$emit('input', parentValue);
53 parent.$emit('change', parentValue);
54 }
55 }
56 else {
57 const index = parentValue.indexOf(name);
58 /* istanbul ignore else */
59 if (index !== -1) {
60 parentValue.splice(index, 1);
61 parent.$emit('input', parentValue);
62 parent.$emit('change', parentValue);
63 }
64 }
65 }
66 }
67 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="van-checkbox custom-class">
4 <view class="van-checkbox__icon-wrap" bindtap="toggle">
5 <slot wx:if="{{ useIconSlot }}" name="icon" />
6 <van-icon
7 wx:else
8 name="success"
9 class="{{ utils.bem('checkbox__icon', [shape, { disabled, checked: value }]) }}"
10 style="{{ checkedColor && value && !disabled ? 'border-color:' + checkedColor + '; background-color:' + checkedColor : '' }}"
11 custom-class="icon-class"
12 custom-style="line-height: 20px;"
13 />
14 </view>
15 <view class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled }]) }}" bindtap="onClickLabel">
16 <slot />
17 </view>
18 </view>
1 @import '../common/index.wxss';.van-checkbox{overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{display:inline-block;line-height:20px;vertical-align:middle}.van-checkbox__icon{display:block;font-size:14px;width:20px;height:20px;color:transparent;text-align:center;box-sizing:border-box;border:1px solid #e5e5e5;transition:.2s}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;border-color:#1989fa;background-color:#1989fa}.van-checkbox__icon--disabled{border-color:#c9c9c9;background-color:#eee}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c9c9c9}.van-checkbox__label{color:#333;margin-left:10px}.van-checkbox__label--left{float:left;margin:0 10px 0 0}.van-checkbox__label--disabled{color:#c9c9c9}.van-checkbox__label:empty{margin:0}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 relation: {
4 name: 'row',
5 type: 'ancestor'
6 },
7 props: {
8 span: Number,
9 offset: Number
10 },
11 data: {
12 style: ''
13 },
14 methods: {
15 setGutter(gutter) {
16 const padding = `${gutter / 2}px`;
17 const style = gutter ? `padding-left: ${padding}; padding-right: ${padding};` : '';
18 if (style !== this.data.style) {
19 this.set({ style });
20 }
21 }
22 }
23 });
1 {
2 "component": true
3 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ utils.bem('col', [span]) }} {{ offset ? 'van-col--offset-' + offset : '' }}"
5 style="{{ style }}"
6 >
7 <slot />
8 </view>
1 @import '../common/index.wxss';.van-col{float:left;box-sizing:border-box}.van-col--1{width:4.16666667%}.van-col--offset-1{margin-left:4.16666667%}.van-col--2{width:8.33333333%}.van-col--offset-2{margin-left:8.33333333%}.van-col--3{width:12.5%}.van-col--offset-3{margin-left:12.5%}.van-col--4{width:16.66666667%}.van-col--offset-4{margin-left:16.66666667%}.van-col--5{width:20.83333333%}.van-col--offset-5{margin-left:20.83333333%}.van-col--6{width:25%}.van-col--offset-6{margin-left:25%}.van-col--7{width:29.16666667%}.van-col--offset-7{margin-left:29.16666667%}.van-col--8{width:33.33333333%}.van-col--offset-8{margin-left:33.33333333%}.van-col--9{width:37.5%}.van-col--offset-9{margin-left:37.5%}.van-col--10{width:41.66666667%}.van-col--offset-10{margin-left:41.66666667%}.van-col--11{width:45.83333333%}.van-col--offset-11{margin-left:45.83333333%}.van-col--12{width:50%}.van-col--offset-12{margin-left:50%}.van-col--13{width:54.16666667%}.van-col--offset-13{margin-left:54.16666667%}.van-col--14{width:58.33333333%}.van-col--offset-14{margin-left:58.33333333%}.van-col--15{width:62.5%}.van-col--offset-15{margin-left:62.5%}.van-col--16{width:66.66666667%}.van-col--offset-16{margin-left:66.66666667%}.van-col--17{width:70.83333333%}.van-col--offset-17{margin-left:70.83333333%}.van-col--18{width:75%}.van-col--offset-18{margin-left:75%}.van-col--19{width:79.16666667%}.van-col--offset-19{margin-left:79.16666667%}.van-col--20{width:83.33333333%}.van-col--offset-20{margin-left:83.33333333%}.van-col--21{width:87.5%}.van-col--offset-21{margin-left:87.5%}.van-col--22{width:91.66666667%}.van-col--offset-22{margin-left:91.66666667%}.van-col--23{width:95.83333333%}.van-col--offset-23{margin-left:95.83333333%}.van-col--24{width:100%}.van-col--offset-24{margin-left:100%}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 const nextTick = () => new Promise(resolve => setTimeout(resolve, 20));
3 VantComponent({
4 classes: ['title-class', 'content-class'],
5 relation: {
6 name: 'collapse',
7 type: 'ancestor',
8 linked(parent) {
9 this.parent = parent;
10 }
11 },
12 props: {
13 name: null,
14 title: null,
15 value: null,
16 icon: String,
17 label: String,
18 disabled: Boolean,
19 border: {
20 type: Boolean,
21 value: true
22 },
23 isLink: {
24 type: Boolean,
25 value: true
26 }
27 },
28 data: {
29 contentHeight: 0,
30 expanded: false,
31 transition: false
32 },
33 mounted() {
34 this.updateExpanded()
35 .then(nextTick)
36 .then(() => {
37 this.set({ transition: true });
38 });
39 },
40 methods: {
41 updateExpanded() {
42 if (!this.parent) {
43 return Promise.resolve();
44 }
45 const { value, accordion } = this.parent.data;
46 const { children = [] } = this.parent;
47 const { name } = this.data;
48 const index = children.indexOf(this);
49 const currentName = name == null ? index : name;
50 const expanded = accordion
51 ? value === currentName
52 : (value || []).some((name) => name === currentName);
53 const stack = [];
54 if (expanded !== this.data.expanded) {
55 stack.push(this.updateStyle(expanded));
56 }
57 stack.push(this.set({ index, expanded }));
58 return Promise.all(stack);
59 },
60 updateStyle(expanded) {
61 return this.getRect('.van-collapse-item__content')
62 .then((rect) => rect.height)
63 .then((height) => {
64 if (expanded) {
65 return this.set({
66 contentHeight: height ? `${height}px` : 'auto'
67 });
68 }
69 else {
70 return this.set({ contentHeight: `${height}px` })
71 .then(nextTick)
72 .then(() => this.set({ contentHeight: 0 }));
73 }
74 });
75 },
76 onClick() {
77 if (this.data.disabled) {
78 return;
79 }
80 const { name, expanded } = this.data;
81 const index = this.parent.children.indexOf(this);
82 const currentName = name == null ? index : name;
83 this.parent.switch(currentName, !expanded);
84 },
85 onTransitionEnd() {
86 if (this.data.expanded) {
87 this.set({
88 contentHeight: 'auto'
89 });
90 }
91 }
92 }
93 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-cell": "../cell/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="van-collapse-item custom-class {{ index !== 0 ? 'van-hairline--top' : '' }}">
4 <van-cell
5 title="{{ title }}"
6 title-class="title-class"
7 icon="{{ icon }}"
8 is-link="{{ isLink }}"
9 value="{{ value }}"
10 label="{{ label }}"
11 border="{{ border && expanded }}"
12 class="{{ utils.bem('collapse-item__title', { disabled, expanded }) }}"
13 right-icon-class="van-cell__right-icon"
14 custom-class="van-cell"
15 hover-class="van-cell--hover"
16 bind:click="onClick"
17 >
18 <slot
19 name="title"
20 slot="title"
21 />
22 <slot
23 name="icon"
24 slot="icon"
25 />
26 <slot name="value" />
27 <slot
28 name="right-icon"
29 slot="right-icon"
30 />
31 </van-cell>
32 <view
33 class="{{ utils.bem('collapse-item__wrapper', { transition }) }}"
34 style="height: {{ contentHeight }};"
35 bind:transitionend="onTransitionEnd"
36 >
37 <view
38 class="van-collapse-item__content content-class"
39 >
40 <slot />
41 </view>
42 </view>
43 </view>
1 @import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{-webkit-transform:rotate(90deg);transform:rotate(90deg);transition:.3s}.van-collapse-item__title--expanded .van-cell__right-icon{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:#c9c9c9!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__wrapper--transition{transition:height .3s ease-in-out}.van-collapse-item__content{padding:15px;font-size:13px;line-height:1.5;color:#999;background-color:#fff}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 relation: {
4 name: 'collapse-item',
5 type: 'descendant',
6 linked(child) {
7 this.children.push(child);
8 }
9 },
10 props: {
11 value: {
12 type: null,
13 observer: 'updateExpanded'
14 },
15 accordion: {
16 type: Boolean,
17 observer: 'updateExpanded'
18 },
19 border: {
20 type: Boolean,
21 value: true
22 }
23 },
24 beforeCreate() {
25 this.children = [];
26 },
27 methods: {
28 updateExpanded() {
29 this.children.forEach((child) => {
30 child.updateExpanded();
31 });
32 },
33 switch(name, expanded) {
34 const { accordion, value } = this.data;
35 if (!accordion) {
36 name = expanded
37 ? (value || []).concat(name)
38 : (value || []).filter((activeName) => activeName !== name);
39 }
40 else {
41 name = expanded ? name : '';
42 }
43 this.$emit('change', name);
44 this.$emit('input', name);
45 }
46 }
47 });
1 <view class="custom-class van-collapse {{ border ? 'van-hairline--top-bottom' : '' }}">
2 <slot />
3 </view>
1 @import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 export declare const RED = "#f44";
2 export declare const BLUE = "#1989fa";
3 export declare const GREEN = "#07c160";
1 export const RED = '#f44';
2 export const BLUE = '#1989fa';
3 export const GREEN = '#07c160';
1 declare function VantComponent<Data, Props, Watch, Methods, Computed>(vantOptions?: VantComponentOptions<Data, Props, Watch, Methods, Computed, CombinedComponentInstance<Data, Props, Watch, Methods, Computed>>): void;
2 export { VantComponent };
1 import { basic } from '../mixins/basic';
2 import { observe } from '../mixins/observer/index';
3 function mapKeys(source, target, map) {
4 Object.keys(map).forEach(key => {
5 if (source[key]) {
6 target[map[key]] = source[key];
7 }
8 });
9 }
10 function VantComponent(vantOptions = {}) {
11 const options = {};
12 mapKeys(vantOptions, options, {
13 data: 'data',
14 props: 'properties',
15 mixins: 'behaviors',
16 methods: 'methods',
17 beforeCreate: 'created',
18 created: 'attached',
19 mounted: 'ready',
20 relations: 'relations',
21 destroyed: 'detached',
22 classes: 'externalClasses'
23 });
24 const { relation } = vantOptions;
25 if (relation) {
26 options.relations = Object.assign(options.relations || {}, {
27 [`../${relation.name}/index`]: relation
28 });
29 }
30 // add default externalClasses
31 options.externalClasses = options.externalClasses || [];
32 options.externalClasses.push('custom-class');
33 // add default behaviors
34 options.behaviors = options.behaviors || [];
35 options.behaviors.push(basic);
36 // map field to form-field behavior
37 if (vantOptions.field) {
38 options.behaviors.push('wx://form-field');
39 }
40 // add default options
41 options.options = {
42 multipleSlots: true,
43 addGlobalClass: true
44 };
45 observe(vantOptions, options);
46 Component(options);
47 }
48 export { VantComponent };
1 .van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{content:"";display:table;clear:both}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #eee}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
...\ No newline at end of file ...\ No newline at end of file
1 .van-clearfix:after{content:"";display:table;clear:both}
...\ No newline at end of file ...\ No newline at end of file
1 .van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}
...\ No newline at end of file ...\ No newline at end of file
1 .van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #eee}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
...\ No newline at end of file ...\ No newline at end of file
1 declare function isDef(value: any): boolean;
2 declare function isObj(x: any): boolean;
3 declare function isNumber(value: any): boolean;
4 declare function range(num: number, min: number, max: number): number;
5 export { isObj, isDef, isNumber, range };
1 function isDef(value) {
2 return value !== undefined && value !== null;
3 }
4 function isObj(x) {
5 const type = typeof x;
6 return x !== null && (type === 'object' || type === 'function');
7 }
8 function isNumber(value) {
9 return /^\d+$/.test(value);
10 }
11 function range(num, min, max) {
12 return Math.min(Math.max(num, min), max);
13 }
14 export { isObj, isDef, isNumber, range };
1 import { VantComponent } from '../common/component';
2 import { isDef } from '../common/utils';
3 const currentYear = new Date().getFullYear();
4 function isValidDate(date) {
5 return isDef(date) && !isNaN(new Date(date).getTime());
6 }
7 function range(num, min, max) {
8 return Math.min(Math.max(num, min), max);
9 }
10 function padZero(val) {
11 return `00${val}`.slice(-2);
12 }
13 function times(n, iteratee) {
14 let index = -1;
15 const result = Array(n);
16 while (++index < n) {
17 result[index] = iteratee(index);
18 }
19 return result;
20 }
21 function getTrueValue(formattedValue) {
22 if (!formattedValue)
23 return;
24 while (isNaN(parseInt(formattedValue, 10))) {
25 formattedValue = formattedValue.slice(1);
26 }
27 return parseInt(formattedValue, 10);
28 }
29 function getMonthEndDay(year, month) {
30 return 32 - new Date(year, month - 1, 32).getDate();
31 }
32 VantComponent({
33 props: {
34 value: null,
35 title: String,
36 loading: Boolean,
37 itemHeight: {
38 type: Number,
39 value: 44
40 },
41 visibleItemCount: {
42 type: Number,
43 value: 5
44 },
45 confirmButtonText: {
46 type: String,
47 value: '确认'
48 },
49 cancelButtonText: {
50 type: String,
51 value: '取消'
52 },
53 type: {
54 type: String,
55 value: 'datetime'
56 },
57 showToolbar: {
58 type: Boolean,
59 value: true
60 },
61 minDate: {
62 type: Number,
63 value: new Date(currentYear - 10, 0, 1).getTime()
64 },
65 maxDate: {
66 type: Number,
67 value: new Date(currentYear + 10, 11, 31).getTime()
68 },
69 minHour: {
70 type: Number,
71 value: 0
72 },
73 maxHour: {
74 type: Number,
75 value: 23
76 },
77 minMinute: {
78 type: Number,
79 value: 0
80 },
81 maxMinute: {
82 type: Number,
83 value: 59
84 }
85 },
86 data: {
87 innerValue: Date.now(),
88 columns: []
89 },
90 watch: {
91 value(val) {
92 const { data } = this;
93 val = this.correctValue(val);
94 const isEqual = val === data.innerValue;
95 if (!isEqual) {
96 this.updateColumnValue(val).then(() => {
97 this.$emit('input', val);
98 });
99 }
100 },
101 type: 'updateColumns',
102 minHour: 'updateColumns',
103 maxHour: 'updateColumns',
104 minMinute: 'updateColumns',
105 maxMinute: 'updateColumns'
106 },
107 methods: {
108 getPicker() {
109 if (this.picker == null) {
110 const picker = this.picker = this.selectComponent('.van-datetime-picker');
111 const { setColumnValues } = picker;
112 picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]);
113 }
114 return this.picker;
115 },
116 updateColumns() {
117 const results = this.getRanges().map(({ type, range }, index) => {
118 const values = times(range[1] - range[0] + 1, index => {
119 let value = range[0] + index;
120 value = type === 'year' ? `${value}` : padZero(value);
121 return value;
122 });
123 return { values };
124 });
125 return this.set({ columns: results });
126 },
127 getRanges() {
128 const { data } = this;
129 if (data.type === 'time') {
130 return [
131 {
132 type: 'hour',
133 range: [data.minHour, data.maxHour]
134 },
135 {
136 type: 'minute',
137 range: [data.minMinute, data.maxMinute]
138 }
139 ];
140 }
141 const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = this.getBoundary('max', data.innerValue);
142 const { minYear, minDate, minMonth, minHour, minMinute } = this.getBoundary('min', data.innerValue);
143 const result = [
144 {
145 type: 'year',
146 range: [minYear, maxYear]
147 },
148 {
149 type: 'month',
150 range: [minMonth, maxMonth]
151 },
152 {
153 type: 'day',
154 range: [minDate, maxDate]
155 },
156 {
157 type: 'hour',
158 range: [minHour, maxHour]
159 },
160 {
161 type: 'minute',
162 range: [minMinute, maxMinute]
163 }
164 ];
165 if (data.type === 'date')
166 result.splice(3, 2);
167 if (data.type === 'year-month')
168 result.splice(2, 3);
169 return result;
170 },
171 correctValue(value) {
172 const { data } = this;
173 // validate value
174 const isDateType = data.type !== 'time';
175 if (isDateType && !isValidDate(value)) {
176 value = data.minDate;
177 }
178 else if (!isDateType && !value) {
179 const { minHour } = data;
180 value = `${padZero(minHour)}:00`;
181 }
182 // time type
183 if (!isDateType) {
184 let [hour, minute] = value.split(':');
185 hour = padZero(range(hour, data.minHour, data.maxHour));
186 minute = padZero(range(minute, data.minMinute, data.maxMinute));
187 return `${hour}:${minute}`;
188 }
189 // date type
190 value = Math.max(value, data.minDate);
191 value = Math.min(value, data.maxDate);
192 return value;
193 },
194 getBoundary(type, innerValue) {
195 const value = new Date(innerValue);
196 const boundary = new Date(this.data[`${type}Date`]);
197 const year = boundary.getFullYear();
198 let month = 1;
199 let date = 1;
200 let hour = 0;
201 let minute = 0;
202 if (type === 'max') {
203 month = 12;
204 date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1);
205 hour = 23;
206 minute = 59;
207 }
208 if (value.getFullYear() === year) {
209 month = boundary.getMonth() + 1;
210 if (value.getMonth() + 1 === month) {
211 date = boundary.getDate();
212 if (value.getDate() === date) {
213 hour = boundary.getHours();
214 if (value.getHours() === hour) {
215 minute = boundary.getMinutes();
216 }
217 }
218 }
219 }
220 return {
221 [`${type}Year`]: year,
222 [`${type}Month`]: month,
223 [`${type}Date`]: date,
224 [`${type}Hour`]: hour,
225 [`${type}Minute`]: minute
226 };
227 },
228 onCancel() {
229 this.$emit('cancel');
230 },
231 onConfirm() {
232 this.$emit('confirm', this.data.innerValue);
233 },
234 onChange() {
235 const { data } = this;
236 let value;
237 const picker = this.getPicker();
238 if (data.type === 'time') {
239 const indexes = picker.getIndexes();
240 value = `${indexes[0] + data.minHour}:${indexes[1] + data.minMinute}`;
241 }
242 else {
243 const values = picker.getValues();
244 const year = getTrueValue(values[0]);
245 const month = getTrueValue(values[1]);
246 const maxDate = getMonthEndDay(year, month);
247 let date = getTrueValue(values[2]);
248 if (data.type === 'year-month') {
249 date = 1;
250 }
251 date = date > maxDate ? maxDate : date;
252 let hour = 0;
253 let minute = 0;
254 if (data.type === 'datetime') {
255 hour = getTrueValue(values[3]);
256 minute = getTrueValue(values[4]);
257 }
258 value = new Date(year, month - 1, date, hour, minute);
259 }
260 value = this.correctValue(value);
261 this.updateColumnValue(value).then(() => {
262 this.$emit('input', value);
263 this.$emit('change', picker);
264 });
265 },
266 updateColumnValue(value) {
267 let values = [];
268 const { data } = this;
269 const picker = this.getPicker();
270 if (data.type === 'time') {
271 const pair = value.split(':');
272 values = [pair[0], pair[1]];
273 }
274 else {
275 const date = new Date(value);
276 values = [`${date.getFullYear()}`, padZero(date.getMonth() + 1)];
277 if (data.type === 'date') {
278 values.push(padZero(date.getDate()));
279 }
280 if (data.type === 'datetime') {
281 values.push(padZero(date.getDate()), padZero(date.getHours()), padZero(date.getMinutes()));
282 }
283 }
284 return this.set({ innerValue: value })
285 .then(() => this.updateColumns())
286 .then(() => picker.setValues(values));
287 }
288 },
289 created() {
290 const innerValue = this.correctValue(this.data.value);
291 this.updateColumnValue(innerValue).then(() => {
292 this.$emit('input', innerValue);
293 });
294 }
295 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-picker": "../picker/index"
5 }
6 }
1 <van-picker
2 class="van-datetime-picker"
3 title="{{ title }}"
4 columns="{{ columns }}"
5 item-height="{{ itemHeight }}"
6 show-toolbar="{{ showToolbar }}"
7 visible-item-count="{{ visibleItemCount }}"
8 confirm-button-text="{{ confirmButtonText }}"
9 cancel-button-text="{{ cancelButtonText }}"
10 bind:change="onChange"
11 bind:confirm="onConfirm"
12 bind:cancel="onCancel"
13 />
1 @import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 declare type DialogAction = 'confirm' | 'cancel';
2 declare type DialogOptions = {
3 lang?: string;
4 show?: boolean;
5 title?: string;
6 zIndex?: number;
7 context?: any;
8 message?: string;
9 overlay?: boolean;
10 selector?: string;
11 ariaLabel?: string;
12 transition?: string;
13 asyncClose?: boolean;
14 businessId?: number;
15 sessionFrom?: string;
16 appParameter?: string;
17 messageAlign?: string;
18 sendMessageImg?: string;
19 showMessageCard?: boolean;
20 sendMessagePath?: string;
21 sendMessageTitle?: string;
22 confirmButtonText?: string;
23 cancelButtonText?: string;
24 showConfirmButton?: boolean;
25 showCancelButton?: boolean;
26 closeOnClickOverlay?: boolean;
27 confirmButtonOpenType?: string;
28 };
29 interface Dialog {
30 (options: DialogOptions): Promise<DialogAction>;
31 alert?: (options: DialogOptions) => Promise<DialogAction>;
32 confirm?: (options: DialogOptions) => Promise<DialogAction>;
33 close?: () => void;
34 stopLoading?: () => void;
35 install?: () => void;
36 setDefaultOptions?: (options: DialogOptions) => void;
37 resetDefaultOptions?: () => void;
38 defaultOptions?: DialogOptions;
39 currentOptions?: DialogOptions;
40 }
41 declare const Dialog: Dialog;
42 export default Dialog;
1 let queue = [];
2 function getContext() {
3 const pages = getCurrentPages();
4 return pages[pages.length - 1];
5 }
6 const Dialog = options => {
7 options = Object.assign({}, Dialog.currentOptions, options);
8 return new Promise((resolve, reject) => {
9 const context = options.context || getContext();
10 const dialog = context.selectComponent(options.selector);
11 delete options.selector;
12 if (dialog) {
13 dialog.set(Object.assign({ onCancel: reject, onConfirm: resolve }, options));
14 queue.push(dialog);
15 }
16 else {
17 console.warn('未找到 van-dialog 节点,请确认 selector 及 context 是否正确');
18 }
19 });
20 };
21 Dialog.defaultOptions = {
22 show: true,
23 title: '',
24 message: '',
25 zIndex: 100,
26 overlay: true,
27 asyncClose: false,
28 messageAlign: '',
29 transition: 'scale',
30 selector: '#van-dialog',
31 confirmButtonText: '确认',
32 cancelButtonText: '取消',
33 showConfirmButton: true,
34 showCancelButton: false,
35 closeOnClickOverlay: false,
36 confirmButtonOpenType: ''
37 };
38 Dialog.alert = Dialog;
39 Dialog.confirm = options => Dialog(Object.assign({ showCancelButton: true }, options));
40 Dialog.close = () => {
41 queue.forEach(dialog => {
42 dialog.close();
43 });
44 queue = [];
45 };
46 Dialog.stopLoading = () => {
47 queue.forEach(dialog => {
48 dialog.stopLoading();
49 });
50 };
51 Dialog.setDefaultOptions = options => {
52 Object.assign(Dialog.currentOptions, options);
53 };
54 Dialog.resetDefaultOptions = () => {
55 Dialog.currentOptions = Object.assign({}, Dialog.defaultOptions);
56 };
57 Dialog.resetDefaultOptions();
58 export default Dialog;
1 import { VantComponent } from '../common/component';
2 import { button } from '../mixins/button';
3 import { openType } from '../mixins/open-type';
4 VantComponent({
5 mixins: [button, openType],
6 props: {
7 show: Boolean,
8 title: String,
9 message: String,
10 useSlot: Boolean,
11 asyncClose: Boolean,
12 messageAlign: String,
13 showCancelButton: Boolean,
14 closeOnClickOverlay: Boolean,
15 confirmButtonOpenType: String,
16 zIndex: {
17 type: Number,
18 value: 2000
19 },
20 confirmButtonText: {
21 type: String,
22 value: '确认'
23 },
24 cancelButtonText: {
25 type: String,
26 value: '取消'
27 },
28 showConfirmButton: {
29 type: Boolean,
30 value: true
31 },
32 overlay: {
33 type: Boolean,
34 value: true
35 },
36 transition: {
37 type: String,
38 value: 'scale'
39 }
40 },
41 data: {
42 loading: {
43 confirm: false,
44 cancel: false
45 }
46 },
47 watch: {
48 show(show) {
49 !show && this.stopLoading();
50 }
51 },
52 methods: {
53 onConfirm() {
54 this.handleAction('confirm');
55 },
56 onCancel() {
57 this.handleAction('cancel');
58 },
59 onClickOverlay() {
60 this.onClose('overlay');
61 },
62 handleAction(action) {
63 if (this.data.asyncClose) {
64 this.set({
65 [`loading.${action}`]: true
66 });
67 }
68 this.onClose(action);
69 },
70 close() {
71 this.set({
72 show: false
73 });
74 },
75 stopLoading() {
76 this.set({
77 loading: {
78 confirm: false,
79 cancel: false
80 }
81 });
82 },
83 onClose(action) {
84 if (!this.data.asyncClose) {
85 this.close();
86 }
87 this.$emit('close', action);
88 //把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading
89 this.$emit(action, { dialog: this });
90 const callback = this.data[action === 'confirm' ? 'onConfirm' : 'onCancel'];
91 if (callback) {
92 callback(this);
93 }
94 }
95 }
96 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-popup": "../popup/index",
5 "van-button": "../button/index"
6 }
7 }
1 <van-popup
2 show="{{ show }}"
3 z-index="{{ zIndex }}"
4 overlay="{{ overlay }}"
5 custom-class="van-dialog"
6 transition="{{ transition }}"
7 close-on-click-overlay="{{ closeOnClickOverlay }}"
8 bind:close="onClickOverlay"
9 >
10 <view
11 wx:if="{{ title }}"
12 class="van-dialog__header {{ message || useSlot ? '' : 'van-dialog--isolated' }}"
13 >
14 {{ title }}
15 </view>
16
17 <slot wx:if="{{ useSlot }}" />
18 <view
19 wx:elif="{{ message }}"
20 class="van-dialog__message {{ title ? 'van-dialog__message--has-title' : '' }} {{ messageAlign ? 'van-dialog__message--' + messageAlign : '' }}"
21 >
22 <text>{{ message }}</text>
23 </view>
24
25 <view class="van-hairline--top van-dialog__footer">
26 <van-button
27 wx:if="{{ showCancelButton }}"
28 size="large"
29 loading="{{ loading.cancel }}"
30 class="van-dialog__button van-hairline--right"
31 custom-class="van-dialog__cancel"
32 bind:click="onCancel"
33 >
34 {{ cancelButtonText }}
35 </van-button>
36 <van-button
37 wx:if="{{ showConfirmButton }}"
38 size="large"
39 class="van-dialog__button"
40 loading="{{ loading.confirm }}"
41 custom-class="van-dialog__confirm"
42
43 open-type="{{ confirmButtonOpenType }}"
44 lang="{{ lang }}"
45 business-id="{{ businessId }}"
46 session-from="{{ sessionFrom }}"
47 send-message-title="{{ sendMessageTitle }}"
48 send-message-path="{{ sendMessagePath }}"
49 send-message-img="{{ sendMessageImg }}"
50 show-message-card="{{ showMessageCard }}"
51 app-parameter="{{ appParameter }}"
52
53 bind:click="onConfirm"
54 bindgetuserinfo="bindGetUserInfo"
55 bindcontact="bindContact"
56 bindgetphonenumber="bindGetPhoneNumber"
57 binderror="bindError"
58 bindlaunchapp="bindLaunchApp"
59 bindopensetting="bindOpenSetting"
60 >
61 {{ confirmButtonText }}
62 </van-button>
63 </view>
64 </van-popup>
1 @import '../common/index.wxss';.van-dialog{width:85%;overflow:hidden;font-size:16px;background-color:#fff;border-radius:4px}.van-dialog__header{padding-top:25px;font-weight:500;text-align:center}.van-dialog__header--isolated{padding:25px 0}.van-dialog__message{max-height:60vh;padding:25px;overflow-y:auto;font-size:14px;line-height:1.5;text-align:center;-webkit-overflow-scrolling:touch}.van-dialog__message--has-title{padding-top:12px;color:#7d7e80}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__footer{display:-webkit-flex;display:flex}.van-dialog__button{-webkit-flex:1;flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog__confirm{color:#1989fa!important}.van-dialog-bounce-enter{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7)}.van-dialog-bounce-leave-active{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.9);transform:translate3d(-50%,-50%,0) scale(.9)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 classes: ['input-class'],
5 props: {
6 size: String,
7 icon: String,
8 label: String,
9 error: Boolean,
10 fixed: Boolean,
11 focus: Boolean,
12 center: Boolean,
13 isLink: Boolean,
14 leftIcon: String,
15 disabled: Boolean,
16 autosize: Boolean,
17 readonly: Boolean,
18 required: Boolean,
19 iconClass: String,
20 clearable: Boolean,
21 inputAlign: String,
22 errorMessageAlign: String,
23 customClass: String,
24 confirmType: String,
25 confirmHold: Boolean,
26 errorMessage: String,
27 placeholder: String,
28 customStyle: String,
29 useIconSlot: Boolean,
30 useButtonSlot: Boolean,
31 showConfirmBar: {
32 type: Boolean,
33 value: true
34 },
35 placeholderStyle: String,
36 adjustPosition: {
37 type: Boolean,
38 value: true
39 },
40 cursorSpacing: {
41 type: Number,
42 value: 50
43 },
44 maxlength: {
45 type: Number,
46 value: -1
47 },
48 type: {
49 type: String,
50 value: 'text'
51 },
52 border: {
53 type: Boolean,
54 value: true
55 },
56 titleWidth: {
57 type: String,
58 value: '90px'
59 }
60 },
61 data: {
62 showClear: false
63 },
64 beforeCreate() {
65 this.focused = false;
66 },
67 methods: {
68 onInput(event) {
69 const { value = '' } = event.detail || {};
70 this.set({
71 value,
72 showClear: this.getShowClear(value)
73 }, () => {
74 this.emitChange(value);
75 });
76 },
77 onFocus(event) {
78 const { value = '', height = 0 } = event.detail || {};
79 this.$emit('focus', { value, height });
80 this.focused = true;
81 this.blurFromClear = false;
82 this.set({
83 showClear: this.getShowClear()
84 });
85 },
86 onBlur(event) {
87 const { value = '', cursor = 0 } = event.detail || {};
88 this.$emit('blur', { value, cursor });
89 this.focused = false;
90 const showClear = this.getShowClear();
91 if (this.data.value === value) {
92 this.set({
93 showClear
94 });
95 }
96 else if (!this.blurFromClear) {
97 // fix: the handwritten keyboard does not trigger input change
98 this.set({
99 value,
100 showClear
101 }, () => {
102 this.emitChange(value);
103 });
104 }
105 },
106 onClickIcon() {
107 this.$emit('click-icon');
108 },
109 getShowClear(value) {
110 value = value === undefined ? this.data.value : value;
111 return (this.data.clearable && this.focused && value && !this.data.readonly);
112 },
113 onClear() {
114 this.blurFromClear = true;
115 this.set({
116 value: '',
117 showClear: this.getShowClear('')
118 }, () => {
119 this.emitChange('');
120 this.$emit('clear', '');
121 });
122 },
123 onConfirm() {
124 this.$emit('confirm', this.data.value);
125 },
126 emitChange(value) {
127 this.$emit('input', value);
128 this.$emit('change', value);
129 }
130 }
131 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-cell": "../cell/index",
5 "van-icon": "../icon/index"
6 }
7 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <van-cell
4 icon="{{ leftIcon }}"
5 title="{{ label }}"
6 center="{{ center }}"
7 border="{{ border }}"
8 is-link="{{ isLink }}"
9 required="{{ required }}"
10 custom-style="{{ customStyle }}"
11 title-width="{{ titleWidth }}"
12 custom-class="van-field"
13 size="{{ size }}"
14 >
15 <slot name="left-icon" slot="icon" />
16 <slot name="label" slot="title" />
17 <view class="van-field__body {{ type === 'textarea' ? 'van-field__body--textarea' : '' }}">
18 <textarea
19 wx:if="{{ type === 'textarea' }}"
20 class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}"
21 fixed="{{ fixed }}"
22 focus="{{ focus }}"
23 value="{{ value }}"
24 disabled="{{ disabled || readonly }}"
25 maxlength="{{ maxlength }}"
26 auto-height="{{ autosize }}"
27 placeholder="{{ placeholder }}"
28 placeholder-style="{{ placeholderStyle }}"
29 placeholder-class="{{ error ? 'van-field__input--error' : 'van-field__placeholder' }}"
30 cursor-spacing="{{ cursorSpacing }}"
31 adjust-position="{{ adjustPosition }}"
32 show-confirm-bar="{{ showConfirmBar }}"
33 bindinput="onInput"
34 bind:blur="onBlur"
35 bind:focus="onFocus"
36 bind:confirm="onConfirm"
37 />
38 <input
39 wx:else
40 class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}"
41 type="{{ type }}"
42 focus="{{ focus }}"
43 value="{{ value }}"
44 disabled="{{ disabled || readonly }}"
45 maxlength="{{ maxlength }}"
46 placeholder="{{ placeholder }}"
47 placeholder-style="{{ placeholderStyle }}"
48 placeholder-class="{{ error ? 'van-field__input--error' : 'van-field__placeholder' }}"
49 confirm-type="{{ confirmType }}"
50 confirm-hold="{{ confirmHold }}"
51 cursor-spacing="{{ cursorSpacing }}"
52 adjust-position="{{ adjustPosition }}"
53 bindinput="onInput"
54 bind:blur="onBlur"
55 bind:focus="onFocus"
56 bind:confirm="onConfirm"
57 />
58 <van-icon
59 wx:if="{{ showClear }}"
60 size="16px"
61 name="clear"
62 class="van-field__clear-root"
63 custom-class="van-field__clear"
64 bind:touchstart="onClear"
65 />
66 <view class="van-field__icon-container" wx:if="{{ icon || useIconSlot }}" bind:tap="onClickIcon">
67 <van-icon
68 wx:if="{{ icon }}"
69 size="16px"
70 name="{{ icon }}"
71 custom-class="van-field__icon {{ iconClass }}"
72 />
73 <slot wx:else name="icon" />
74 </view>
75 <view wx:if="{{ useButtonSlot }}" class="van-field__button">
76 <slot name="button" />
77 </view>
78 </view>
79 <view wx:if="{{ errorMessage }}" class="van-field__error-message {{ utils.bem('field__error', [errorMessageAlign, { disabled, error }]) }}">
80 {{ errorMessage }}
81 </view>
82 </van-cell>
1 @import '../common/index.wxss';.van-field__body{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center}.van-field__body--textarea{min-height:24px}.van-field__input{display:block;width:100%;height:24px;min-height:24px;padding:0;margin:0;line-height:inherit;color:#333;text-align:left;background-color:initial;border:0;box-sizing:border-box;resize:none}.van-field__input--disabled{color:#999;background-color:initial;opacity:1}.van-field__input--center{text-align:center}.van-field__input--right{text-align:right}.van-field__input--error{color:#f44}.van-field__placeholder{color:#999}.van-field__clear-root{display:-webkit-flex;display:flex;height:24px;-webkit-align-items:center;align-items:center}.van-field__button,.van-field__clear,.van-field__icon-container{-webkit-flex-shrink:0;flex-shrink:0}.van-field__clear,.van-field__icon-container{padding:0 10px;margin-right:-10px;line-height:inherit;vertical-align:middle}.van-field__clear{color:#c9c9c9}.van-field__icon-container{color:#999}.van-field__icon{display:block!important}.van-field__button{padding-left:10px}.van-field__error-message{font-size:12px;color:#f44;text-align:left}.van-field__error--center{text-align:center}.van-field__error--right{text-align:right}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { link } from '../mixins/link';
3 import { button } from '../mixins/button';
4 import { openType } from '../mixins/open-type';
5 VantComponent({
6 mixins: [link, button, openType],
7 props: {
8 text: String,
9 loading: Boolean,
10 disabled: Boolean,
11 type: {
12 type: String,
13 value: 'danger'
14 }
15 },
16 methods: {
17 onClick(event) {
18 this.$emit('click', event.detail);
19 this.jumpLink();
20 }
21 }
22 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-button": "../button/index"
5 }
6 }
1 <van-button
2 square
3 id="{{ id }}"
4 size="large"
5 lang="{{ lang }}"
6 type="{{ type }}"
7 loading="{{ loading }}"
8 disabled="{{ disabled }}"
9 open-type="{{ openType }}"
10 custom-class="custom-class"
11 business-id="{{ businessId }}"
12 session-from="{{ sessionFrom }}"
13 app-parameter="{{ appParameter }}"
14 send-message-img="{{ sendMessageImg }}"
15 send-message-path="{{ sendMessagePath }}"
16 show-message-card="{{ showMessageCard }}"
17 send-message-title="{{ sendMessageTitle }}"
18 bind:click="onClick"
19 binderror="bindError"
20 bindcontact="bindContact"
21 bindopensetting="bindOpenSetting"
22 bindgetuserinfo="bindGetUserInfo"
23 bindgetphonenumber="bindGetPhoneNumber"
24 bindlaunchapp="bindLaunchApp"
25 >
26 {{ text }}
27 </van-button>
1 @import '../common/index.wxss';:host{-webkit-flex:1;flex:1}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { link } from '../mixins/link';
3 import { button } from '../mixins/button';
4 import { openType } from '../mixins/open-type';
5 VantComponent({
6 classes: ['icon-class', 'text-class'],
7 mixins: [link, button, openType],
8 props: {
9 text: String,
10 info: String,
11 icon: String,
12 disabled: Boolean,
13 loading: Boolean
14 },
15 methods: {
16 onClick(event) {
17 this.$emit('click', event.detail);
18 this.jumpLink();
19 }
20 }
21 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-button": "../button/index"
6 }
7 }
1 <van-button
2 square
3 id="{{ id }}"
4 size="large"
5 lang="{{ lang }}"
6 loading="{{ loading }}"
7 disabled="{{ disabled }}"
8 open-type="{{ openType }}"
9 business-id="{{ businessId }}"
10 custom-class="van-goods-action-icon"
11 session-from="{{ sessionFrom }}"
12 app-parameter="{{ appParameter }}"
13 send-message-img="{{ sendMessageImg }}"
14 send-message-path="{{ sendMessagePath }}"
15 show-message-card="{{ showMessageCard }}"
16 send-message-title="{{ sendMessageTitle }}"
17 bind:click="onClick"
18 binderror="bindError"
19 bindcontact="bindContact"
20 bindopensetting="bindOpenSetting"
21 bindgetuserinfo="bindGetUserInfo"
22 bindgetphonenumber="bindGetPhoneNumber"
23 bindlaunchapp="bindLaunchApp"
24 >
25 <view class="van-goods-action-icon__content van-hairline--right">
26 <van-icon
27 size="20px"
28 name="{{ icon }}"
29 info="{{ info }}"
30 class="van-goods-action-icon__icon"
31 custom-class="icon-class"
32 />
33 <text class="text-class">{{ text }}</text>
34 </view>
35 </van-button>
1 @import '../common/index.wxss';.van-goods-action-icon{width:50px!important;border:none!important}.van-goods-action-icon__content{display:-webkit-flex;display:flex;height:100%;font-size:10px;line-height:1;color:#7d7e80;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center}.van-goods-action-icon__icon{margin-bottom:4px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({
4 mixins: [safeArea()]
5 });
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="custom-class {{ utils.bem('goods-action', { safe: isIPhoneX && safeAreaInsetBottom }) }}">
4 <slot />
5 </view>
1 @import '../common/index.wxss';.van-goods-action{position:fixed;right:0;bottom:0;left:0;display:-webkit-flex;display:flex;background-color:#fff}.van-goods-action--safe{padding-bottom:34px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 info: null,
5 name: String,
6 size: String,
7 color: String,
8 customStyle: String,
9 classPrefix: {
10 type: String,
11 value: 'van-icon'
12 }
13 },
14 methods: {
15 onClick() {
16 this.$emit('click');
17 }
18 }
19 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-info": "../info/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ classPrefix }} {{ utils.isSrc(name) ? 'van-icon--image' : classPrefix + '-' + name }}"
5 style="{{ color ? 'color: ' + color + ';' : '' }}{{ size ? 'font-size: ' + size + ';' : '' }}{{ customStyle }}"
6 bind:tap="onClick"
7 >
8 <van-info
9 wx:if="{{ info !== null }}"
10 info="{{ info }}"
11 custom-class="van-icon__info"
12 />
13 <image
14 wx:if="{{ utils.isSrc(name) }}"
15 src="{{ name }}"
16 class="van-icon__image"
17 />
18 </view>
1 @import '../common/index.wxss';@font-face{font-style:normal;font-weight:400;font-family:vant-icon;src:url(https://img.yzcdn.cn/vant/vant-icon-29f643.woff2) format("woff2"),url(https://img.yzcdn.cn/vant/vant-icon-29f643.woff) format("woff"),url(https://img.yzcdn.cn/vant/vant-icon-29f643.ttf) format("truetype")}.van-icon{position:relative;font:normal normal normal 14px/1 vant-icon;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}.van-icon,.van-icon:before{display:inline-block}.van-icon-add-o:before{content:"\F000"}.van-icon-add-square:before{content:"\F001"}.van-icon-add:before{content:"\F002"}.van-icon-after-sale:before{content:"\F003"}.van-icon-aim:before{content:"\F004"}.van-icon-alipay:before{content:"\F005"}.van-icon-apps-o:before{content:"\F006"}.van-icon-arrow-down:before{content:"\F007"}.van-icon-arrow-left:before{content:"\F008"}.van-icon-arrow-up:before{content:"\F009"}.van-icon-arrow:before{content:"\F00A"}.van-icon-ascending:before{content:"\F00B"}.van-icon-audio:before{content:"\F00C"}.van-icon-award-o:before{content:"\F00D"}.van-icon-award:before{content:"\F00E"}.van-icon-bag-o:before{content:"\F00F"}.van-icon-bag:before{content:"\F010"}.van-icon-balance-list-o:before{content:"\F011"}.van-icon-balance-list:before{content:"\F012"}.van-icon-balance-o:before{content:"\F013"}.van-icon-balance-pay:before{content:"\F014"}.van-icon-bar-chart-o:before{content:"\F015"}.van-icon-bars:before{content:"\F016"}.van-icon-bell:before{content:"\F017"}.van-icon-bill-o:before{content:"\F018"}.van-icon-bill:before{content:"\F019"}.van-icon-birthday-cake-o:before{content:"\F01A"}.van-icon-bookmark-o:before{content:"\F01B"}.van-icon-bookmark:before{content:"\F01C"}.van-icon-browsing-history-o:before{content:"\F01D"}.van-icon-browsing-history:before{content:"\F01E"}.van-icon-brush-o:before{content:"\F01F"}.van-icon-bulb-o:before{content:"\F020"}.van-icon-bullhorn-o:before{content:"\F021"}.van-icon-calender-o:before{content:"\F022"}.van-icon-card:before{content:"\F023"}.van-icon-cart-circle-o:before{content:"\F024"}.van-icon-cart-circle:before{content:"\F025"}.van-icon-cart-o:before{content:"\F026"}.van-icon-cart:before{content:"\F027"}.van-icon-cash-back-record:before{content:"\F028"}.van-icon-cash-on-deliver:before{content:"\F029"}.van-icon-cashier-o:before{content:"\F02A"}.van-icon-certificate:before{content:"\F02B"}.van-icon-chart-trending-o:before{content:"\F02C"}.van-icon-chat-o:before{content:"\F02D"}.van-icon-chat:before{content:"\F02E"}.van-icon-checked:before{content:"\F02F"}.van-icon-circle:before{content:"\F030"}.van-icon-clear:before{content:"\F031"}.van-icon-clock-o:before{content:"\F032"}.van-icon-clock:before{content:"\F033"}.van-icon-close:before{content:"\F034"}.van-icon-closed-eye:before{content:"\F035"}.van-icon-cluster-o:before{content:"\F036"}.van-icon-cluster:before{content:"\F037"}.van-icon-column:before{content:"\F038"}.van-icon-comment-circle-o:before{content:"\F039"}.van-icon-comment-o:before{content:"\F03A"}.van-icon-comment:before{content:"\F03B"}.van-icon-completed:before{content:"\F03C"}.van-icon-contact:before{content:"\F03D"}.van-icon-coupon-o:before{content:"\F03E"}.van-icon-coupon:before{content:"\F03F"}.van-icon-credit-pay:before{content:"\F040"}.van-icon-cross:before{content:"\F041"}.van-icon-debit-pay:before{content:"\F042"}.van-icon-delete:before{content:"\F043"}.van-icon-descending:before{content:"\F044"}.van-icon-description:before{content:"\F045"}.van-icon-desktop-o:before{content:"\F046"}.van-icon-diamond-o:before{content:"\F047"}.van-icon-diamond:before{content:"\F048"}.van-icon-discount:before{content:"\F049"}.van-icon-ecard-pay:before{content:"\F04A"}.van-icon-edit:before{content:"\F04B"}.van-icon-ellipsis:before{content:"\F04C"}.van-icon-empty:before{content:"\F04D"}.van-icon-envelop-o:before{content:"\F04E"}.van-icon-exchange:before{content:"\F04F"}.van-icon-expand-o:before{content:"\F050"}.van-icon-expand:before{content:"\F051"}.van-icon-eye-o:before{content:"\F052"}.van-icon-eye:before{content:"\F053"}.van-icon-fail:before{content:"\F054"}.van-icon-failure:before{content:"\F055"}.van-icon-filter-o:before{content:"\F056"}.van-icon-fire-o:before{content:"\F057"}.van-icon-fire:before{content:"\F058"}.van-icon-flag-o:before{content:"\F059"}.van-icon-flower-o:before{content:"\F05A"}.van-icon-free-postage:before{content:"\F05B"}.van-icon-friends-o:before{content:"\F05C"}.van-icon-friends:before{content:"\F05D"}.van-icon-gem-o:before{content:"\F05E"}.van-icon-gem:before{content:"\F05F"}.van-icon-gift-card-o:before{content:"\F060"}.van-icon-gift-card:before{content:"\F061"}.van-icon-gift-o:before{content:"\F062"}.van-icon-gift:before{content:"\F063"}.van-icon-gold-coin-o:before{content:"\F064"}.van-icon-gold-coin:before{content:"\F065"}.van-icon-goods-collect-o:before{content:"\F066"}.van-icon-goods-collect:before{content:"\F067"}.van-icon-graphic:before{content:"\F068"}.van-icon-home-o:before{content:"\F069"}.van-icon-hot-o:before{content:"\F06A"}.van-icon-hot-sale-o:before{content:"\F06B"}.van-icon-hot-sale:before{content:"\F06C"}.van-icon-hot:before{content:"\F06D"}.van-icon-hotel-o:before{content:"\F06E"}.van-icon-idcard:before{content:"\F06F"}.van-icon-info-o:before{content:"\F070"}.van-icon-info:before{content:"\F071"}.van-icon-invition:before{content:"\F072"}.van-icon-label-o:before{content:"\F073"}.van-icon-label:before{content:"\F074"}.van-icon-like-o:before{content:"\F075"}.van-icon-like:before{content:"\F076"}.van-icon-live:before{content:"\F077"}.van-icon-location-o:before{content:"\F078"}.van-icon-location:before{content:"\F079"}.van-icon-lock:before{content:"\F07A"}.van-icon-logistics:before{content:"\F07B"}.van-icon-manager-o:before{content:"\F07C"}.van-icon-manager:before{content:"\F07D"}.van-icon-map-marked:before{content:"\F07E"}.van-icon-medel-o:before{content:"\F07F"}.van-icon-medel:before{content:"\F080"}.van-icon-more-o:before{content:"\F081"}.van-icon-more:before{content:"\F082"}.van-icon-music-o:before{content:"\F083"}.van-icon-new-arrival-o:before{content:"\F084"}.van-icon-new-arrival:before{content:"\F085"}.van-icon-new-o:before{content:"\F086"}.van-icon-new:before{content:"\F087"}.van-icon-newspaper-o:before{content:"\F088"}.van-icon-notes-o:before{content:"\F089"}.van-icon-orders-o:before{content:"\F08A"}.van-icon-other-pay:before{content:"\F08B"}.van-icon-paid:before{content:"\F08C"}.van-icon-passed:before{content:"\F08D"}.van-icon-pause-circle-o:before{content:"\F08E"}.van-icon-pause-circle:before{content:"\F08F"}.van-icon-pause:before{content:"\F090"}.van-icon-peer-pay:before{content:"\F091"}.van-icon-pending-payment:before{content:"\F092"}.van-icon-phone-circle-o:before{content:"\F093"}.van-icon-phone-o:before{content:"\F094"}.van-icon-phone:before{content:"\F095"}.van-icon-photo-o:before{content:"\F096"}.van-icon-photo:before{content:"\F097"}.van-icon-photograph:before{content:"\F098"}.van-icon-play-circle-o:before{content:"\F099"}.van-icon-play-circle:before{content:"\F09A"}.van-icon-play:before{content:"\F09B"}.van-icon-plus:before{content:"\F09C"}.van-icon-point-gift-o:before{content:"\F09D"}.van-icon-point-gift:before{content:"\F09E"}.van-icon-points:before{content:"\F09F"}.van-icon-printer:before{content:"\F0A0"}.van-icon-qr-invalid:before{content:"\F0A1"}.van-icon-qr:before{content:"\F0A2"}.van-icon-question-o:before{content:"\F0A3"}.van-icon-question:before{content:"\F0A4"}.van-icon-records:before{content:"\F0A5"}.van-icon-refund-o:before{content:"\F0A6"}.van-icon-replay:before{content:"\F0A7"}.van-icon-scan:before{content:"\F0A8"}.van-icon-search:before{content:"\F0A9"}.van-icon-send-gift-o:before{content:"\F0AA"}.van-icon-send-gift:before{content:"\F0AB"}.van-icon-service-o:before{content:"\F0AC"}.van-icon-service:before{content:"\F0AD"}.van-icon-setting-o:before{content:"\F0AE"}.van-icon-setting:before{content:"\F0AF"}.van-icon-share:before{content:"\F0B0"}.van-icon-shop-collect-o:before{content:"\F0B1"}.van-icon-shop-collect:before{content:"\F0B2"}.van-icon-shop-o:before{content:"\F0B3"}.van-icon-shop:before{content:"\F0B4"}.van-icon-shopping-cart-o:before{content:"\F0B5"}.van-icon-shopping-cart:before{content:"\F0B6"}.van-icon-shrink:before{content:"\F0B7"}.van-icon-sign:before{content:"\F0B8"}.van-icon-smile-comment-o:before{content:"\F0B9"}.van-icon-smile-comment:before{content:"\F0BA"}.van-icon-smile-o:before{content:"\F0BB"}.van-icon-star-o:before{content:"\F0BC"}.van-icon-star:before{content:"\F0BD"}.van-icon-stop-circle-o:before{content:"\F0BE"}.van-icon-stop-circle:before{content:"\F0BF"}.van-icon-stop:before{content:"\F0C0"}.van-icon-success:before{content:"\F0C1"}.van-icon-thumb-circle-o:before{content:"\F0C2"}.van-icon-todo-list-o:before{content:"\F0C3"}.van-icon-todo-list:before{content:"\F0C4"}.van-icon-tosend:before{content:"\F0C5"}.van-icon-tv-o:before{content:"\F0C6"}.van-icon-umbrella-circle:before{content:"\F0C7"}.van-icon-underway-o:before{content:"\F0C8"}.van-icon-underway:before{content:"\F0C9"}.van-icon-upgrade:before{content:"\F0CA"}.van-icon-user-circle-o:before{content:"\F0CB"}.van-icon-user-o:before{content:"\F0CC"}.van-icon-video-o:before{content:"\F0CD"}.van-icon-video:before{content:"\F0CE"}.van-icon-vip-card-o:before{content:"\F0CF"}.van-icon-vip-card:before{content:"\F0D0"}.van-icon-volume-o:before{content:"\F0D1"}.van-icon-volume:before{content:"\F0D2"}.van-icon-wap-home:before{content:"\F0D3"}.van-icon-wap-nav:before{content:"\F0D4"}.van-icon-warn-o:before{content:"\F0D5"}.van-icon-warning-o:before{content:"\F0D6"}.van-icon-weapp-nav:before{content:"\F0D7"}.van-icon-wechat:before{content:"\F0D8"}.van-icon-youzan-shield:before{content:"\F0D9"}.van-icon--image{width:1em;height:1em}.van-icon__image{position:absolute;top:0;right:0;bottom:0;left:0;max-width:100%;max-height:100%;margin:auto}.van-icon__info{z-index:1}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 info: null,
5 customStyle: String
6 }
7 });
1 {
2 "component": true
3 }
1 <view
2 wx:if="{{ info !== null }}"
3 class="custom-class van-info"
4 style="{{ customStyle }}"
5 >{{ info }}</view>
1 @import '../common/index.wxss';.van-info{position:absolute;top:-8px;right:0;min-width:16px;padding:0 3px;font-family:PingFang SC,Helvetica Neue,Arial,sans-serif;font-size:12px;font-weight:500;line-height:14px;color:#fff;text-align:center;white-space:nowrap;background-color:#f44;border:1px solid #fff;border-radius:16px;-webkit-transform:translateX(50%);transform:translateX(50%);box-sizing:border-box;-webkit-transform-origin:100%;transform-origin:100%}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 size: {
5 type: String,
6 value: '30px'
7 },
8 type: {
9 type: String,
10 value: 'circular'
11 },
12 color: {
13 type: String,
14 value: '#c9c9c9'
15 }
16 }
17 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <view
2 class="van-loading custom-class"
3 style="width: {{ size }}; height: {{ size }}"
4 >
5 <view
6 class="van-loading__spinner van-loading__spinner--{{ type }}"
7 style="color: {{ color }};"
8 >
9 <view
10 wx:if="{{ type === 'spinner' }}"
11 wx:for="item in 12"
12 wx:key="index"
13 class="van-loading__dot"
14 />
15 </view>
16 </view>
1 @import '../common/index.wxss';.van-loading{z-index:0;line-height:0;vertical-align:middle}.van-loading,.van-loading__spinner{position:relative;display:inline-block}.van-loading__spinner{z-index:-1;width:100%;height:100%;box-sizing:border-box;-webkit-animation:van-rotate .8s linear infinite;animation:van-rotate .8s linear infinite}.van-loading__spinner--spinner{-webkit-animation-timing-function:steps(12);animation-timing-function:steps(12)}.van-loading__spinner--circular{border-radius:100%;border:1px solid transparent;border-top-color:initial}.van-loading__dot{top:0;left:0;width:100%;height:100%;position:absolute}.van-loading__dot:before{width:2px;height:25%;content:" ";display:block;margin:0 auto;border-radius:40%;background-color:currentColor}.van-loading__dot:first-of-type{opacity:1;-webkit-transform:rotate(30deg);transform:rotate(30deg)}.van-loading__dot:nth-of-type(2){opacity:.9375;-webkit-transform:rotate(60deg);transform:rotate(60deg)}.van-loading__dot:nth-of-type(3){opacity:.875;-webkit-transform:rotate(90deg);transform:rotate(90deg)}.van-loading__dot:nth-of-type(4){opacity:.8125;-webkit-transform:rotate(120deg);transform:rotate(120deg)}.van-loading__dot:nth-of-type(5){opacity:.75;-webkit-transform:rotate(150deg);transform:rotate(150deg)}.van-loading__dot:nth-of-type(6){opacity:.6875;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.van-loading__dot:nth-of-type(7){opacity:.625;-webkit-transform:rotate(210deg);transform:rotate(210deg)}.van-loading__dot:nth-of-type(8){opacity:.5625;-webkit-transform:rotate(240deg);transform:rotate(240deg)}.van-loading__dot:nth-of-type(9){opacity:.5;-webkit-transform:rotate(270deg);transform:rotate(270deg)}.van-loading__dot:nth-of-type(10){opacity:.4375;-webkit-transform:rotate(300deg);transform:rotate(300deg)}.van-loading__dot:nth-of-type(11){opacity:.375;-webkit-transform:rotate(330deg);transform:rotate(330deg)}.van-loading__dot:nth-of-type(12){opacity:.3125;-webkit-transform:rotate(1turn);transform:rotate(1turn)}@-webkit-keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}
...\ No newline at end of file ...\ No newline at end of file
1 export declare const basic: void;
1 export const basic = Behavior({
2 methods: {
3 $emit() {
4 this.triggerEvent.apply(this, arguments);
5 },
6 getRect(selector, all) {
7 return new Promise(resolve => {
8 wx.createSelectorQuery()
9 .in(this)[all ? 'selectAll' : 'select'](selector)
10 .boundingClientRect(rect => {
11 if (all && Array.isArray(rect) && rect.length) {
12 resolve(rect);
13 }
14 if (!all && rect) {
15 resolve(rect);
16 }
17 })
18 .exec();
19 });
20 }
21 }
22 });
1 export declare const button: void;
1 export const button = Behavior({
2 externalClasses: ['hover-class'],
3 properties: {
4 id: String,
5 lang: {
6 type: String,
7 value: 'en'
8 },
9 businessId: Number,
10 sessionFrom: String,
11 sendMessageTitle: String,
12 sendMessagePath: String,
13 sendMessageImg: String,
14 showMessageCard: Boolean,
15 appParameter: String,
16 ariaLabel: String
17 }
18 });
1 export declare const link: void;
1 export const link = Behavior({
2 properties: {
3 url: String,
4 linkType: {
5 type: String,
6 value: 'navigateTo'
7 }
8 },
9 methods: {
10 jumpLink(urlKey = 'url') {
11 const url = this.data[urlKey];
12 if (url) {
13 wx[this.data.linkType]({ url });
14 }
15 }
16 }
17 });
1 export declare const behavior: void;
1 function setAsync(context, data) {
2 return new Promise(resolve => {
3 context.setData(data, resolve);
4 });
5 }
6 ;
7 export const behavior = Behavior({
8 created() {
9 if (!this.$options) {
10 return;
11 }
12 const cache = {};
13 const { computed } = this.$options();
14 const keys = Object.keys(computed);
15 this.calcComputed = () => {
16 const needUpdate = {};
17 keys.forEach(key => {
18 const value = computed[key].call(this);
19 if (cache[key] !== value) {
20 cache[key] = needUpdate[key] = value;
21 }
22 });
23 return needUpdate;
24 };
25 },
26 attached() {
27 this.set();
28 },
29 methods: {
30 // set data and set computed data
31 set(data, callback) {
32 const stack = [];
33 if (data) {
34 stack.push(setAsync(this, data));
35 }
36 if (this.calcComputed) {
37 stack.push(setAsync(this, this.calcComputed()));
38 }
39 return Promise.all(stack).then(res => {
40 if (callback && typeof callback === 'function') {
41 callback.call(this);
42 }
43 return res;
44 });
45 }
46 }
47 });
1 export declare function observe(vantOptions: any, options: any): void;
1 import { behavior } from './behavior';
2 import { observeProps } from './props';
3 export function observe(vantOptions, options) {
4 const { watch, computed } = vantOptions;
5 options.behaviors.push(behavior);
6 if (watch) {
7 const props = options.properties || {};
8 Object.keys(watch).forEach(key => {
9 if (key in props) {
10 let prop = props[key];
11 if (prop === null || !('type' in prop)) {
12 prop = { type: prop };
13 }
14 prop.observer = watch[key];
15 props[key] = prop;
16 }
17 });
18 options.properties = props;
19 }
20 if (computed) {
21 options.methods = options.methods || {};
22 options.methods.$options = () => vantOptions;
23 if (options.properties) {
24 observeProps(options.properties);
25 }
26 }
27 }
1 export declare function observeProps(props: any): void;
1 export function observeProps(props) {
2 if (!props) {
3 return;
4 }
5 Object.keys(props).forEach(key => {
6 let prop = props[key];
7 if (prop === null || !('type' in prop)) {
8 prop = { type: prop };
9 }
10 let { observer } = prop;
11 prop.observer = function () {
12 if (observer) {
13 if (typeof observer === 'string') {
14 observer = this[observer];
15 }
16 observer.apply(this, arguments);
17 }
18 this.set();
19 };
20 props[key] = prop;
21 });
22 }
1 export declare const openType: void;
1 export const openType = Behavior({
2 properties: {
3 openType: String
4 },
5 methods: {
6 bindGetUserInfo(event) {
7 this.$emit('getuserinfo', event.detail);
8 },
9 bindContact(event) {
10 this.$emit('contact', event.detail);
11 },
12 bindGetPhoneNumber(event) {
13 this.$emit('getphonenumber', event.detail);
14 },
15 bindError(event) {
16 this.$emit('error', event.detail);
17 },
18 bindLaunchApp(event) {
19 this.$emit('launchapp', event.detail);
20 },
21 bindOpenSetting(event) {
22 this.$emit('opensetting', event.detail);
23 },
24 }
25 });
1 export declare const safeArea: ({ safeAreaInsetBottom, safeAreaInsetTop }?: {
2 safeAreaInsetBottom?: boolean;
3 safeAreaInsetTop?: boolean;
4 }) => void;
1 let cache = null;
2 function getSafeArea() {
3 return new Promise((resolve, reject) => {
4 if (cache != null) {
5 resolve(cache);
6 }
7 else {
8 wx.getSystemInfo({
9 success: ({ model, screenHeight, statusBarHeight }) => {
10 const iphoneX = /iphone x/i.test(model);
11 const iphoneNew = /iPhone11/i.test(model) && screenHeight === 812;
12 cache = {
13 isIPhoneX: iphoneX || iphoneNew,
14 statusBarHeight
15 };
16 resolve(cache);
17 },
18 fail: reject
19 });
20 }
21 });
22 }
23 export const safeArea = ({ safeAreaInsetBottom = true, safeAreaInsetTop = false } = {}) => Behavior({
24 properties: {
25 safeAreaInsetTop: {
26 type: Boolean,
27 value: safeAreaInsetTop
28 },
29 safeAreaInsetBottom: {
30 type: Boolean,
31 value: safeAreaInsetBottom
32 }
33 },
34 created() {
35 getSafeArea().then(({ isIPhoneX, statusBarHeight }) => {
36 this.set({ isIPhoneX, statusBarHeight });
37 });
38 }
39 });
1 export declare const touch: void;
1 export const touch = Behavior({
2 methods: {
3 touchStart(event) {
4 const touch = event.touches[0];
5 this.direction = '';
6 this.deltaX = 0;
7 this.deltaY = 0;
8 this.offsetX = 0;
9 this.offsetY = 0;
10 this.startX = touch.clientX;
11 this.startY = touch.clientY;
12 },
13 touchMove(event) {
14 const touch = event.touches[0];
15 this.deltaX = touch.clientX - this.startX;
16 this.deltaY = touch.clientY - this.startY;
17 this.offsetX = Math.abs(this.deltaX);
18 this.offsetY = Math.abs(this.deltaY);
19 this.direction =
20 this.offsetX > this.offsetY
21 ? 'horizontal'
22 : this.offsetX < this.offsetY
23 ? 'vertical'
24 : '';
25 }
26 }
27 });
1 export declare const transition: (showDefaultValue: boolean) => void;
1 import { isObj } from '../common/utils';
2 const getClassNames = (name) => ({
3 enter: `van-${name}-enter van-${name}-enter-active enter-class enter-active-class`,
4 'enter-to': `van-${name}-enter-to van-${name}-enter-active enter-to-class enter-active-class`,
5 leave: `van-${name}-leave van-${name}-leave-active leave-class leave-active-class`,
6 'leave-to': `van-${name}-leave-to van-${name}-leave-active leave-to-class leave-active-class`
7 });
8 const nextTick = () => new Promise(resolve => setTimeout(resolve, 1000 / 30));
9 export const transition = function (showDefaultValue) {
10 return Behavior({
11 properties: {
12 customStyle: String,
13 show: {
14 type: Boolean,
15 value: showDefaultValue,
16 observer: 'observeShow'
17 },
18 duration: {
19 type: [Number, Object],
20 value: 300,
21 observer: 'observeDuration'
22 },
23 name: {
24 type: String,
25 value: 'fade',
26 observer: 'updateClasses'
27 }
28 },
29 data: {
30 type: '',
31 inited: false,
32 display: false,
33 classNames: getClassNames('fade')
34 },
35 attached() {
36 if (this.data.show) {
37 this.show();
38 }
39 },
40 methods: {
41 observeShow(value) {
42 if (value) {
43 this.show();
44 }
45 else {
46 this.leave();
47 }
48 },
49 updateClasses(name) {
50 this.set({
51 classNames: getClassNames(name)
52 });
53 },
54 show() {
55 const { classNames, duration } = this.data;
56 const currentDuration = isObj(duration) ? duration.leave : duration;
57 Promise.resolve()
58 .then(nextTick)
59 .then(() => this.set({
60 inited: true,
61 display: true,
62 classes: classNames.enter,
63 currentDuration
64 }))
65 .then(nextTick)
66 .then(() => this.set({
67 classes: classNames['enter-to']
68 }));
69 },
70 leave() {
71 const { classNames, duration } = this.data;
72 const currentDuration = isObj(duration) ? duration.leave : duration;
73 if (+currentDuration === 0) {
74 this.onTransitionEnd();
75 return;
76 }
77 Promise.resolve()
78 .then(nextTick)
79 .then(() => this.set({
80 classes: classNames.leave,
81 currentDuration
82 }))
83 .then(nextTick)
84 .then(() => this.set({
85 classes: classNames['leave-to']
86 }));
87 },
88 onTransitionEnd() {
89 if (!this.data.show) {
90 this.set({ display: false });
91 this.$emit('transitionEnd');
92 }
93 }
94 }
95 });
96 };
1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({
4 mixins: [safeArea({ safeAreaInsetTop: true })],
5 classes: ['title-class'],
6 props: {
7 title: String,
8 fixed: Boolean,
9 leftText: String,
10 rightText: String,
11 leftArrow: Boolean,
12 border: {
13 type: Boolean,
14 value: true
15 },
16 zIndex: {
17 type: Number,
18 value: 120
19 }
20 },
21 methods: {
22 onClickLeft() {
23 this.$emit('click-left');
24 },
25 onClickRight() {
26 this.$emit('click-right');
27 }
28 }
29 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="{{ utils.bem('nav-bar', { fixed }) }} custom-class {{ border ? 'van-hairline--bottom' : '' }}"
5 style="z-index: {{ zIndex }}; {{ safeAreaInsetTop ? 'padding-top: ' + statusBarHeight + 'px;' : '' }}"
6 >
7 <view class="van-nav-bar__left" bind:tap="onClickLeft">
8 <block wx:if="{{ leftArrow || leftText }}">
9 <van-icon
10 wx:if="{{ leftArrow }}"
11 size="16px"
12 name="arrow-left"
13 custom-class="van-nav-bar__arrow"
14 />
15 <view
16 wx:if="{{ leftText }}"
17 class="van-nav-bar__text"
18 hover-class="van-nav-bar__text--hover"
19 hover-stay-time="70"
20 >{{ leftText }}</view>
21 </block>
22 <slot wx:else name="left" />
23 </view>
24 <view class="van-nav-bar__title title-class van-ellipsis">
25 <block wx:if="{{ title }}">{{ title }}</block>
26 <slot wx:else name="title" />
27 </view>
28 <view class="van-nav-bar__right" bind:tap="onClickRight">
29 <view
30 wx:if="{{ rightText }}"
31 class="van-nav-bar__text"
32 hover-class="van-nav-bar__text--hover"
33 hover-stay-time="70"
34 >{{ rightText }}</view>
35 <slot wx:else name="right" />
36 </view>
37 </view>
1 @import '../common/index.wxss';.van-nav-bar{position:relative;height:44px;line-height:44px;text-align:center;background-color:#fff;-webkit-user-select:none;user-select:none}.van-nav-bar__text{display:inline-block;padding:0 15px;margin:0 -15px;color:#1989fa;vertical-align:middle}.van-nav-bar__text--hover{background-color:#f2f3f5}.van-nav-bar__arrow{color:#1989fa;vertical-align:middle}.van-nav-bar__arrow+.van-nav-bar__text{padding-left:25px;margin-left:-20px}.van-nav-bar--fixed{position:fixed;top:0;left:0;width:100%}.van-nav-bar__title{max-width:60%;margin:0 auto;font-size:16px;font-weight:500}.van-nav-bar__left,.van-nav-bar__right{position:absolute;bottom:0;font-size:14px}.van-nav-bar__left{left:15px}.van-nav-bar__right{right:15px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 const FONT_COLOR = '#ed6a0c';
3 const BG_COLOR = '#fffbe8';
4 VantComponent({
5 props: {
6 text: {
7 type: String,
8 value: ''
9 },
10 mode: {
11 type: String,
12 value: ''
13 },
14 url: {
15 type: String,
16 value: ''
17 },
18 openType: {
19 type: String,
20 value: 'navigate'
21 },
22 delay: {
23 type: Number,
24 value: 0
25 },
26 speed: {
27 type: Number,
28 value: 50
29 },
30 scrollable: {
31 type: Boolean,
32 value: true
33 },
34 leftIcon: {
35 type: String,
36 value: ''
37 },
38 color: {
39 type: String,
40 value: FONT_COLOR
41 },
42 backgroundColor: {
43 type: String,
44 value: BG_COLOR
45 }
46 },
47 data: {
48 show: true,
49 hasRightIcon: false
50 },
51 watch: {
52 text() {
53 this.set({}, this.init);
54 }
55 },
56 created() {
57 if (this.data.mode) {
58 this.set({
59 hasRightIcon: true
60 });
61 }
62 this.resetAnimation = wx.createAnimation({
63 duration: 0,
64 timingFunction: 'linear'
65 });
66 },
67 destroyed() {
68 this.timer && clearTimeout(this.timer);
69 },
70 methods: {
71 init() {
72 Promise.all([
73 this.getRect('.van-notice-bar__content'),
74 this.getRect('.van-notice-bar__content-wrap')
75 ]).then((rects) => {
76 const [contentRect, wrapRect] = rects;
77 if (contentRect == null ||
78 wrapRect == null ||
79 !contentRect.width ||
80 !wrapRect.width) {
81 return;
82 }
83 const { speed, scrollable, delay } = this.data;
84 if (scrollable && wrapRect.width < contentRect.width) {
85 const duration = (contentRect.width / speed) * 1000;
86 this.wrapWidth = wrapRect.width;
87 this.contentWidth = contentRect.width;
88 this.duration = duration;
89 this.animation = wx.createAnimation({
90 duration,
91 timingFunction: 'linear',
92 delay
93 });
94 this.scroll();
95 }
96 });
97 },
98 scroll() {
99 this.timer && clearTimeout(this.timer);
100 this.timer = null;
101 this.set({
102 animationData: this.resetAnimation
103 .translateX(this.wrapWidth)
104 .step()
105 .export()
106 });
107 setTimeout(() => {
108 this.set({
109 animationData: this.animation
110 .translateX(-this.contentWidth)
111 .step()
112 .export()
113 });
114 }, 20);
115 this.timer = setTimeout(() => {
116 this.scroll();
117 }, this.duration);
118 },
119 onClickIcon() {
120 this.timer && clearTimeout(this.timer);
121 this.timer = null;
122 this.set({ show: false });
123 },
124 onClick(event) {
125 this.$emit('click', event);
126 }
127 }
128 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
...\ No newline at end of file ...\ No newline at end of file
1 <view
2 wx:if="{{ show }}"
3 class="custom-class van-notice-bar {{ hasRightIcon ? 'van-notice-bar--within-icon' : '' }}"
4 style="color: {{ color }}; background-color: {{ backgroundColor }};"
5 bind:tap="onClick"
6 >
7 <view wx:if="{{ leftIcon }}" class="van-notice-bar__left-icon">
8 <image src="{{ leftIcon }}" />
9 </view>
10 <view class="van-notice-bar__content-wrap">
11 <view class="van-notice-bar__content {{ scrollable ? '' : 'van-ellipsis' }}" animation="{{ animationData }}">
12 {{ text }}
13 </view>
14 </view>
15
16 <van-icon
17 wx:if="{{ mode === 'closeable' }}"
18 class="van-notice-bar__right-icon"
19 name="cross"
20 bind:tap="onClickIcon"
21 />
22 <navigator
23 wx:if="{{ mode === 'link' }}"
24 url="{{ url }}"
25 open-type="{{ openType }}"
26 >
27 <van-icon class="van-notice-bar__right-icon" name="arrow" />
28 </navigator>
29 </view>
1 @import '../common/index.wxss';.van-notice-bar{display:-webkit-flex;display:flex;height:40px;padding:0 15px;font-size:14px;line-height:24px;-webkit-align-items:center;align-items:center}.van-notice-bar--within-icon{position:relative;padding-right:40px}.van-notice-bar__left-icon{height:18px;min-width:20px;box-sizing:border-box}.van-notice-bar__left-icon>image{width:16px;height:16px}.van-notice-bar__right-icon{position:absolute;top:10px;right:15px;font-size:16px}.van-notice-bar__content-wrap{position:relative;height:24px;overflow:hidden;-webkit-flex:1;flex:1}.van-notice-bar__content{position:absolute;white-space:nowrap}.van-notice-bar__content.van-ellipsis{max-width:100%}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { RED } from '../common/color';
3 import { safeArea } from '../mixins/safe-area';
4 VantComponent({
5 mixins: [safeArea()],
6 props: {
7 text: String,
8 color: {
9 type: String,
10 value: '#fff'
11 },
12 backgroundColor: {
13 type: String,
14 value: RED
15 },
16 duration: {
17 type: Number,
18 value: 3000
19 }
20 },
21 methods: {
22 show() {
23 const { duration } = this.data;
24 clearTimeout(this.timer);
25 this.set({
26 show: true
27 });
28 if (duration > 0 && duration !== Infinity) {
29 this.timer = setTimeout(() => {
30 this.hide();
31 }, duration);
32 }
33 },
34 hide() {
35 clearTimeout(this.timer);
36 this.set({
37 show: false
38 });
39 }
40 }
41 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-transition": "../transition/index"
5 }
6 }
1 <van-transition
2 name="slide-down"
3 show="{{ show }}"
4 custom-class="van-notify"
5 custom-style="background-color:{{ backgroundColor }}; color: {{ color }};"
6 >
7 <view wx:if="{{ safeAreaInsetTop }}" class="van-notify__safe-top" style="padding-top: {{ statusBarHeight }}px"></view>
8 {{ text }}
9 </van-transition>
1 @import '../common/index.wxss';.van-notify{position:fixed;top:0;z-index:110;width:100%;padding:6px 15px;font-size:14px;line-height:20px;text-align:center;word-break:break-all;box-sizing:border-box}.van-notify__safe-top{height:44px}
...\ No newline at end of file ...\ No newline at end of file
1 declare type NotifyOptions = {
2 text: string;
3 color?: string;
4 backgroundColor?: string;
5 duration?: number;
6 selector?: string;
7 context?: any;
8 safeAreaInsetTop?: boolean;
9 };
10 export default function Notify(options: NotifyOptions | string): void;
11 export {};
1 import { isObj } from '../common/utils';
2 const defaultOptions = {
3 selector: '#van-notify',
4 duration: 3000
5 };
6 function parseOptions(text) {
7 return isObj(text) ? text : { text };
8 }
9 function getContext() {
10 const pages = getCurrentPages();
11 return pages[pages.length - 1];
12 }
13 export default function Notify(options) {
14 options = Object.assign({}, defaultOptions, parseOptions(options));
15 const context = options.context || getContext();
16 const notify = context.selectComponent(options.selector);
17 delete options.selector;
18 if (notify) {
19 notify.set(options);
20 notify.show();
21 }
22 else {
23 console.warn('未找到 van-notify 节点,请确认 selector 及 context 是否正确');
24 }
25 }
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 show: Boolean,
5 mask: Boolean,
6 customStyle: String,
7 duration: {
8 type: [Number, Object],
9 value: 300
10 },
11 zIndex: {
12 type: Number,
13 value: 1
14 }
15 },
16 methods: {
17 onClick() {
18 this.$emit('click');
19 },
20 // for prevent touchmove
21 noop() { }
22 }
23 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-transition": "../transition/index"
5 }
6 }
1 <van-transition
2 show="{{ show }}"
3 custom-class="van-overlay"
4 custom-style="z-index: {{ zIndex }}; {{ mask ? 'background-color: rgba(0, 0, 0, .7);' : '' }}; {{ customStyle }}"
5 duration="{{ duration }}"
6 bind:tap="onClick"
7 catch:touchmove="noop"
8 />
1 @import '../common/index.wxss';.van-overlay{position:fixed;top:0;right:0;bottom:0;left:0}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 classes: ['header-class', 'footer-class'],
4 props: {
5 desc: String,
6 title: String,
7 status: String,
8 useFooterSlot: Boolean
9 }
10 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-cell": "../cell/index"
5 }
6 }
1 <view class="van-panel van-hairline--top-bottom custom-class">
2 <van-cell
3 wx:if="{{ title || desc || status }}"
4 title="{{ title }}"
5 label="{{ desc }}"
6 value="{{ status }}"
7 custom-class="header-class"
8 value-class="van-panel__header-value"
9 />
10 <slot wx:else name="header" />
11
12 <view class="van-panel__content">
13 <slot />
14 </view>
15
16 <view wx:if="{{ useFooterSlot }}" class="van-panel__footer van-hairline--top footer-class">
17 <slot name="footer" />
18 </view>
19 </view>
1 @import '../common/index.wxss';.van-panel{background:#fff}.van-panel__header-value{color:#f44}.van-panel__footer{padding:10px 15px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { isObj, range } from '../common/utils';
3 const DEFAULT_DURATION = 200;
4 VantComponent({
5 classes: ['active-class'],
6 props: {
7 valueKey: String,
8 className: String,
9 itemHeight: Number,
10 visibleItemCount: Number,
11 initialOptions: {
12 type: Array,
13 value: []
14 },
15 defaultIndex: {
16 type: Number,
17 value: 0
18 }
19 },
20 data: {
21 startY: 0,
22 offset: 0,
23 duration: 0,
24 startOffset: 0,
25 options: [],
26 currentIndex: 0
27 },
28 created() {
29 const { defaultIndex, initialOptions } = this.data;
30 this.set({
31 currentIndex: defaultIndex,
32 options: initialOptions
33 }).then(() => {
34 this.setIndex(defaultIndex);
35 });
36 },
37 computed: {
38 count() {
39 return this.data.options.length;
40 },
41 baseOffset() {
42 const { data } = this;
43 return (data.itemHeight * (data.visibleItemCount - 1)) / 2;
44 },
45 wrapperStyle() {
46 const { data } = this;
47 return [
48 `transition: ${data.duration}ms`,
49 `transform: translate3d(0, ${data.offset + data.baseOffset}px, 0)`,
50 `line-height: ${data.itemHeight}px`
51 ].join('; ');
52 }
53 },
54 watch: {
55 defaultIndex(value) {
56 this.setIndex(value);
57 }
58 },
59 methods: {
60 onTouchStart(event) {
61 this.set({
62 startY: event.touches[0].clientY,
63 startOffset: this.data.offset,
64 duration: 0
65 });
66 },
67 onTouchMove(event) {
68 const { data } = this;
69 const deltaY = event.touches[0].clientY - data.startY;
70 this.set({
71 offset: range(data.startOffset + deltaY, -(data.count * data.itemHeight), data.itemHeight)
72 });
73 },
74 onTouchEnd() {
75 const { data } = this;
76 if (data.offset !== data.startOffset) {
77 this.set({
78 duration: DEFAULT_DURATION
79 });
80 const index = range(Math.round(-data.offset / data.itemHeight), 0, data.count - 1);
81 this.setIndex(index, true);
82 }
83 },
84 onClickItem(event) {
85 const { index } = event.currentTarget.dataset;
86 this.setIndex(index, true);
87 },
88 adjustIndex(index) {
89 const { data } = this;
90 index = range(index, 0, data.count);
91 for (let i = index; i < data.count; i++) {
92 if (!this.isDisabled(data.options[i]))
93 return i;
94 }
95 for (let i = index - 1; i >= 0; i--) {
96 if (!this.isDisabled(data.options[i]))
97 return i;
98 }
99 },
100 isDisabled(option) {
101 return isObj(option) && option.disabled;
102 },
103 getOptionText(option) {
104 const { data } = this;
105 return isObj(option) && data.valueKey in option
106 ? option[data.valueKey]
107 : option;
108 },
109 setIndex(index, userAction) {
110 const { data } = this;
111 index = this.adjustIndex(index) || 0;
112 const offset = -index * data.itemHeight;
113 if (index !== data.currentIndex) {
114 return this.set({ offset, currentIndex: index }).then(() => {
115 userAction && this.$emit('change', index);
116 });
117 }
118 else {
119 return this.set({ offset });
120 }
121 },
122 setValue(value) {
123 const { options } = this.data;
124 for (let i = 0; i < options.length; i++) {
125 if (this.getOptionText(options[i]) === value) {
126 return this.setIndex(i);
127 }
128 }
129 return Promise.resolve();
130 },
131 getValue() {
132 const { data } = this;
133 return data.options[data.currentIndex];
134 }
135 }
136 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <view
2 class="van-picker-column custom-class"
3 style="height: {{ itemHeight * visibleItemCount }}px"
4 bind:touchstart="onTouchStart"
5 catch:touchmove="onTouchMove"
6 bind:touchend="onTouchEnd"
7 bind:touchcancel="onTouchEnd"
8 >
9 <view style="{{ wrapperStyle }}">
10 <view
11 wx:for="{{ options }}"
12 wx:for-item="option"
13 wx:key="index"
14 data-index="{{ index }}"
15 style="height: {{ itemHeight }}px"
16 class="van-ellipsis van-picker-column__item {{ option && option.disabled ? 'van-picker-column__item--disabled' : '' }} {{ index === currentIndex ? 'van-picker-column__item--selected active-class' : '' }}"
17 bindtap="onClickItem"
18 >{{ getOptionText(option, valueKey) }}</view>
19 </view>
20 </view>
21
22 <wxs module="getOptionText">
23 function isObj(x) {
24 var type = typeof x;
25 return x !== null && (type === 'object' || type === 'function');
26 }
27
28 module.exports = function (option, valueKey) {
29 return isObj(option) && option[valueKey] ? option[valueKey] : option;
30 }
31 </wxs>
1 @import '../common/index.wxss';.van-picker-column{overflow:hidden;font-size:16px;text-align:center}.van-picker-column__item{padding:0 5px;color:#999}.van-picker-column__item--selected{font-weight:500;color:#333}.van-picker-column__item--disabled{opacity:.3}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 function isSimple(columns) {
3 return columns.length && !columns[0].values;
4 }
5 VantComponent({
6 classes: ['active-class', 'toolbar-class', 'column-class'],
7 props: {
8 title: String,
9 loading: Boolean,
10 showToolbar: Boolean,
11 confirmButtonText: String,
12 cancelButtonText: String,
13 visibleItemCount: {
14 type: Number,
15 value: 5
16 },
17 valueKey: {
18 type: String,
19 value: 'text'
20 },
21 itemHeight: {
22 type: Number,
23 value: 44
24 },
25 columns: {
26 type: Array,
27 value: [],
28 observer(columns = []) {
29 this.simple = isSimple(columns);
30 this.children = this.selectAllComponents('.van-picker__column');
31 if (Array.isArray(this.children) && this.children.length) {
32 this.setColumns().catch(() => { });
33 }
34 }
35 }
36 },
37 beforeCreate() {
38 this.children = [];
39 },
40 methods: {
41 noop() { },
42 setColumns() {
43 const { data } = this;
44 const columns = this.simple ? [{ values: data.columns }] : data.columns;
45 const stack = columns.map((column, index) => this.setColumnValues(index, column.values));
46 return Promise.all(stack);
47 },
48 emit(event) {
49 const { type } = event.currentTarget.dataset;
50 if (this.simple) {
51 this.$emit(type, {
52 value: this.getColumnValue(0),
53 index: this.getColumnIndex(0)
54 });
55 }
56 else {
57 this.$emit(type, {
58 value: this.getValues(),
59 index: this.getIndexes()
60 });
61 }
62 },
63 onChange(event) {
64 if (this.simple) {
65 this.$emit('change', {
66 picker: this,
67 value: this.getColumnValue(0),
68 index: this.getColumnIndex(0)
69 });
70 }
71 else {
72 this.$emit('change', {
73 picker: this,
74 value: this.getValues(),
75 index: event.currentTarget.dataset.index
76 });
77 }
78 },
79 // get column instance by index
80 getColumn(index) {
81 return this.children[index];
82 },
83 // get column value by index
84 getColumnValue(index) {
85 const column = this.getColumn(index);
86 return column && column.getValue();
87 },
88 // set column value by index
89 setColumnValue(index, value) {
90 const column = this.getColumn(index);
91 if (column == null) {
92 return Promise.reject('setColumnValue: 对应列不存在');
93 }
94 return column.setValue(value);
95 },
96 // get column option index by column index
97 getColumnIndex(columnIndex) {
98 return (this.getColumn(columnIndex) || {}).data.currentIndex;
99 },
100 // set column option index by column index
101 setColumnIndex(columnIndex, optionIndex) {
102 const column = this.getColumn(columnIndex);
103 if (column == null) {
104 return Promise.reject('setColumnIndex: 对应列不存在');
105 }
106 return column.setIndex(optionIndex);
107 },
108 // get options of column by index
109 getColumnValues(index) {
110 return (this.children[index] || {}).data.options;
111 },
112 // set options of column by index
113 setColumnValues(index, options, needReset = true) {
114 const column = this.children[index];
115 if (column == null) {
116 return Promise.reject('setColumnValues: 对应列不存在');
117 }
118 const isSame = JSON.stringify(column.data.options) === JSON.stringify(options);
119 if (isSame) {
120 return Promise.resolve();
121 }
122 return column.set({ options }).then(() => {
123 if (needReset) {
124 column.setIndex(0);
125 }
126 });
127 },
128 // get values of all columns
129 getValues() {
130 return this.children.map((child) => child.getValue());
131 },
132 // set values of all columns
133 setValues(values) {
134 const stack = values.map((value, index) => this.setColumnValue(index, value));
135 return Promise.all(stack);
136 },
137 // get indexes of all columns
138 getIndexes() {
139 return this.children.map((child) => child.data.currentIndex);
140 },
141 // set indexes of all columns
142 setIndexes(indexes) {
143 const stack = indexes.map((optionIndex, columnIndex) => this.setColumnIndex(columnIndex, optionIndex));
144 return Promise.all(stack);
145 }
146 }
147 });
1 {
2 "component": true,
3 "usingComponents": {
4 "picker-column": "../picker-column/index",
5 "loading": "../loading/index"
6 }
7 }
1 <view class="van-picker custom-class">
2 <view
3 wx:if="{{ showToolbar }}"
4 class="van-picker__toolbar van-hairline--top-bottom toolbar-class"
5 >
6 <view
7 class="van-picker__cancel"
8 hover-class="van-picker__cancel--hover"
9 hover-stay-time="70"
10 data-type="cancel"
11 bindtap="emit"
12 >
13 {{ cancelButtonText || '取消' }}
14 </view>
15 <view wx:if="{{ title }}" class="van-picker__title van-ellipsis">{{ title }}</view>
16 <view
17 class="van-picker__confirm"
18 hover-class="van-picker__confirm--hover"
19 hover-stay-time="70"
20 data-type="confirm"
21 bindtap="emit"
22 >
23 {{ confirmButtonText || '确认' }}
24 </view>
25 </view>
26 <view wx:if="{{ loading }}" class="van-picker__loading">
27 <loading color="#1989fa"/>
28 </view>
29 <view
30 class="van-picker__columns"
31 style="height: {{ itemHeight * visibleItemCount }}px"
32 catch:touchmove="noop"
33 >
34 <picker-column
35 class="van-picker__column"
36 wx:for="{{ isSimple(columns) ? [columns] : columns }}"
37 wx:key="{{ index }}"
38 data-index="{{ index }}"
39 custom-class="column-class"
40 value-key="{{ valueKey }}"
41 initial-options="{{ isSimple(columns) ? item : item.values }}"
42 default-index="{{ item.defaultIndex }}"
43 item-height="{{ itemHeight }}"
44 visible-item-count="{{ visibleItemCount }}"
45 active-class="active-class"
46 bind:change="onChange"
47 />
48 <view
49 class="van-picker__frame van-hairline--top-bottom"
50 style="height: {{ itemHeight }}px"
51 />
52 </view>
53 </view>
54
55 <wxs module="isSimple">
56 function isSimple(columns) {
57 return columns.length && !columns[0].values;
58 }
59 module.exports = isSimple;
60 </wxs>
1 @import '../common/index.wxss';.van-picker{position:relative;overflow:hidden;-webkit-text-size-adjust:100%;background-color:#fff;-webkit-user-select:none;user-select:none}.van-picker__toolbar{display:-webkit-flex;display:flex;height:44px;line-height:44px;-webkit-justify-content:space-between;justify-content:space-between}.van-picker__cancel,.van-picker__confirm{padding:0 15px;font-size:14px;color:#1989fa}.van-picker__cancel--hover,.van-picker__confirm--hover{background-color:#f2f3f5}.van-picker__title{max-width:50%;font-size:16px;font-weight:500;text-align:center}.van-picker__columns{position:relative;display:-webkit-flex;display:flex}.van-picker__column{-webkit-flex:1 1;flex:1 1;width:0}.van-picker__loading{position:absolute;top:0;right:0;bottom:0;left:0;z-index:4;display:-webkit-flex;display:flex;background-color:hsla(0,0%,100%,.9);-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-picker__frame,.van-picker__loading .van-loading{position:absolute;top:50%;left:0;z-index:1;width:100%;pointer-events:none;-webkit-transform:translateY(-50%);transform:translateY(-50%)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { transition } from '../mixins/transition';
3 import { safeArea } from '../mixins/safe-area';
4 VantComponent({
5 classes: [
6 'enter-class',
7 'enter-active-class',
8 'enter-to-class',
9 'leave-class',
10 'leave-active-class',
11 'leave-to-class'
12 ],
13 mixins: [transition(false), safeArea()],
14 props: {
15 transition: {
16 type: String,
17 observer: 'observeClass'
18 },
19 customStyle: String,
20 overlayStyle: String,
21 zIndex: {
22 type: Number,
23 value: 100
24 },
25 overlay: {
26 type: Boolean,
27 value: true
28 },
29 closeOnClickOverlay: {
30 type: Boolean,
31 value: true
32 },
33 position: {
34 type: String,
35 value: 'center',
36 observer: 'observeClass'
37 }
38 },
39 created() {
40 this.observeClass();
41 },
42 methods: {
43 onClickOverlay() {
44 this.$emit('click-overlay');
45 if (this.data.closeOnClickOverlay) {
46 this.$emit('close');
47 }
48 },
49 observeClass() {
50 const { transition, position } = this.data;
51 this.updateClasses(transition || position);
52 if (transition === 'none') {
53 this.set({ duration: 0 });
54 }
55 }
56 }
57 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-overlay": "../overlay/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <van-overlay
4 wx:if="{{ inited && overlay }}"
5 mask
6 show="{{ show }}"
7 z-index="{{ zIndex }}"
8 custom-style="{{ overlayStyle }}"
9 duration="{{ duration }}"
10 bind:click="onClickOverlay"
11 />
12 <view
13 wx:if="{{ inited }}"
14 class="custom-class {{ classes }} {{ utils.bem('popup', [position, { safe: isIPhoneX && safeAreaInsetBottom }]) }}"
15 style="z-index: {{ zIndex }}; -webkit-transition-duration:{{ currentDuration }}ms; transition-duration:{{ currentDuration }}ms; {{ display ? '' : 'display: none;' }} {{ customStyle }}"
16 bind:transitionend="onTransitionEnd"
17 >
18 <view wx:if="{{ safeAreaInsetTop }}" class="van-popup__safe-top" style="padding-top: {{ statusBarHeight }}px;"></view>
19 <slot />
20 </view>
1 @import '../common/index.wxss';.van-popup{position:fixed;top:50%;left:50%;max-height:100%;overflow-y:auto;background-color:#fff;box-sizing:border-box;-webkit-animation:ease both;animation:ease both;-webkit-overflow-scrolling:touch;transition-timing-function:ease}.van-popup--center{-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-popup--top{top:0;right:auto;bottom:auto;left:50%;width:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-popup--right{top:50%;right:0;bottom:auto;left:auto;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--bottom{top:auto;right:auto;bottom:0;left:50%;width:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-popup--left{top:50%;right:auto;bottom:auto;left:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--bottom.van-popup--safe{padding-bottom:34px}.van-popup--left .van-popup__safe-top,.van-popup--right .van-popup__safe-top,.van-popup--top .van-popup__safe-top{height:44px}.van-popup--bottom .van-popup__safe-top,.van-popup--center .van-popup__safe-top{padding-top:0!important}.van-scale-enter-active,.van-scale-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-scale-enter,.van-scale-leave-to{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7)}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-center-enter-active,.van-center-leave-active{transition-property:opacity}.van-center-enter,.van-center-leave-to{opacity:0}.van-bottom-enter-active,.van-bottom-leave-active,.van-left-enter-active,.van-left-leave-active,.van-right-enter-active,.van-right-leave-active,.van-top-enter-active,.van-top-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-bottom-enter,.van-bottom-leave-to{-webkit-transform:translate3d(-50%,100%,0);transform:translate3d(-50%,100%,0)}.van-top-enter,.van-top-leave-to{-webkit-transform:translate3d(-50%,-100%,0);transform:translate3d(-50%,-100%,0)}.van-left-enter,.van-left-leave-to{-webkit-transform:translate3d(-100%,-50%,0);transform:translate3d(-100%,-50%,0)}.van-right-enter,.van-right-leave-to{-webkit-transform:translate3d(100%,-50%,0);transform:translate3d(100%,-50%,0)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { BLUE } from '../common/color';
3 VantComponent({
4 props: {
5 inactive: Boolean,
6 percentage: Number,
7 pivotText: String,
8 pivotColor: String,
9 showPivot: {
10 type: Boolean,
11 value: true
12 },
13 color: {
14 type: String,
15 value: BLUE
16 },
17 textColor: {
18 type: String,
19 value: '#fff'
20 }
21 },
22 data: {
23 pivotWidth: 0,
24 progressWidth: 0
25 },
26 watch: {
27 pivotText: 'getWidth',
28 showPivot: 'getWidth'
29 },
30 computed: {
31 portionStyle() {
32 const width = (this.data.progressWidth - this.data.pivotWidth) * this.data.percentage / 100 + 'px';
33 const background = this.getCurrentColor();
34 return `width: ${width}; background: ${background}; `;
35 },
36 pivotStyle() {
37 const color = this.data.textColor;
38 const background = this.data.pivotColor || this.getCurrentColor();
39 return `color: ${color}; background: ${background}`;
40 },
41 text() {
42 return this.data.pivotText || this.data.percentage + '%';
43 }
44 },
45 mounted() {
46 this.getWidth();
47 },
48 methods: {
49 getCurrentColor() {
50 return this.data.inactive ? '#cacaca' : this.data.color;
51 },
52 getWidth() {
53 this.getRect('.van-progress').then(rect => {
54 this.set({
55 progressWidth: rect.width
56 });
57 });
58 this.getRect('.van-progress__pivot').then(rect => {
59 this.set({
60 pivotWidth: rect.width || 0
61 });
62 });
63 }
64 }
65 });
1 <view class="van-progress custom-class">
2 <view
3 class="van-progress__portion {{ showPivot && text ? 'van-progress__portion--with-pivot' : '' }}"
4 style="{{ portionStyle }}"
5 >
6 <view
7 wx:if="{{ showPivot && text }}"
8 style="{{ pivotStyle }}"
9 class="van-progress__pivot"
10 >
11 {{ text }}
12 </view>
13 </view>
14 </view>
1 @import '../common/index.wxss';.van-progress{height:4px;position:relative;border-radius:4px;background:#e5e5e5}.van-progress__portion{left:0;height:100%;position:absolute;border-radius:inherit}.van-progress__portion--with-pivot{border-top-right-radius:0;border-bottom-right-radius:0}.van-progress__pivot{top:50%;right:0;min-width:2em;padding:0 5px;font-size:10px;position:absolute;line-height:1.6;text-align:center;border-radius:1em;word-break:keep-all;box-sizing:border-box;background-color:#e5e5e5;-webkit-transform:translate(100%,-50%);transform:translate(100%,-50%)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 relation: {
5 name: 'radio',
6 type: 'descendant',
7 linked(target) {
8 const { value, disabled } = this.data;
9 target.set({
10 value: value,
11 disabled: disabled || target.data.disabled
12 });
13 }
14 },
15 props: {
16 value: null,
17 disabled: Boolean
18 },
19 watch: {
20 value(value) {
21 const children = this.getRelationNodes('../radio/index');
22 children.forEach(child => {
23 child.set({ value });
24 });
25 },
26 disabled(disabled) {
27 const children = this.getRelationNodes('../radio/index');
28 children.forEach(child => {
29 child.set({ disabled: disabled || child.data.disabled });
30 });
31 }
32 }
33 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 @import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 relation: {
5 name: 'radio-group',
6 type: 'ancestor'
7 },
8 classes: ['icon-class', 'label-class'],
9 props: {
10 name: null,
11 value: null,
12 disabled: Boolean,
13 labelDisabled: Boolean,
14 labelPosition: String,
15 checkedColor: String
16 },
17 methods: {
18 emitChange(value) {
19 const instance = this.getRelationNodes('../radio-group/index')[0] || this;
20 instance.$emit('input', value);
21 instance.$emit('change', value);
22 },
23 onChange(event) {
24 this.emitChange(event.detail.value);
25 },
26 onClickLabel() {
27 if (!this.data.disabled && !this.data.labelDisabled) {
28 this.emitChange(this.data.name);
29 }
30 }
31 }
32 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="van-radio custom-class">
4 <view class="van-radio__input">
5 <radio-group bindchange="onChange">
6 <radio
7 value="{{ name }}"
8 checked="{{ value === name }}"
9 disabled="{{ disabled }}"
10 class="van-radio__control"
11 />
12 </radio-group>
13 <van-icon
14 class="{{ utils.bem('radio__icon', { disabled, checked: !disabled && name === value, check: !disabled && name !== value }) }}"
15 custom-class="icon-class"
16 color="{{ value === name ? checkedColor : '' }}"
17 name="{{ value === name ? 'checked' : 'circle' }}"
18 />
19 </view>
20 <view class="van-radio__label van-radio__label--{{ labelPosition }} label-class" bindtap="onClickLabel">
21 <slot />
22 </view>
23 </view>
1 @import '../common/index.wxss';.van-radio{overflow:hidden;line-height:1;-webkit-user-select:none;user-select:none}.van-radio__input,.van-radio__label{display:inline-block;vertical-align:middle}.van-radio__input{position:relative;font-size:20px}.van-radio__control{z-index:1;position:absolute;top:0;left:0;width:100%;height:100%;margin:0;opacity:0}.van-radio__label{margin-left:10px;color:#333;font-size:16px;line-height:20px}.van-radio__label--left{margin:0 10px 0 0;float:left}.van-radio__label:empty{margin:0}.van-radio__icon{pointer-events:none;display:block;line-height:0}.van-radio__icon--disabled{color:#e5e5e5}.van-radio__icon--checked{color:#1989fa}.van-radio__icon--check{color:#c9c9c9}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 classes: ['icon-class'],
5 props: {
6 readonly: Boolean,
7 disabled: Boolean,
8 size: {
9 type: Number,
10 value: 20
11 },
12 icon: {
13 type: String,
14 value: 'star'
15 },
16 voidIcon: {
17 type: String,
18 value: 'star-o'
19 },
20 color: {
21 type: String,
22 value: '#ffd21e'
23 },
24 voidColor: {
25 type: String,
26 value: '#c7c7c7'
27 },
28 disabledColor: {
29 type: String,
30 value: '#bdbdbd'
31 },
32 count: {
33 type: Number,
34 value: 5
35 },
36 value: {
37 type: Number,
38 value: 0
39 }
40 },
41 data: {
42 innerValue: 0
43 },
44 watch: {
45 value(value) {
46 if (value !== this.data.innerValue) {
47 this.set({ innerValue: value });
48 }
49 }
50 },
51 computed: {
52 list() {
53 const { count, innerValue } = this.data;
54 return Array.from({ length: count }, (_, index) => index < innerValue);
55 }
56 },
57 methods: {
58 onSelect(event) {
59 const { data } = this;
60 const { index } = event.currentTarget.dataset;
61 if (!data.disabled && !data.readonly) {
62 this.set({ innerValue: index + 1 });
63 this.$emit('input', index + 1);
64 this.$emit('change', index + 1);
65 }
66 },
67 onTouchMove(event) {
68 const { clientX, clientY } = event.touches[0];
69 this.getRect('.van-rate__item', true).then(list => {
70 const target = list.find(item => clientX >= item.left &&
71 clientX <= item.right &&
72 clientY >= item.top &&
73 clientY <= item.bottom);
74 if (target != null) {
75 this.onSelect(Object.assign({}, event, { currentTarget: target }));
76 }
77 });
78 }
79 }
80 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 <view
2 class="van-rate custom-class"
3 bind:touchmove="onTouchMove"
4 >
5 <van-icon
6 wx:for="{{ list }}"
7 wx:key="index"
8 class="van-rate__item"
9 custom-class="icon-class"
10 size="{{ size }}px"
11 data-index="{{ index }}"
12 name="{{ item ? icon : voidIcon }}"
13 color="{{ disabled ? disabledColor : item ? color : voidColor }}"
14 bind:click="onSelect"
15 />
16 </view>
1 @import '../common/index.wxss';.van-rate{-webkit-user-select:none;user-select:none}.van-rate__item{width:1em;padding:0 2px;box-sizing:initial}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 relation: {
4 name: 'col',
5 type: 'descendant',
6 linked(target) {
7 if (this.data.gutter) {
8 target.setGutter(this.data.gutter);
9 }
10 }
11 },
12 props: {
13 gutter: Number
14 },
15 watch: {
16 gutter: 'setGutter'
17 },
18 mounted() {
19 if (this.data.gutter) {
20 this.setGutter();
21 }
22 },
23 methods: {
24 setGutter() {
25 const { gutter } = this.data;
26 const margin = `-${Number(gutter) / 2}px`;
27 const style = gutter
28 ? `margin-right: ${margin}; margin-left: ${margin};`
29 : '';
30 this.set({ style });
31 this.getRelationNodes('../col/index').forEach(col => {
32 col.setGutter(this.data.gutter);
33 });
34 }
35 }
36 });
1 {
2 "component": true
3 }
1 <view class="custom-class van-row" style="{{ style }}">
2 <slot />
3 </view>
1 @import '../common/index.wxss';.van-row:after{content:"";display:table;clear:both}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 classes: ['field-class', 'input-class', 'cancel-class'],
5 props: {
6 focus: Boolean,
7 error: Boolean,
8 disabled: Boolean,
9 readonly: Boolean,
10 inputAlign: String,
11 showAction: Boolean,
12 useActionSlot: Boolean,
13 placeholder: String,
14 placeholderStyle: String,
15 background: {
16 type: String,
17 value: '#ffffff'
18 },
19 maxlength: {
20 type: Number,
21 value: -1
22 },
23 shape: {
24 type: String,
25 value: 'square'
26 },
27 label: String
28 },
29 methods: {
30 onChange(event) {
31 this.set({ value: event.detail });
32 this.$emit('change', event.detail);
33 },
34 onCancel() {
35 this.set({ value: '' });
36 this.$emit('cancel');
37 this.$emit('change', '');
38 },
39 onSearch() {
40 this.$emit('search', this.data.value);
41 },
42 onFocus() {
43 this.$emit('focus');
44 },
45 onBlur() {
46 this.$emit('blur');
47 },
48 onClear() {
49 this.$emit('clear');
50 },
51 }
52 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-field": "../field/index"
6 }
7 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="{{ utils.bem('search', { withaction: showAction || useActionSlot }) }} custom-class"
5 style="background: {{ background }}"
6 >
7 <view class="{{ utils.bem('search__content', [shape]) }}">
8 <view class="van-search__label" wx:if="{{ label }}">{{ label }}</view>
9 <slot wx:else name="label" />
10
11 <van-field
12 clearable
13 type="search"
14 left-icon="search"
15 focus="{{ focus }}"
16 error="{{ error }}"
17 border="{{ false }}"
18 confirm-type="search"
19 class="van-search__field field-class"
20 value="{{ value }}"
21 disabled="{{ disabled }}"
22 readonly="{{ readonly }}"
23 maxlength="{{ maxlength }}"
24 input-align="{{ inputAlign }}"
25 input-class="input-class"
26 placeholder="{{ placeholder }}"
27 placeholder-style="{{ placeholderStyle }}"
28 custom-style="padding: 5px 10px 5px 0; background-color: transparent;"
29 bind:blur="onBlur"
30 bind:focus="onFocus"
31 bind:change="onChange"
32 bind:confirm="onSearch"
33 bind:clear="onClear"
34 />
35 </view>
36
37 <view
38 wx:if="{{ showAction || useActionSlot }}"
39 class="van-search__action"
40 hover-class="van-search__action--hover"
41 hover-stay-time="70"
42 >
43 <slot wx:if="{{ useActionSlot }}" name="action" />
44 <view wx:else bind:tap="onCancel" class="cancel-class">取消</view>
45 </view>
46 </view>
1 @import '../common/index.wxss';.van-search{padding:10px 16px;-webkit-align-items:center;align-items:center;box-sizing:border-box}.van-search,.van-search__content{display:-webkit-flex;display:flex}.van-search__content{padding-left:10px;background-color:#f7f8fa;border-radius:2px;-webkit-flex:1;flex:1}.van-search__content--round{border-radius:17px}.van-search__label{padding:0 5px;font-size:14px;line-height:34px;color:#333}.van-search__field{-webkit-flex:1;flex:1}.van-search__field__left-icon{color:#999}.van-search--withaction{padding-right:0}.van-search input::-webkit-search-cancel-button,.van-search input::-webkit-search-decoration,.van-search input::-webkit-search-results-button,.van-search input::-webkit-search-results-decoration{display:none}.van-search__action{padding:0 10px;font-size:14px;line-height:34px;color:#333}.van-search__action--hover{background-color:#f2f3f5}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { touch } from '../mixins/touch';
3 VantComponent({
4 mixins: [touch],
5 props: {
6 disabled: Boolean,
7 useButtonSlot: Boolean,
8 activeColor: String,
9 inactiveColor: String,
10 max: {
11 type: Number,
12 value: 100
13 },
14 min: {
15 type: Number,
16 value: 0
17 },
18 step: {
19 type: Number,
20 value: 1
21 },
22 value: {
23 type: Number,
24 value: 0
25 },
26 barHeight: {
27 type: String,
28 value: '2px'
29 }
30 },
31 watch: {
32 value(value) {
33 this.updateValue(value, false);
34 }
35 },
36 created() {
37 this.updateValue(this.data.value);
38 },
39 methods: {
40 onTouchStart(event) {
41 if (this.data.disabled)
42 return;
43 this.touchStart(event);
44 this.startValue = this.format(this.data.value);
45 },
46 onTouchMove(event) {
47 if (this.data.disabled)
48 return;
49 this.touchMove(event);
50 this.getRect('.van-slider').then((rect) => {
51 const diff = this.deltaX / rect.width * 100;
52 this.updateValue(this.startValue + diff, false, true);
53 });
54 },
55 onTouchEnd() {
56 if (this.data.disabled)
57 return;
58 this.updateValue(this.data.value, true);
59 },
60 onClick(event) {
61 if (this.data.disabled)
62 return;
63 this.getRect('.van-slider').then((rect) => {
64 const value = (event.detail.x - rect.left) / rect.width * 100;
65 this.updateValue(value, true);
66 });
67 },
68 updateValue(value, end, drag) {
69 value = this.format(value);
70 this.set({
71 value,
72 barStyle: `width: ${value}%; height: ${this.data.barHeight};`
73 });
74 if (drag) {
75 this.$emit('drag', { value });
76 }
77 if (end) {
78 this.$emit('change', value);
79 }
80 },
81 format(value) {
82 const { max, min, step } = this.data;
83 return Math.round(Math.max(min, Math.min(value, max)) / step) * step;
84 }
85 }
86 });
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ utils.bem('slider', { disabled }) }}"
5 style="{{ inactiveColor ? 'background:' + inactiveColor : '' }}"
6 bind:tap="onClick"
7 >
8 <view
9 class="van-slider__bar"
10 style="{{ barStyle }}; {{ activeColor ? 'background:' + activeColor : '' }}"
11 >
12 <view
13 class="van-slider__button-wrapper"
14 bind:touchstart="onTouchStart"
15 catch:touchmove="onTouchMove"
16 bind:touchend="onTouchEnd"
17 bind:touchcancel="onTouchEnd"
18 >
19 <slot
20 wx:if="{{ useButtonSlot }}"
21 name="button"
22 />
23 <view
24 wx:else
25 class="van-slider__button"
26 />
27 </view>
28 </view>
29 </view>
1 @import '../common/index.wxss';.van-slider{position:relative;border-radius:999px;background-color:#e5e5e5}.van-slider__bar{position:relative;border-radius:inherit;background-color:#1989fa}.van-slider__button{width:20px;height:20px;border-radius:50%;background-color:#fff;box-shadow:0 1px 2px rgba(0,0,0,.5)}.van-slider__button-wrapper{position:absolute;top:50%;right:0;-webkit-transform:translate3d(50%,-50%,0);transform:translate3d(50%,-50%,0)}.van-slider__button-wrapper:after{content:"";position:absolute;width:200%;height:200%;top:-50%;left:-50%}.van-slider--disabled{opacity:.3}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 classes: [
5 'input-class',
6 'plus-class',
7 'minus-class'
8 ],
9 props: {
10 value: null,
11 integer: Boolean,
12 disabled: Boolean,
13 inputWidth: String,
14 asyncChange: Boolean,
15 disableInput: Boolean,
16 min: {
17 type: null,
18 value: 1
19 },
20 max: {
21 type: null,
22 value: Number.MAX_SAFE_INTEGER
23 },
24 step: {
25 type: null,
26 value: 1
27 }
28 },
29 computed: {
30 minusDisabled() {
31 return this.data.disabled || this.data.value <= this.data.min;
32 },
33 plusDisabled() {
34 return this.data.disabled || this.data.value >= this.data.max;
35 }
36 },
37 watch: {
38 value(value) {
39 if (value === '') {
40 return;
41 }
42 const newValue = this.range(value);
43 if (typeof newValue === 'number' && value !== newValue) {
44 this.set({ value: newValue });
45 }
46 }
47 },
48 data: {
49 focus: false
50 },
51 created() {
52 this.set({
53 value: this.range(this.data.value)
54 });
55 },
56 methods: {
57 onFocus(event) {
58 this.$emit('focus', event.detail);
59 },
60 onBlur(event) {
61 const value = this.range(this.data.value);
62 this.triggerInput(value);
63 this.$emit('blur', event.detail);
64 },
65 // limit value range
66 range(value) {
67 return Math.max(Math.min(this.data.max, value), this.data.min);
68 },
69 onInput(event) {
70 const { value = '' } = event.detail || {};
71 this.triggerInput(value);
72 },
73 onChange(type) {
74 if (this.data[`${type}Disabled`]) {
75 this.$emit('overlimit', type);
76 return;
77 }
78 const diff = type === 'minus' ? -this.data.step : +this.data.step;
79 const value = Math.round((this.data.value + diff) * 100) / 100;
80 this.triggerInput(this.range(value));
81 this.$emit(type);
82 },
83 onMinus() {
84 this.onChange('minus');
85 },
86 onPlus() {
87 this.onChange('plus');
88 },
89 triggerInput(value) {
90 this.set({
91 value: this.data.asyncChange ? this.data.value : value
92 });
93 this.$emit('change', value);
94 }
95 }
96 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="van-stepper custom-class">
4 <view
5 class="minus-class {{ utils.bem('stepper__minus', { disabled: minusDisabled }) }}"
6 hover-class="van-stepper__minus--hover"
7 hover-stay-time="70"
8 bind:tap="onMinus"
9 />
10 <input
11 type="{{ integer ? 'number' : 'digit' }}"
12 class="input-class {{ utils.bem('stepper__input', { disabled: disabled || disableInput }) }}"
13 style="{{ inputWidth ? 'width: ' + inputWidth : '' }}"
14 value="{{ value }}"
15 focus="{{ focus }}"
16 disabled="{{ disabled || disableInput }}"
17 bindinput="onInput"
18 bind:focus="onFocus"
19 bind:blur="onBlur"
20 />
21 <view
22 class="plus-class {{ utils.bem('stepper__plus', { disabled: plusDisabled }) }}"
23 hover-class="van-stepper__plus--hover"
24 hover-stay-time="70"
25 bind:tap="onPlus"
26 />
27 </view>
1 @import '../common/index.wxss';.van-stepper{font-size:0}.van-stepper__minus,.van-stepper__plus{position:relative;display:inline-block;width:28px;height:28px;padding:5px;margin:1px;vertical-align:middle;background-color:#f2f3f5;border:0;box-sizing:border-box}.van-stepper__minus:before,.van-stepper__plus:before{width:9px;height:1px}.van-stepper__minus:after,.van-stepper__plus:after{width:1px;height:9px}.van-stepper__minus:after,.van-stepper__minus:before,.van-stepper__plus:after,.van-stepper__plus:before{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;background-color:#333;content:""}.van-stepper__minus--hover,.van-stepper__plus--hover{background-color:#e8e8e8}.van-stepper__minus--disabled,.van-stepper__plus--disabled{background-color:#f7f8fa}.van-stepper__minus--disabled:after,.van-stepper__minus--disabled:before,.van-stepper__plus--disabled:after,.van-stepper__plus--disabled:before{background-color:#c9c9c9}.van-stepper__minus--disabled.van-stepper__minus--hover,.van-stepper__minus--disabled.van-stepper__plus--hover,.van-stepper__plus--disabled.van-stepper__minus--hover,.van-stepper__plus--disabled.van-stepper__plus--hover{background-color:#f7f8fa}.van-stepper__minus{border-radius:4px 0 0 4px}.van-stepper__minus:after{display:none}.van-stepper__plus{border-radius:0 4px 4px 0}.van-stepper__input{display:inline-block;width:30px;height:26px;padding:1px;margin:1px;font-size:14px;color:#333;text-align:center;vertical-align:middle;background-color:#f2f3f5;border:0;border-width:1px 0;border-radius:0;box-sizing:initial;-webkit-appearance:none}.van-stepper__input--disabled{color:#c9c9c9;background-color:#f2f3f5}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { GREEN } from '../common/color';
3 VantComponent({
4 props: {
5 icon: String,
6 steps: Array,
7 active: Number,
8 direction: {
9 type: String,
10 value: 'horizontal'
11 },
12 activeColor: {
13 type: String,
14 value: GREEN
15 }
16 }
17 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="custom-class {{ utils.bem('steps', [direction]) }}">
4 <view class="van-step__wrapper">
5 <view
6 wx:for="{{ steps }}"
7 wx:key="index"
8 class="{{ utils.bem('step', [direction, status(index, active)]) }} van-hairline"
9 >
10 <view class="van-step__title" style="{{ index === active ? 'color: ' + activeColor : '' }}">
11 <view>{{ item.text }}</view>
12 <view>{{ item.desc }}</view>
13 </view>
14 <view class="van-step__circle-container">
15 <view class="van-step__circle" wx:if="{{ index !== active }}" style="{{ index < active ? 'background-color: ' + activeColor : '' }}" />
16 <van-icon wx:else name="checked" color="{{ activeColor }}" custom-class="van-step__active" />
17 </view>
18 <view wx:if="{{ index !== steps.length - 1 }}" class="van-step__line" style="{{ index < active ? 'background-color: ' + activeColor : '' }}" />
19 </view>
20 </view>
21 </view>
22
23 <wxs module="status">
24 function get(index, active) {
25 if (index < active) {
26 return 'finish';
27 } else if (index === active) {
28 return 'process';
29 }
30
31 return '';
32 }
33
34 module.exports = get;
35 </wxs>
1 @import '../common/index.wxss';.van-steps{overflow:hidden;background-color:#fff}.van-steps--horizontal{padding:10px}.van-steps--horizontal .van-step__wrapper{position:relative;display:-webkit-flex;display:flex;overflow:hidden}.van-steps--vertical{padding-left:10px}.van-steps--vertical .van-step__wrapper{padding:0 0 0 20px}.van-step{position:relative;-webkit-flex:1;flex:1;font-size:14px;color:#999}.van-step--finish{color:#333}.van-step__circle{width:5px;height:5px;background-color:#999;border-radius:50%}.van-step--horizontal{padding-bottom:14px}.van-step--horizontal:first-child .van-step__title{-webkit-transform:none;transform:none}.van-step--horizontal:first-child .van-step__circle-container{padding:0 8px 0 0;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal:last-child{position:absolute;right:0;width:auto}.van-step--horizontal:last-child .van-step__title{text-align:right;-webkit-transform:none;transform:none}.van-step--horizontal:last-child .van-step__circle-container{right:0;padding:0 0 0 8px;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal .van-step__circle-container{position:absolute;bottom:6px;z-index:1;padding:0 8px;background-color:#fff;-webkit-transform:translate3d(-50%,50%,0);transform:translate3d(-50%,50%,0)}.van-step--horizontal .van-step__title{display:inline-block;font-size:12px;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-step--horizontal .van-step__line{position:absolute;right:0;bottom:6px;left:0;height:1px;background-color:#eee;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal.van-step--process{color:#333}.van-step--horizontal.van-step--process .van-step__active{display:block;font-size:12px;line-height:1}.van-step--vertical{padding:10px 10px 10px 0;font-size:14px;line-height:18px}.van-step--vertical:after{border-bottom-width:1px}.van-step--vertical:last-child:after{border-bottom-width:none}.van-step--vertical:first-child:before{position:absolute;top:0;left:-15px;z-index:1;width:1px;height:20px;background-color:#fff;content:""}.van-step--vertical .van-step__active,.van-step--vertical .van-step__circle,.van-step--vertical .van-step__line{position:absolute;top:19px;left:-14px;z-index:2;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-step--vertical .van-step__active{font-size:12px;line-height:1}.van-step--vertical .van-step__line{z-index:1;width:1px;height:100%;background-color:#eee;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({
4 mixins: [safeArea()],
5 classes: [
6 'bar-class',
7 'price-class',
8 'button-class'
9 ],
10 props: {
11 tip: null,
12 type: Number,
13 price: null,
14 label: String,
15 loading: Boolean,
16 disabled: Boolean,
17 buttonText: String,
18 currency: {
19 type: String,
20 value: '¥'
21 },
22 buttonType: {
23 type: String,
24 value: 'danger'
25 }
26 },
27 computed: {
28 hasPrice() {
29 return typeof this.data.price === 'number';
30 },
31 priceStr() {
32 return (this.data.price / 100).toFixed(2);
33 },
34 tipStr() {
35 const { tip } = this.data;
36 return typeof tip === 'string' ? tip : '';
37 }
38 },
39 methods: {
40 onSubmit(event) {
41 this.$emit('submit', event.detail);
42 }
43 }
44 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-button": "../button/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="van-submit-bar custom-class">
4 <slot name="top" />
5
6 <view wx:if="{{ tip }}" class="van-submit-bar__tip">
7 {{ tipStr }}<slot name="tip" />
8 </view>
9
10 <view class="bar-class {{ utils.bem('submit-bar__bar', { safe: safeAreaInsetBottom && isIPhoneX }) }}">
11 <slot />
12 <view class="van-submit-bar__text">
13 <block wx:if="{{ hasPrice }}">
14 <text>{{ label || '合计:' }}</text>
15 <text class="van-submit-bar__price price-class">
16 <text class="van-submit-bar__currency">{{ currency }}</text> {{ priceStr }}
17 </text>
18 </block>
19 </view>
20 <van-button
21 square
22 size="large"
23 type="{{ buttonType }}"
24 loading="{{ loading }}"
25 disabled="{{ disabled }}"
26 class="van-submit-bar__button"
27 custom-class="button-class"
28 bind:click="onSubmit"
29 >
30 {{ loading ? '' : buttonText }}
31 </van-button>
32 </view>
33 </view>
1 @import '../common/index.wxss';.van-submit-bar{z-index:100;position:fixed;bottom:0;left:0;width:100%;-webkit-user-select:none;user-select:none}.van-submit-bar__tip{padding:10px;color:#f56723;font-size:12px;line-height:18px;background-color:#fff7cc}.van-submit-bar__bar{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:50px;background-color:#fff;font-size:14px}.van-submit-bar__bar--safe{padding-bottom:34px}.van-submit-bar__text{-webkit-flex:1;flex:1;color:#333;font-weight:500;text-align:right}.van-submit-bar__price{color:#f44;font-size:18px;padding-right:12px}.van-submit-bar__currency{font-size:14px}.van-submit-bar__button button{width:110px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { touch } from '../mixins/touch';
3 const THRESHOLD = 0.3;
4 VantComponent({
5 props: {
6 disabled: Boolean,
7 leftWidth: {
8 type: Number,
9 value: 0
10 },
11 rightWidth: {
12 type: Number,
13 value: 0
14 },
15 asyncClose: Boolean
16 },
17 mixins: [touch],
18 data: {
19 catchMove: true
20 },
21 created() {
22 this.offset = 0;
23 },
24 methods: {
25 open(position) {
26 const { leftWidth, rightWidth } = this.data;
27 const offset = position === 'left' ? leftWidth : -rightWidth;
28 this.swipeMove(offset);
29 },
30 close() {
31 this.swipeMove(0);
32 },
33 swipeMove(offset = 0) {
34 this.offset = offset;
35 const transform = `translate3d(${offset}px, 0, 0)`;
36 const transition = this.draging
37 ? 'none'
38 : '.6s cubic-bezier(0.18, 0.89, 0.32, 1)';
39 this.set({
40 wrapperStyle: `
41 -webkit-transform: ${transform};
42 -webkit-transition: ${transition};
43 transform: ${transform};
44 transition: ${transition};
45 `
46 });
47 },
48 swipeLeaveTransition() {
49 const { leftWidth, rightWidth } = this.data;
50 const { offset } = this;
51 if (rightWidth > 0 && -offset > rightWidth * THRESHOLD) {
52 this.open('right');
53 }
54 else if (leftWidth > 0 && offset > leftWidth * THRESHOLD) {
55 this.open('left');
56 }
57 else {
58 this.swipeMove(0);
59 }
60 },
61 startDrag(event) {
62 if (this.data.disabled) {
63 return;
64 }
65 this.draging = true;
66 this.startOffset = this.offset;
67 this.firstDirection = '';
68 this.touchStart(event);
69 },
70 noop() { },
71 onDrag(event) {
72 if (this.data.disabled) {
73 return;
74 }
75 this.touchMove(event);
76 if (!this.firstDirection) {
77 this.firstDirection = this.direction;
78 this.set({ catchMove: this.firstDirection === 'horizontal' });
79 }
80 if (this.firstDirection === 'vertical') {
81 return;
82 }
83 const { leftWidth, rightWidth } = this.data;
84 const offset = this.startOffset + this.deltaX;
85 if ((rightWidth > 0 && -offset > rightWidth) ||
86 (leftWidth > 0 && offset > leftWidth)) {
87 return;
88 }
89 this.swipeMove(offset);
90 },
91 endDrag() {
92 if (this.data.disabled) {
93 return;
94 }
95 this.draging = false;
96 this.swipeLeaveTransition();
97 },
98 onClick(event) {
99 const { key: position = 'outside' } = event.currentTarget.dataset;
100 this.$emit('click', position);
101 if (!this.offset) {
102 return;
103 }
104 if (this.data.asyncClose) {
105 this.$emit('close', { position, instance: this });
106 }
107 else {
108 this.swipeMove(0);
109 }
110 }
111 }
112 });
1 <view
2 class="van-swipe-cell"
3 data-key="cell"
4 catchtap="onClick"
5 bindtouchstart="startDrag"
6 catchtouchmove="{{ catchMove ? 'noop' : '' }}"
7 capture-bind:touchmove="onDrag"
8 catchtouchend="endDrag"
9 catchtouchcancel="endDrag"
10 >
11 <view style="{{ wrapperStyle }}">
12 <view wx:if="{{ leftWidth }}" class="van-swipe-cell__left" data-key="left" catch:tap="onClick">
13 <slot name="left" />
14 </view>
15 <slot />
16 <view wx:if="{{ rightWidth }}" class="van-swipe-cell__right" data-key="right" catch:tap="onClick">
17 <slot name="right" />
18 </view>
19 </view>
20 </view>
1 @import '../common/index.wxss';.van-swipe-cell{position:relative;overflow:hidden}.van-swipe-cell__left,.van-swipe-cell__right{position:absolute;top:0;height:100%}.van-swipe-cell__left{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-swipe-cell__right{right:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 props: {
5 value: null,
6 title: String,
7 border: Boolean,
8 checked: Boolean,
9 loading: Boolean,
10 disabled: Boolean,
11 activeColor: String,
12 inactiveColor: String,
13 size: {
14 type: String,
15 value: '24px'
16 },
17 activeValue: {
18 type: null,
19 value: true
20 },
21 inactiveValue: {
22 type: null,
23 value: false
24 }
25 },
26 watch: {
27 checked(value) {
28 this.set({ value });
29 }
30 },
31 created() {
32 this.set({ value: this.data.checked });
33 },
34 methods: {
35 onChange(event) {
36 this.$emit('change', event.detail);
37 }
38 }
39 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-cell": "../cell/index",
5 "van-switch": "../switch/index"
6 }
7 }
1 <van-cell
2 center
3 title="{{ title }}"
4 border="{{ border }}"
5 custom-class="van-switch-cell"
6 >
7 <van-switch
8 size="{{ size }}"
9 checked="{{ checked }}"
10 loading="{{ loading }}"
11 disabled="{{ disabled }}"
12 active-color="{{ activeColor }}"
13 inactive-color="{{ inactiveColor }}"
14 active-value="{{ activeValue }}"
15 inactive-value="{{ inactiveValue }}"
16 custom-class="van-switch-cell__switch"
17 bind:change="onChange"
18 />
19 </van-cell>
1 @import '../common/index.wxss';.van-switch-cell{padding-top:9px;padding-bottom:9px}.van-switch-cell__switch{vertical-align:middle}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 classes: ['node-class'],
5 props: {
6 checked: null,
7 loading: Boolean,
8 disabled: Boolean,
9 activeColor: String,
10 inactiveColor: String,
11 size: {
12 type: String,
13 value: '30px'
14 },
15 activeValue: {
16 type: null,
17 value: true
18 },
19 inactiveValue: {
20 type: null,
21 value: false
22 }
23 },
24 watch: {
25 checked(value) {
26 this.set({ value });
27 }
28 },
29 created() {
30 this.set({ value: this.data.checked });
31 },
32 methods: {
33 onClick() {
34 const { activeValue, inactiveValue } = this.data;
35 if (!this.data.disabled && !this.data.loading) {
36 const checked = this.data.checked === activeValue;
37 const value = checked ? inactiveValue : activeValue;
38 this.$emit('input', value);
39 this.$emit('change', value);
40 }
41 }
42 }
43 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-loading": "../loading/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ utils.bem('switch', { on: value === activeValue, disabled }) }}"
5 style="font-size: {{ size }}; {{ (checked ? activeColor : inactiveColor) ? 'background-color: ' + (checked ? activeColor : inactiveColor ) : '' }}"
6 bind:tap="onClick"
7 >
8 <view class="van-switch__node node-class">
9 <van-loading wx:if="{{ loading }}" size="50%" custom-class="van-switch__loading" />
10 </view>
11 </view>
1 @import '../common/index.wxss';.van-switch{display:inline-block;position:relative;width:2em;border:1px solid rgba(0,0,0,.1);border-radius:1em;box-sizing:initial;transition:background-color .3s}.van-switch,.van-switch__node{height:1em;background-color:#fff}.van-switch__node{top:0;left:0;position:absolute;border-radius:100%;width:1em;z-index:1;transition:.3s;box-shadow:0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05)}.van-switch__loading{top:25%;left:25%;position:absolute!important}.van-switch--on{background-color:#1989fa}.van-switch--on .van-switch__node{-webkit-transform:translateX(1em);transform:translateX(1em)}.van-switch--disabled{opacity:.4}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 relation: {
4 name: 'tabs',
5 type: 'ancestor'
6 },
7 props: {
8 dot: Boolean,
9 info: null,
10 title: String,
11 disabled: Boolean,
12 titleStyle: String
13 },
14 data: {
15 width: null,
16 inited: false,
17 active: false,
18 animated: false
19 },
20 watch: {
21 title: 'update',
22 disabled: 'update',
23 dot: 'update',
24 info: 'update',
25 titleStyle: 'update'
26 },
27 methods: {
28 update() {
29 const parent = this.getRelationNodes('../tabs/index')[0];
30 if (parent) {
31 parent.updateTabs();
32 }
33 }
34 }
35 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 wx:if="{{ animated || inited }}"
5 class="custom-class {{ utils.bem('tab__pane', { active, inactive: !active }) }}"
6 style="{{ animated || active ? '' : 'display: none;' }} {{ width ? 'width:' + width + 'px;' : '' }}"
7 >
8 <slot />
9 </view>
1 @import '../common/index.wxss';.van-tab__pane{box-sizing:border-box;overflow-y:auto}.van-tab__pane--active{height:auto}.van-tab__pane--inactive{height:0;overflow:visible}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 info: null,
5 icon: String,
6 dot: Boolean
7 },
8 relation: {
9 name: 'tabbar',
10 type: 'ancestor',
11 linked(target) {
12 this.parent = target;
13 }
14 },
15 data: {
16 active: false
17 },
18 methods: {
19 onClick() {
20 if (this.parent) {
21 this.parent.onChange(this);
22 }
23 this.$emit('click');
24 },
25 setActive({ active, color }) {
26 if (this.data.active !== active) {
27 return this.set({ active, color });
28 }
29 return Promise.resolve();
30 }
31 }
32 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-info": "../info/index"
6 }
7 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="{{ utils.bem('tabbar-item', { active }) }} custom-class"
5 style="{{ active && color ? 'color: ' + color : '' }}"
6 bind:tap="onClick"
7 >
8 <view class="{{ utils.bem('tabbar-item__icon', { dot }) }}">
9 <van-icon
10 wx:if="{{ icon }}"
11 name="{{ icon }}"
12 customStyle="display: block"
13 />
14 <block wx:else>
15 <slot
16 wx:if="{{ active }}"
17 name="icon-active"
18 />
19 <slot wx:else name="icon" />
20 </block>
21 <van-info
22 wx:if="{{ info !== null }}"
23 info="{{ info }}"
24 custom-style="margin-top: 2px"
25 />
26 </view>
27 <view class="van-tabbar-item__text">
28 <slot />
29 </view>
30 </view>
1 @import '../common/index.wxss';:host{-webkit-flex:1;flex:1}.van-tabbar-item{color:#7d7e80;height:100%;display:-webkit-flex;display:flex;line-height:1;font-size:12px;-webkit-align-items:center;align-items:center;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center}.van-tabbar-item__icon{font-size:18px;margin-bottom:5px;position:relative}.van-tabbar-item__icon--dot:after{top:0;right:-8px;width:8px;height:8px;content:" ";position:absolute;border-radius:100%;background-color:#f44}.van-tabbar-item__icon image{width:30px;height:18px;display:block}.van-tabbar-item--active{color:#1989fa}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({
4 mixins: [safeArea()],
5 relation: {
6 name: 'tabbar-item',
7 type: 'descendant',
8 linked(target) {
9 this.children = this.children || [];
10 this.children.push(target);
11 this.setActiveItem();
12 },
13 unlinked(target) {
14 this.children = this.children || [];
15 this.children = this.children.filter(item => item !== target);
16 this.setActiveItem();
17 }
18 },
19 props: {
20 active: Number,
21 activeColor: String,
22 fixed: {
23 type: Boolean,
24 value: true
25 },
26 zIndex: {
27 type: Number,
28 value: 1
29 }
30 },
31 watch: {
32 active(active) {
33 this.currentActive = active;
34 this.setActiveItem();
35 }
36 },
37 created() {
38 this.currentActive = this.data.active;
39 },
40 methods: {
41 setActiveItem() {
42 if (!Array.isArray(this.children) || !this.children.length) {
43 return Promise.resolve();
44 }
45 return Promise.all(this.children.map((item, index) => item.setActive({
46 active: index === this.currentActive,
47 color: this.data.activeColor
48 })));
49 },
50 onChange(child) {
51 const active = (this.children || []).indexOf(child);
52 if (active !== this.currentActive && active !== -1) {
53 this.currentActive = active;
54 this.setActiveItem().then(() => {
55 this.$emit('change', active);
56 });
57 }
58 }
59 }
60 });
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class van-hairline--top-bottom {{ utils.bem('tabbar', { fixed, safe: isIPhoneX && safeAreaInsetBottom }) }}"
5 style="{{ zIndex ? 'z-index: ' + zIndex : '' }}"
6 >
7 <slot />
8 </view>
1 @import '../common/index.wxss';.van-tabbar{display:-webkit-flex;display:flex;width:100%;height:50px;background-color:#fff}.van-tabbar--fixed{position:fixed;bottom:0;left:0}.van-tabbar--safe{padding-bottom:34px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { touch } from '../mixins/touch';
3 VantComponent({
4 mixins: [touch],
5 classes: ['nav-class', 'tab-class', 'tab-active-class', 'line-class'],
6 relation: {
7 name: 'tab',
8 type: 'descendant',
9 linked(child) {
10 this.child.push(child);
11 this.updateTabs(this.data.tabs.concat(child.data));
12 },
13 unlinked(child) {
14 const index = this.child.indexOf(child);
15 const { tabs } = this.data;
16 tabs.splice(index, 1);
17 this.child.splice(index, 1);
18 this.updateTabs(tabs);
19 }
20 },
21 props: {
22 color: String,
23 sticky: Boolean,
24 animated: Boolean,
25 swipeable: Boolean,
26 lineWidth: {
27 type: Number,
28 value: -1
29 },
30 lineHeight: {
31 type: Number,
32 value: -1
33 },
34 active: {
35 type: Number,
36 value: 0
37 },
38 type: {
39 type: String,
40 value: 'line'
41 },
42 border: {
43 type: Boolean,
44 value: true
45 },
46 duration: {
47 type: Number,
48 value: 0.3
49 },
50 zIndex: {
51 type: Number,
52 value: 1
53 },
54 swipeThreshold: {
55 type: Number,
56 value: 4
57 },
58 offsetTop: {
59 type: Number,
60 value: 0
61 }
62 },
63 data: {
64 tabs: [],
65 lineStyle: '',
66 scrollLeft: 0,
67 scrollable: false,
68 trackStyle: '',
69 wrapStyle: '',
70 position: ''
71 },
72 watch: {
73 swipeThreshold() {
74 this.set({
75 scrollable: this.child.length > this.data.swipeThreshold
76 });
77 },
78 color: 'setLine',
79 lineWidth: 'setLine',
80 lineHeight: 'setLine',
81 active: 'setActiveTab',
82 animated: 'setTrack',
83 offsetTop: 'setWrapStyle'
84 },
85 beforeCreate() {
86 this.child = [];
87 },
88 mounted() {
89 this.setLine(true);
90 this.setTrack();
91 this.scrollIntoView();
92 this.getRect('.van-tabs__wrap').then((rect) => {
93 this.navHeight = rect.height;
94 this.observerContentScroll();
95 });
96 },
97 destroyed() {
98 this.createIntersectionObserver().disconnect();
99 },
100 methods: {
101 updateTabs(tabs) {
102 tabs = tabs || this.data.tabs;
103 this.set({
104 tabs,
105 scrollable: tabs.length > this.data.swipeThreshold
106 });
107 this.setActiveTab();
108 },
109 trigger(eventName, index) {
110 this.$emit(eventName, {
111 index,
112 title: this.data.tabs[index].title
113 });
114 },
115 onTap(event) {
116 const { index } = event.currentTarget.dataset;
117 if (this.data.tabs[index].disabled) {
118 this.trigger('disabled', index);
119 }
120 else {
121 this.trigger('click', index);
122 this.setActive(index);
123 }
124 },
125 setActive(active) {
126 if (active !== this.data.active) {
127 this.trigger('change', active);
128 this.set({ active });
129 this.setActiveTab();
130 }
131 },
132 setLine(skipTransition) {
133 if (this.data.type !== 'line') {
134 return;
135 }
136 const { color, active, duration, lineWidth, lineHeight } = this.data;
137 this.getRect('.van-tab', true).then((rects) => {
138 const rect = rects[active];
139 const width = lineWidth !== -1 ? lineWidth : rect.width / 2;
140 const height = lineHeight !== -1 ? `height: ${lineHeight}px;` : '';
141 let left = rects
142 .slice(0, active)
143 .reduce((prev, curr) => prev + curr.width, 0);
144 left += (rect.width - width) / 2;
145 const transition = skipTransition
146 ? ''
147 : `transition-duration: ${duration}s; -webkit-transition-duration: ${duration}s;`;
148 this.set({
149 lineStyle: `
150 ${height}
151 width: ${width}px;
152 background-color: ${color};
153 -webkit-transform: translateX(${left}px);
154 transform: translateX(${left}px);
155 ${transition}
156 `
157 });
158 });
159 },
160 setTrack() {
161 const { animated, active, duration } = this.data;
162 if (!animated)
163 return '';
164 this.getRect('.van-tabs__content').then((rect) => {
165 const { width } = rect;
166 this.set({
167 trackStyle: `
168 width: ${width * this.child.length}px;
169 left: ${-1 * active * width}px;
170 transition: left ${duration}s;
171 display: -webkit-box;
172 display: flex;
173 `
174 });
175 const props = { width, animated };
176 this.child.forEach((item) => {
177 item.set(props);
178 });
179 });
180 },
181 setActiveTab() {
182 this.child.forEach((item, index) => {
183 const data = {
184 active: index === this.data.active
185 };
186 if (data.active) {
187 data.inited = true;
188 }
189 if (data.active !== item.data.active) {
190 item.set(data);
191 }
192 });
193 this.set({}, () => {
194 this.setLine();
195 this.setTrack();
196 this.scrollIntoView();
197 });
198 },
199 // scroll active tab into view
200 scrollIntoView() {
201 const { active, scrollable } = this.data;
202 if (!scrollable) {
203 return;
204 }
205 Promise.all([
206 this.getRect('.van-tab', true),
207 this.getRect('.van-tabs__nav')
208 ]).then(([tabRects, navRect]) => {
209 const tabRect = tabRects[active];
210 const offsetLeft = tabRects
211 .slice(0, active)
212 .reduce((prev, curr) => prev + curr.width, 0);
213 this.set({
214 scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2
215 });
216 });
217 },
218 onTouchStart(event) {
219 if (!this.data.swipeable)
220 return;
221 this.touchStart(event);
222 },
223 onTouchMove(event) {
224 if (!this.data.swipeable)
225 return;
226 this.touchMove(event);
227 },
228 // watch swipe touch end
229 onTouchEnd() {
230 if (!this.data.swipeable)
231 return;
232 const { active, tabs } = this.data;
233 const { direction, deltaX, offsetX } = this;
234 const minSwipeDistance = 50;
235 if (direction === 'horizontal' && offsetX >= minSwipeDistance) {
236 if (deltaX > 0 && active !== 0) {
237 this.setActive(active - 1);
238 }
239 else if (deltaX < 0 && active !== tabs.length - 1) {
240 this.setActive(active + 1);
241 }
242 }
243 },
244 setWrapStyle() {
245 const { offsetTop, position } = this.data;
246 let wrapStyle;
247 switch (position) {
248 case 'top':
249 wrapStyle = `
250 top: ${offsetTop}px;
251 position: fixed;
252 `;
253 break;
254 case 'bottom':
255 wrapStyle = `
256 top: auto;
257 bottom: 0;
258 `;
259 break;
260 default:
261 wrapStyle = '';
262 }
263 // cut down `set`
264 if (wrapStyle === this.data.wrapStyle)
265 return;
266 this.set({ wrapStyle });
267 },
268 observerContentScroll() {
269 if (!this.data.sticky) {
270 return;
271 }
272 const { offsetTop } = this.data;
273 const { windowHeight } = wx.getSystemInfoSync();
274 this.createIntersectionObserver().disconnect();
275 this.createIntersectionObserver()
276 .relativeToViewport({ top: -(this.navHeight + offsetTop) })
277 .observe('.van-tabs', (res) => {
278 const { top } = res.boundingClientRect;
279 if (top > offsetTop) {
280 return;
281 }
282 const position = res.intersectionRatio > 0 ? 'top' : 'bottom';
283 this.$emit('scroll', {
284 scrollTop: top + offsetTop,
285 isFixed: position === 'top'
286 });
287 this.setPosition(position);
288 });
289 this.createIntersectionObserver()
290 .relativeToViewport({ bottom: -(windowHeight - 1 - offsetTop) })
291 .observe('.van-tabs', (res) => {
292 const { top, bottom } = res.boundingClientRect;
293 if (bottom < this.navHeight) {
294 return;
295 }
296 const position = res.intersectionRatio > 0 ? 'top' : '';
297 this.$emit('scroll', {
298 scrollTop: top + offsetTop,
299 isFixed: position === 'top'
300 });
301 this.setPosition(position);
302 });
303 },
304 setPosition(position) {
305 if (position !== this.data.position) {
306 this.set({ position }).then(() => {
307 this.setWrapStyle();
308 });
309 }
310 }
311 }
312 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-info": "../info/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="custom-class {{ utils.bem('tabs', [type]) }}">
4 <view style="z-index: {{ zIndex }}; {{ wrapStyle }}" class="{{ utils.bem('tabs__wrap', { scrollable }) }} {{ type === 'line' && border ? 'van-hairline--top-bottom' : '' }}">
5 <slot name="nav-left" />
6
7 <scroll-view
8 scroll-x="{{ scrollable }}"
9 scroll-with-animation
10 scroll-left="{{ scrollLeft }}"
11 class="van-tabs__scroll--{{ type }}"
12 style="{{ color ? 'border-color: ' + color : '' }}"
13 >
14 <view class="{{ utils.bem('tabs__nav', [type]) }} nav-class">
15 <view wx:if="{{ type === 'line' }}" class="van-tabs__line" style="{{ lineStyle }}" />
16 <view
17 wx:for="{{ tabs }}"
18 wx:key="index"
19 data-index="{{ index }}"
20 class="van-ellipsis tab-class {{ index === active ? 'tab-active-class' : '' }} {{ utils.bem('tab', { active: index === active, disabled: item.disabled }) }}"
21 style="{{ color && index !== active && type === 'card' && !item.disabled ? 'color: ' + color : '' }} {{ color && index === active && type === 'card' ? ';background-color:' + color : '' }} {{ color ? ';border-color: ' + color : '' }} {{ scrollable ? ';flex-basis:' + (88 / swipeThreshold) + '%' : '' }}"
22 bind:tap="onTap"
23 >
24 <view class="van-ellipsis {{ utils.bem('tab__title', { dot: item.dot }) }}" style="{{ item.titleStyle }}">
25 {{ item.title }}
26 <van-info
27 wx:if="{{ item.info !== null }}"
28 info="{{ item.info }}"
29 custom-class="van-tab__title__info"
30 />
31 </view>
32 </view>
33 </view>
34 </scroll-view>
35
36 <slot name="nav-right" />
37 </view>
38 <view
39 class="van-tabs__content"
40 bind:touchstart="onTouchStart"
41 bind:touchmove="onTouchMove"
42 bind:touchend="onTouchEnd"
43 bind:touchcancel="onTouchEnd"
44 >
45 <view class="van-tabs__track" style="{{ trackStyle }}">
46 <slot />
47 </view>
48 </view>
49 </view>
1 @import '../common/index.wxss';.van-tabs{position:relative;-webkit-tap-highlight-color:transparent}.van-tabs__wrap{position:absolute;top:0;right:0;left:0;display:-webkit-flex;display:flex;background-color:#fff}.van-tabs__wrap--page-top{position:fixed}.van-tabs__wrap--content-bottom{top:auto;bottom:0}.van-tabs__wrap--scrollable .van-tab{-webkit-flex:0 0 22%;flex:0 0 22%}.van-tabs__scroll--card{border:1px solid #f44;border-radius:2px}.van-tabs__nav{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none}.van-tabs__nav--line{height:100%}.van-tabs__nav--card{height:30px}.van-tabs__nav--card .van-tab{line-height:30px;color:#f44;border-right:1px solid #f44}.van-tabs__nav--card .van-tab:last-child{border-right:none}.van-tabs__nav--card .van-tab.van-tab--active{color:#fff;background-color:#f44}.van-tabs__line{position:absolute;bottom:0;left:0;z-index:1;height:3px;background-color:#f44;border-radius:3px}.van-tabs--line{padding-top:44px}.van-tabs--line .van-tabs__wrap{height:44px}.van-tabs--card{padding-top:30px;margin:0 15px}.van-tabs--card .van-tabs__wrap{height:30px}.van-tabs__content{overflow:hidden}.van-tab,.van-tabs__track{position:relative}.van-tab{min-width:0;padding:0 5px;font-size:14px;line-height:44px;color:#7d7e80;text-align:center;cursor:pointer;box-sizing:border-box;-webkit-flex:1;flex:1}.van-tab--active{font-weight:500;color:#333}.van-tab--disabled{color:#c9c9c9}.van-tab__title--dot:after{display:inline-block;width:8px;height:8px;vertical-align:middle;background-color:#f44;border-radius:100%;content:""}.van-tab__title__info{position:relative!important;top:-1px!important;display:inline-block;-webkit-transform:translateX(0)!important;transform:translateX(0)!important}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { RED, BLUE, GREEN } from '../common/color';
3 const DEFAULT_COLOR = '#999';
4 const COLOR_MAP = {
5 danger: RED,
6 primary: BLUE,
7 success: GREEN
8 };
9 VantComponent({
10 props: {
11 size: String,
12 type: String,
13 mark: Boolean,
14 color: String,
15 plain: Boolean,
16 round: Boolean,
17 textColor: String
18 },
19 computed: {
20 style() {
21 const color = this.data.color || COLOR_MAP[this.data.type] || DEFAULT_COLOR;
22 const key = this.data.plain ? 'color' : 'background-color';
23 const style = { [key]: color };
24 if (this.data.textColor) {
25 style.color = this.data.textColor;
26 }
27 return Object.keys(style).map(key => `${key}: ${style[key]}`).join(';');
28 }
29 }
30 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ utils.bem('tag', [size, { mark, plain, round }]) }} {{ plain ? 'van-hairline--surround' : '' }}"
5 style="{{ style }}"
6 >
7 <slot />
8 </view>
1 @import '../common/index.wxss';.van-tag{color:#fff;font-size:10px;padding:.2em .5em;line-height:normal;border-radius:.2em;display:inline-block}.van-tag:after{border-color:currentColor;border-radius:.4em}.van-tag--mark{padding-right:.6em;border-radius:0 .8em .8em 0}.van-tag--mark:after{border-radius:0 1.6em 1.6em 0}.van-tag--round{border-radius:.8em}.van-tag--round:after{border-radius:1.6em}.van-tag--medium{font-size:12px}.van-tag--large{font-size:14px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 show: Boolean,
5 mask: Boolean,
6 message: String,
7 forbidClick: Boolean,
8 zIndex: {
9 type: Number,
10 value: 1000
11 },
12 type: {
13 type: String,
14 value: 'text'
15 },
16 loadingType: {
17 type: String,
18 value: 'circular'
19 },
20 position: {
21 type: String,
22 value: 'middle'
23 }
24 },
25 methods: {
26 clear() {
27 this.set({
28 show: false
29 });
30 },
31 // for prevent touchmove
32 noop() { }
33 }
34 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-loading": "../loading/index",
6 "van-overlay": "../overlay/index",
7 "van-transition": "../transition/index"
8 }
9 }
1 <van-overlay
2 wx:if="{{ mask || forbidClick }}"
3 show="{{ show }}"
4 mask="{{ mask }}"
5 z-index="{{ zIndex }}"
6 />
7 <van-transition
8 show="{{ show }}"
9 custom-style="z-index: {{ zIndex }}"
10 custom-class="van-toast__container"
11 >
12 <view
13 class="van-toast van-toast--{{ type === 'text' ? 'text' : 'icon' }} van-toast--{{ position }}"
14 catch:touchmove="noop"
15 >
16 <!-- text only -->
17 <text wx:if="{{ type === 'text' }}">{{ message }}</text>
18
19 <!-- with icon -->
20 <block wx:else>
21 <van-loading
22 wx:if="{{ type === 'loading' }}"
23 color="white"
24 type="{{ loadingType }}"
25 custom-class="van-toast__loading"
26 />
27 <van-icon wx:else class="van-toast__icon" name="{{ type }}" />
28 <text wx:if="{{ message }}" class="van-toast__text">{{ message }}</text>
29 </block>
30 </view>
31 </van-transition>
1 @import '../common/index.wxss';.van-toast{display:-webkit-flex;display:flex;color:#fff;font-size:14px;line-height:20px;border-radius:4px;word-break:break-all;-webkit-align-items:center;align-items:center;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center;box-sizing:initial;background-color:rgba(51,51,51,.88);white-space:pre-wrap}.van-toast__container{position:fixed;top:50%;left:50%;max-width:70%;width:-webkit-fit-content;width:fit-content;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.van-toast--text{padding:8px 12px;min-width:96px}.van-toast--icon{width:90px;padding:15px;min-height:90px}.van-toast--icon .van-toast__icon{font-size:48px}.van-toast--icon .van-toast__text{padding-top:5px}.van-toast__loading{margin:10px 0}.van-toast--top{-webkit-transform:translateY(-30vh);transform:translateY(-30vh)}.van-toast--bottom{-webkit-transform:translateY(30vh);transform:translateY(30vh)}
...\ No newline at end of file ...\ No newline at end of file
1 declare type ToastMessage = string | number;
2 export declare type ToastOptions = {
3 show?: boolean;
4 type?: string;
5 mask?: boolean;
6 zIndex?: number;
7 context?: any;
8 position?: string;
9 duration?: number;
10 selector?: string;
11 forbidClick?: boolean;
12 loadingType?: string;
13 message?: ToastMessage;
14 };
15 export interface Toast {
16 (message: ToastOptions | ToastMessage, options?: ToastOptions): Weapp.Component;
17 loading?(options?: ToastOptions | ToastMessage): Weapp.Component;
18 success?(options?: ToastOptions | ToastMessage): Weapp.Component;
19 fail?(options?: ToastOptions | ToastMessage): Weapp.Component;
20 clear?(): void;
21 setDefaultOptions?(options: ToastOptions): void;
22 resetDefaultOptions?(): void;
23 }
24 declare const Toast: Toast;
25 export default Toast;
1 import { isObj } from '../common/utils';
2 const defaultOptions = {
3 type: 'text',
4 mask: false,
5 message: '',
6 show: true,
7 zIndex: 1000,
8 duration: 3000,
9 position: 'middle',
10 forbidClick: false,
11 loadingType: 'circular',
12 selector: '#van-toast'
13 };
14 let queue = [];
15 let currentOptions = Object.assign({}, defaultOptions);
16 function parseOptions(message) {
17 return isObj(message) ? message : { message };
18 }
19 function getContext() {
20 const pages = getCurrentPages();
21 return pages[pages.length - 1];
22 }
23 const Toast = (options = {}) => {
24 options = Object.assign({}, currentOptions, parseOptions(options));
25 const context = options.context || getContext();
26 const toast = context.selectComponent(options.selector);
27 if (!toast) {
28 console.warn('未找到 van-toast 节点,请确认 selector 及 context 是否正确');
29 return;
30 }
31 delete options.context;
32 delete options.selector;
33 queue.push(toast);
34 toast.set(options);
35 clearTimeout(toast.timer);
36 if (options.duration > 0) {
37 toast.timer = setTimeout(() => {
38 toast.clear();
39 queue = queue.filter(item => item !== toast);
40 }, options.duration);
41 }
42 return toast;
43 };
44 const createMethod = type => options => Toast(Object.assign({ type }, parseOptions(options)));
45 ['loading', 'success', 'fail'].forEach(method => {
46 Toast[method] = createMethod(method);
47 });
48 Toast.clear = () => {
49 queue.forEach(toast => {
50 toast.clear();
51 });
52 queue = [];
53 };
54 Toast.setDefaultOptions = options => {
55 Object.assign(currentOptions, options);
56 };
57 Toast.resetDefaultOptions = () => {
58 currentOptions = Object.assign({}, defaultOptions);
59 };
60 export default Toast;
1 import { VantComponent } from '../common/component';
2 import { transition } from '../mixins/transition';
3 VantComponent({
4 classes: [
5 'enter-class',
6 'enter-active-class',
7 'enter-to-class',
8 'leave-class',
9 'leave-active-class',
10 'leave-to-class'
11 ],
12 mixins: [transition(true)]
13 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <view
2 wx:if="{{ inited }}"
3 class="van-transition custom-class {{ classes }}"
4 style="-webkit-transition-duration:{{ currentDuration }}ms; transition-duration:{{ currentDuration }}ms; {{ display ? '' : 'display: none;' }} {{ customStyle }}"
5 bind:transitionend="onTransitionEnd"
6 >
7 <slot />
8 </view>
1 @import '../common/index.wxss';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-fade-up-enter,.van-fade-up-leave-to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-fade-down-enter,.van-fade-down-leave-to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-fade-left-enter,.van-fade-left-leave-to{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-fade-right-enter,.van-fade-right-leave-to{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.van-slide-down-enter-active,.van-slide-down-leave-active,.van-slide-left-enter-active,.van-slide-left-leave-active,.van-slide-right-enter-active,.van-slide-right-leave-active,.van-slide-up-enter-active,.van-slide-up-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-slide-up-enter,.van-slide-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 const ITEM_HEIGHT = 44;
3 VantComponent({
4 classes: [
5 'main-item-class',
6 'content-item-class',
7 'main-active-class',
8 'content-active-class',
9 'main-disabled-class',
10 'content-disabled-class'
11 ],
12 props: {
13 items: Array,
14 mainActiveIndex: {
15 type: Number,
16 value: 0
17 },
18 activeId: {
19 type: [Number, String]
20 },
21 maxHeight: {
22 type: Number,
23 value: 300
24 }
25 },
26 data: {
27 subItems: [],
28 mainHeight: 0,
29 itemHeight: 0
30 },
31 watch: {
32 items() {
33 this.updateSubItems().then(() => {
34 this.updateMainHeight();
35 });
36 },
37 maxHeight() {
38 this.updateItemHeight(this.data.subItems);
39 this.updateMainHeight();
40 },
41 mainActiveIndex: 'updateSubItems'
42 },
43 methods: {
44 // 当一个子项被选择时
45 onSelectItem(event) {
46 const { item } = event.currentTarget.dataset;
47 if (!item.disabled) {
48 this.$emit('click-item', item);
49 }
50 },
51 // 当一个导航被点击时
52 onClickNav(event) {
53 const { index } = event.currentTarget.dataset;
54 const item = this.data.items[index];
55 if (!item.disabled) {
56 this.$emit('click-nav', { index });
57 }
58 },
59 // 更新子项列表
60 updateSubItems() {
61 const { items, mainActiveIndex } = this.data;
62 const { children = [] } = items[mainActiveIndex] || {};
63 this.updateItemHeight(children);
64 return this.set({ subItems: children });
65 },
66 // 更新组件整体高度,根据最大高度和当前组件需要展示的高度来决定
67 updateMainHeight() {
68 const { items = [], subItems = [] } = this.data;
69 const maxHeight = Math.max(items.length * ITEM_HEIGHT, subItems.length * ITEM_HEIGHT);
70 this.set({ mainHeight: Math.min(maxHeight, this.data.maxHeight) });
71 },
72 // 更新子项列表高度,根据可展示的最大高度和当前子项列表的高度决定
73 updateItemHeight(subItems) {
74 const itemHeight = Math.min(subItems.length * ITEM_HEIGHT, this.data.maxHeight);
75 return this.set({ itemHeight });
76 }
77 }
78 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-cell": "../cell/index"
6 }
7 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="van-tree-select"
5 style="height: {{ mainHeight }}px"
6 >
7 <scroll-view scroll-y class="van-tree-select__nav">
8 <view
9 wx:for="{{ items }}"
10 wx:key="index"
11 class="van-ellipsis main-item-class {{ utils.bem('tree-select__nitem', { active: mainActiveIndex === index, disabled: item.disabled }) }} {{ mainActiveIndex === index ? 'main-active-class' : '' }} {{ item.disabled ? 'main-disabled-class' : '' }}"
12 data-index="{{ index }}"
13 bind:tap="onClickNav"
14 >
15 {{ item.text }}
16 </view>
17 </scroll-view>
18 <scroll-view
19 scroll-y
20 class="van-tree-select__content"
21 style="height: {{ itemHeight }}px"
22 >
23 <view
24 wx:for="{{ subItems }}"
25 wx:key="id"
26 class="van-ellipsis van-hairline--bottom content-item-class {{ utils.bem('tree-select__item', { active: activeId === item.id, disabled: item.disabled }) }} {{ activeId === item.id ? 'content-active-class' : '' }} {{ item.disabled ? 'content-disabled-class' : '' }}"
27 data-item="{{ item }}"
28 bind:tap="onSelectItem"
29 >
30 {{ item.text }}
31 <van-icon
32 wx:if="{{ activeId === item.id }}"
33 name="checked"
34 size="16px"
35 class="van-tree-select__selected"
36 />
37 </view>
38 </scroll-view>
39 </view>
1 @import '../common/index.wxss';.van-tree-select{position:relative;font-size:14px;-webkit-user-select:none;user-select:none}.van-tree-select__nav{position:absolute;top:0;bottom:0;left:0;width:35%;min-width:120px;background-color:#fafafa}.van-tree-select__nitem{position:relative;padding:0 9px 0 15px;line-height:44px}.van-tree-select__nitem--active:after{position:absolute;top:0;bottom:0;left:0;width:3.6px;background-color:#f44;content:""}.van-tree-select__nitem--active{font-weight:700;background-color:#fff}.van-tree-select__nitem--disabled{color:#999}.van-tree-select__content{width:65%;padding-left:15px;margin-left:35%;background-color:#fff;box-sizing:border-box}.van-tree-select__item{position:relative;font-weight:700;line-height:44px}.van-tree-select__item--active{color:#f44}.van-tree-select__item--disabled{color:#999}.van-tree-select__selected{position:absolute;top:0;right:15px;bottom:0;height:24px;margin:auto 0;line-height:24px}
...\ No newline at end of file ...\ No newline at end of file
1 function isArray(array) {
2 return array && array.constructor === 'Array';
3 }
4
5 module.exports.isArray = isArray;
1 var array = require('./array.wxs');
2 var object = require('./object.wxs');
3 var PREFIX = 'van-';
4
5 function join(name, mods) {
6 name = PREFIX + name;
7 mods = mods.map(function(mod) {
8 return name + '--' + mod;
9 });
10 mods.unshift(name);
11 return mods.join(' ');
12 }
13
14 function traversing(mods, conf) {
15 if (!conf) {
16 return;
17 }
18
19 if (typeof conf === 'string' || typeof conf === 'number') {
20 mods.push(conf);
21 } else if (array.isArray(conf)) {
22 conf.forEach(function(item) {
23 traversing(mods, item);
24 });
25 } else if (typeof conf === 'object') {
26 object.keys(conf).forEach(function(key) {
27 conf[key] && mods.push(key);
28 });
29 }
30 }
31
32 function bem(name, conf) {
33 var mods = [];
34 traversing(mods, conf);
35 return join(name, mods);
36 }
37
38 module.exports.bem = bem;
1 /**
2 * Simple memoize
3 * wxs doesn't support fn.apply, so this memoize only support up to 2 args
4 */
5
6 function isPrimitive(value) {
7 var type = typeof value;
8 return (
9 type === 'boolean' ||
10 type === 'number' ||
11 type === 'string' ||
12 type === 'undefined' ||
13 value === null
14 );
15 }
16
17 // mock simple fn.call in wxs
18 function call(fn, args) {
19 if (args.length === 2) {
20 return fn(args[0], args[1]);
21 }
22
23 if (args.length === 1) {
24 return fn(args[0]);
25 }
26
27 return fn();
28 }
29
30 function serializer(args) {
31 if (args.length === 1 && isPrimitive(args[0])) {
32 return args[0];
33 }
34 var obj = {};
35 for (var i = 0; i < args.length; i++) {
36 obj['key' + i] = args[i];
37 }
38 return JSON.stringify(obj);
39 }
40
41 function memoize(fn) {
42 var cache = {};
43
44 return function() {
45 var key = serializer(arguments);
46 if (cache[key] === undefined) {
47 cache[key] = call(fn, arguments);
48 }
49
50 return cache[key];
51 };
52 }
53
54 module.exports.memoize = memoize;
1 /* eslint-disable */
2 var REGEXP = getRegExp('{|}|"', 'g');
3
4 function keys(obj) {
5 return JSON.stringify(obj)
6 .replace(REGEXP, '')
7 .split(',')
8 .map(function(item) {
9 return item.split(':')[0];
10 });
11 }
12
13 module.exports.keys = keys;
1 var bem = require('./bem.wxs').bem;
2 var memoize = require('./memoize.wxs').memoize;
3
4 function isSrc(url) {
5 return url.indexOf('http') === 0 || url.indexOf('data:image') === 0 || url.indexOf('//') === 0;
6 }
7
8 module.exports = {
9 bem: memoize(bem),
10 isSrc: isSrc,
11 memoize: memoize
12 };