v-uni-app-ui 1.0.0 → 1.0.2

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.
Files changed (61) hide show
  1. package/components/config.js +123 -0
  2. package/components/layout/v-card/v-card.vue +108 -0
  3. package/components/layout/v-grid/v-grid.vue +162 -0
  4. package/components/layout/v-icon-grid/v-icon-grid.vue +195 -0
  5. package/components/layout/v-infinite-scroll/v-infinite-scroll.vue +172 -0
  6. package/components/layout/v-list/v-list.vue +43 -0
  7. package/components/layout/v-row/v-row.vue +142 -0
  8. package/components/layout/v-waterfall/v-waterfall.vue +79 -0
  9. package/components/model/compound/v-checkbox-group/v-checkbox-group.vue +96 -0
  10. package/components/model/compound/v-console/v-console.js +20 -0
  11. package/components/model/compound/v-console/v-console.vue +299 -0
  12. package/components/model/compound/v-date-time/v-date-time.vue +261 -0
  13. package/components/model/compound/v-dialog/v-dialog.vue +178 -0
  14. package/components/model/compound/v-drum-select-picker/v-drum-select-picker.vue +83 -0
  15. package/components/model/compound/v-form/v-form.vue +226 -0
  16. package/components/model/compound/v-form-item/v-form-item.vue +255 -0
  17. package/components/model/compound/v-image/v-image.vue +357 -0
  18. package/components/model/compound/v-input-desensitize/v-input-desensitize.vue +101 -0
  19. package/components/model/compound/v-page/v-page.vue +11 -0
  20. package/components/model/compound/v-pages/v-pages.vue +141 -0
  21. package/components/model/compound/v-picker-list/v-picker-list.vue +109 -0
  22. package/components/model/compound/v-popup/v-popup.vue +151 -0
  23. package/components/model/compound/v-radio-group/v-radio-group.vue +86 -0
  24. package/components/model/compound/v-select-picker/v-select-picker.vue +202 -0
  25. package/components/model/compound/v-series-picker-list/v-series-picker-list.vue +221 -0
  26. package/components/model/compound/v-series-select-picker/v-series-select-picker.vue +203 -0
  27. package/components/model/compound/v-switch/v-switch.vue +136 -0
  28. package/components/model/compound/v-tabs-page/v-tabs-page.vue +138 -0
  29. package/components/model/native/v-badge/v-badge.vue +143 -0
  30. package/components/model/native/v-button/v-button.vue +273 -0
  31. package/components/model/native/v-carousel/v-carousel.vue +138 -0
  32. package/components/model/native/v-checkbox/v-checkbox.vue +215 -0
  33. package/components/model/native/v-collapse/v-collapse.vue +190 -0
  34. package/components/model/native/v-header-navigation-bar/v-header-navigation-bar.vue +92 -0
  35. package/components/model/native/v-input/v-input.vue +352 -0
  36. package/components/model/native/v-input-code/v-input-code.vue +146 -0
  37. package/components/model/native/v-loading/v-loading.vue +206 -0
  38. package/components/model/native/v-menu/v-menu.vue +222 -0
  39. package/components/model/native/v-menu-slide/v-menu-slide.vue +364 -0
  40. package/components/model/native/v-min-loading/v-min-loading.vue +80 -0
  41. package/components/model/native/v-null/v-null.vue +97 -0
  42. package/components/model/native/v-overlay/v-overlay.vue +96 -0
  43. package/components/model/native/v-pull-up-refresh/v-pull-up-refresh.vue +157 -0
  44. package/components/model/native/v-radio/v-radio.vue +138 -0
  45. package/components/model/native/v-scroll-list/v-scroll-list.vue +169 -0
  46. package/components/model/native/v-steps/v-steps.vue +253 -0
  47. package/components/model/native/v-table/v-table.vue +203 -0
  48. package/components/model/native/v-tabs/v-tabs.vue +235 -0
  49. package/components/model/native/v-tag/v-tag.vue +206 -0
  50. package/components/model/native/v-text/v-text.vue +187 -0
  51. package/components/model/native/v-text-button/v-text-button.vue +139 -0
  52. package/components/model/native/v-textarea/v-textarea.vue +178 -0
  53. package/components/model/native/v-title/v-title.vue +91 -0
  54. package/components/model/native/v-toast/info.png +0 -0
  55. package/components/model/native/v-toast/success.png +0 -0
  56. package/components/model/native/v-toast/v-toast.vue +198 -0
  57. package/components/model/native/v-toast/warn.png +0 -0
  58. package/components/model/native/v-upload-file-button/v-upload-file-button.vue +296 -0
  59. package/components/model/native/v-video/v-video.vue +175 -0
  60. package/components/model/native/v-window/v-window.vue +158 -0
  61. package/package.json +18 -94
@@ -0,0 +1,206 @@
1
+ <template>
2
+ <view
3
+ v-show="show"
4
+ :class="['v-tag', `v-tag--${type}`, `v-tag--${model}`, { 'v-tag--disabled': disabled, 'v-tag--plain': plain }, `v-tag--${size}`]"
5
+ @click="handleClick"
6
+ :style="{ backgroundColor: bgColor, color: txtColor }"
7
+ >
8
+ <view v-if="closable && !disabled" class="v-tag-close" @click.stop="handleClose">×</view>
9
+ <text class="v-tag-content">
10
+ <slot>{{ content }}</slot>
11
+ </text>
12
+ </view>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ import { ref, inject, computed } from 'vue';
17
+
18
+ const props = defineProps({
19
+ type: {
20
+ type: String,
21
+ default: 'default',
22
+ validator: (value: string) => {
23
+ return ['default', 'delete', 'succeed', 'info', 'warn'].includes(value);
24
+ }
25
+ },
26
+ model: {
27
+ type: String,
28
+ default: 'semicircle',
29
+ validator: (value: string) => {
30
+ return ['semicircle', 'circle', 'square'].includes(value);
31
+ }
32
+ },
33
+ size: {
34
+ type: String,
35
+ default: 'medium',
36
+ validator: (value: string) => ['small', 'medium', 'large'].includes(value)
37
+ },
38
+ content: {
39
+ type: String,
40
+ default: ''
41
+ },
42
+ backgroundColor: {
43
+ type: String,
44
+ default: ''
45
+ },
46
+ fontColor: {
47
+ type: String,
48
+ default: ''
49
+ },
50
+ closable: {
51
+ type: Boolean,
52
+ default: false
53
+ },
54
+ disabled: {
55
+ type: Boolean,
56
+ default: false
57
+ },
58
+ plain: {
59
+ type: Boolean,
60
+ default: false
61
+ }
62
+ });
63
+
64
+ const emit = defineEmits(['click', 'close']);
65
+
66
+ const config = inject<any>('config');
67
+ const show = ref(true);
68
+
69
+ const bgColor = computed(() => props.backgroundColor );
70
+
71
+ const txtColor = computed(() => props.fontColor );
72
+
73
+ const handleClick = (event: MouseEvent) => {
74
+ if (!props.disabled) {
75
+ emit('click', event);
76
+ }
77
+ };
78
+
79
+ const handleClose = () => {
80
+ if (!props.disabled && props.closable) {
81
+ show.value = false;
82
+ emit('close', props.content, show.value);
83
+ }
84
+ };
85
+ </script>
86
+
87
+ <style lang="scss" scoped>
88
+ .v-tag {
89
+ display: inline-flex;
90
+ align-items: center;
91
+ cursor: pointer;
92
+ position: relative;
93
+ transition: all 0.3s;
94
+ color: v-bind('config.fontColor.reversal');
95
+
96
+ .v-tag-content {
97
+ text-align: center;
98
+ margin: auto;
99
+ }
100
+
101
+ .v-tag-close {
102
+ width: 18rpx;
103
+ height: 18rpx;
104
+ position: absolute;
105
+ top: -10rpx;
106
+ right: -10rpx;
107
+ cursor: pointer;
108
+ color: #fff;
109
+ background-color: #666666;
110
+ font-weight: bold;
111
+ font-size: 15rpx;
112
+ padding: 5rpx;
113
+ border-radius: 50%;
114
+ text-align: center;
115
+ line-height: 18rpx;
116
+ }
117
+
118
+ &--small {
119
+ padding: 14rpx 10rpx;
120
+ font-size: v-bind('config.fontSize.smallText');
121
+ }
122
+ &--medium {
123
+ padding: 15rpx 12.5rpx;
124
+ font-size: v-bind('config.fontSize.mediumText');
125
+ }
126
+ &--large {
127
+ padding: 20rpx 15rpx;
128
+ font-size: v-bind('config.fontSize.largeText');
129
+ }
130
+
131
+ &--default {
132
+ background-color: v-bind('config.backgroundColor.default');
133
+ }
134
+
135
+ &--succeed {
136
+ background-color: v-bind('config.backgroundColor.succeed');
137
+ }
138
+
139
+ &--warn {
140
+ background-color: v-bind('config.backgroundColor.warn');
141
+ }
142
+
143
+ &--delete {
144
+ background-color: v-bind('config.backgroundColor.delete');
145
+ }
146
+
147
+ &--info {
148
+ background-color: v-bind('config.backgroundColor.info');
149
+ }
150
+
151
+ &--semicircle {
152
+ border-radius: v-bind('config.borderRadius.semicircle');
153
+ }
154
+
155
+ &--circle {
156
+ border-radius: v-bind('config.borderRadius.circle');
157
+ }
158
+
159
+ &--square {
160
+ border-radius: v-bind('config.borderRadius.square');
161
+ }
162
+
163
+ &--disabled {
164
+ opacity: v-bind('config.opacity.disabled');
165
+ }
166
+
167
+ &--plain {
168
+ background-color: transparent;
169
+ border: 1rpx solid;
170
+ padding: 8rpx 12rpx;
171
+
172
+ &.v-tag--default {
173
+ border-color: v-bind('config.border.default');
174
+ color: v-bind('config.fontColor.default');
175
+ }
176
+
177
+ &.v-tag--succeed {
178
+ border-color: v-bind('config.border.succeed');
179
+ color: v-bind('config.fontColor.succeed');
180
+ }
181
+
182
+ &.v-tag--warn {
183
+ border-color: v-bind('config.border.warn');
184
+ color: v-bind('config.fontColor.warn');
185
+ }
186
+
187
+ &.v-tag--delete {
188
+ border-color: v-bind('config.border.delete');
189
+ color: v-bind('config.fontColor.delete');
190
+ }
191
+
192
+ &.v-tag--info {
193
+ border-color: v-bind('config.border.info');
194
+ color: v-bind('config.fontColor.info');
195
+ }
196
+
197
+ &.v-tag--semicircle {
198
+ border-radius: v-bind('config.borderRadius.semicircle');
199
+ }
200
+
201
+ &.v-tag--square {
202
+ border-radius: v-bind('config.borderRadius.square');
203
+ }
204
+ }
205
+ }
206
+ </style>
@@ -0,0 +1,187 @@
1
+ <template>
2
+ <!-- <text :class="['v-text', `v-text--${type}`, `v-text--${size}`]" :style="textStyle">
3
+ <slot v-if="!processedText">{{ processedText }}</slot>
4
+ <view v-html="processedText">
5
+
6
+ </view>
7
+ </text> -->
8
+ <view :class="['v-text', `v-text--${type}`, `v-text--${size}`]" :style="textStyle">
9
+ <slot v-if="!processedText">{{ processedText }}</slot>
10
+ <rich-text :nodes="processedText"></rich-text>
11
+ </view>
12
+ </template>
13
+
14
+ <script setup lang="ts">
15
+ import { computed, inject } from 'vue';
16
+
17
+ const props = defineProps({
18
+ text: {
19
+ type: String,
20
+ default: ''
21
+ },
22
+ type: {
23
+ type: String,
24
+ default: 'default',
25
+ validator: (value: string) => {
26
+ return ['default', 'primary', 'succeed', 'warning', 'delete', 'info'].includes(value);
27
+ }
28
+ },
29
+ size: {
30
+ type: String,
31
+ default: 'medium',
32
+ validator: (value: string) => {
33
+ return ['small', 'medium', 'large'].includes(value);
34
+ }
35
+ },
36
+ color: {
37
+ type: String,
38
+ default: ''
39
+ },
40
+ lineHeight: {
41
+ type: [Number, String],
42
+ default: 1.5
43
+ },
44
+ mode: {
45
+ type: String,
46
+ default: '',
47
+ validator: (value: string) => {
48
+ return ['', 'timestamp', 'amount'].includes(value);
49
+ }
50
+ },
51
+ encrypt: {
52
+ type: String,
53
+ default: '',
54
+ validator: (value: string) => {
55
+ return ['', 'phone', 'name'].includes(value);
56
+ }
57
+ },
58
+ lines: {
59
+ type: [Number, String],
60
+ default: 1
61
+ },
62
+ format: {
63
+ type: String,
64
+ default: ''
65
+ },
66
+ keyword: { type: String, default: '' },
67
+ keywordColor: { type: String, default: '#ff5e5e' }
68
+ });
69
+
70
+ const config = inject<any>('config');
71
+
72
+ const processedText = computed(() => {
73
+ let result = props.text;
74
+
75
+ if (props.mode === 'timestamp' && props.format) {
76
+ // 尝试将文本转换为日期对象
77
+ let date: Date;
78
+ if (/^\d+$/.test(props.text)) {
79
+ // 如果是时间戳(数字)
80
+ date = new Date(parseInt(props.text));
81
+ } else {
82
+ // 如果是日期字符串
83
+ date = new Date(props.text);
84
+ }
85
+
86
+ if (!isNaN(date.getTime())) {
87
+ const year = date.getFullYear();
88
+ const month = date.getMonth() + 1;
89
+ const day = date.getDate();
90
+ const hours = date.getHours();
91
+ const minutes = date.getMinutes();
92
+ const seconds = date.getSeconds();
93
+
94
+ result = props.format
95
+ .replace('yyyy', year.toString())
96
+ .replace('MM', month.toString().padStart(2, '0'))
97
+ .replace('dd', day.toString().padStart(2, '0'))
98
+ .replace('HH', hours.toString().padStart(2, '0'))
99
+ .replace('mm', minutes.toString().padStart(2, '0'))
100
+ .replace('ss', seconds.toString().padStart(2, '0'));
101
+ }
102
+ } else if (props.mode === 'amount' && props.format) {
103
+ const amount = parseFloat(props.text);
104
+ if (!isNaN(amount)) {
105
+ if (props.format === '$') {
106
+ result = `$${amount.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
107
+ } else if (props.format === '¥') {
108
+ result = `¥${amount.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
109
+ }
110
+ }
111
+ }
112
+
113
+ if (props.encrypt === 'phone' && result.length === 11) {
114
+ result = result.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
115
+ } else if (props.encrypt === 'name' && result.length > 1) {
116
+ const firstChar = result.charAt(0);
117
+ result = firstChar + '****' + result.slice(-1);
118
+ }
119
+
120
+ // 关键字高亮(最后一步)
121
+ if (props.keyword) {
122
+ const reg = new RegExp(`(${props.keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
123
+ // 先转义再替换
124
+ const escape = (str: string) => str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;');
125
+ result = escape(result).replace(reg, `<span style="color:${props.keywordColor}" class="v-text__keyword">$1</span>`);
126
+ }
127
+
128
+ return result;
129
+ });
130
+
131
+ const textStyle = computed(() => {
132
+ const style: Record<string, string | number> = {};
133
+ if (props.color) style.color = props.color;
134
+ if (props.lineHeight) style.lineHeight = typeof props.lineHeight === 'number' ? `${props.lineHeight}` : props.lineHeight;
135
+ if (props.lines) {
136
+ style.webkitLineClamp = typeof props.lines === 'number' ? `${props.lines}` : props.lines;
137
+ style.overflow = 'hidden';
138
+ style.textOverflow = 'ellipsis';
139
+ style.display = '-webkit-box';
140
+ style.webkitBoxOrient = 'vertical';
141
+ }
142
+ return style;
143
+ });
144
+ </script>
145
+
146
+ <style lang="scss" scoped>
147
+ .v-text {
148
+ font-size: v-bind('config.fontSize.mediumText');
149
+ line-height: 1.5;
150
+
151
+ &--default {
152
+ color: v-bind('config.fontColor.text');
153
+ }
154
+
155
+ &--primary {
156
+ color: v-bind('config.fontColor.default');
157
+ }
158
+
159
+ &--succeed {
160
+ color: v-bind('config.fontColor.succeed');
161
+ }
162
+
163
+ &--warn {
164
+ color: v-bind('config.fontColor.warn');
165
+ }
166
+
167
+ &--delete {
168
+ color: v-bind('config.fontColor.delete');
169
+ }
170
+
171
+ &--info {
172
+ color: v-bind('config.fontColor.info');
173
+ }
174
+
175
+ &--small {
176
+ font-size: v-bind('config.fontSize.smallText');
177
+ }
178
+
179
+ &--medium {
180
+ font-size: v-bind('config.fontSize.mediumText');
181
+ }
182
+
183
+ &--large {
184
+ font-size: v-bind('config.fontSize.largeText');
185
+ }
186
+ }
187
+ </style>
@@ -0,0 +1,139 @@
1
+ <template>
2
+ <button
3
+ :class="['v-text-button', { 'v-text-button--disabled': disabled, 'v-text-button--loading': loading }, ` v-text-button--${type}`, `v-text-button--${size}`]"
4
+ :disabled="disabled || loading"
5
+ @click="handleClick"
6
+ >
7
+ <span v-if="loading" class="loading-text">{{ loadingText }}</span>
8
+ <span v-else>
9
+ <slot>{{ text }}</slot>
10
+ </span>
11
+ </button>
12
+ </template>
13
+
14
+ <script setup lang="ts">
15
+ import { ref, inject } from 'vue';
16
+
17
+
18
+ const props = defineProps({
19
+ type: {
20
+ type: String,
21
+ default: 'default'
22
+ },
23
+ size: {
24
+ type: String,
25
+ default: 'medium',
26
+ validator: (value: string) => ['small', 'medium', 'large'].includes(value)
27
+ },
28
+ text: {
29
+ type: String,
30
+ default: '',
31
+ required: true
32
+ },
33
+ disabled: {
34
+ type: Boolean,
35
+ default: false
36
+ },
37
+ loading: {
38
+ type: Boolean,
39
+ default: false
40
+ },
41
+ loadingText: {
42
+ type: String,
43
+ default: '加载中...'
44
+ }
45
+ });
46
+
47
+ const emit = defineEmits(['click']);
48
+ const config = inject<any>('config');
49
+
50
+ const handleClick = (event: MouseEvent) => {
51
+ if (!props.disabled && !props.loading) {
52
+ emit('click', event);
53
+ }
54
+ };
55
+ </script>
56
+
57
+ <style lang="scss" scoped>
58
+ .v-text-button {
59
+ border: none;
60
+ background-color: transparent;
61
+ cursor: pointer;
62
+ transition: all 0.3s;
63
+
64
+ &:hover {
65
+ opacity: 0.9;
66
+ text-decoration: underline;
67
+ }
68
+
69
+ &:active {
70
+ opacity: 0.8;
71
+ }
72
+
73
+ &--default {
74
+ color: v-bind("config.fontColor.default");
75
+ }
76
+
77
+ &--delete {
78
+ color: v-bind("config.fontColor.delete");
79
+ }
80
+
81
+ &--succeed {
82
+ color: v-bind("config.fontColor.succeed");
83
+ }
84
+
85
+ &--info {
86
+ color: v-bind("config.fontColor.info");
87
+ }
88
+
89
+ &--warn {
90
+ color: v-bind("config.fontColor.warn");
91
+ }
92
+
93
+ &--small {
94
+ font-size: v-bind("config.fontSize.smallText");
95
+ }
96
+
97
+ &--medium {
98
+ font-size: v-bind("config.fontSize.mediumText");
99
+ }
100
+
101
+ &--large {
102
+ font-size: v-bind("config.fontSize.largeText");
103
+ }
104
+
105
+ &--disabled,
106
+ &[disabled] {
107
+ opacity: v-bind("config.opacity.disabled");
108
+ cursor: not-allowed;
109
+ }
110
+
111
+ &--loading {
112
+ color: #287afa;
113
+ cursor: wait;
114
+ }
115
+
116
+ .loading-text {
117
+ animation: loadingDots 1.5s infinite;
118
+ }
119
+
120
+ @keyframes loadingDots {
121
+ 0% {
122
+ opacity: 1;
123
+ }
124
+ 50% {
125
+ opacity: 0.5;
126
+ }
127
+ 100% {
128
+ opacity: 1;
129
+ }
130
+ }
131
+ }
132
+ uni-button:after {
133
+ border: none;
134
+ }
135
+ uni-button[disabled][type='default'],
136
+ uni-button[disabled]:not([type]) {
137
+ background-color: transparent;
138
+ }
139
+ </style>
@@ -0,0 +1,178 @@
1
+ <template>
2
+ <view class="v-textarea-container">
3
+ <textarea
4
+ :value="inputValue"
5
+ :class="['v-textarea', { 'v-textarea--disabled': disabled, 'v-textarea--focused': focused }, `v-textarea--border--${boderModel}`]"
6
+ :placeholder="placeholder"
7
+ :maxlength="maxlength || undefined"
8
+ :disabled="disabled"
9
+ :auto-height="autoHeight"
10
+ @input="handleInput"
11
+ @focus="handleFocus"
12
+ @blur="handleBlur"
13
+ @confirm="handleConfirm"
14
+ ></textarea>
15
+ <view v-if="showCounter" class="v-textarea-counter">{{ currentLength }}/{{ maxlength }}</view>
16
+ </view>
17
+ </template>
18
+
19
+ <script setup lang="ts">
20
+ import { ref, watch,inject } from 'vue';
21
+
22
+ /**
23
+ * v-textarea 文本框
24
+ * value 双向绑定
25
+ * placeholder 提示词
26
+ * maxlength 最大输入限制
27
+ * disabled 是否禁用 默认值:false 可选值:true禁用 false不禁用
28
+ * autoHeight 是否自动延长高度 默认值:true 可选值:true禁用 false不禁用
29
+ * boderModel 边框模式 默认值:all 可选值:all普通边框 nont无边框模式 bottom底部边框模式 top上边框模式 left左边框模式 right右边框模式 ends左右两端边框模式 up-down上下边框模式
30
+ * showCounter 是否显示字数
31
+ * inputTextPosition 输入框文本位置 默认值:left 可选值:left居左 right居右 center居中
32
+ * 相关事件:focus、blur、confirm
33
+ */
34
+ const props = defineProps({
35
+ value: {
36
+ type: String,
37
+ default: '',
38
+ required: true
39
+ },
40
+ placeholder: {
41
+ type: String,
42
+ default: ''
43
+ },
44
+ maxlength: {
45
+ type: Number,
46
+ default: null
47
+ },
48
+ disabled: {
49
+ type: Boolean,
50
+ default: false
51
+ },
52
+ autoHeight: {
53
+ type: Boolean,
54
+ default: true
55
+ },
56
+ boderModel: {
57
+ type: String,
58
+ default: 'all'
59
+ },
60
+ showCounter: {
61
+ type: Boolean,
62
+ default: false
63
+ },
64
+ inputTextPosition:{
65
+ type:String,
66
+ default:"left"
67
+ }
68
+ });
69
+
70
+ const emit = defineEmits(['update:value', 'input', 'focus', 'blur', 'confirm']);
71
+
72
+ const config = inject<any>('config');
73
+ const inputValue = ref(props.value);
74
+ const focused = ref(false);
75
+ const currentLength = ref(props.value.length);
76
+
77
+ watch(
78
+ () => props.value,
79
+ (newVal) => {
80
+ inputValue.value = newVal;
81
+ currentLength.value = newVal.length;
82
+ }
83
+ );
84
+
85
+ const handleInput = (e: any) => {
86
+ const value = e.detail.value;
87
+ inputValue.value = value;
88
+ currentLength.value = value.length;
89
+ emit('update:value', value);
90
+ emit('input', value);
91
+ };
92
+
93
+ const handleFocus = (e: any) => {
94
+ focused.value = true;
95
+ emit('focus', e);
96
+ };
97
+
98
+ const handleBlur = (e: any) => {
99
+ focused.value = false;
100
+ emit('blur', e);
101
+ };
102
+
103
+ const handleConfirm = (e: any) => {
104
+ emit('confirm', e);
105
+ };
106
+ </script>
107
+
108
+ <style lang="scss" scoped>
109
+ .v-textarea-container {
110
+ position: relative;
111
+ }
112
+
113
+ .v-textarea {
114
+ width: 100%;
115
+ padding: 24rpx;
116
+ box-sizing: border-box;
117
+ background-color: #fff;
118
+ font-size: v-bind("config.fontSize.mediumText");
119
+ line-height: 1.5;
120
+ transition: border-color 0.3s;
121
+ resize: none;
122
+ text-align: v-bind("props.inputTextPosition");
123
+
124
+ &--border--all {
125
+ border-radius: 6rpx;
126
+ border: 1px solid v-bind("config.border.color");
127
+
128
+ &.v-textarea--focused {
129
+ border-color: v-bind("config.border.default");
130
+ box-shadow: v-bind("config.VInput.boxShadow");
131
+ }
132
+ }
133
+
134
+ &--border--none {
135
+ border: none;
136
+ }
137
+
138
+ &--border--bottom {
139
+ border-bottom: 1rpx solid v-bind("config.border.color");
140
+ }
141
+
142
+ &--border--top {
143
+ border-top: 1rpx solid v-bind("config.border.color");
144
+ }
145
+
146
+ &--border--left {
147
+ border-left: 1rpx solid v-bind("config.border.color");
148
+ }
149
+
150
+ &--border--right {
151
+ border-right: 1rpx solid v-bind("config.border.color");
152
+ }
153
+
154
+ &--border--ends {
155
+ border-left: 1rpx solid v-bind("config.border.color");
156
+ border-right: 1rpx solid v-bind("config.border.color");
157
+ }
158
+
159
+ &--border--up-down {
160
+ border-top: 1rpx solid v-bind("config.border.color");
161
+ border-bottom: 1rpx solid v-bind("config.border.color");
162
+ }
163
+
164
+ &--disabled{
165
+ opacity: v-bind('config.opacity.disabled');
166
+ background-color: v-bind('config.backgroundColor.disabled');
167
+ color: v-bind('config.fontColor.text');
168
+ }
169
+ }
170
+
171
+ .v-textarea-counter {
172
+ position: absolute;
173
+ bottom: 5rpx;
174
+ right: 5rpx;
175
+ font-size: v-bind("config.fontSize.mediumText");
176
+ color: #999;
177
+ }
178
+ </style>