@neatui/vue 2.17.1 → 2.17.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neatui/vue",
3
- "version": "2.17.1",
3
+ "version": "2.17.3",
4
4
  "description": "basic component ui",
5
5
  "main": "./src/index.ts",
6
6
  "license": "MIT",
@@ -3,24 +3,33 @@
3
3
  <slot>
4
4
  <button ui-btn="@a s case :border"><i class="icon icon-dropdown"></i></button>
5
5
  </slot>
6
- <Teleport to="#ifollow" v-if="$slots.tips">
7
- <div
8
- ref="tip"
9
- :class="tipClass"
10
- :style="`position: fixed; pointer-events: none; ${tipStyle}`"
11
- ui-tips="@a"
12
- :ui-tips-view="state.show ? 1 : 0"
13
- @mouseover="hovershow"
14
- @mouseout="hoverhide"
15
- @click="clickhide"
16
- >
17
- <div ref="box" :ui-tips-box="state.pos" :class="tipBoxClass" :style="tipBoxStyle" @mousedown="downdom">
18
- <slot name="tips"></slot>
19
- <div v-if="arrow" ui-tips-arrow="" v-bind="arrow"></div>
6
+ </div>
7
+ <Teleport v-if="$slots.tips" to="#ifollow">
8
+ <div
9
+ ref="tip"
10
+ :class="`${tipClass}${mobile ? ' fekit-follow-mobile' : ''}`"
11
+ :style="`position: fixed; pointer-events: none; ${tipStyle}`"
12
+ ui-tips="@a"
13
+ :ui-tips-view="state.show ? 1 : 0"
14
+ @mouseover="hovershow"
15
+ @mouseout="hoverhide"
16
+ @click="clickhide"
17
+ >
18
+ <div ref="box" :ui-tips-box="state.pos" :class="tipBoxClass" :style="tipBoxStyle">
19
+ <div ui-hide=">mob" class="mob-follow-tips w-full n-ss" ui-flex="row xm">
20
+ <div class="w-sm"></div>
21
+ <div>
22
+ <h5 class="bold">{{ title }}</h5>
23
+ </div>
24
+ <div class="w-sm" ui-flex="row rm">
25
+ <button ui-btn="@a none s :square" @click="toggle"><i class="icon icon-close"></i></button>
26
+ </div>
20
27
  </div>
28
+ <slot name="tips"></slot>
29
+ <div v-if="arrow" ui-tips-arrow="" v-bind="arrow"></div>
21
30
  </div>
22
- </Teleport>
23
- </div>
31
+ </div>
32
+ </Teleport>
24
33
  </template>
25
34
  <script setup lang="ts">
26
35
  import { reactive, ref, onMounted, onUnmounted, watch } from 'vue';
@@ -48,6 +57,8 @@
48
57
  tipBoxStyle?: string;
49
58
  arrow?: any;
50
59
  clickTipHide?: boolean;
60
+ mobile?: boolean;
61
+ title?: string;
51
62
  }
52
63
 
53
64
  // 入参
@@ -63,6 +74,8 @@
63
74
  tipBoxStyle: '',
64
75
  arrow: {},
65
76
  clickTipHide: false,
77
+ mobile: true,
78
+ title: '',
66
79
  });
67
80
 
68
81
  const dom: any = ref(null);
@@ -74,6 +87,7 @@
74
87
  pos: props.pos,
75
88
  hover: 0,
76
89
  tipdom: false,
90
+ isMobile: false,
77
91
  });
78
92
 
79
93
  const showTimer: any = ref(null);
@@ -148,42 +162,47 @@
148
162
  }
149
163
  };
150
164
 
151
- const downdom = (ev: any) => {
152
- // 不记得了这个当时为什么要加上这个,这个会影响单选框的选中后不自动关闭下拉框啊~
153
- // state.tipdom = true;
154
- // document.addEventListener(
155
- // 'mouseup',
156
- // () => {
157
- // setTimeout(() => {
158
- // state.tipdom = false;
159
- // }, 10);
160
- // },
161
- // true
162
- // );
165
+ // 阻止触摸事件冒泡和默认行为
166
+ const preventTouchScroll = (e: TouchEvent) => {
167
+ // 只有当触摸点在遮罩层本身时才阻止,不影响子元素
168
+ if (e.target === tip.value && tip.value?.classList.contains('fekit-follow-mobile')) {
169
+ e.preventDefault();
170
+ e.stopPropagation();
171
+ }
163
172
  };
164
173
 
165
174
  onMounted(() => {
166
175
  document.addEventListener('click', cancel, true);
176
+ // 添加触摸事件监听器以防止页面滚动
177
+ document.addEventListener('touchstart', preventTouchScroll, { passive: false });
178
+ document.addEventListener('touchmove', preventTouchScroll, { passive: false });
179
+ // 判断是否为移动端
180
+ state.isMobile = window.innerWidth < 800;
167
181
  });
168
182
 
169
183
  const ex: any = ref(null);
170
184
  watch([() => dom.value, () => tip.value], () => {
171
185
  if (dom.value && tip.value) {
172
- ex.value = new Follow(dom.value, tip.value, (status) => {
173
- if (!props?.pos?.includes(':fixed')) {
174
- if (status === 'b') {
175
- const _pos = props?.pos?.replace(/b/g, 't');
176
- if (_pos) {
177
- state.pos = _pos;
178
- }
179
- } else {
180
- const _pos = props?.pos?.replace(/t/g, 'b');
181
- if (_pos) {
182
- state.pos = _pos;
186
+ ex.value = new Follow(
187
+ dom.value,
188
+ tip.value,
189
+ (status) => {
190
+ if (!props?.pos?.includes(':fixed')) {
191
+ if (status === 'b') {
192
+ const _pos = props?.pos?.replace(/b/g, 't');
193
+ if (_pos) {
194
+ state.pos = _pos;
195
+ }
196
+ } else {
197
+ const _pos = props?.pos?.replace(/t/g, 'b');
198
+ if (_pos) {
199
+ state.pos = _pos;
200
+ }
183
201
  }
184
202
  }
185
- }
186
- });
203
+ },
204
+ { hideOnScrollOut: false },
205
+ );
187
206
  } else {
188
207
  ex.value = null;
189
208
  }
@@ -191,6 +210,9 @@
191
210
 
192
211
  onUnmounted(() => {
193
212
  document.removeEventListener('click', cancel, true);
213
+ // 移除触摸事件监听器
214
+ document.removeEventListener('touchstart', preventTouchScroll);
215
+ document.removeEventListener('touchmove', preventTouchScroll);
194
216
  state.show = 0;
195
217
 
196
218
  if (ex.value) {
@@ -218,3 +240,64 @@
218
240
  cancel,
219
241
  });
220
242
  </script>
243
+ <style lang="scss">
244
+ @use '@neatui/css' as neatui;
245
+ @include neatui.mob {
246
+ .fekit-follow-mobile {
247
+ position: fixed !important;
248
+ width: 100% !important;
249
+ height: 100% !important;
250
+
251
+ display: flex !important;
252
+ flex-direction: column !important;
253
+ justify-content: flex-end !important;
254
+ align-items: center !important;
255
+ align-content: center !important;
256
+ inset: 0 0 0 0 !important;
257
+
258
+ &[ui-tips-view='1'] {
259
+ background-color: rgba(0, 0, 0, 0.5);
260
+ pointer-events: auto !important;
261
+ touch-action: none !important;
262
+ }
263
+
264
+ &[ui-tips~='@a'] [ui-tips-box] {
265
+ position: relative !important;
266
+
267
+ width: 100% !important;
268
+ bottom: env(safe-area-inset-bottom) !important;
269
+ right: unset !important;
270
+ top: unset !important;
271
+ left: unset !important;
272
+ transform: translate3d(0, 0.5em, 0);
273
+
274
+ display: flex !important;
275
+ flex-direction: column !important;
276
+ justify-content: flex-end !important;
277
+ align-items: center !important;
278
+ align-content: center !important;
279
+
280
+ [ui-tips-arrow] {
281
+ display: none;
282
+ }
283
+ }
284
+ }
285
+
286
+ .mob-follow-tips {
287
+ position: relative;
288
+ padding-bottom: env(safe-area-inset-bottom, 16px);
289
+ &::before {
290
+ position: absolute;
291
+ content: '';
292
+ display: block;
293
+ width: 4rem;
294
+ height: 3px;
295
+ border-radius: 1em;
296
+ background-color: var(--co-text-o-ss);
297
+ top: 5px;
298
+ left: 50%;
299
+ transform: translateX(-50%);
300
+ }
301
+ }
302
+ }
303
+ </style>
@@ -1,64 +1,79 @@
1
1
  <template>
2
- <form class="m-sm-sub">
3
- <label v-for="(item, idx) in state.lists" :key="idx" :ui-form="`${theme} type:checkbox${item.disabled ? ' disabled' : ''}`">
4
- <input v-model="item.__checked" type="checkbox" :disabled="item.disabled" />
5
- <slot>
6
- <span>{{ item.label }}</span>
7
- </slot>
8
- </label>
9
- </form>
2
+ <CheckboxGroup v-if="isMultiple" v-bind="groupBindings" :modelValue="arrayValue" @update:modelValue="emitValue">
3
+ <template #default="slotProps">
4
+ <slot v-bind="slotProps" />
5
+ </template>
6
+ </CheckboxGroup>
7
+ <Checkbox v-else v-bind="singleBindings" :modelValue="modelValue" @update:modelValue="emitValue">
8
+ <template #default="slotProps">
9
+ <slot v-bind="slotProps" />
10
+ </template>
11
+ </Checkbox>
10
12
  </template>
13
+
11
14
  <script setup lang="ts">
12
- import { reactive, watch } from 'vue';
15
+ import { computed } from 'vue';
16
+ import Checkbox from './CheckboxItem.vue';
17
+ import CheckboxGroup from './CheckboxGroup.vue';
18
+
19
+ type ValueType = any | { label?: string; value: any };
13
20
 
14
- // 定义类型
15
- interface OptionsTypes {
21
+ interface OptionType {
16
22
  label: string;
17
- value: any;
23
+ value?: any;
18
24
  disabled?: boolean;
19
25
  }
26
+
20
27
  interface Props {
21
- modelValue: any[];
22
- options: OptionsTypes[];
28
+ modelValue?: any | any[];
29
+ label?: string;
30
+ disabled?: boolean;
23
31
  theme?: string;
32
+ attrs?: any;
33
+ checkedValue?: ValueType;
34
+ defaultValue?: ValueType;
35
+ options?: (OptionType | string)[] | [ValueType, ValueType];
36
+ required?: boolean;
24
37
  }
25
- // 外部入参
38
+
26
39
  const props = withDefaults(defineProps<Props>(), {
40
+ modelValue: () => false,
27
41
  theme: '@a',
28
- modelValue: () => [],
42
+ disabled: false,
43
+ label: '',
44
+ attrs: () => ({}),
45
+ checkedValue: () => true,
46
+ defaultValue: () => false,
47
+ required: false,
29
48
  options: () => [],
30
49
  });
31
50
 
32
- // 定义事件
33
- const emits = defineEmits(['update:modelValue']);
51
+ const emit = defineEmits<{
52
+ (e: 'update:modelValue', value: any | any[]): void;
53
+ }>();
34
54
 
35
- // 内部数据
36
- const state: any = reactive({
37
- lists: [],
38
- });
55
+ const isMultiple = computed(() => Array.isArray(props.modelValue));
56
+ const arrayValue = computed(() => (Array.isArray(props.modelValue) ? props.modelValue : []));
57
+
58
+ const singleOptions = computed(() => (Array.isArray(props.options) && props.options.length === 2 ? (props.options as [ValueType, ValueType]) : undefined));
59
+
60
+ const singleBindings = computed(() => ({
61
+ label: props.label,
62
+ disabled: props.disabled,
63
+ theme: props.theme,
64
+ attrs: props.attrs,
65
+ checkedValue: props.checkedValue,
66
+ defaultValue: props.defaultValue,
67
+ options: singleOptions.value,
68
+ required: props.required,
69
+ }));
70
+
71
+ const groupBindings = computed(() => ({
72
+ options: props.options as (OptionType | string)[],
73
+ disabled: props.disabled,
74
+ theme: props.theme,
75
+ attrs: props.attrs,
76
+ }));
39
77
 
40
- // 监听数据
41
- watch(
42
- [() => props.options, () => props.modelValue],
43
- ([options, value]) => {
44
- const lists = options?.map((item) => ({ ...item, __checked: value?.includes(item.value) }));
45
- // 只有在内容变化时才更新
46
- if (JSON.stringify(state.lists) !== JSON.stringify(lists)) {
47
- state.lists = lists;
48
- }
49
- },
50
- {
51
- immediate: true,
52
- },
53
- );
54
- watch(
55
- () => state.lists,
56
- (val) => {
57
- const value = val.filter((item: any) => item.__checked).map((item: any) => item.value);
58
- emits('update:modelValue', value);
59
- },
60
- {
61
- deep: true,
62
- },
63
- );
78
+ const emitValue = (value: any | any[]) => emit('update:modelValue', value);
64
79
  </script>
@@ -0,0 +1,74 @@
1
+ <template>
2
+ <form class="m-sm-sub">
3
+ <label v-for="(item, idx) in normalizedOptions" :key="idx" :ui-form="`${theme} type:checkbox${item.disabled ? ' disabled' : ''}`" v-bind="attrs">
4
+ <input type="checkbox" :checked="isChecked(item.value)" :disabled="item.disabled" @change="handleChange(item.value, $event)" />
5
+ <slot :item="item" :index="idx">
6
+ <span>{{ item.label }}</span>
7
+ </slot>
8
+ </label>
9
+ </form>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ import { computed } from 'vue';
14
+
15
+ interface OptionType {
16
+ label: string;
17
+ value?: any;
18
+ disabled?: boolean;
19
+ }
20
+
21
+ interface Props {
22
+ modelValue?: any[];
23
+ options?: (OptionType | string)[];
24
+ disabled?: boolean;
25
+ theme?: string;
26
+ attrs?: any;
27
+ }
28
+
29
+ const props = withDefaults(defineProps<Props>(), {
30
+ modelValue: () => [],
31
+ options: () => [],
32
+ disabled: false,
33
+ theme: '@a',
34
+ attrs: () => ({}),
35
+ });
36
+
37
+ const emits = defineEmits<{
38
+ (e: 'update:modelValue', value: any[]): void;
39
+ }>();
40
+
41
+ // 规范化 options
42
+ const normalizedOptions = computed(() => {
43
+ return props.options.map((item) =>
44
+ typeof item === 'string'
45
+ ? { label: item, value: item, disabled: props.disabled }
46
+ : {
47
+ label: item?.label ?? '',
48
+ value: 'value' in item ? item.value : item?.label,
49
+ disabled: item?.disabled ?? props.disabled,
50
+ },
51
+ );
52
+ });
53
+
54
+ // 判断某个值是否被选中
55
+ const isChecked = (value: any) => {
56
+ return props.modelValue.includes(value);
57
+ };
58
+
59
+ // 处理选中状态变化
60
+ const handleChange = (value: any, e: Event) => {
61
+ const checked = (e.target as HTMLInputElement).checked;
62
+ let newValue: any[];
63
+
64
+ if (checked) {
65
+ // 添加到选中列表
66
+ newValue = [...props.modelValue, value];
67
+ } else {
68
+ // 从选中列表移除
69
+ newValue = props.modelValue.filter((v) => v !== value);
70
+ }
71
+
72
+ emits('update:modelValue', newValue);
73
+ };
74
+ </script>
@@ -0,0 +1,87 @@
1
+ <template>
2
+ <label :ui-form="`${theme} type:checkbox${disabled ? ' disabled' : ''}`" v-bind="attrs">
3
+ <input type="checkbox" :checked="isChecked" :disabled="disabled" @change="handleChange" />
4
+ <slot :item="slotItem">
5
+ <span v-if="label">{{ label }}</span>
6
+ </slot>
7
+ </label>
8
+ </template>
9
+
10
+ <script setup lang="ts">
11
+ import { computed, onMounted } from 'vue';
12
+
13
+ type ValueType = any | { label?: string; value: any };
14
+
15
+ interface Props {
16
+ modelValue?: any;
17
+ label?: string;
18
+ disabled?: boolean;
19
+ theme?: string;
20
+ attrs?: any;
21
+ checkedValue?: ValueType;
22
+ defaultValue?: ValueType;
23
+ options?: [ValueType, ValueType]; // [checkedValue, defaultValue]
24
+ required?: boolean; // 是否必填,必填时自动初始化为 defaultValue
25
+ }
26
+
27
+ const props = withDefaults(defineProps<Props>(), {
28
+ modelValue: () => false,
29
+ theme: '@a',
30
+ disabled: false,
31
+ label: '',
32
+ attrs: () => ({}),
33
+ checkedValue: () => true,
34
+ defaultValue: () => false,
35
+ required: false,
36
+ });
37
+
38
+ const emits = defineEmits<{
39
+ (e: 'update:modelValue', value: any): void;
40
+ }>();
41
+
42
+ // 获取实际的值(支持对象和基本类型)
43
+ const getActualValue = (val: ValueType) => {
44
+ return val && typeof val === 'object' && 'value' in val ? val.value : val;
45
+ };
46
+
47
+ // 优先使用 options,否则使用 checkedValue/defaultValue
48
+ const actualCheckedValue = computed(() => {
49
+ const checkedVal = props.options ? props.options[0] : props.checkedValue;
50
+ return getActualValue(checkedVal);
51
+ });
52
+
53
+ const actualDefaultValue = computed(() => {
54
+ const defaultVal = props.options ? props.options[1] : props.defaultValue;
55
+ return getActualValue(defaultVal);
56
+ });
57
+
58
+ const slotItem = computed(() => {
59
+ if (props.options && props.options.length) {
60
+ const checkedVal = props.options[0];
61
+ const label = checkedVal && typeof checkedVal === 'object' && 'label' in checkedVal ? checkedVal.label : props.label;
62
+ return { label, value: getActualValue(checkedVal) };
63
+ }
64
+ return { label: props.label, value: actualCheckedValue.value };
65
+ });
66
+
67
+ // 判断是否选中
68
+ const isChecked = computed(() => {
69
+ return props.modelValue === actualCheckedValue.value;
70
+ });
71
+
72
+ const handleChange = (e: Event) => {
73
+ const checked = (e.target as HTMLInputElement).checked;
74
+ emits('update:modelValue', checked ? actualCheckedValue.value : actualDefaultValue.value);
75
+ };
76
+
77
+ // 如果是必填项,且值不是有效的 checkedValue 或 defaultValue,自动初始化为 defaultValue
78
+ onMounted(() => {
79
+ if (props.required) {
80
+ const currentVal = props.modelValue;
81
+ const isValidValue = currentVal === actualCheckedValue.value || currentVal === actualDefaultValue.value;
82
+ if (!isValidValue) {
83
+ emits('update:modelValue', actualDefaultValue.value);
84
+ }
85
+ }
86
+ });
87
+ </script>
@@ -30,11 +30,7 @@
30
30
  <div v-if="state.type === 2" class="full">
31
31
  <ul ui-grid="mob:4" class="n-ms ny-sm-sub">
32
32
  <li v-for="(year, idx) in panel.years" :key="idx" ui-flex="col cm" @click="setDateValue('y', year)">
33
- <div
34
- ui-flex="col cm"
35
- class="w-ss h-xs ac ux-none r-sm"
36
- :class="isSelectedYear(year) ? 'active bg-main-o-lm co-w' : 'co-main:hover'"
37
- >
33
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedYear(year) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">
38
34
  {{ year }}
39
35
  </div>
40
36
  </li>
@@ -42,18 +38,42 @@
42
38
  </div>
43
39
  <div v-else-if="state.type === 1" class="full">
44
40
  <ul ui-grid="mob:4" class="n-ms ny-sm-sub">
45
- <li ui-flex="col cm" @click="setDateValue('m', 1)"><div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(1) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">1月</div></li>
46
- <li ui-flex="col cm" @click="setDateValue('m', 2)"><div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(2) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">2月</div></li>
47
- <li ui-flex="col cm" @click="setDateValue('m', 3)"><div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(3) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">3月</div></li>
48
- <li ui-flex="col cm" @click="setDateValue('m', 4)"><div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(4) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">4月</div></li>
49
- <li ui-flex="col cm" @click="setDateValue('m', 5)"><div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(5) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">5月</div></li>
50
- <li ui-flex="col cm" @click="setDateValue('m', 6)"><div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(6) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">6月</div></li>
51
- <li ui-flex="col cm" @click="setDateValue('m', 7)"><div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(7) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">7月</div></li>
52
- <li ui-flex="col cm" @click="setDateValue('m', 8)"><div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(8) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">8月</div></li>
53
- <li ui-flex="col cm" @click="setDateValue('m', 9)"><div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(9) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">9月</div></li>
54
- <li ui-flex="col cm" @click="setDateValue('m', 10)"><div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(10) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">10月</div></li>
55
- <li ui-flex="col cm" @click="setDateValue('m', 11)"><div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(11) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">11月</div></li>
56
- <li ui-flex="col cm" @click="setDateValue('m', 12)"><div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(12) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">12月</div></li>
41
+ <li ui-flex="col cm" @click="setDateValue('m', 1)">
42
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(1) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">1月</div>
43
+ </li>
44
+ <li ui-flex="col cm" @click="setDateValue('m', 2)">
45
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(2) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">2月</div>
46
+ </li>
47
+ <li ui-flex="col cm" @click="setDateValue('m', 3)">
48
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(3) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">3月</div>
49
+ </li>
50
+ <li ui-flex="col cm" @click="setDateValue('m', 4)">
51
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(4) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">4月</div>
52
+ </li>
53
+ <li ui-flex="col cm" @click="setDateValue('m', 5)">
54
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(5) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">5月</div>
55
+ </li>
56
+ <li ui-flex="col cm" @click="setDateValue('m', 6)">
57
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(6) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">6月</div>
58
+ </li>
59
+ <li ui-flex="col cm" @click="setDateValue('m', 7)">
60
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(7) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">7月</div>
61
+ </li>
62
+ <li ui-flex="col cm" @click="setDateValue('m', 8)">
63
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(8) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">8月</div>
64
+ </li>
65
+ <li ui-flex="col cm" @click="setDateValue('m', 9)">
66
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(9) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">9月</div>
67
+ </li>
68
+ <li ui-flex="col cm" @click="setDateValue('m', 10)">
69
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(10) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">10月</div>
70
+ </li>
71
+ <li ui-flex="col cm" @click="setDateValue('m', 11)">
72
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(11) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">11月</div>
73
+ </li>
74
+ <li ui-flex="col cm" @click="setDateValue('m', 12)">
75
+ <div ui-flex="col cm" class="w-ss h-xs ac ux-none r-sm" :class="isSelectedMonth(12) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">12月</div>
76
+ </li>
57
77
  </ul>
58
78
  </div>
59
79
  <div v-else class="full">
@@ -161,8 +181,7 @@
161
181
  </template>
162
182
  <script setup lang="ts">
163
183
  import { computed, ref, reactive, watch, onMounted } from 'vue';
164
- import { isDateString, isObject, isString } from '@fekit/utils';
165
- import { idate } from './date';
184
+ import { idate, isDateString, isObject, isString } from '@fekit/utils';
166
185
  import { Icon } from '../basic';
167
186
 
168
187
  const normalizeDateInput = (value: any) => {