@neatui/vue 2.15.2 → 2.15.5

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.15.2",
3
+ "version": "2.15.5",
4
4
  "description": "basic component ui",
5
5
  "main": "./src/index.ts",
6
6
  "license": "MIT",
@@ -28,6 +28,7 @@
28
28
  "@fekit/scrollto": "^3.0.3",
29
29
  "@fekit/toast": "^2.7.2",
30
30
  "@fekit/utils": "^4.3.1",
31
+ "@neatui/css": "^3.10.3",
31
32
  "@rollup/plugin-commonjs": "^26.0.1",
32
33
  "@rollup/plugin-node-resolve": "^15.2.3",
33
34
  "@vue/compiler-sfc": "^3.4.30",
@@ -3,7 +3,7 @@
3
3
  <div class="mt-mm" ui-note="@b risk">抠图和压缩处理需要较长时间,期间请耐心等待不要关闭本窗口或进行操作,本功能需要付费,请尽量珍惜每一次处理避免不必要的浪费~</div>
4
4
  <div v-if="state.img" class="photo-editor-viewer bg-weak my-mm" ui-flex="row">
5
5
  <div class="mr-mm" style="flex: 1">
6
- <vue-cropper ref="cropperRef" :img="state.img" :autoCrop="state.autoCrop" @realTime="realTime"></vue-cropper>
6
+ <vue-cropper ref="cropperRef" :img="state.img" :auto-crop="state.autoCrop" @real-time="realTime" />
7
7
  </div>
8
8
  <div style="flex: 1" class="photo-editor-transparent">
9
9
  <img :src="state.previews || ''" />
@@ -32,14 +32,14 @@
32
32
  import { VueCropper } from 'vue-cropper/next';
33
33
  import Compressor from 'compressorjs';
34
34
  import { LayerById } from '../basic';
35
- import axios from 'axios';
35
+ // import axios from 'axios';
36
36
  import 'vue-cropper/next/dist/index.css';
37
37
 
38
38
  const props: any = defineProps({
39
39
  layerId: {
40
40
  type: String,
41
- default: 'PhotoEditor'
42
- }
41
+ default: 'PhotoEditor',
42
+ },
43
43
  });
44
44
 
45
45
  const state = reactive({
@@ -47,7 +47,7 @@
47
47
  // outputType: 'jepg', // 裁剪生成图片格式
48
48
  autoCrop: true,
49
49
  previews: null, //base格式
50
- cropLoad: 0
50
+ cropLoad: 0,
51
51
  });
52
52
 
53
53
  const emit = defineEmits(['fileChange']);
@@ -63,7 +63,7 @@
63
63
  success: resolve,
64
64
  maxWidth: 1000,
65
65
  maxHeight: 700,
66
- error: reject
66
+ error: reject,
67
67
  });
68
68
  });
69
69
  const _file = blobToFile(blob);
@@ -91,36 +91,36 @@
91
91
  if (!state.cropLoad) {
92
92
  state.cropLoad = 1;
93
93
 
94
- const formData = {
95
- image_file_b64: state.previews,
96
- image_url: '',
97
- size: 'preview',
98
- type: 'auto',
99
- type_level: '1',
100
- format: 'auto',
101
- roi: '0% 0% 100% 100%',
102
- crop: false,
103
- crop_margin: '0',
104
- scale: 'original',
105
- position: 'original',
106
- channels: 'rgba',
107
- add_shadow: false,
108
- semitransparency: true,
109
- bg_color: '',
110
- bg_image_url: ''
111
- };
112
- const res: any = await axios.post(
113
- 'https://api.remove.bg/v1.0/removebg',
114
- { ...formData },
115
- { responseType: 'arraybuffer', headers: { 'X-Api-Key': 'kg4jrcKZd6Gjdx5CmBYmksuN' } }
116
- );
117
- if (res.status === 200) {
118
- const blob = new Blob([res.data], { type: 'image/png' });
119
- blobToDataURI(blob, (data: any) => {
120
- state.previews = data;
121
- state.cropLoad = 0;
122
- });
123
- }
94
+ // const formData = {
95
+ // image_file_b64: state.previews,
96
+ // image_url: '',
97
+ // size: 'preview',
98
+ // type: 'auto',
99
+ // type_level: '1',
100
+ // format: 'auto',
101
+ // roi: '0% 0% 100% 100%',
102
+ // crop: false,
103
+ // crop_margin: '0',
104
+ // scale: 'original',
105
+ // position: 'original',
106
+ // channels: 'rgba',
107
+ // add_shadow: false,
108
+ // semitransparency: true,
109
+ // bg_color: '',
110
+ // bg_image_url: '',
111
+ // };
112
+ // const res: any = await axios.post(
113
+ // 'https://api.remove.bg/v1.0/removebg',
114
+ // { ...formData },
115
+ // { responseType: 'arraybuffer', headers: { 'X-Api-Key': 'kg4jrcKZd6Gjdx5CmBYmksuN' } },
116
+ // );
117
+ // if (res.status === 200) {
118
+ // const blob = new Blob([res.data], { type: 'image/png' });
119
+ // blobToDataURI(blob, (data: any) => {
120
+ // state.previews = data;
121
+ // state.cropLoad = 0;
122
+ // });
123
+ // }
124
124
  }
125
125
  };
126
126
 
@@ -66,7 +66,7 @@
66
66
  </div>
67
67
  </div>
68
68
  <div v-if="!state.isNoTime" class="ny-sm nx-ms">
69
- <div class="full ac b-solid bk-back b-xs r-sm" ui-row="mob-8" style="width: 100%; height: 3em; padding: 0.5em">
69
+ <div class="full ac b-solid bk-line b-xs r-sm" ui-row="mob-8" style="width: 100%; height: 3em; padding: 0.5em">
70
70
  <ul
71
71
  :style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
72
72
  class="fekit-date-view-time-scroll"
@@ -7,7 +7,7 @@
7
7
  </div>
8
8
  </div>
9
9
  <div ui-btns="@a none s" @click="setPanelType()">
10
- <p v-if="state.type > 2" class="nowrap" ui-flex="row cm">
10
+ <p v-if="state.type === 2" class="nowrap" ui-flex="row cm">
11
11
  <b class="nx-ss">{{ panel.sta }}年</b>
12
12
  <span class="nx-xs">-</span>
13
13
  <b class="nx-ss">{{ panel.end }}年</b>
@@ -26,32 +26,38 @@
26
26
  </div>
27
27
  </div>
28
28
  </div>
29
- <div ui-date-body="" class="flex-block pr">
30
- <div v-if="state.type === 2" class="full n-ms">
31
- <ul ui-row="mob-6" class="n-ms ny-sm-sub">
29
+ <div ui-date-body="" :class="['flex-block pr', bodyClass]">
30
+ <div v-if="state.type === 2" class="full">
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 ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">{{ year }}</div>
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
+ >
38
+ {{ year }}
39
+ </div>
34
40
  </li>
35
41
  </ul>
36
42
  </div>
37
43
  <div v-else-if="state.type === 1" class="full">
38
- <ul ui-row="mob-4" class="n-ms ny-sm-sub">
39
- <li ui-flex="col cm" @click="setDateValue('m', 1)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">1月</div></li>
40
- <li ui-flex="col cm" @click="setDateValue('m', 2)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">2月</div></li>
41
- <li ui-flex="col cm" @click="setDateValue('m', 3)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">3月</div></li>
42
- <li ui-flex="col cm" @click="setDateValue('m', 4)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">4月</div></li>
43
- <li ui-flex="col cm" @click="setDateValue('m', 5)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">5月</div></li>
44
- <li ui-flex="col cm" @click="setDateValue('m', 6)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">6月</div></li>
45
- <li ui-flex="col cm" @click="setDateValue('m', 7)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">7月</div></li>
46
- <li ui-flex="col cm" @click="setDateValue('m', 8)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">8月</div></li>
47
- <li ui-flex="col cm" @click="setDateValue('m', 9)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">9月</div></li>
48
- <li ui-flex="col cm" @click="setDateValue('m', 10)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">10月</div></li>
49
- <li ui-flex="col cm" @click="setDateValue('m', 11)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">11月</div></li>
50
- <li ui-flex="col cm" @click="setDateValue('m', 12)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">12月</div></li>
44
+ <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>
51
57
  </ul>
52
58
  </div>
53
59
  <div v-else class="full">
54
- <ul ui-flex="row am" class="fs-xs nx-sm nt-sm">
60
+ <ul ui-flex="row am" class="fs-xs nx-sm nt-ss">
55
61
  <li class="flex-block ac"><span>日</span></li>
56
62
  <li class="flex-block ac"><span>一</span></li>
57
63
  <li class="flex-block ac"><span>二</span></li>
@@ -73,9 +79,9 @@
73
79
  >
74
80
  <div
75
81
  ui-flex="col cm"
76
- class="r-sm b-solid bk-none b-xs my-ss ux-scale co-main:hover"
82
+ class="r-sm b-solid bk-none b-xs my-ss ux-scale"
77
83
  style="width: 1.8em; height: 1.8em"
78
- :class="`${item.isLastMonth || item.isNextMonth ? 'co-idle' : item.isHoliday ? 'co-risk' : ''} ${item.selected ? 'active bg-main-o-lm co-fore' : 'hover-bg-weak'}`"
84
+ :class="`${item.isLastMonth || item.isNextMonth ? 'co-idle' : item.isHoliday ? 'co-risk' : ''} ${item.selected ? 'active bg-main-o-lm co-w' : 'bg-weak:hover co-main:hover'}`"
79
85
  >
80
86
  <span>{{ item.day }}</span>
81
87
  </div>
@@ -86,54 +92,57 @@
86
92
  </ul>
87
93
  </div>
88
94
  </div>
89
- <div v-if="!state.isNoTime && state.type === 0" class="ny-sm nx-ms">
90
- <div class="full ac b-solid bk-back b-xs r-sm" ui-row="mob-8" style="width: 100%; height: 3em; padding: 0.5em">
91
- <ul
92
- :style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
93
- class="fekit-date-view-time-scroll"
94
- ref="ths"
95
- ui-scroll=":y xs"
96
- ui-btns="@a none s :block"
97
- data-type="h"
98
- @scroll="timeScroll"
99
- >
100
- <li v-for="(item, idx) in hours" :key="idx">
101
- {{ item }}
102
- </li>
103
- </ul>
104
- <ul
105
- :style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
106
- class="fekit-date-view-time-scroll"
107
- ref="tms"
108
- ui-scroll=":y xs"
109
- ui-btns="@a none s :block"
110
- data-type="m"
111
- @scroll="timeScroll"
112
- >
113
- <li v-for="(item, idx) in seconds" :key="idx">
114
- {{ item }}
115
- </li>
116
- </ul>
117
- <ul
118
- :style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
119
- class="fekit-date-view-time-scroll"
120
- ref="tss"
121
- ui-scroll=":y xs"
122
- ui-btns="@a none s :block"
123
- data-type="s"
124
- @scroll="timeScroll"
125
- >
126
- <li v-for="(item, idx) in seconds" :key="idx">
127
- {{ item }}
128
- </li>
129
- </ul>
95
+ <template v-if="!state.isNoTime">
96
+ <div v-if="state.type === 0" class="h-ss ny-sm nx-ms">
97
+ <div class="full ac b-solid bk-back b-xs r-sm" ui-row="mob-8" style="width: 100%; height: 3em; padding: 0.5em">
98
+ <ul
99
+ :style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
100
+ class="fekit-date-view-time-scroll"
101
+ ref="ths"
102
+ ui-scroll=":y xs"
103
+ ui-btns="@a none s :block"
104
+ data-type="h"
105
+ @scroll="timeScroll"
106
+ >
107
+ <li v-for="(item, idx) in hours" :key="idx">
108
+ {{ item }}
109
+ </li>
110
+ </ul>
111
+ <ul
112
+ :style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
113
+ class="fekit-date-view-time-scroll"
114
+ ref="tms"
115
+ ui-scroll=":y xs"
116
+ ui-btns="@a none s :block"
117
+ data-type="m"
118
+ @scroll="timeScroll"
119
+ >
120
+ <li v-for="(item, idx) in seconds" :key="idx">
121
+ {{ item }}
122
+ </li>
123
+ </ul>
124
+ <ul
125
+ :style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
126
+ class="fekit-date-view-time-scroll"
127
+ ref="tss"
128
+ ui-scroll=":y xs"
129
+ ui-btns="@a none s :block"
130
+ data-type="s"
131
+ @scroll="timeScroll"
132
+ >
133
+ <li v-for="(item, idx) in seconds" :key="idx">
134
+ {{ item }}
135
+ </li>
136
+ </ul>
137
+ </div>
130
138
  </div>
131
- </div>
132
- <div v-if="tools" ui-date-foot="" ui-flex="row xm" class="flex-fixed nx-sl ny-sl b-solid bk-line-o-mm bt-xs">
139
+ <div v-else class="h-ss"></div>
140
+ </template>
141
+ <div v-if="showTools" ui-date-foot="" ui-flex="row xm" class="flex-fixed nx-sl ny-sl b-solid bk-line-o-mm bt-xs">
133
142
  <div ui-flex="row lm" class="nl-ss">
134
143
  <div v-if="state.panel" ui-flex="row lm">
135
- <span :anim-editing="state.type === 'date'" class="nx-ss">{{ idate(state.panel).format('YYYY-MM-DD') }}</span>
136
- <span v-if="!state.isNoTime" :anim-editing="state.type === 'time'" class="nx-ss">{{ idate(state.panel).format('HH:mm:ss') }}</span>
144
+ <span :anim-editing="state.type === baseType" class="nx-ss">{{ idate(state.panel).format(panelFormat) }}</span>
145
+ <span v-if="!state.isNoTime" :anim-editing="state.type === baseType" class="nx-ss">{{ idate(state.panel).format('HH:mm:ss') }}</span>
137
146
  </div>
138
147
  <div v-else-if="state.shortcuts?.length" ui-flex="row lm">
139
148
  <div class="mr-sm-sub nx-sl-sub ny-ss-sub lh-ss nowrap fs-ss dib-sub" ui-scroll=":x y:hidden">
@@ -153,15 +162,43 @@
153
162
  <script setup lang="ts">
154
163
  import { computed, ref, reactive, watch, onMounted } from 'vue';
155
164
  import { isDateString, isObject, isString } from '@fekit/utils';
156
- // import { idate } from '@fekit/utils';
157
165
  import { idate } from './date';
158
166
  import { Icon } from '../basic';
159
167
 
160
- // const _level: any = { 0: ['d', 1], 1: ['m', 1], 2: ['y', 10], 3: ['y', 100] };
168
+ const normalizeDateInput = (value: any) => {
169
+ if (!value) {
170
+ return value;
171
+ }
172
+ if (isString(value)) {
173
+ if (/^\d{4}$/.test(value)) {
174
+ return `${value}-01-01`;
175
+ }
176
+ if (/^\d{4}-(\d{1,2})$/.test(value)) {
177
+ const [year, month] = value.split('-');
178
+ const m = month.padStart(2, '0');
179
+ return `${year}-${m}-01`;
180
+ }
181
+ }
182
+ return value;
183
+ };
184
+
185
+ interface PickerConfig {
186
+ baseType: number;
187
+ format: string;
188
+ bodyClass: string;
189
+ tools: boolean;
190
+ }
191
+
192
+ const PICKER_CONFIGS: Record<string, PickerConfig> = {
193
+ date: { baseType: 0, format: 'YYYY-MM-DD', bodyClass: 'min-h-ls+', tools: true },
194
+ month: { baseType: 1, format: 'YYYY-MM', bodyClass: 'min-h-ms', tools: false },
195
+ year: { baseType: 2, format: 'YYYY', bodyClass: 'min-h-ms', tools: false },
196
+ };
161
197
 
162
198
  // 创建日期
163
199
  const cDate = (date: any = null) => {
164
- return isDateString(date) ? new Date(date) : new Date();
200
+ const normalized = normalizeDateInput(date);
201
+ return isDateString(normalized) ? new Date(normalized) : new Date();
165
202
  };
166
203
 
167
204
  // 快捷预设
@@ -198,7 +235,7 @@
198
235
  tools?: boolean;
199
236
  range?: boolean;
200
237
  format?: string;
201
- picker?: 'date' | 'week' | 'month' | 'quarter';
238
+ picker?: 'date' | 'week' | 'month' | 'quarter' | 'year';
202
239
  holiday?: object;
203
240
  shortcuts?: Array<'yesterday' | 'today' | 'tomorrow'>;
204
241
  extras?: (item: any) => string;
@@ -211,19 +248,19 @@
211
248
  // 是否显示框架
212
249
  frame: false,
213
250
  // 是否是示工具
214
- tools: true,
251
+ tools: undefined,
215
252
  // 时间范围
216
253
  range: false,
217
254
  // 面板类型
218
255
  picker: 'date',
219
256
  // 额外内容
220
257
  extras: (item: any) => {
221
- return `<i class="dib o-ms mb-xs r-xl ${item.today ? 'bg-main' : 'bg-none'}" style="width:.6em; height:.6em;"></i>`;
258
+ return `<i class="dib o-ms mb-xs r-xl ${item.today ? 'bg-main' : 'bg-none'}" style="width:.5em; height:.5em;"></i>`;
222
259
  },
223
260
  // 快捷选择
224
261
  shortcuts: () => ['yesterday', 'today', 'tomorrow'],
225
262
  // 数据格式化
226
- format: 'YYYY-MM-DD',
263
+ format: undefined,
227
264
  // 节假日
228
265
  holiday: () => ({}),
229
266
  time: false,
@@ -231,6 +268,11 @@
231
268
  lang: 'zh-CN',
232
269
  });
233
270
 
271
+ const pickerConfig = computed<PickerConfig>(() => {
272
+ const key = props.picker || 'date';
273
+ return PICKER_CONFIGS[key] || PICKER_CONFIGS.date;
274
+ });
275
+
234
276
  // 小时
235
277
  const hours = computed(() => {
236
278
  const _hours: any = [];
@@ -248,6 +290,27 @@
248
290
  return _seconds;
249
291
  });
250
292
 
293
+ const baseType = computed(() => pickerConfig.value.baseType);
294
+
295
+ const panelFormat = computed(() => props.format || pickerConfig.value.format);
296
+
297
+ const bodyClass = computed(() => pickerConfig.value.bodyClass);
298
+
299
+ const showTools = computed(() => {
300
+ if (props.tools !== undefined) {
301
+ return !!props.tools;
302
+ }
303
+ return pickerConfig.value.tools;
304
+ });
305
+
306
+ const isSelectedYear = (year: number) => {
307
+ return !!state.panel && state.curr?.y === year;
308
+ };
309
+
310
+ const isSelectedMonth = (month: number) => {
311
+ return !!state.panel && state.curr?.M === month;
312
+ };
313
+
251
314
  // 内部数据
252
315
  const state: any = reactive({
253
316
  // 面板显示时间
@@ -256,7 +319,6 @@
256
319
  years: 0,
257
320
  // 当前时间计算
258
321
  curr: computed(() => {
259
- // console.log(158, state.panel);
260
322
  const date = idate(state.panel);
261
323
  const days = date.calendar({ group: true, value: [state.panel] });
262
324
  return { days, ...date.attr };
@@ -281,6 +343,28 @@
281
343
  }),
282
344
  });
283
345
 
346
+ watch(
347
+ () => baseType.value,
348
+ (value) => {
349
+ state.type = value;
350
+ },
351
+ { immediate: true },
352
+ );
353
+
354
+ watch(
355
+ () => panelFormat.value,
356
+ (format) => {
357
+ if (state.panel) {
358
+ const formatted = idate(state.panel).format(format);
359
+ if (formatted !== state.panel) {
360
+ state.panel = formatted;
361
+ }
362
+ state.value = formatted;
363
+ }
364
+ },
365
+ { immediate: true },
366
+ );
367
+
284
368
  // 面板
285
369
  const panel: any = reactive({
286
370
  years: computed(() => {
@@ -301,9 +385,18 @@
301
385
 
302
386
  // 设置日期
303
387
  const setDateValue = (type: any, value: number = 0, add: number = 0) => {
304
- state.panel = upload(type, value, add);
388
+ const panelValue = upload(type, value, add);
389
+ state.panel = panelValue;
390
+ state.value = panelValue;
305
391
  // 面板返回上一级
306
- state.type -= 1;
392
+ const base = baseType.value;
393
+ const nextType = Math.max(base, state.type - 1);
394
+ state.type = nextType;
395
+
396
+ if (base > 0 && nextType === base) {
397
+ emits('change', panelValue);
398
+ update();
399
+ }
307
400
  };
308
401
 
309
402
  // 时分秒
@@ -338,10 +431,11 @@
338
431
  watch(
339
432
  () => props.modelValue,
340
433
  (value: any) => {
434
+ const formatted = value ? idate(value).format(panelFormat.value) : undefined;
341
435
  // 面板显示日期
342
- state.panel = value || undefined;
436
+ state.panel = formatted;
343
437
  // 值
344
- state.value = value || undefined;
438
+ state.value = formatted;
345
439
  },
346
440
  { deep: true, immediate: true },
347
441
  );
@@ -406,7 +500,7 @@
406
500
  default:
407
501
  break;
408
502
  }
409
- return idate(date).format(props.format);
503
+ return idate(date).format(panelFormat.value);
410
504
  };
411
505
 
412
506
  // 日期前翻
@@ -420,8 +514,10 @@
420
514
 
421
515
  // 向外通信
422
516
  const change = (item: any) => {
423
- state.panel = item ? idate(item.date).format(props.format) : item;
424
- emits('change', state.value);
517
+ const panelValue = item ? idate(item.date).format(panelFormat.value) : item;
518
+ state.panel = panelValue;
519
+ state.value = panelValue;
520
+ emits('change', panelValue);
425
521
  if (state.isNoTime) {
426
522
  update();
427
523
  }
@@ -430,18 +526,24 @@
430
526
  // 清空日期
431
527
  const remove = () => {
432
528
  state.panel = undefined;
529
+ state.value = undefined;
433
530
  update();
434
531
  };
435
532
 
436
533
  // 更新数据
437
534
  const update = () => {
438
- emits('update:modelValue', state.panel ? idate(state.panel).format(props.format) : undefined);
439
- emits('update', state.panel ? idate(state.panel).format(props.format) : undefined);
535
+ const nextValue = state.panel ? idate(state.panel).format(panelFormat.value) : undefined;
536
+ if (state.panel && nextValue !== state.panel) {
537
+ state.panel = nextValue;
538
+ }
539
+ state.value = nextValue;
540
+ emits('update:modelValue', nextValue);
541
+ emits('update', nextValue);
440
542
  };
441
543
 
442
544
  // 面板类型
443
545
  const setPanelType = () => {
444
- if (state.type < 3) {
546
+ if (state.type < 2) {
445
547
  state.type += 1;
446
548
  }
447
549
  };
@@ -456,16 +558,18 @@
456
558
  _timer.value = setTimeout(() => {
457
559
  const h = item.offsetHeight;
458
560
  const idx = Math.floor(ev.target.scrollTop / h);
561
+ const maxIdx = type === 'h' ? 23 : 59;
562
+ const safeIdx = Math.min(Math.max(idx, 0), maxIdx);
459
563
  const { YYYY = 0, MM = 0, DD = 0, HH = '', mm = '', ss = '' }: any = state.curr || {};
460
564
  let _panel = `${YYYY}-${MM}-${DD}`;
461
565
  if (type === 'h') {
462
- _panel += ` ${idx}:${mm}:${ss}`;
566
+ _panel += ` ${safeIdx}:${mm}:${ss}`;
463
567
  }
464
568
  if (type === 'm') {
465
- _panel += ` ${HH}:${idx}:${ss}`;
569
+ _panel += ` ${HH}:${safeIdx}:${ss}`;
466
570
  }
467
571
  if (type === 's') {
468
- _panel += ` ${HH}:${mm}:${idx}`;
572
+ _panel += ` ${HH}:${mm}:${safeIdx}`;
469
573
  }
470
574
  state.panel = idate(_panel).format('YYYY-MM-DD HH:mm:ss');
471
575
  }, 100);
@@ -1,5 +1,5 @@
1
1
  // 主题
2
- export const theme = (then = (_theme: any) => {}) => {
2
+ export const theme = (then: (theme: string) => void = () => {}) => {
3
3
  // 自动设置主题
4
4
  const auto = (scheme: any) => {
5
5
  const _theme = window.localStorage.getItem('theme') || (scheme.matches ? 'dark' : 'light');