vdesign-ui 0.1.24 → 0.2.0
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.
- package/dist/components/activityviews/index.vue +14 -12
- package/dist/components/button/index.vue +1 -1
- package/dist/components/checkbox/checkbox-group/index.vue +2 -1
- package/dist/components/checkbox/index.vue +19 -20
- package/dist/components/dialog/index.vue +15 -11
- package/dist/components/dropdown/index.vue +43 -31
- package/dist/components/empty/404-dark.png +0 -0
- package/dist/components/empty/404.png +0 -0
- package/dist/components/empty/index.vue +30 -2
- package/dist/components/empty/network-dark.png +0 -0
- package/dist/components/empty/network.png +0 -0
- package/dist/components/empty/nocoupons-dark.png +0 -0
- package/dist/components/empty/nocoupons.png +0 -0
- package/dist/components/empty/nodata-dark.png +0 -0
- package/dist/components/empty/nodata.png +0 -0
- package/dist/components/empty/nomargin-dark.png +0 -0
- package/dist/components/empty/nomargin.png +0 -0
- package/dist/components/empty/nonotice-dark.png +0 -0
- package/dist/components/empty/nonotice.png +0 -0
- package/dist/components/empty/noocomments-dark.png +0 -0
- package/dist/components/empty/noocomments.png +0 -0
- package/dist/components/empty/noorders-dark.png +0 -0
- package/dist/components/empty/noorders.png +0 -0
- package/dist/components/empty/noposition-dark.png +0 -0
- package/dist/components/empty/noposition.png +0 -0
- package/dist/components/empty/nosearch-dark.png +0 -0
- package/dist/components/empty/nosearch.png +0 -0
- package/dist/components/empty/style.less +4 -0
- package/dist/components/footer/index.vue +5 -1
- package/dist/components/footnav/footnav-item/index.vue +11 -42
- package/dist/components/footnav/index.vue +29 -33
- package/dist/components/headnav/index.vue +55 -37
- package/dist/components/headnav/style.less +0 -9
- package/dist/components/icon/font/iconfont.css +62 -952
- package/dist/components/icon/font/iconfont.js +5 -1
- package/dist/components/icon/index.vue +26 -18
- package/dist/components/input/calcTextareaHeight.js +36 -140
- package/dist/components/input/index.vue +107 -109
- package/dist/components/input/search/index.vue +18 -22
- package/dist/components/input/stepper/index.vue +32 -26
- package/dist/components/input/style.less +20 -33
- package/dist/components/list/index.vue +57 -69
- package/dist/components/list/style.less +20 -92
- package/dist/components/loading/img_status_loading_white_ani.svg +155 -0
- package/dist/components/loading/img_status_refresh_ani.svg +158 -0
- package/dist/components/loading/index.vue +28 -11
- package/dist/components/loading/style.less +1 -1
- package/dist/components/mixins/clickoutside.js +81 -81
- package/dist/components/mixins/outlineConfigPlugin.js +11 -6
- package/dist/components/noticebar/index.vue +9 -4
- package/dist/components/pagebreak/index.vue +21 -14
- package/dist/components/radio/index.vue +164 -135
- package/dist/components/radio/radio-group/index.vue +40 -52
- package/dist/components/result/index.vue +1 -2
- package/dist/components/selector/index.vue +49 -31
- package/dist/components/selector/style.less +14 -0
- package/dist/components/step-item/index.vue +2 -2
- package/dist/components/tabs/index.vue +55 -32
- package/dist/components/tabs/tab/index.vue +13 -16
- package/dist/components/tag/index.vue +18 -4
- package/dist/components/tag/style.less +2 -2
- package/dist/components/title/index.vue +11 -8
- package/dist/components/title/style.less +6 -0
- package/dist/img/img_status_loading_white_ani.b56fcfae.svg +155 -0
- package/dist/img/img_status_refresh_ani.d0e59f12.svg +158 -0
- package/dist/token.css +8 -0
- package/dist/vdesign-ui.common.js +1481 -1354
- package/dist/vdesign-ui.css +1 -1
- package/dist/vdesign-ui.umd.js +1481 -1354
- package/dist/vdesign-ui.umd.min.js +3 -3
- package/package.json +1 -1
- package/dist/components/loading/loading.png +0 -0
- package/dist/components/loading/refresh.png +0 -0
- package/dist/img/404-dark.775df5bb.png +0 -0
- package/dist/img/network-dark.11a147bb.png +0 -0
- package/dist/img/nodata-dark.b0ea0e39.png +0 -0
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
<span>
|
|
3
|
+
<template v-if="name">
|
|
4
|
+
<svg v-if="isSvg" class="vd-iconfont vd-svg-icon" :class="[`vd-icon-${name}`, sizeClass]" :style="{ fill: color }"
|
|
5
|
+
@click="$emit('click', $event)">
|
|
6
|
+
<use :xlink:href="`#vd-icon-${name}`" />
|
|
7
|
+
</svg>
|
|
8
|
+
<i v-else class="vd-iconfont" :class="[isImage ? '' : `vd-icon-${name}`, sizeClass]" :style="{ color }"
|
|
9
|
+
@click="$emit('click', $event)">
|
|
10
|
+
<img class="vd-img-icon" v-if="isImage" :src="name" />
|
|
11
|
+
</i>
|
|
12
|
+
</template>
|
|
13
|
+
<slot v-else></slot>
|
|
14
|
+
</span>
|
|
11
15
|
</template>
|
|
12
16
|
|
|
13
17
|
<script>
|
|
14
|
-
import './font/iconfont.js'
|
|
15
18
|
import "./font/iconfont.css";
|
|
19
|
+
import "./font/iconfont.js";
|
|
20
|
+
|
|
16
21
|
export default {
|
|
17
22
|
name: 'vd-icon',
|
|
18
23
|
props: {
|
|
@@ -28,16 +33,19 @@ export default {
|
|
|
28
33
|
type: String,
|
|
29
34
|
default: '',
|
|
30
35
|
},
|
|
31
|
-
svg: {
|
|
32
|
-
type: Boolean,
|
|
33
|
-
default: false,
|
|
34
|
-
}
|
|
35
36
|
},
|
|
36
|
-
|
|
37
|
-
isImage(
|
|
38
|
-
return name
|
|
37
|
+
computed: {
|
|
38
|
+
isImage() {
|
|
39
|
+
return this.name.includes('/');
|
|
40
|
+
},
|
|
41
|
+
isSvg() {
|
|
42
|
+
// 判断是否为 SVG 图标,依据 name 是否以 '.svg' 结尾
|
|
43
|
+
return this.name.endsWith('_svg');
|
|
44
|
+
},
|
|
45
|
+
sizeClass() {
|
|
46
|
+
return this.size ? `vd-icon-${this.size}` : '';
|
|
39
47
|
}
|
|
40
|
-
}
|
|
48
|
+
}
|
|
41
49
|
}
|
|
42
50
|
</script>
|
|
43
51
|
|
|
@@ -1,117 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// let hiddenTextarea;
|
|
5
|
-
//
|
|
6
|
-
// const HIDDEN_STYLE = `
|
|
7
|
-
// height:0 !important;
|
|
8
|
-
// min-height:0 !important;
|
|
9
|
-
// max-height:none !important;
|
|
10
|
-
// visibility:hidden !important;
|
|
11
|
-
// overflow:hidden !important;
|
|
12
|
-
// position:absolute !important;
|
|
13
|
-
// z-index:-1000 !important;
|
|
14
|
-
// top:0 !important;
|
|
15
|
-
// right:0 !important
|
|
16
|
-
// `;
|
|
17
|
-
//
|
|
18
|
-
// const CONTEXT_STYLE = [
|
|
19
|
-
// 'letter-spacing',
|
|
20
|
-
// 'line-height',
|
|
21
|
-
// 'padding-top',
|
|
22
|
-
// 'padding-bottom',
|
|
23
|
-
// 'font-family',
|
|
24
|
-
// 'font-weight',
|
|
25
|
-
// 'font-size',
|
|
26
|
-
// 'text-rendering',
|
|
27
|
-
// 'text-transform',
|
|
28
|
-
// 'width',
|
|
29
|
-
// 'text-indent',
|
|
30
|
-
// 'padding-left',
|
|
31
|
-
// 'padding-right',
|
|
32
|
-
// 'border-width',
|
|
33
|
-
// 'box-sizing'
|
|
34
|
-
// ];
|
|
35
|
-
//
|
|
36
|
-
// function calculateNodeStyling(node) {
|
|
37
|
-
// const style = window.getComputedStyle(node);
|
|
38
|
-
//
|
|
39
|
-
// const boxSizing = style.getPropertyValue('box-sizing');
|
|
40
|
-
//
|
|
41
|
-
// const paddingSize = (
|
|
42
|
-
// parseFloat(style.getPropertyValue('padding-bottom')) +
|
|
43
|
-
// parseFloat(style.getPropertyValue('padding-top'))
|
|
44
|
-
// );
|
|
45
|
-
//
|
|
46
|
-
// const borderSize = (
|
|
47
|
-
// parseFloat(style.getPropertyValue('border-bottom-width')) +
|
|
48
|
-
// parseFloat(style.getPropertyValue('border-top-width'))
|
|
49
|
-
// );
|
|
50
|
-
//
|
|
51
|
-
// const contextStyle = CONTEXT_STYLE
|
|
52
|
-
// .map(name => `${name}:${style.getPropertyValue(name)}`)
|
|
53
|
-
// .join(';');
|
|
54
|
-
//
|
|
55
|
-
// return {contextStyle, paddingSize, borderSize, boxSizing};
|
|
56
|
-
// }
|
|
57
|
-
//
|
|
58
|
-
// export default function calcTextareaHeight(targetNode, minRows = null, maxRows = null) {
|
|
59
|
-
// if (!hiddenTextarea) {
|
|
60
|
-
// hiddenTextarea = document.createElement('textarea');
|
|
61
|
-
// document.body.appendChild(hiddenTextarea);
|
|
62
|
-
// }
|
|
63
|
-
//
|
|
64
|
-
// let {
|
|
65
|
-
// paddingSize,
|
|
66
|
-
// borderSize,
|
|
67
|
-
// boxSizing,
|
|
68
|
-
// contextStyle
|
|
69
|
-
// } = calculateNodeStyling(targetNode);
|
|
70
|
-
//
|
|
71
|
-
// hiddenTextarea.setAttribute('style', `${contextStyle};${HIDDEN_STYLE}`);
|
|
72
|
-
// hiddenTextarea.value = targetNode.value || targetNode.placeholder || '';
|
|
73
|
-
//
|
|
74
|
-
// let height = hiddenTextarea.scrollHeight;
|
|
75
|
-
// let minHeight = -Infinity;
|
|
76
|
-
// let maxHeight = Infinity;
|
|
77
|
-
// let overflowY;
|
|
78
|
-
//
|
|
79
|
-
// if (boxSizing === 'border-box') {
|
|
80
|
-
// height = height + borderSize;
|
|
81
|
-
// } else if (boxSizing === 'content-box') {
|
|
82
|
-
// height = height - paddingSize;
|
|
83
|
-
// }
|
|
84
|
-
//
|
|
85
|
-
// hiddenTextarea.value = '';
|
|
86
|
-
// let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;
|
|
87
|
-
//
|
|
88
|
-
// if (minRows !== null) {
|
|
89
|
-
// minHeight = singleRowHeight * minRows;
|
|
90
|
-
// if (boxSizing === 'border-box') {
|
|
91
|
-
// minHeight = minHeight + paddingSize + borderSize;
|
|
92
|
-
// }
|
|
93
|
-
// height = Math.max(minHeight, height);
|
|
94
|
-
// }
|
|
95
|
-
// if (maxRows !== null) {
|
|
96
|
-
// maxHeight = singleRowHeight * maxRows;
|
|
97
|
-
// if (boxSizing === 'border-box') {
|
|
98
|
-
// maxHeight = maxHeight + paddingSize + borderSize;
|
|
99
|
-
// }
|
|
100
|
-
// overflowY = height > maxHeight ? '' : 'hidden';
|
|
101
|
-
// height = Math.min(maxHeight, height);
|
|
102
|
-
// }
|
|
103
|
-
//
|
|
104
|
-
// if (!maxRows) {
|
|
105
|
-
// overflowY = 'hidden';
|
|
106
|
-
// }
|
|
107
|
-
//
|
|
108
|
-
// return {
|
|
109
|
-
// height: `${height}px`,
|
|
110
|
-
// minHeight: `${minHeight}px`,
|
|
111
|
-
// maxHeight: `${maxHeight}px`,
|
|
112
|
-
// overflowY
|
|
113
|
-
// };
|
|
114
|
-
// }
|
|
1
|
+
// 定义全局的环境检查
|
|
2
|
+
const inBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
115
3
|
|
|
116
4
|
const HIDDEN_TEXTAREA_STYLE = `
|
|
117
5
|
min-height:0 !important;
|
|
@@ -122,7 +10,7 @@ const HIDDEN_TEXTAREA_STYLE = `
|
|
|
122
10
|
position:absolute !important;
|
|
123
11
|
z-index:-1000 !important;
|
|
124
12
|
top:0 !important;
|
|
125
|
-
right:0 !important
|
|
13
|
+
right:0 !important;
|
|
126
14
|
`;
|
|
127
15
|
|
|
128
16
|
const SIZING_STYLE = [
|
|
@@ -144,13 +32,25 @@ const SIZING_STYLE = [
|
|
|
144
32
|
];
|
|
145
33
|
|
|
146
34
|
let computedStyleCache = {};
|
|
147
|
-
let hiddenTextarea;
|
|
35
|
+
let hiddenTextarea = null;
|
|
148
36
|
|
|
37
|
+
// 计算节点的样式信息
|
|
149
38
|
function calculateNodeStyling(node, useCache = false) {
|
|
39
|
+
if (!inBrowser || !node) {
|
|
40
|
+
// 如果不在浏览器环境中,返回默认的样式对象,防止报错
|
|
41
|
+
return {
|
|
42
|
+
sizingStyle: '',
|
|
43
|
+
paddingSize: 0,
|
|
44
|
+
borderSize: 0,
|
|
45
|
+
boxSizing: 'content-box',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
150
49
|
const nodeRef = (
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
50
|
+
node.getAttribute('id') ||
|
|
51
|
+
node.getAttribute('data-reactid') ||
|
|
52
|
+
node.getAttribute('name')
|
|
53
|
+
);
|
|
154
54
|
|
|
155
55
|
if (useCache && computedStyleCache[nodeRef]) {
|
|
156
56
|
return computedStyleCache[nodeRef];
|
|
@@ -192,30 +92,27 @@ function calculateNodeStyling(node, useCache = false) {
|
|
|
192
92
|
return nodeInfo;
|
|
193
93
|
}
|
|
194
94
|
|
|
95
|
+
// 计算 textarea 的高度
|
|
195
96
|
export default function calcTextareaHeight(uiTextNode, minRows = null, maxRows = null, useCache = false) {
|
|
97
|
+
if (!inBrowser || !uiTextNode) {
|
|
98
|
+
// 如果不在浏览器环境中,返回默认的高度,避免 SSR 中出错
|
|
99
|
+
return { height: '0px', minHeight: '0px', maxHeight: '0px', overflowY: 'hidden' };
|
|
100
|
+
}
|
|
101
|
+
|
|
196
102
|
if (!hiddenTextarea) {
|
|
103
|
+
// 创建一个隐藏的 textarea 元素来测量高度
|
|
197
104
|
hiddenTextarea = document.createElement('textarea');
|
|
198
105
|
document.body.appendChild(hiddenTextarea);
|
|
199
106
|
}
|
|
200
107
|
|
|
201
|
-
// Fix wrap="off" issue
|
|
202
|
-
// https://github.com/ant-design/ant-design/issues/6577
|
|
203
108
|
if (uiTextNode.getAttribute('wrap')) {
|
|
204
109
|
hiddenTextarea.setAttribute('wrap', uiTextNode.getAttribute('wrap'));
|
|
205
110
|
} else {
|
|
206
111
|
hiddenTextarea.removeAttribute('wrap');
|
|
207
112
|
}
|
|
208
113
|
|
|
209
|
-
|
|
210
|
-
// the textbox
|
|
211
|
-
let {
|
|
212
|
-
paddingSize, borderSize,
|
|
213
|
-
boxSizing, sizingStyle,
|
|
214
|
-
} = calculateNodeStyling(uiTextNode, useCache);
|
|
114
|
+
const { paddingSize, borderSize, boxSizing, sizingStyle } = calculateNodeStyling(uiTextNode, useCache);
|
|
215
115
|
|
|
216
|
-
// Need to have the overflow attribute to hide the scrollbar otherwise
|
|
217
|
-
// text-lines will not calculated properly as the shadow will technically be
|
|
218
|
-
// narrower for content
|
|
219
116
|
hiddenTextarea.setAttribute('style', `${sizingStyle};${HIDDEN_TEXTAREA_STYLE}`);
|
|
220
117
|
hiddenTextarea.value = uiTextNode.value || uiTextNode.placeholder || '';
|
|
221
118
|
|
|
@@ -225,34 +122,33 @@ export default function calcTextareaHeight(uiTextNode, minRows = null, maxRows =
|
|
|
225
122
|
let overflowY;
|
|
226
123
|
|
|
227
124
|
if (boxSizing === 'border-box') {
|
|
228
|
-
|
|
229
|
-
height = height + borderSize;
|
|
125
|
+
height += borderSize;
|
|
230
126
|
} else if (boxSizing === 'content-box') {
|
|
231
|
-
|
|
232
|
-
height = height - paddingSize;
|
|
127
|
+
height -= paddingSize;
|
|
233
128
|
}
|
|
234
129
|
|
|
235
130
|
if (minRows !== null || maxRows !== null) {
|
|
236
|
-
// measure height of a textarea with a single row
|
|
237
131
|
hiddenTextarea.value = ' ';
|
|
238
|
-
|
|
132
|
+
const singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;
|
|
133
|
+
|
|
239
134
|
if (minRows !== null) {
|
|
240
135
|
minHeight = singleRowHeight * minRows;
|
|
241
136
|
if (boxSizing === 'border-box') {
|
|
242
|
-
minHeight
|
|
137
|
+
minHeight += paddingSize + borderSize;
|
|
243
138
|
}
|
|
244
139
|
height = Math.max(minHeight, height);
|
|
245
140
|
}
|
|
141
|
+
|
|
246
142
|
if (maxRows !== null) {
|
|
247
143
|
maxHeight = singleRowHeight * maxRows;
|
|
248
144
|
if (boxSizing === 'border-box') {
|
|
249
|
-
maxHeight
|
|
145
|
+
maxHeight += paddingSize + borderSize;
|
|
250
146
|
}
|
|
251
147
|
overflowY = height > maxHeight ? '' : 'hidden';
|
|
252
148
|
height = Math.min(maxHeight, height);
|
|
253
149
|
}
|
|
254
150
|
}
|
|
255
|
-
|
|
151
|
+
|
|
256
152
|
if (!maxRows) {
|
|
257
153
|
overflowY = 'hidden';
|
|
258
154
|
}
|
|
@@ -261,6 +157,6 @@ export default function calcTextareaHeight(uiTextNode, minRows = null, maxRows =
|
|
|
261
157
|
height: `${height}px`,
|
|
262
158
|
minHeight: `${minHeight}px`,
|
|
263
159
|
maxHeight: `${maxHeight}px`,
|
|
264
|
-
overflowY
|
|
160
|
+
overflowY,
|
|
265
161
|
};
|
|
266
162
|
}
|
|
@@ -1,34 +1,17 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div :class="wrapClasses" class="vd-input">
|
|
3
|
-
|
|
4
|
-
<span v-if="
|
|
3
|
+
<!-- 前缀,还有前缀右边框 -->
|
|
4
|
+
<span v-if="hasPrefix" class="vd-input-form__prefix" :class="borderRightClasses">
|
|
5
5
|
<slot name="prefix">{{ prefix }}</slot>
|
|
6
6
|
</span>
|
|
7
|
-
<input
|
|
8
|
-
v-if="!inputTextArea"
|
|
9
|
-
ref="input"
|
|
10
|
-
v-bind="$attrs"
|
|
11
|
-
:type="passwordIcon ? (passwordVisible ? 'text' : 'password') : type"
|
|
12
|
-
:class="inputClasses"
|
|
13
|
-
:disabled="disabled"
|
|
14
|
-
:placeholder="placeholder"
|
|
15
|
-
:value="currentValue"
|
|
16
|
-
@input="handleInput"
|
|
17
|
-
@focus="handleFocus"
|
|
18
|
-
@blur="handleBlur"
|
|
19
|
-
/>
|
|
20
|
-
|
|
21
7
|
<textarea
|
|
22
|
-
v-
|
|
8
|
+
v-if="type === 'textarea'"
|
|
23
9
|
ref="textarea"
|
|
24
10
|
v-bind="$attrs"
|
|
25
|
-
:id="elementId"
|
|
26
|
-
:wrap="wrap"
|
|
27
|
-
:type="type"
|
|
28
11
|
:rows="rows"
|
|
29
12
|
:class="inputClasses"
|
|
30
13
|
:disabled="disabled"
|
|
31
|
-
:
|
|
14
|
+
:readonly="readonly"
|
|
32
15
|
:value="currentValue"
|
|
33
16
|
@focus="handleFocus"
|
|
34
17
|
@blur="handleBlur"
|
|
@@ -36,71 +19,58 @@
|
|
|
36
19
|
:style="textareaStyles"
|
|
37
20
|
>
|
|
38
21
|
</textarea>
|
|
22
|
+
<input
|
|
23
|
+
v-else
|
|
24
|
+
ref="input"
|
|
25
|
+
v-bind="$attrs"
|
|
26
|
+
:type="passwordIcon ? (passwordVisible ? 'text' : 'password') : type"
|
|
27
|
+
:class="inputClasses"
|
|
28
|
+
:disabled="disabled"
|
|
29
|
+
:readonly="readonly"
|
|
30
|
+
:value="currentValue"
|
|
31
|
+
@input="handleInput"
|
|
32
|
+
@focus="handleFocus"
|
|
33
|
+
@blur="handleBlur"
|
|
34
|
+
/>
|
|
35
|
+
|
|
36
|
+
<!-- 右侧功能区域 -->
|
|
37
|
+
|
|
39
38
|
<div
|
|
40
|
-
v-if="
|
|
39
|
+
v-if="showRightSection"
|
|
41
40
|
class="vd-input-form__right"
|
|
42
41
|
>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
</slot>
|
|
42
|
+
<!-- 清除按钮 -->
|
|
43
|
+
<span v-if="showClear" class="vd-input-form__suffix">
|
|
44
|
+
<vd-icon name="icon_btn_clean" @mousedown.prevent.native="handleClear"></vd-icon>
|
|
47
45
|
</span>
|
|
48
|
-
|
|
46
|
+
<!-- (大数字的时候)设计要求的自定义文字 -->
|
|
47
|
+
<span v-if="hasAppend" class="vd-input-form__append">
|
|
49
48
|
<slot name="append">{{ append }}</slot>
|
|
50
49
|
</span>
|
|
50
|
+
<!-- 字数限制 -->
|
|
51
51
|
<div
|
|
52
52
|
v-if="isWordLimitVisible"
|
|
53
|
-
:class="
|
|
54
|
-
'vd-input__word-limit',
|
|
55
|
-
{ 'vd-input__word-limit--error': isOverLimit },
|
|
56
|
-
]"
|
|
53
|
+
:class="wordLimitClasses"
|
|
57
54
|
>
|
|
58
55
|
<span>{{ textLength }}</span
|
|
59
56
|
>/<span>{{ upperLimit }}</span>
|
|
60
57
|
</div>
|
|
61
58
|
</div>
|
|
59
|
+
<!-- 密码的时候,单独的清空按钮 -->
|
|
62
60
|
<span
|
|
63
|
-
v-if="
|
|
61
|
+
v-if="showPasswordControls"
|
|
64
62
|
class="vd-input-form__password"
|
|
65
63
|
>
|
|
66
|
-
<span v-if="
|
|
67
|
-
<vd-icon name="icon_btn_close" @
|
|
64
|
+
<span v-if="showPasswordClear" class="vd-input-form__password--close">
|
|
65
|
+
<vd-icon name="icon_btn_close" @mousedown.prevent.native="handleClear"></vd-icon>
|
|
68
66
|
</span>
|
|
69
|
-
<span v-if="
|
|
67
|
+
<span v-if="showPasswordIcon" class="vd-input-form__password--password">
|
|
70
68
|
<vd-icon
|
|
71
69
|
:name="passwordVisible ? 'icon_btn_eye' : 'icon_btn_eye_close'"
|
|
72
70
|
@click="handlePasswordVisible"
|
|
73
71
|
></vd-icon>
|
|
74
72
|
</span>
|
|
75
73
|
</span>
|
|
76
|
-
</template>
|
|
77
|
-
<template v-else>
|
|
78
|
-
<textarea
|
|
79
|
-
ref="textarea"
|
|
80
|
-
:type="type"
|
|
81
|
-
v-bind="$attrs"
|
|
82
|
-
:wrap="wrap"
|
|
83
|
-
:class="inputClasses"
|
|
84
|
-
:disabled="disabled"
|
|
85
|
-
:placeholder="placeholder"
|
|
86
|
-
:value="currentValue"
|
|
87
|
-
:rows="rows"
|
|
88
|
-
:name="name"
|
|
89
|
-
@input="handleInput"
|
|
90
|
-
:style="textareaStyles"
|
|
91
|
-
>
|
|
92
|
-
</textarea>
|
|
93
|
-
<div
|
|
94
|
-
v-if="isWordLimitVisible"
|
|
95
|
-
:class="[
|
|
96
|
-
'vd-input__word-limit',
|
|
97
|
-
{ 'vd-input__word-limit--error': isOverLimit },
|
|
98
|
-
]"
|
|
99
|
-
>
|
|
100
|
-
<span>{{ textLength }}</span
|
|
101
|
-
>/<span>{{ upperLimit }}</span>
|
|
102
|
-
</div>
|
|
103
|
-
</template>
|
|
104
74
|
</div>
|
|
105
75
|
</template>
|
|
106
76
|
|
|
@@ -111,26 +81,26 @@ const prefixCls = "vd-input";
|
|
|
111
81
|
export default {
|
|
112
82
|
name: "vd-input",
|
|
113
83
|
props: {
|
|
84
|
+
value: {
|
|
85
|
+
type: [String, Number],
|
|
86
|
+
default: "",
|
|
87
|
+
},
|
|
114
88
|
type: {
|
|
115
89
|
type: String,
|
|
116
90
|
default: "text",
|
|
117
91
|
},
|
|
118
92
|
prefix: {
|
|
119
93
|
type: [Boolean, String],
|
|
94
|
+
default: ''
|
|
120
95
|
},
|
|
121
96
|
borderRight: {
|
|
122
97
|
type: Boolean,
|
|
123
98
|
default: true
|
|
124
99
|
},
|
|
125
|
-
suffix: {
|
|
126
|
-
type: Boolean,
|
|
127
|
-
},
|
|
128
100
|
// 设计如此,单独的文字
|
|
129
101
|
append: {
|
|
130
|
-
type: Boolean,
|
|
131
|
-
|
|
132
|
-
placeholder: {
|
|
133
|
-
type: String,
|
|
102
|
+
type: [Boolean, String],
|
|
103
|
+
default: ''
|
|
134
104
|
},
|
|
135
105
|
error: {
|
|
136
106
|
type: Boolean,
|
|
@@ -144,27 +114,17 @@ export default {
|
|
|
144
114
|
passwordClose: {
|
|
145
115
|
type: Boolean,
|
|
146
116
|
},
|
|
147
|
-
|
|
148
|
-
type: String,
|
|
149
|
-
default: "icon_btn_eye_close",
|
|
150
|
-
},
|
|
117
|
+
// 输入框类型 表单类型,常规输入库,搜索框
|
|
151
118
|
form: {
|
|
152
119
|
type: String,
|
|
153
120
|
},
|
|
154
121
|
disabled: {
|
|
155
122
|
type: Boolean,
|
|
156
123
|
},
|
|
157
|
-
value: {
|
|
158
|
-
type: [String, Number],
|
|
159
|
-
default: "",
|
|
160
|
-
},
|
|
161
124
|
rows: {
|
|
162
125
|
type: Number,
|
|
163
126
|
default: 2,
|
|
164
127
|
},
|
|
165
|
-
name: {
|
|
166
|
-
type: String,
|
|
167
|
-
},
|
|
168
128
|
// 设计如此多行textarea,跟input属性一样
|
|
169
129
|
inputTextArea: {
|
|
170
130
|
type: Boolean,
|
|
@@ -180,29 +140,66 @@ export default {
|
|
|
180
140
|
type: [Boolean, Object],
|
|
181
141
|
default: false,
|
|
182
142
|
},
|
|
183
|
-
elementId: {
|
|
184
|
-
type: String,
|
|
185
|
-
},
|
|
186
|
-
wrap: {
|
|
187
|
-
type: String,
|
|
188
|
-
default: "soft",
|
|
189
|
-
},
|
|
190
143
|
// 新增0118
|
|
191
144
|
showWordLimit: {
|
|
192
145
|
type: Boolean,
|
|
193
146
|
default: false,
|
|
194
147
|
},
|
|
148
|
+
clearable:Boolean,
|
|
149
|
+
readonly:Boolean
|
|
195
150
|
},
|
|
196
151
|
data() {
|
|
197
152
|
return {
|
|
198
153
|
focusClass: false,
|
|
199
154
|
currentValue: this.value,
|
|
200
|
-
isOnComposition: false,
|
|
201
155
|
textareaStyles: {},
|
|
202
156
|
passwordVisible: false,
|
|
157
|
+
focused: false,
|
|
203
158
|
};
|
|
204
159
|
},
|
|
205
160
|
computed: {
|
|
161
|
+
hasPrefix() {
|
|
162
|
+
return (this.prefix !== undefined && this.prefix !== '') || this.$slots.prefix;
|
|
163
|
+
},
|
|
164
|
+
// 是否显示右侧区域
|
|
165
|
+
showRightSection() {
|
|
166
|
+
return this.showClear || this.hasAppend || this.isWordLimitVisible;
|
|
167
|
+
},
|
|
168
|
+
// 是否有附加内容
|
|
169
|
+
hasAppend() {
|
|
170
|
+
return (this.append !== undefined && this.append !== '') || this.$slots.append;
|
|
171
|
+
},
|
|
172
|
+
// 是否显示清除按钮(假设已经在 computed 中定义)
|
|
173
|
+
showClear() {
|
|
174
|
+
return (
|
|
175
|
+
this.clearable &&
|
|
176
|
+
this.focused &&
|
|
177
|
+
this.currentValue !== '' &&
|
|
178
|
+
!this.disabled &&
|
|
179
|
+
!this.readonly
|
|
180
|
+
);
|
|
181
|
+
},
|
|
182
|
+
wordLimitClasses() {
|
|
183
|
+
return [
|
|
184
|
+
'vd-input__word-limit',
|
|
185
|
+
{ 'vd-input__word-limit--error': this.isOverLimit },
|
|
186
|
+
];
|
|
187
|
+
},
|
|
188
|
+
showPasswordClear() {
|
|
189
|
+
return (
|
|
190
|
+
this.passwordClose &&
|
|
191
|
+
this.focused &&
|
|
192
|
+
this.currentValue !== '' &&
|
|
193
|
+
!this.disabled &&
|
|
194
|
+
!this.readonly
|
|
195
|
+
);
|
|
196
|
+
},
|
|
197
|
+
showPasswordIcon() {
|
|
198
|
+
return this.passwordIcon && this.type === 'password';
|
|
199
|
+
},
|
|
200
|
+
showPasswordControls() {
|
|
201
|
+
return this.showPasswordClear || this.showPasswordIcon;
|
|
202
|
+
},
|
|
206
203
|
wrapClasses() {
|
|
207
204
|
return [
|
|
208
205
|
{
|
|
@@ -212,7 +209,7 @@ export default {
|
|
|
212
209
|
[`${prefixCls}-${this.type}--warning`]: this.warning,
|
|
213
210
|
[`${prefixCls}--bigsize`]: this.bigSize,
|
|
214
211
|
[`${prefixCls}--error`]: this.error,
|
|
215
|
-
[`${prefixCls}--active`]: this.
|
|
212
|
+
[`${prefixCls}--active`]: this.focused,
|
|
216
213
|
[`${prefixCls}-inputarea`]: this.inputTextArea,
|
|
217
214
|
"vd-hairline--bottom": this.hairline,
|
|
218
215
|
"vd-textarea-auto": this.inputTextArea,
|
|
@@ -235,6 +232,7 @@ export default {
|
|
|
235
232
|
},
|
|
236
233
|
];
|
|
237
234
|
},
|
|
235
|
+
// 当前输入的文本长度
|
|
238
236
|
textLength() {
|
|
239
237
|
if (typeof this.value === "number") {
|
|
240
238
|
return String(this.value).length;
|
|
@@ -257,37 +255,34 @@ export default {
|
|
|
257
255
|
},
|
|
258
256
|
methods: {
|
|
259
257
|
handleFocus(event) {
|
|
260
|
-
|
|
261
|
-
this.focusClass = true;
|
|
262
|
-
}
|
|
258
|
+
this.focused = true;
|
|
263
259
|
this.$emit("focus", event);
|
|
260
|
+
|
|
261
|
+
if (this.readonly) {
|
|
262
|
+
this.blur();
|
|
263
|
+
}
|
|
264
264
|
},
|
|
265
265
|
handleBlur(event) {
|
|
266
|
-
|
|
267
|
-
this.focusClass = false;
|
|
268
|
-
}
|
|
266
|
+
this.focused = false;
|
|
269
267
|
this.$emit("blur", event);
|
|
270
268
|
},
|
|
271
269
|
focus() {
|
|
272
270
|
if (this.type === "textarea") {
|
|
273
|
-
this.$refs.textarea.focus();
|
|
271
|
+
this.$refs.textarea && this.$refs.textarea.focus();
|
|
274
272
|
} else {
|
|
275
|
-
this.$refs.input.focus();
|
|
273
|
+
this.$refs.input && this.$refs.input.focus();
|
|
276
274
|
}
|
|
277
275
|
},
|
|
278
276
|
blur() {
|
|
279
277
|
if (this.type === "textarea") {
|
|
280
|
-
this.$refs.textarea.blur();
|
|
278
|
+
this.$refs.textarea && this.$refs.textarea.blur();
|
|
281
279
|
} else {
|
|
282
|
-
this.$refs.input.blur();
|
|
280
|
+
this.$refs.input && this.$refs.input.blur();
|
|
283
281
|
}
|
|
284
282
|
},
|
|
285
283
|
|
|
286
284
|
handleInput(event) {
|
|
287
|
-
if (this.isOnComposition) return;
|
|
288
285
|
let value = event.target.value;
|
|
289
|
-
if (this.number && value !== "")
|
|
290
|
-
value = Number.isNaN(Number(value)) ? value : Number(value);
|
|
291
286
|
this.$emit("input", value);
|
|
292
287
|
this.setCurrentValue(value);
|
|
293
288
|
this.$emit("change", event);
|
|
@@ -295,18 +290,16 @@ export default {
|
|
|
295
290
|
|
|
296
291
|
setCurrentValue(value) {
|
|
297
292
|
if (value === this.currentValue) return;
|
|
293
|
+
this.currentValue = value;
|
|
298
294
|
this.$nextTick(() => {
|
|
299
295
|
this.resizeTextarea();
|
|
300
296
|
});
|
|
301
|
-
this.currentValue = value;
|
|
302
297
|
},
|
|
303
298
|
resizeTextarea() {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
return false;
|
|
299
|
+
if (!this.autosize || this.type !== "textarea") {
|
|
300
|
+
return;
|
|
307
301
|
}
|
|
308
|
-
const minRows = autosize
|
|
309
|
-
const maxRows = autosize.maxRows;
|
|
302
|
+
const { minRows, maxRows } = this.autosize;
|
|
310
303
|
this.textareaStyles = calcTextareaHeight(
|
|
311
304
|
this.$refs.textarea,
|
|
312
305
|
minRows,
|
|
@@ -319,7 +312,12 @@ export default {
|
|
|
319
312
|
this.setCurrentValue("");
|
|
320
313
|
this.$emit("change", e);
|
|
321
314
|
this.$emit("clear");
|
|
315
|
+
this.$nextTick(() => {
|
|
316
|
+
this.focus();
|
|
317
|
+
});
|
|
322
318
|
},
|
|
319
|
+
|
|
320
|
+
// 切换密码显示状态
|
|
323
321
|
handlePasswordVisible() {
|
|
324
322
|
this.passwordVisible = !this.passwordVisible;
|
|
325
323
|
this.$nextTick(() => {
|