mali-applet-ui 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,8 +4,8 @@
4
4
  </view>
5
5
  <view v-else class="ml-amount-input" :class="[{'is-right': align === 'right', 'is-border': border}, className]">
6
6
  <view v-if="showTip" class="ml-amount-tip">
7
- <text>首位:</text>
8
- <text>{{ firstNumLabel }}</text>
7
+ <view>首位:</view>
8
+ <view class="ml-amount-tip-label">{{ firstNumLabel }}</view>
9
9
  </view>
10
10
  <input
11
11
  v-model="inpVal"
@@ -30,7 +30,7 @@ export default {
30
30
  virtualHost: true
31
31
  },
32
32
  props: {
33
- value: String,
33
+ value: [String, Number],
34
34
  align: String,
35
35
  border: Boolean,
36
36
  min: {
@@ -39,7 +39,7 @@ export default {
39
39
  },
40
40
  max: {
41
41
  type: [Number, String],
42
- default: 9999999999999
42
+ default: 9999999999
43
43
  },
44
44
  maxLength: {
45
45
  type: Number,
@@ -124,7 +124,10 @@ export default {
124
124
  },
125
125
  watch: {
126
126
  value (val) {
127
- this.inpVal = val
127
+ if (!this.updateModel) {
128
+ this.inpVal = val
129
+ }
130
+ this.updateModel = false
128
131
  },
129
132
  min () {
130
133
  this.checkValue()
@@ -134,14 +137,14 @@ export default {
134
137
  }
135
138
  },
136
139
  created () {
137
- this.updateValue()
140
+ this.updateValue(this.inpVal)
138
141
  },
139
142
  methods: {
140
- updateValue () {
141
- this.inpVal = this.value ? XEUtils.toFixed(XEUtils.toNumber(this.value), 2) : ''
143
+ updateValue (value) {
144
+ this.inpVal = value === '' || XEUtils.eqNull(value) ? '' : XEUtils.toFixed(XEUtils.toNumber(value), 2)
142
145
  },
143
146
  checkValue () {
144
- const numVal = XEUtils.toNumber(this.value)
147
+ const numVal = XEUtils.toNumber(this.inpVal)
145
148
  if (this.minNum !== null && (numVal < this.minNum)) {
146
149
  this.$emit('input', this.minNum)
147
150
  return { status: false, value: this.minNum }
@@ -155,12 +158,15 @@ export default {
155
158
  this.$emit('input', val)
156
159
  return { status: false, value: val }
157
160
  }
158
- return { status: true, value: 0 }
161
+ return { status: true, value: numVal }
159
162
  },
160
163
  blurEvent () {
161
- this.checkValue()
162
- this.updateValue()
163
- this.$emit('blur')
164
+ const rest = this.checkValue()
165
+ this.updateModel = rest.status
166
+ this.$nextTick(() => {
167
+ this.updateValue(rest.value)
168
+ })
169
+ this.$emit('blur', { value: this.inpVal })
164
170
  },
165
171
  inputEvent () {
166
172
  const value = this.inpVal
@@ -186,10 +192,16 @@ export default {
186
192
  }
187
193
  }
188
194
  .ml-amount-tip {
195
+ display: flex;
196
+ flex-direction: row;
189
197
  position: absolute;
190
198
  top: -60rpx;
191
199
  right: 10rpx;
192
200
  z-index: 1;
201
+ .ml-amount-tip-label {
202
+ min-width: 60rpx;
203
+ text-align: right;
204
+ }
193
205
  }
194
206
  .ml-amount-input-inp {
195
207
  font-size: $uni-font-size-base;
@@ -10,6 +10,7 @@
10
10
  <view class="ml-form-item-content-warpper">
11
11
  <slot>
12
12
  <ml-input v-if="matchComponent('MlInput')" :value="itemValue" border @change="modelEvent"></ml-input>
13
+ <ml-number-input v-if="matchComponent('MlNumberInput')" :value="itemValue" border @change="modelEvent"></ml-number-input>
13
14
  <ml-date-picker v-else-if="matchComponent('MlDatePicker')" :value="itemValue" border @change="modelEvent"></ml-date-picker>
14
15
  <ml-select-picker v-else-if="matchComponent('MlSelectPicker')" :value="itemValue" :options="renderOpts.options" border @change="modelEvent"></ml-select-picker>
15
16
  <ml-textarea v-else-if="matchComponent('MlTextarea')" :value="itemValue" :rows="renderOpts.rows || 3" :showVoice="renderOpts.showVoice || true" border @change="modelEvent"></ml-textarea>
@@ -28,7 +28,7 @@ export default {
28
28
  .ml-full-watermark-text{
29
29
  float: left;
30
30
  padding: 0 50rpx;
31
- color: rgba(169,169,169,0.15);
31
+ color: rgba(169,169,169,0.2);
32
32
  text-align: center;
33
33
  font-size: 22rpx;
34
34
  margin: 80rpx 0;
@@ -2,7 +2,7 @@
2
2
  <view v-if="isFromReadonly" class="ml-input is-readonly">
3
3
  <view class="ml-input-readonly-content">{{ inpVal }}</view>
4
4
  </view>
5
- <view v-else class="ml-input" :class="[className || '', {'is-right': align === 'right', 'is-border': border, 'is-prefix': prefixIcon || type === 'search', 'is-suffix': suffixIcon, 'is-disabled': disabled}]">
5
+ <view v-else class="ml-input" :class="[className || '', {'is-right': align === 'right', 'is-border': border, 'is-prefix': prefixIcon || type === 'search', 'is-suffix': suffixIcon, 'is-disabled': disabled, 'is-clear': clearable && inpVal}]">
6
6
  <view v-if="prefixIcon || type === 'search'" class="ml-input-prefix-icon">
7
7
  <ml-icon v-if="prefixIcon" :className="prefixIcon"></ml-icon>
8
8
  <ml-icon v-else name="search"></ml-icon>
@@ -12,10 +12,15 @@
12
12
  type="text"
13
13
  class="ml-input-inp"
14
14
  autocomplete="off"
15
+ :confirm-type="type === 'search' ? 'search' : 'done'"
15
16
  :placeholder="placeholder"
16
17
  :maxlength="maxlength"
17
- @input="inputEvent"
18
+ @input="inputEvent"
19
+ @blur="blurEvent"
18
20
  @confirm="confirmEvent"/>
21
+ <view v-if="clearable && inpVal" class="ml-input-clear-icon" @click.stop="clearEvent">
22
+ <ml-icon name="delete-filling"></ml-icon>
23
+ </view>
19
24
  <view v-if="suffixIcon" class="ml-input-suffix-icon">
20
25
  <ml-icon :className="suffixIcon"></ml-icon>
21
26
  </view>
@@ -36,13 +41,14 @@ export default {
36
41
  disabled: Boolean,
37
42
  prefixIcon: String,
38
43
  suffixIcon: String,
44
+ clearable: Boolean,
39
45
  placeholder: {
40
46
  type: String,
41
47
  default: '请输入'
42
48
  },
43
49
  maxlength: {
44
- type: String,
45
- default: '50'
50
+ type: [String, Number],
51
+ default: 30
46
52
  },
47
53
  className: String
48
54
  },
@@ -76,9 +82,17 @@ export default {
76
82
  this.$emit('input', value)
77
83
  this.$emit('change', { value })
78
84
  },
85
+ blurEvent () {
86
+ this.$emit('blur', { value: this.inpVal })
87
+ },
79
88
  confirmEvent () {
80
89
  const value = this.inpVal
81
90
  this.$emit('confirm', { value })
91
+ },
92
+ clearEvent () {
93
+ this.inpVal = ''
94
+ this.inputEvent()
95
+ this.$emit('clear', { value: this.inpVal })
82
96
  }
83
97
  }
84
98
  }
@@ -98,6 +112,16 @@ export default {
98
112
  width: 100%;
99
113
  font-size: $uni-font-size-base;
100
114
  }
115
+ .ml-input-clear-icon {
116
+ width: 60rpx;
117
+ display: flex;
118
+ flex-shrink: 0;
119
+ align-items: center;
120
+ justify-content: center;
121
+ background: #fff;
122
+ color: #c0c4cc;
123
+ border-radius: 0 10rpx 10rpx 0;
124
+ }
101
125
  .ml-input-prefix-icon,
102
126
  .ml-input-suffix-icon {
103
127
  min-width: 70rpx;
@@ -108,6 +132,7 @@ export default {
108
132
  border: 1px solid #e5e5e5;
109
133
  font-size: 30rpx;
110
134
  padding: 0 10rpx;
135
+ color: rgba(0, 0, 0, 0.4);
111
136
  }
112
137
  .ml-input-prefix-icon {
113
138
  border-right: 0;
@@ -123,6 +148,10 @@ export default {
123
148
  &.is-prefix,
124
149
  &.is-suffix,
125
150
  &.is-border {
151
+ .ml-input-clear-icon {
152
+ border: 1px solid #e5e5e5;
153
+ border-left: 0;
154
+ }
126
155
  .ml-input-inp {
127
156
  border: 1px solid #e5e5e5;
128
157
  border-radius: 10rpx;
@@ -138,6 +167,10 @@ export default {
138
167
  }
139
168
  }
140
169
  &.is-suffix {
170
+ .ml-input-clear-icon {
171
+ border-radius: 0;
172
+ border-right: 0;
173
+ }
141
174
  .ml-input-suffix-icon {
142
175
  border-radius: 0 10rpx 10rpx 0;
143
176
  }
@@ -146,6 +179,12 @@ export default {
146
179
  border-radius: 10rpx 0 0 10rpx;
147
180
  }
148
181
  }
182
+ &.is-clear {
183
+ .ml-input-inp {
184
+ padding-right: 0;
185
+ border-right: 0;
186
+ }
187
+ }
149
188
  &.is-prefix.is-suffix {
150
189
  .ml-input-inp {
151
190
  border-radius: 0;
@@ -8,17 +8,20 @@
8
8
  :placeholder="placeholder"
9
9
  :maxlength="maxLength"
10
10
  :disabled="disabled"
11
+ @blur="blurEvent"
11
12
  @input="inputEvent" />
12
13
  </template>
13
14
 
14
15
  <script>
16
+ import XEUtils from 'xe-utils'
17
+
15
18
  export default {
16
19
  name: 'MlNumberInput',
17
20
  options: {
18
21
  virtualHost: true
19
22
  },
20
23
  props: {
21
- value: String,
24
+ value: [String, Number],
22
25
  align: String,
23
26
  border: Boolean,
24
27
  type: String,
@@ -43,13 +46,29 @@ export default {
43
46
  },
44
47
  watch: {
45
48
  value (val) {
46
- this.inpVal = val
49
+ if (!this.updateModel) {
50
+ this.inpVal = val
51
+ }
52
+ this.updateModel = false
47
53
  }
48
54
  },
49
55
  created () {
50
56
  this.inpVal = this.value
51
57
  },
52
58
  methods: {
59
+ checkValue () {
60
+ const numVal = XEUtils.toNumber(this.inpVal)
61
+ if (`${numVal}` !== `${this.value}`) {
62
+ this.$emit('input', numVal)
63
+ return { status: false, value: numVal }
64
+ }
65
+ return { status: true, value: numVal }
66
+ },
67
+ blurEvent () {
68
+ const rest = this.checkValue()
69
+ this.updateModel = rest.status
70
+ this.$emit('blur', { value: this.inpVal })
71
+ },
53
72
  inputEvent () {
54
73
  this.$emit('input', this.inpVal)
55
74
  }
@@ -146,7 +146,7 @@ export default {
146
146
  width: 100%;
147
147
  padding-bottom: 20rpx;
148
148
  transform: translateY(100%);
149
- transition: transform 0.3s ease, transform 0.3s ease;
149
+ transition: transform 0.25s ease, transform 0.3s ease;
150
150
  background: #fff;
151
151
  }
152
152
  .ml-popup-header-title {
@@ -1,15 +1,31 @@
1
1
  <template>
2
- <view class="ml-region-picker" :class="className" :style="{width: width}">
3
- <uni-data-picker
4
- v-model="selectVals"
5
- popup-title="请选择城市"
6
- :placeholder="placeholder"
7
- :border="border"
8
- :localdata="cityList"
9
- :clear-icon="false"
10
- :map="{text: optLabelField, value: optValueField}"
11
- @change="changeEvent">
12
- </uni-data-picker>
2
+ <view v-if="isFromReadonly" class="ml-province-city-picker is-readonly">
3
+ <view class="ml-province-city-picker-readonly-content">{{ selectLabel }}</view>
4
+ </view>
5
+ <view v-else class="ml-province-city-picker" :class="[className || '', {'is-border': border, 'is-clear': value !== null}]">
6
+ <view class="ml-province-city-picker-warpper" @click="openPopup()">
7
+ <view class="ml-province-city-picker-text">
8
+ <text v-if="value !== null">{{ selectLabel }}</text>
9
+ <text v-else class="picker-placeholder">{{ placeholder }}</text>
10
+ </view>
11
+ <view v-if="clearable && value !== null" class="ml-province-city-picker-clear-icon" @click.stop="clearEvent">
12
+ <ml-icon name="delete-filling"></ml-icon>
13
+ </view>
14
+ <view v-else class="ml-province-city-picker-icon">
15
+ <ml-icon name="arrow-down" />
16
+ </view>
17
+ </view>
18
+
19
+ <ml-popup v-model="showPopup" title="请选择省/市" showConfirmButton showCancelButton @confirm="confirmEvent">
20
+ <picker-view v-if="showPopup" :value="selectVals" @change="changeEvent" class="ml-province-city-picker-view">
21
+ <picker-view-column>
22
+ <view class="item" v-for="(item, index) in provinceList" :key="index">{{ item[optLabelField] }}</view>
23
+ </picker-view-column>
24
+ <picker-view-column>
25
+ <view class="item" v-for="(item, index) in cityList" :key="index">{{ item[optLabelField] }}</view>
26
+ </picker-view-column>
27
+ </picker-view>
28
+ </ml-popup>
13
29
  </view>
14
30
  </template>
15
31
 
@@ -25,15 +41,26 @@ export default {
25
41
  province: String,
26
42
  city: String,
27
43
  width: String,
44
+ isAll: Boolean,
28
45
  optionProps: Object,
29
46
  className: String
30
47
  },
48
+ inject: {
49
+ form: {
50
+ from: 'mlForm',
51
+ default: null
52
+ }
53
+ },
31
54
  data () {
32
55
  return {
33
- selectVals: []
56
+ showPopup: false,
57
+ selectVals: [0]
34
58
  }
35
59
  },
36
60
  computed: {
61
+ isFromReadonly () {
62
+ return this.form ? this.form.readonly : false
63
+ },
37
64
  optOptions () {
38
65
  return Object.assign({}, this.optionProps)
39
66
  },
@@ -43,26 +70,103 @@ export default {
43
70
  optValueField () {
44
71
  return this.optOptions.value || 'name'
45
72
  },
73
+ selectLabel () {
74
+ const province = this.province || (this.value ? this.value[0] : '')
75
+ const city = this.city || (this.value ? this.value[1] : '')
76
+ const provinceItem = this.provinceList.find(item => item[this.optValueField] === province)
77
+ const cityItem = provinceItem && provinceItem.children? provinceItem.children.find(item => item[this.optValueField] === city) : null
78
+ if (provinceItem) {
79
+ return [provinceItem ? provinceItem[this.optLabelField] : '', cityItem ? cityItem[this.optLabelField] : ''].join(' / ')
80
+ }
81
+ return ''
82
+ },
83
+ provinceList () {
84
+ if (this.isAll) {
85
+ return [{ name: '全部', code: '' }].concat(provinceCity)
86
+ }
87
+ return provinceCity
88
+ },
89
+ selectProvince () {
90
+ return this.provinceList[this.selectVals[0] || 0]
91
+ },
46
92
  cityList () {
47
- return [{ [`${this.optLabelField}`]: '全部', [`${this.optValueField}`]: '' }].concat(provinceCity)
93
+ return (this.selectProvince ? this.selectProvince.children : []) || []
94
+ },
95
+ selectCity () {
96
+ return this.cityList[this.selectVals[1] || 0]
97
+ },
98
+ },
99
+ watch: {
100
+ selectProvince () {
101
+ this.selectVals[1] = 0
48
102
  }
49
103
  },
50
104
  methods: {
105
+ closePopup () {
106
+ this.showPopup = false
107
+ },
108
+ openPopup () {
109
+ this.showPopup = true
110
+ },
51
111
  changeEvent (e) {
52
- const value = e.detail.value.map(item => item.value)
53
- const province = value ? value[0] : ''
54
- this.$emit('update:province', province)
55
- this.$emit('update:city', province ? value[1] : '')
112
+ this.selectVals = e.detail.value
113
+ },
114
+ confirmEvent () {
115
+ const { selectProvince, selectCity } = this
116
+ const value = [selectProvince ? selectProvince[this.optValueField] : '', selectCity ? selectCity[this.optValueField] : '']
117
+ this.$emit('update:province', value[0])
118
+ this.$emit('update:city', value[1])
56
119
  this.$emit('input', value)
57
120
  this.$emit('change', { value })
121
+ this.closePopup()
58
122
  }
59
123
  }
60
124
  }
61
125
  </script>
62
126
 
63
127
  <style lang="scss">
64
- .ml-region-picker {
65
- display: inline-block;
66
- width: 100%;
128
+ .ml-province-city-picker-readonly-content {
129
+ padding: 20rpx;
130
+ }
131
+ .ml-province-city-picker {
132
+ width: 100%;
133
+ &.is-border {
134
+ border: 1px solid #e5e5e5;
135
+ background: #fff;
136
+ }
137
+ }
138
+ .ml-province-city-picker-warpper {
139
+ position: relative;
140
+ display: flex;
141
+ flex-direction: row;
142
+ align-items: center;
143
+ padding: 0 20rpx;
144
+ height: 70rpx;
145
+ border-radius: 10rpx;
146
+ .ml-province-city-picker-text {
147
+ flex-grow: 1;
148
+ padding-right: 10rpx;
149
+ overflow: hidden;
150
+ text-overflow: ellipsis;
151
+ white-space: nowrap;
152
+ }
153
+ .ml-province-city-picker-clear-icon {
154
+ width: 60rpx;
155
+ display: flex;
156
+ flex-shrink: 0;
157
+ align-items: center;
158
+ justify-content: center;
159
+ background: #fff;
160
+ color: #c0c4cc;
161
+ border-radius: 0 10rpx 10rpx 0;
162
+ }
163
+ .ml-province-city-picker-icon {
164
+ width: 60rpx;
165
+ display: flex;
166
+ flex-shrink: 0;
167
+ align-items: center;
168
+ justify-content: center;
169
+ color: #6a6a6a;
170
+ }
67
171
  }
68
- </style>
172
+ </style>
@@ -2,13 +2,16 @@
2
2
  <view v-if="isFromReadonly" class="ml-select-picker is-readonly">
3
3
  <view class="ml-select-picker-readonly-content">{{ selectLabel }}</view>
4
4
  </view>
5
- <picker v-else class="ml-select-picker" :style="{width: width || '100%'}" :range="optionList" :range-key="optLabelField" @change="changeEvent">
6
- <view class="ml-select-picker-warpper" :class="[className || '', {'is-border': border}]">
5
+ <picker v-else class="ml-select-picker" mode="selector" :style="{width: width || '100%'}" :range="optionList" :range-key="optLabelField" @change="changeEvent">
6
+ <view class="ml-select-picker-warpper" :class="[className || '', {'is-border': border, 'is-clear': value !== null}]">
7
7
  <view class="ml-select-picker-text">
8
8
  <text v-if="value !== null">{{ selectLabel }}</text>
9
9
  <text v-else class="picker-placeholder">{{ placeholder }}</text>
10
10
  </view>
11
- <view class="ml-select-picker-icon">
11
+ <view v-if="clearable && value !== null" class="ml-select-picker-clear-icon" @click.stop="clearEvent">
12
+ <ml-icon name="delete-filling"></ml-icon>
13
+ </view>
14
+ <view v-else class="ml-select-picker-icon">
12
15
  <ml-icon name="arrow-down" />
13
16
  </view>
14
17
  </view>
@@ -28,6 +31,7 @@ export default {
28
31
  type: String,
29
32
  default: '请选择'
30
33
  },
34
+ clearable: Boolean,
31
35
  options: Array,
32
36
  optionProps: Object,
33
37
  width: String,
@@ -83,6 +87,12 @@ export default {
83
87
  }
84
88
  this.$emit('input', value)
85
89
  this.$emit('change', { value, option: item })
90
+ },
91
+ clearEvent () {
92
+ const value = null
93
+ this.$emit('input', value)
94
+ this.$emit('change', { value, option: null })
95
+ this.$emit('clear', { value })
86
96
  }
87
97
  }
88
98
  }
@@ -109,11 +119,12 @@ export default {
109
119
  display: flex;
110
120
  flex-direction: row;
111
121
  align-items: center;
112
- padding: 0 10rpx;
122
+ padding: 0 20rpx;
113
123
  height: 70rpx;
114
124
  border-radius: 10rpx;
115
125
  &.is-border {
116
126
  border: 1px solid #e5e5e5;
127
+ background: #fff;
117
128
  }
118
129
  }
119
130
  .ml-select-picker-text {
@@ -123,8 +134,22 @@ export default {
123
134
  text-overflow: ellipsis;
124
135
  white-space: nowrap;
125
136
  }
137
+ .ml-select-picker-clear-icon {
138
+ width: 60rpx;
139
+ display: flex;
140
+ flex-shrink: 0;
141
+ align-items: center;
142
+ justify-content: center;
143
+ background: #fff;
144
+ color: #c0c4cc;
145
+ border-radius: 0 10rpx 10rpx 0;
146
+ }
126
147
  .ml-select-picker-icon {
127
- display: inline;
148
+ width: 60rpx;
149
+ display: flex;
150
+ flex-shrink: 0;
151
+ align-items: center;
152
+ justify-content: center;
128
153
  color: #6a6a6a;
129
154
  }
130
155
  </style>
@@ -7,7 +7,7 @@
7
7
  <view v-else>
8
8
  <textarea class="ml-textarea-inp" v-model="inpVal" :rows="rows" :maxlength="maxLength" :placeholder="placeholder" :show-count="false" @input="inputEvent" :style="{color: fontColor, height: `${rows * 30}rpx`}"></textarea>
9
9
  <view v-if="showWordLimit" class="ml-textarea-word-count">
10
- <VoiceInput v-if="showVoice" v-model="inpVal" @input="inputEvent"></VoiceInput>
10
+ <!-- <VoiceInput v-if="showVoice" v-model="inpVal" @input="inputEvent"></VoiceInput> -->
11
11
  <view class="ml-textarea-word-numbers">{{ value ? value.length : 0 }}/{{ maxLength }}</view>
12
12
  </view>
13
13
  </view>
@@ -37,7 +37,7 @@ export default {
37
37
  },
38
38
  maxLength: {
39
39
  type: Number,
40
- default: 250
40
+ default: 200
41
41
  },
42
42
  placeholder: {
43
43
  type: String,
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <picker :value="value" class="ml-year-picker" mode="date" fields="year" @change="changeEvent">
2
+ <picker :value="value" class="ml-year-picker" mode="date" fields="year" @change="changeEvent">
3
3
  <view class="ml-year-picker-warpper" :class="[className || '', {'is-border': border}]">
4
4
  <view class="ml-year-picker-text">{{ value || '请选择' }}</view>
5
5
  <ml-icon class="ml-year-picker-icon" name="arrow-down"></ml-icon>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mali-applet-ui",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "码里云小程序组件库",
5
5
  "files": [
6
6
  "components",