5e7fefff by simon

默认提交

1 parent bdaddaca
Showing 227 changed files with 1918 additions and 15 deletions
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
11 </view> 11 </view>
12 <view class="bid"> 12 <view class="bid">
13 我要报价 13 我要报价
14 <input value="{{bidPrice}}" class="val" bindinput="bindBidPriceInput" class="ipt" placeholder="{{maxPrice + productInfo.minScope}}" /> 14 <input value="{{bidPrice}}" class="val" bindinput="bindBidPriceInput" class="ipt" placeholder="{{filter.Fen2Yuan(maxPrice + productInfo.minScope)}}" />
15 15
16 </view> 16 </view>
17 </view> 17 </view>
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
14 top: 16px; 14 top: 16px;
15 font-size: 40px; 15 font-size: 40px;
16 color: #333333; 16 color: #333333;
17 z-index: 11;
17 } 18 }
18 19
19 .succ { 20 .succ {
......
...@@ -28,6 +28,7 @@ Page({ ...@@ -28,6 +28,7 @@ Page({
28 wxTimerList: {}, 28 wxTimerList: {},
29 lastTime: "", 29 lastTime: "",
30 bidPrice: 0, // 我的出价 单位元 30 bidPrice: 0, // 我的出价 单位元
31 isTimeEnd: false, //倒计时结束
31 }, 32 },
32 onShareAppMessage() {}, 33 onShareAppMessage() {},
33 showAuth() { 34 showAuth() {
...@@ -53,12 +54,20 @@ Page({ ...@@ -53,12 +54,20 @@ Page({
53 54
54 initData() { 55 initData() {
55 this.queryMember().then((result) => { 56 this.queryMember().then((result) => {
57 this.refreshView();
58 this.openSocket();
59 });
60 },
61
62 /**
63 * 刷新页面
64 */
65 refreshView() {
56 this.queryAuctionDetail().then((result) => { 66 this.queryAuctionDetail().then((result) => {
67 this.removeTimer();
57 this.startTimer(); 68 this.startTimer();
58 }) 69 })
59 this.queryAuctionRecordLast(); 70 this.queryAuctionRecordLast();
60 this.openSocket();
61 });
62 }, 71 },
63 72
64 // 开始倒计时 73 // 开始倒计时
...@@ -73,6 +82,9 @@ Page({ ...@@ -73,6 +82,9 @@ Page({
73 wxTimer = new timer({ 82 wxTimer = new timer({
74 beginTime: beginTime, 83 beginTime: beginTime,
75 complete() { 84 complete() {
85 _this.setData({
86 isTimeEnd: true
87 })
76 _this.removeTimer(); 88 _this.removeTimer();
77 _this.queryAuctionDetail(); 89 _this.queryAuctionDetail();
78 }, 90 },
...@@ -288,6 +300,7 @@ Page({ ...@@ -288,6 +300,7 @@ Page({
288 socketStatus: 'connected', 300 socketStatus: 'connected',
289 waitingResponse: false 301 waitingResponse: false
290 }) 302 })
303 this.refreshView();
291 }) 304 })
292 305
293 wx.onSocketClose(() => { 306 wx.onSocketClose(() => {
...@@ -307,10 +320,11 @@ Page({ ...@@ -307,10 +320,11 @@ Page({
307 320
308 // 监听服务器推送消息 321 // 监听服务器推送消息
309 wx.onSocketMessage(message => { 322 wx.onSocketMessage(message => {
310 console.log('socket message:', message) 323 console.log('socket message:', message);
311 this.setData({ 324 this.setData({
312 loading: false 325 loading: false
313 }) 326 });
327 this.refreshView();
314 }) 328 })
315 329
316 // 打开信道 330 // 打开信道
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
23 <text class="price">¥{{filter.Fen2Yuan(maxPrice)}}</text> 23 <text class="price">¥{{filter.Fen2Yuan(maxPrice)}}</text>
24 <text class="t1">当前价格</text> 24 <text class="t1">当前价格</text>
25 </view> 25 </view>
26 <view class="func-ele func-right {{productInfo.status != 1 ? 'disable' : ''}}"> 26 <view class="func-ele func-right {{productInfo.status != 1 || isTimeEnd ? 'disable' : ''}}">
27 <text wx:if="{{productInfo.status == 0}}" class="t1 t2">拍卖未开始</text> 27 <text wx:if="{{productInfo.status == 0}}" class="t1 t2">拍卖未开始</text>
28 <text wx:if="{{productInfo.status == 1}}" class="t1">拍卖进行中</text> 28 <text wx:if="{{productInfo.status == 1}}" class="t1">拍卖进行中</text>
29 <text wx:if="{{productInfo.status == 2}}" class="t1 t2">拍卖已结束</text> 29 <text wx:if="{{productInfo.status == 2}}" class="t1 t2">拍卖已结束</text>
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
78 </view> 78 </view>
79 </view> 79 </view>
80 <!-- 按钮 --> 80 <!-- 按钮 -->
81 <view bindtap="onSubmitHandler" class="submit-btn {{productInfo.status != 1 ? 'disable' : ''}}"> 81 <view bindtap="onSubmitHandler" class="submit-btn {{productInfo.status != 1 || isTimeEnd ? 'disable' : ''}}">
82 我要出价 82 我要出价
83 </view> 83 </view>
84 </view> 84 </view>
......
...@@ -20,12 +20,10 @@ Page({ ...@@ -20,12 +20,10 @@ Page({
20 }) 20 })
21 }, 21 },
22 onShow() { 22 onShow() {
23
24 },
25 onLoad(options) {
26 this.resetPage(); 23 this.resetPage();
27 this.initData(); 24 this.initData();
28 }, 25 },
26 onLoad(options) {},
29 initData() { 27 initData() {
30 this.queryAuctionList(); 28 this.queryAuctionList();
31 }, 29 },
...@@ -79,6 +77,12 @@ Page({ ...@@ -79,6 +77,12 @@ Page({
79 success(res) {} 77 success(res) {}
80 }) 78 })
81 } 79 }
80 } else {
81 wx.showModal({
82 content: "活动已结束",
83 showCancel: false,
84 success(res) {}
85 })
82 } 86 }
83 }, 87 },
84 88
......
...@@ -20,6 +20,7 @@ Page({ ...@@ -20,6 +20,7 @@ Page({
20 lastTime: "", 20 lastTime: "",
21 isSellOut: false, 21 isSellOut: false,
22 orderStatus: 0, // 0.未下单 1.下单成功 22 orderStatus: 0, // 0.未下单 1.下单成功
23 isTimeEnd: false, //倒计时结束
23 }, 24 },
24 onShareAppMessage() {}, 25 onShareAppMessage() {},
25 showAuth() { 26 showAuth() {
...@@ -62,6 +63,9 @@ Page({ ...@@ -62,6 +63,9 @@ Page({
62 wxTimer = new timer({ 63 wxTimer = new timer({
63 beginTime: beginTime, 64 beginTime: beginTime,
64 complete() { 65 complete() {
66 _this.setData({
67 isTimeEnd: true
68 })
65 _this.removeTimer(); 69 _this.removeTimer();
66 _this.querySeckillDetail(); 70 _this.querySeckillDetail();
67 }, 71 },
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
24 <text class="t1 line-th">¥{{filter.Fen2Yuan(productInfo.specialPrice)}}</text> 24 <text class="t1 line-th">¥{{filter.Fen2Yuan(productInfo.specialPrice)}}</text>
25 <text class="t1">仅剩{{productInfo.stock}}个</text> 25 <text class="t1">仅剩{{productInfo.stock}}个</text>
26 </view> 26 </view>
27 <view class="func-ele func-right {{productInfo.status != 1 ? 'disable' : ''}}"> 27 <view class="func-ele func-right {{productInfo.status != 1 || isTimeEnd ? 'disable' : ''}}">
28 <text wx:if="{{productInfo.status == 0}}" class="t1 t2">秒杀未开始</text> 28 <text wx:if="{{productInfo.status == 0}}" class="t1 t2">秒杀未开始</text>
29 <text wx:if="{{productInfo.status == 1}}" class="t1">秒杀进行中</text> 29 <text wx:if="{{productInfo.status == 1}}" class="t1">秒杀进行中</text>
30 <text wx:if="{{productInfo.status == 2}}" class="t1 t2">秒杀已结束</text> 30 <text wx:if="{{productInfo.status == 2}}" class="t1 t2">秒杀已结束</text>
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
42 </view> 42 </view>
43 </view> 43 </view>
44 <!-- 按钮 --> 44 <!-- 按钮 -->
45 <view bindtap="onSubmitHandler" class="submit-btn {{productInfo.status != 1 ? 'disable' : ''}}"> 45 <view bindtap="onSubmitHandler" class="submit-btn {{productInfo.status != 1 || isTimeEnd ? 'disable' : ''}}">
46 立即秒杀 46 立即秒杀
47 </view> 47 </view>
48 </view> 48 </view>
......
...@@ -20,12 +20,12 @@ Page({ ...@@ -20,12 +20,12 @@ Page({
20 }) 20 })
21 }, 21 },
22 onShow() { 22 onShow() {
23
24 },
25 onLoad(options) {
26 this.resetPage(); 23 this.resetPage();
27 this.initData(); 24 this.initData();
28 }, 25 },
26 onLoad(options) {
27
28 },
29 initData() { 29 initData() {
30 this.querySeckillList(); 30 this.querySeckillList();
31 }, 31 },
......
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 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 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 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