@ecolovo/uniapp-components 1.0.10 → 2.0.1

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 (130) hide show
  1. package/README.md +202 -66
  2. package/components/aspect/aspect.vue +24 -15
  3. package/components/badge/badge.scss +20 -0
  4. package/components/badge/badge.vue +49 -40
  5. package/components/button/button.scss +15 -0
  6. package/components/button/button.vue +121 -177
  7. package/components/checkbox/checkbox.scss +10 -0
  8. package/components/checkbox/checkbox.vue +118 -146
  9. package/components/checkbox-group/checkbox-group.vue +79 -85
  10. package/components/checkbox-group2/checkbox-group2.vue +111 -107
  11. package/components/checkbox-group2/checkbox2.vue +104 -0
  12. package/components/data-list/data-list.scss +9 -0
  13. package/components/data-list/data-list.vue +70 -79
  14. package/components/date-picker/date-picker-view.vue +125 -124
  15. package/components/date-picker/date-picker.vue +145 -146
  16. package/components/dialog/dialog-content.vue +39 -47
  17. package/components/dialog/dialog.scss +11 -0
  18. package/components/dialog/dialog.vue +125 -138
  19. package/components/dropdown/dropdown.scss +11 -0
  20. package/components/dropdown/dropdown.vue +55 -97
  21. package/components/empty/empty.scss +14 -0
  22. package/components/empty/empty.vue +42 -41
  23. package/components/flex/flex.vue +45 -54
  24. package/components/form/form.vue +29 -24
  25. package/components/form-item/form-item.scss +11 -0
  26. package/components/form-item/form-item.vue +43 -40
  27. package/components/icon/icon.vue +70 -85
  28. package/components/image/image.vue +35 -38
  29. package/components/input/input.vue +65 -79
  30. package/components/input/password-input.vue +34 -42
  31. package/components/list-page/list-page.vue +73 -99
  32. package/components/load-more/load-more.scss +12 -0
  33. package/components/load-more/load-more.vue +29 -29
  34. package/components/loading/animations/loading-animation1.vue +8 -8
  35. package/components/loading/animations/loading-animation2.vue +8 -9
  36. package/components/loading/animations/loading-animation3.vue +11 -11
  37. package/components/loading/animations/loading-animation4.vue +8 -8
  38. package/components/loading/loading.vue +19 -20
  39. package/components/message-box/message-box.vue +59 -41
  40. package/components/number-dialog/number-dialog.scss +9 -0
  41. package/components/number-dialog/number-dialog.vue +209 -204
  42. package/components/number-input/number-input.scss +9 -0
  43. package/components/number-input/number-input.vue +233 -232
  44. package/components/numpad/numpad.scss +9 -0
  45. package/components/numpad/numpad.vue +133 -150
  46. package/components/page/page-body.scss +15 -0
  47. package/components/page/page-body.vue +137 -119
  48. package/components/page/page-footer.scss +13 -0
  49. package/components/page/page-footer.vue +31 -33
  50. package/components/page/page-header.scss +17 -0
  51. package/components/page/page-header.vue +89 -94
  52. package/components/page/page.scss +9 -0
  53. package/components/page/page.vue +105 -81
  54. package/components/picker/picker-popup.vue +218 -209
  55. package/components/picker/picker.vue +99 -104
  56. package/components/popover/popover-content.vue +54 -63
  57. package/components/popover/popover-mask.vue +63 -63
  58. package/components/popover/popover.scss +28 -0
  59. package/components/popover/popover.vue +49 -47
  60. package/components/popup/popup-content.vue +49 -53
  61. package/components/popup/popup.scss +11 -0
  62. package/components/popup/popup.vue +117 -132
  63. package/components/price/price.scss +20 -0
  64. package/components/price/price.vue +31 -42
  65. package/components/search/search.scss +12 -0
  66. package/components/search/search.vue +93 -117
  67. package/components/searching/searching.vue +33 -40
  68. package/components/selector/selector.vue +43 -48
  69. package/components/switch/switch.scss +12 -0
  70. package/components/switch/switch.vue +99 -96
  71. package/components/tab/tab.scss +19 -0
  72. package/components/tab/tab.vue +151 -145
  73. package/components/textarea/textarea.vue +104 -101
  74. package/composable/component-name.d.ts +2 -0
  75. package/composable/component-name.js +8 -0
  76. package/composable/component-name.ts +10 -0
  77. package/configs/index.d.ts +25 -10
  78. package/configs/index.js +14 -23
  79. package/configs/index.ts +82 -0
  80. package/easyCom.d.ts +9 -0
  81. package/easyCom.js +1 -2
  82. package/easyCom.ts +31 -0
  83. package/index.d.ts +1 -0
  84. package/index.js +1 -0
  85. package/index.ts +1 -0
  86. package/init.d.ts +4 -7
  87. package/init.js +5 -4
  88. package/init.ts +34 -0
  89. package/package.json +14 -4
  90. package/styles/utils/css-var.scss +12 -15
  91. package/styles/utils/ellipsis.scss +0 -7
  92. package/styles/utils/z-index.scss +1 -1
  93. package/styles/var/component.scss +21 -245
  94. package/utils/date.d.ts +47 -0
  95. package/utils/date.js +23 -43
  96. package/utils/date.ts +153 -0
  97. package/utils/freezeDeep.d.ts +1 -0
  98. package/utils/freezeDeep.js +4 -14
  99. package/utils/freezeDeep.ts +9 -0
  100. package/utils/price.d.ts +24 -0
  101. package/utils/price.js +14 -8
  102. package/utils/price.ts +57 -0
  103. package/utils/round.d.ts +2 -0
  104. package/utils/round.js +2 -14
  105. package/utils/round.ts +11 -0
  106. package/utils/windowInfo.d.ts +24 -0
  107. package/utils/windowInfo.js +8 -36
  108. package/utils/windowInfo.ts +50 -0
  109. package/components/checkbox-group2/checkbox.vue +0 -109
  110. package/components/datetime-picker/datetime-picker-view.vue +0 -209
  111. package/components/datetime-picker/datetime-picker.vue +0 -235
  112. package/components/form/mixin.js +0 -13
  113. package/components/list-page/list-page.js +0 -10
  114. package/components/table/table.vue +0 -112
  115. package/components/time-picker/time-picker-view.vue +0 -127
  116. package/components/time-picker/time-picker.vue +0 -140
  117. package/components/uploader/download.js +0 -81
  118. package/components/uploader/file-uploader.vue +0 -52
  119. package/components/uploader/files.js +0 -225
  120. package/components/uploader/media-uploader.vue +0 -189
  121. package/components/uploader/mixin.js +0 -171
  122. package/components/uploader/uni.js +0 -38
  123. package/components/uploader/upload-button.vue +0 -29
  124. package/components/uploader/uploader copy.vue +0 -547
  125. package/components/uploader/uploader.vue +0 -117
  126. package/mixins/componentName.js +0 -32
  127. package/mixins/listPage.js +0 -1
  128. package/mixins/windowInfo.js +0 -1
  129. package/utils/fileSize.js +0 -39
  130. package/utils/floor.js +0 -20
@@ -1,12 +1,12 @@
1
1
  <template>
2
- <view :class="componentClassNames">
2
+ <view :class="classNames">
3
3
  <popover-mask-cpn
4
- ref="mask"
5
- :value="value"
4
+ ref="maskRef"
5
+ :model-value="modelValue"
6
6
  :modal="modal || isLoading"
7
- @input="$emit('input', $event)"
8
- @close="$emit('close')"
9
- @closed="$emit('closed')"
7
+ @update:model-value="emit('update:modelValue', $event)"
8
+ @close="emit('close')"
9
+ @closed="emit('closed')"
10
10
  >
11
11
  <slot name="content">
12
12
  <popup-content-cpn
@@ -27,142 +27,127 @@
27
27
  </view>
28
28
  </template>
29
29
 
30
- <script>
31
- import componentName from '../../mixins/componentName';
30
+ <script lang="ts" setup>
31
+ import { ref, computed } from 'vue';
32
+ import useClassNames from '../../composable/component-name';
32
33
  import PopoverMaskCpn from '../popover/popover-mask.vue';
33
34
  import PopupContentCpn from './popup-content.vue';
34
35
 
35
- export default {
36
- name: 'Popup',
36
+ defineOptions({
37
37
  options: {
38
38
  virtualHost: true,
39
39
  styleIsolation: 'shared',
40
40
  },
41
- components: { PopoverMaskCpn, PopupContentCpn },
42
- mixins: [componentName],
43
- props: {
44
- /** v-model 绑定值,控制对话框是否可见 */
45
- value: {
46
- type: Boolean,
47
- default: false,
48
- },
49
- /** 是否模态框 */
50
- modal: {
51
- type: Boolean,
52
- default: false,
53
- },
54
- /** 是否显示 loading 动画 */
55
- loading: {
56
- type: Boolean,
57
- default: false,
58
- },
59
- /** 标题 */
60
- title: {
61
- type: String,
62
- default: '',
63
- },
64
- /** 是否居中标题 */
65
- centerTitle: {
66
- type: Boolean,
67
- default: false,
68
- },
69
- /** 是否显示关闭按钮 */
70
- showClose: {
71
- type: Boolean,
72
- default: true,
73
- },
74
- /** 取消按钮文本,为 falsy 时( false 或 '' )不显示 */
75
- cancel: {
76
- type: [String, Boolean],
77
- default: '取消',
78
- },
79
- /** 点击确认按钮时是否自动关闭对话框 */
80
- closeOnCancel: {
81
- type: Boolean,
82
- default: true,
83
- },
84
- /** 确认按钮文本,为 falsy 时( false 或 '' )不显示 */
85
- confirm: {
86
- type: [String, Boolean],
87
- default: '确认',
88
- },
89
- /** 点击确认按钮时是否自动关闭对话框 */
90
- closeOnConfirm: {
91
- type: Boolean,
92
- default: true,
93
- },
94
- /** 是否异步关闭,使用内部 loading 属性,需手动调用 close 方法关闭 */
95
- async: {
96
- type: Boolean,
97
- default: false,
98
- },
99
- },
100
- data() {
101
- return {
102
- isAsyncLoading: false,
103
- };
104
- },
105
- computed: {
106
- /** 按钮 loading */
107
- isLoading() {
108
- return this.loading || this.isAsyncLoading;
109
- },
110
- },
111
- methods: {
112
- close() {
113
- this.$refs.mask.close();
114
- },
115
- /** 隐藏 */
116
- onClose() {
117
- if (this.isLoading) return;
118
-
119
- this.close();
120
- },
121
- /** 点击取消或确认按钮
122
- * @param {'cancel' | 'confirm'} btnType 按钮类型
123
- * @param {boolean} shouldClose 是否自动关闭对话框
124
- */
125
- onButton(btnType, shouldClose) {
126
- if (this.isLoading) return;
127
-
128
- if (btnType === 'confirm' && this.async) {
129
- this.isAsyncLoading = true;
130
- const { promise, resolve, reject } = Promise.withResolvers();
131
- promise
132
- .then((willClose = true) => {
133
- if (willClose === false) {
134
- this.isAsyncLoading = false;
135
- return;
136
- }
137
- this.close();
138
- })
139
- .catch((err) => {
140
- if (process.env.NODE_ENV === 'development') {
141
- // eslint-disable-next-line no-console
142
- console.warn(`${this.componentClass} unresolved error:`, err);
143
- }
144
- this.isAsyncLoading = false;
145
- });
146
- this.$emit(btnType, { resolve, reject });
147
- return;
148
- }
149
-
150
- if (shouldClose) {
151
- this.$emit(btnType);
152
- this.close();
153
- return;
154
- }
155
-
156
- this.$emit(btnType, this.$refs.mask.close.bind(this.$refs.mask));
157
- },
158
- },
41
+ });
42
+
43
+ const classNames = useClassNames('popup');
44
+
45
+ type _Props = {
46
+ /** v-model 绑定值,控制弹出框是否可见 */
47
+ modelValue?: boolean;
48
+ /** 是否模态框 */
49
+ modal?: boolean;
50
+ /** 是否显示 loading 动画 */
51
+ loading?: boolean;
52
+ /** 标题 */
53
+ title?: string;
54
+ /** 是否居中标题 */
55
+ centerTitle?: boolean;
56
+ /** 是否显示关闭按钮 */
57
+ showClose?: boolean;
58
+ /** 取消按钮文本,为 falsy 时( false 或 '' )不显示 */
59
+ cancel?: string | boolean;
60
+ /** 点击取消按钮时是否自动关闭对话框 */
61
+ closeOnCancel?: boolean;
62
+ /** 确认按钮文本,为 falsy 时( false 或 '' )不显示 */
63
+ confirm?: string | boolean;
64
+ /** 点击确认按钮时是否自动关闭对话框 */
65
+ closeOnConfirm?: boolean;
66
+ /** 是否异步关闭,使用内部 loading 属性,需手动调用 close 方法关闭 */
67
+ async?: boolean;
159
68
  };
69
+
70
+ const props = withDefaults(defineProps<_Props>(), {
71
+ modelValue: false,
72
+ modal: false,
73
+ loading: false,
74
+ title: '',
75
+ centerTitle: false,
76
+ showClose: true,
77
+ cancel: '取消',
78
+ closeOnCancel: true,
79
+ confirm: '确认',
80
+ closeOnConfirm: true,
81
+ async: false,
82
+ });
83
+
84
+ const emit = defineEmits<{
85
+ (e: 'update:modelValue', val: boolean): void;
86
+ (e: 'close'): void;
87
+ (e: 'closed'): void;
88
+ (e: 'cancel', closeFn?: VoidFunction): void;
89
+ (e: 'confirm', payload?: Omit<PromiseWithResolvers<unknown>, 'promise'> | VoidFunction): void;
90
+ }>();
91
+
92
+ const isAsyncLoading = ref(false);
93
+ const maskRef = ref<InstanceType<typeof PopoverMaskCpn>>();
94
+
95
+ /** 按钮 loading */
96
+ const isLoading = computed(() => props.loading || isAsyncLoading.value);
97
+
98
+ const close = () => {
99
+ maskRef.value?.close();
100
+ };
101
+
102
+ /** 隐藏 */
103
+ const onClose = () => {
104
+ if (isLoading.value) return;
105
+ close();
106
+ };
107
+
108
+ /** 点击取消或确认按钮
109
+ * @param {'cancel' | 'confirm'} btnType 按钮类型
110
+ * @param {boolean} shouldClose 是否自动关闭对话框
111
+ */
112
+ const onButton = (btnType: 'cancel' | 'confirm', shouldClose: boolean) => {
113
+ if (isLoading.value) return;
114
+
115
+ if (btnType === 'confirm' && props.async) {
116
+ isAsyncLoading.value = true;
117
+ const { promise, resolve, reject } = Promise.withResolvers();
118
+ promise
119
+ .then((willClose = true) => {
120
+ if (willClose === false) {
121
+ isAsyncLoading.value = false;
122
+ return;
123
+ }
124
+ close();
125
+ })
126
+ .catch((err) => {
127
+ if (import.meta.env.DEV) {
128
+ // eslint-disable-next-line no-console
129
+ console.warn(`${classNames[0]} unresolved error:`, err);
130
+ }
131
+ isAsyncLoading.value = false;
132
+ });
133
+ emit(btnType, { resolve, reject });
134
+ return;
135
+ }
136
+
137
+ if (shouldClose) {
138
+ // @ts-expect-error 这里语法是正确的
139
+ emit(btnType);
140
+ close();
141
+ return;
142
+ }
143
+
144
+ // @ts-expect-error 这里语法是正确的
145
+ emit(btnType, maskRef.value?.close.bind(maskRef.value));
146
+ };
147
+
148
+ defineExpose({ close });
160
149
  </script>
161
150
 
162
151
  <style lang="scss" module>
163
152
  @use '../../styles/index' as *;
164
-
165
- :host {
166
- display: block;
167
- }
168
153
  </style>
@@ -0,0 +1,20 @@
1
+ @use 'sass:map';
2
+ @use '../../styles/utils' as *;
3
+
4
+ // 可配置的变量
5
+ $price: () !default;
6
+ $price-default: (
7
+ color: inherit,
8
+ font-size: inherit,
9
+ font-weight: inherit,
10
+ integer-color: UTILS__LOCAL_VAR(color),
11
+ integer-font-size: UTILS__LOCAL_VAR(font-size),
12
+ integer-font-weight: UTILS__LOCAL_VAR(font-weight),
13
+ decimal-color: UTILS__LOCAL_VAR(color),
14
+ decimal-font-size: UTILS__LOCAL_VAR(font-size),
15
+ decimal-font-weight: UTILS__LOCAL_VAR(font-weight),
16
+ unit-color: UTILS__LOCAL_VAR(color),
17
+ unit-font-size: UTILS__LOCAL_VAR(font-size),
18
+ unit-font-weight: UTILS__LOCAL_VAR(font-weight),
19
+ );
20
+ $price: map.merge($price-default, $price);
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <text :class="componentClassNames">
2
+ <text :class="[...classNames, $style['Price']]">
3
3
  <text v-if="prefixUnit" :class="$style['Price--unit']">
4
4
  <!-- 默认插槽用于放置单位 -->
5
5
  <slot>
@@ -20,60 +20,49 @@
20
20
  </text>
21
21
  </template>
22
22
 
23
- <script>
24
- import componentName from '../../mixins/componentName';
23
+ <script lang="ts" setup>
24
+ import { computed } from 'vue';
25
+ import useClassNames from '../../composable/component-name';
25
26
  import { formatPrice } from '../../utils/price';
26
27
 
27
- export default {
28
- name: 'Price',
28
+ defineOptions({
29
29
  options: {
30
30
  virtualHost: true,
31
31
  styleIsolation: 'shared',
32
32
  },
33
- mixins: [componentName],
34
- props: {
35
- /** 价格 */
36
- value: {
37
- type: [Number, String],
38
- default: 0,
39
- },
40
- /** 前置单位 */
41
- prefixUnit: {
42
- type: Boolean,
43
- default: false,
44
- },
45
- /** 是否一直显示符号 */
46
- showSymbol: {
47
- type: Boolean,
48
- default: false,
49
- },
50
- /** 是否始终显示小数 */
51
- alwaysShowDecimal: {
52
- type: Boolean,
53
- default: true,
54
- },
55
- },
56
- computed: {
57
- /** 格式化后的价格 */
58
- formattedPrice() {
59
- return formatPrice(this.value);
60
- },
61
- },
33
+ });
34
+
35
+ const classNames = useClassNames('price');
36
+
37
+ type _Props = {
38
+ /** 价格 */
39
+ value?: number | string;
40
+ /** 前置单位 */
41
+ prefixUnit?: boolean;
42
+ /** 是否一直显示符号 */
43
+ showSymbol?: boolean;
44
+ /** 是否始终显示小数 */
45
+ alwaysShowDecimal?: boolean;
62
46
  };
47
+
48
+ const props = withDefaults(defineProps<_Props>(), {
49
+ value: 0,
50
+ prefixUnit: false,
51
+ showSymbol: false,
52
+ alwaysShowDecimal: true,
53
+ });
54
+
55
+ /** 格式化后的价格 */
56
+ const formattedPrice = computed(() => formatPrice(props.value));
63
57
  </script>
64
58
 
65
59
  <style lang="scss" module>
66
- @use '../../styles/index' as *;
60
+ @use '../../styles/utils' as *;
61
+ @use './price' as *;
67
62
 
68
63
  // 定义外部变量
69
- $component-name: 'price';
70
- $component-vars: $price;
71
64
  %external-vars {
72
- @include UTILS__DEFINE_COMPONENT_VARS();
73
- }
74
-
75
- :host {
76
- display: inline;
65
+ @include UTILS__DEFINE_COMPONENT_VARS($price, 'price');
77
66
  }
78
67
 
79
68
  .Price {
@@ -0,0 +1,12 @@
1
+ @use 'sass:map';
2
+ @use '../../styles/utils' as *;
3
+
4
+ // 可配置的变量
5
+ $search: () !default;
6
+ $search-default: (
7
+ background: UTILS__GLOBAL_VAR(color, background),
8
+ border-radius: 8rpx,
9
+ height: 64rpx,
10
+ padding: 0 20rpx,
11
+ );
12
+ $search: map.merge($search-default, $search);
@@ -1,12 +1,13 @@
1
1
  <template>
2
- <view :class="componentClassNames">
2
+ <view :class="[...classNames, $style['Search']]">
3
3
  <view :class="$style['Search--wrapper']">
4
4
  <icon-cpn icon="search" :class="[$style['Search--icon'], $style['Search--prefix-icon']]"> </icon-cpn>
5
5
  <view
6
6
  v-if="readonly"
7
7
  :class="[
8
8
  $style['Search--text'],
9
- { [$style['Search--ellipsis']]: ellipsis, [$style['Search--placeholder']]: !searchValue },
9
+ $style['Search--ellipsis'],
10
+ { [$style['Search--placeholder']]: !searchValue },
10
11
  ]"
11
12
  >
12
13
  {{ searchValue || placeholder }}
@@ -26,7 +27,7 @@
26
27
  v-if="clearable && searchValue"
27
28
  icon="close-circle-filled"
28
29
  :class="[$style['Search--icon'], $style['Search--close-icon']]"
29
- @click.native="onClear"
30
+ @click="onClear"
30
31
  >
31
32
  </icon-cpn>
32
33
  </view>
@@ -42,126 +43,110 @@
42
43
  </view>
43
44
  </template>
44
45
 
45
- <script>
46
- import debounce from 'lodash-es/debounce';
47
- import componentName from '../../mixins/componentName';
46
+ <script lang="ts" setup>
47
+ import { computed, ref } from 'vue';
48
+ import debounceFn from 'lodash-es/debounce';
49
+ import useClassNames from '../../composable/component-name';
48
50
  import ButtonCpn from '../button/button.vue';
49
51
  import IconCpn from '../icon/icon.vue';
50
52
 
51
- export default {
52
- name: 'Search',
53
+ defineOptions({
53
54
  options: {
54
55
  virtualHost: true,
55
56
  styleIsolation: 'shared',
56
57
  },
57
- components: { ButtonCpn, IconCpn },
58
- mixins: [componentName],
59
- props: {
60
- /** 搜索文本 */
61
- value: {
62
- type: [String, null],
63
- default: '',
64
- },
65
- /** 最大输入文本长度 */
66
- maxlength: {
67
- type: Number,
68
- default: 140,
69
- },
70
- /** 占位文本 */
71
- placeholder: {
72
- type: String,
73
- default: '请输入搜索内容',
74
- },
75
- /** 防抖时长 */
76
- debounce: {
77
- type: Number,
78
- default: 300,
79
- },
80
- /** 是否有清空按钮 */
81
- clearable: {
82
- type: Boolean,
83
- default: true,
84
- },
85
- /** 是否只读 */
86
- readonly: {
87
- type: Boolean,
88
- default: false,
89
- },
90
- /** 是否显示搜索按钮 */
91
- cancelButton: {
92
- type: Boolean,
93
- default: false,
94
- },
95
- /** 当前状态是否可以搜索,仅 `cancelButton` 为 `true` 时有效 */
96
- searchable: {
97
- type: Boolean,
98
- default: true,
99
- },
100
- },
101
- data() {
102
- return {
103
- /** 内部搜索值 */
104
- innerSearchValue: '',
105
- };
106
- },
107
- computed: {
108
- /** 当前搜索值 */
109
- searchValue: {
110
- get: function () {
111
- return this.value === null ? this.innerSearchValue : this.value;
112
- },
113
- set: function (value) {
114
- this.$emit('input', value);
115
- this.innerSearchValue = value;
116
- this.$emit('change', this.innerSearchValue);
117
- },
118
- },
119
- },
120
- created() {
121
- this.debouncedInput = debounce((value) => {
122
- this.$emit('input-search', value);
123
- }, this.debounce);
124
- },
125
- methods: {
126
- /** 输入响应 */
127
- onInput(event) {
128
- this.searchValue = event.detail.value;
129
- this.debouncedInput(event.detail.value);
130
- },
131
- /** 点击键盘搜索按钮响应 */
132
- onConfirm() {
133
- this.$emit('search', this.searchValue);
134
- },
135
- /** 点击清除按钮响应 */
136
- onClear() {
137
- this.searchValue = '';
138
- this.$emit('clear', '');
139
- },
140
- /** 点击取消按钮响应 */
141
- onCancel() {
142
- this.searchValue = '';
143
- this.searchValue = '';
144
- this.$emit('cancel', '');
145
- },
58
+ });
59
+
60
+ const classNames = useClassNames('search');
61
+
62
+ type _Props = {
63
+ /** 搜索文本 */
64
+ modelValue?: string;
65
+ /** 最大输入文本长度 */
66
+ maxlength?: number;
67
+ /** 占位文本 */
68
+ placeholder?: string;
69
+ /** 防抖时长 */
70
+ debounce?: number;
71
+ /** 是否有清空按钮 */
72
+ clearable?: boolean;
73
+ /** 是否只读 */
74
+ disabled?: boolean;
75
+ /** 是否只读 */
76
+ readonly?: boolean;
77
+ /** 是否显示搜索按钮 */
78
+ cancelButton?: boolean;
79
+ };
80
+
81
+ const props = withDefaults(defineProps<_Props>(), {
82
+ modelValue: '',
83
+ maxlength: 140,
84
+ placeholder: '请输入搜索内容',
85
+ debounce: 300,
86
+ clearable: true,
87
+ disabled: false,
88
+ readonly: false,
89
+ cancelButton: false,
90
+ });
91
+
92
+ const emit = defineEmits<{
93
+ (e: 'update:modelValue', val: string): void;
94
+ (e: 'change', val: string): void;
95
+ (e: 'input-search', val: string): void;
96
+ (e: 'search', val: string): void;
97
+ (e: 'clear', val: string): void;
98
+ (e: 'cancel', val: string): void;
99
+ }>();
100
+
101
+ /** 内部搜索值 */
102
+ const innerSearchValue = ref('');
103
+
104
+ /** 当前搜索值 */
105
+ const searchValue = computed({
106
+ get: () => (props.modelValue === undefined ? innerSearchValue.value : props.modelValue),
107
+ set: (value) => {
108
+ emit('update:modelValue', value);
109
+ innerSearchValue.value = value;
110
+ emit('change', innerSearchValue.value);
146
111
  },
112
+ });
113
+
114
+ const debouncedInput = debounceFn((value: string) => {
115
+ emit('input-search', value);
116
+ }, props.debounce);
117
+
118
+ /** 输入响应 */
119
+ const onInput = (event: Event) => {
120
+ const value = (event as CustomEvent).detail.value;
121
+ searchValue.value = value;
122
+ debouncedInput(value);
123
+ };
124
+
125
+ /** 点击键盘搜索按钮响应 */
126
+ const onConfirm = () => {
127
+ emit('search', searchValue.value);
128
+ };
129
+
130
+ /** 点击清除按钮响应 */
131
+ const onClear = () => {
132
+ searchValue.value = '';
133
+ emit('clear', '');
134
+ };
135
+
136
+ /** 点击取消按钮响应 */
137
+ const onCancel = () => {
138
+ searchValue.value = '';
139
+ emit('cancel', '');
147
140
  };
148
141
  </script>
149
142
 
150
143
  <style lang="scss" module>
151
- @use '../../styles/index' as *;
144
+ @use '../../styles/utils' as *;
145
+ @use './search' as *;
152
146
 
153
147
  // 定义外部变量
154
- $component-name: 'search';
155
- $component-vars: $search;
156
148
  %external-vars {
157
- @include UTILS__DEFINE_COMPONENT_VARS();
158
- }
159
-
160
- :host {
161
- display: block;
162
- }
163
- :host(.display-inline) {
164
- display: inline;
149
+ @include UTILS__DEFINE_COMPONENT_VARS($search, 'search');
165
150
  }
166
151
 
167
152
  .Search {
@@ -200,15 +185,6 @@ $component-vars: $search;
200
185
  position: relative;
201
186
  font-size: UTILS__GLOBAL_VAR(font-size, large);
202
187
  color: UTILS__GLOBAL_VAR(color, placeholder);
203
- // &::after {
204
- // content: '';
205
- // position: absolute;
206
- // @include absolute-center(UTILS__LOCAL_VAR(height));
207
- // }
208
- }
209
- .Search--divider {
210
- height: 1em;
211
- border-right: 2rpx solid #ccc;
212
188
  }
213
189
  .Search--cancel-button {
214
190
  flex: none;