@neatui/nuxt 0.1.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.
Files changed (102) hide show
  1. package/README.md +3 -0
  2. package/package.json +43 -0
  3. package/rollup.config.js +35 -0
  4. package/src/components/basic/IDraggable.vue +84 -0
  5. package/src/components/basic/IDraggable@b.vue +80 -0
  6. package/src/components/basic/IFollowView.vue +211 -0
  7. package/src/components/basic/IPickerView.vue +351 -0
  8. package/src/components/basic/IRouterView.vue +360 -0
  9. package/src/components/basic/IScrollView.vue +127 -0
  10. package/src/components/basic/Icon.vue +54 -0
  11. package/src/components/basic/LayerView/Layer.vue +339 -0
  12. package/src/components/basic/LayerView/index.ts +5 -0
  13. package/src/components/basic/index.ts +7 -0
  14. package/src/components/display/Avatar.vue +1 -0
  15. package/src/components/display/Badge.vue +1 -0
  16. package/src/components/display/Calendar.vue +245 -0
  17. package/src/components/display/CalendarReg.vue +245 -0
  18. package/src/components/display/Card.vue +1 -0
  19. package/src/components/display/Carousel.vue +1 -0
  20. package/src/components/display/ChartView.vue +123 -0
  21. package/src/components/display/Collapse.vue +1 -0
  22. package/src/components/display/Desriptions.vue +1 -0
  23. package/src/components/display/Empty.vue +1 -0
  24. package/src/components/display/Image.vue +112 -0
  25. package/src/components/display/List.vue +1 -0
  26. package/src/components/display/PhotoEditor.vue +181 -0
  27. package/src/components/display/PhotoViewer.vue +50 -0
  28. package/src/components/display/Popover.vue +1 -0
  29. package/src/components/display/QRCode.vue +1 -0
  30. package/src/components/display/Segmented.vue +1 -0
  31. package/src/components/display/Statistic.vue +1 -0
  32. package/src/components/display/Table.vue +1 -0
  33. package/src/components/display/Tabs.vue +1 -0
  34. package/src/components/display/Tag.vue +1 -0
  35. package/src/components/display/Timeline.vue +1 -0
  36. package/src/components/display/Tooltip.vue +1 -0
  37. package/src/components/display/Tour.vue +1 -0
  38. package/src/components/display/Tree.vue +431 -0
  39. package/src/components/display/TreeView.vue +225 -0
  40. package/src/components/display/index.ts +8 -0
  41. package/src/components/form/Cascader.vue +435 -0
  42. package/src/components/form/DatePicker.vue +124 -0
  43. package/src/components/form/DateRangePicker@v2.vue.backup +224 -0
  44. package/src/components/form/DateRangePicker@v3.vue +116 -0
  45. package/src/components/form/DateRangeView@v3.vue +386 -0
  46. package/src/components/form/DateView.vue +229 -0
  47. package/src/components/form/DateView@v2.vue +386 -0
  48. package/src/components/form/DateView@v3.vue +471 -0
  49. package/src/components/form/EditUpload.vue +4 -0
  50. package/src/components/form/ImgUpload.vue +174 -0
  51. package/src/components/form/Input.vue.backup +230 -0
  52. package/src/components/form/Input@v3.vue +267 -0
  53. package/src/components/form/InputNumber.vue +200 -0
  54. package/src/components/form/InputRange.vue +235 -0
  55. package/src/components/form/MoreSelect.vue.backup +144 -0
  56. package/src/components/form/MoreSelect@v3.vue +195 -0
  57. package/src/components/form/MoreSelectList.vue +125 -0
  58. package/src/components/form/MoreSelectPanel@v3.vue +190 -0
  59. package/src/components/form/MoreSelectPicker.vue +124 -0
  60. package/src/components/form/MoreSelectTags.vue +124 -0
  61. package/src/components/form/PageMoreSelect.vue +187 -0
  62. package/src/components/form/PageSelect.vue +189 -0
  63. package/src/components/form/SearchMoreSelect.vue +173 -0
  64. package/src/components/form/SearchSelect.vue.backup +194 -0
  65. package/src/components/form/SearchSelect@v3.vue +202 -0
  66. package/src/components/form/Select@v3.vue +201 -0
  67. package/src/components/form/SelectList.vue +58 -0
  68. package/src/components/form/SelectPicker.vue +97 -0
  69. package/src/components/form/SelectTags.vue +52 -0
  70. package/src/components/form/SelectTree/SelectTree@v1.vue +227 -0
  71. package/src/components/form/Switch.vue +135 -0
  72. package/src/components/form/TextArea.vue +193 -0
  73. package/src/components/form/TimePicker.vue +11 -0
  74. package/src/components/form/TimeView.vue +244 -0
  75. package/src/components/form/Upload.vue +346 -0
  76. package/src/components/form/index.ts +82 -0
  77. package/src/components/loader/FormLoader/FormLoader@v2.vue +422 -0
  78. package/src/components/loader/FormLoader/FormLoader@v3.vue.backup +318 -0
  79. package/src/components/loader/FormLoader/index.ts +2 -0
  80. package/src/components/loader/FormLoader@v1/FormLoader.vue +506 -0
  81. package/src/components/loader/FormLoader@v1/FormRender.vue +277 -0
  82. package/src/components/loader/LimitLoader/LimitLoader.vue.backup +131 -0
  83. package/src/components/loader/LimitLoader/LimitLoader@v2.vue.backup +174 -0
  84. package/src/components/loader/LimitLoader/LimitLoader@v3.vue +183 -0
  85. package/src/components/loader/LimitLoader/index.ts +2 -0
  86. package/src/components/loader/TableLoader/TableColView.vue +115 -0
  87. package/src/components/loader/TableLoader/TableLoader.vue +360 -0
  88. package/src/components/loader/TableLoader/index.ts +2 -0
  89. package/src/components/loader/ViewLoader/ViewLoader@v1.vue +256 -0
  90. package/src/components/loader/ViewLoader/index.ts +2 -0
  91. package/src/components/loader/index.ts +5 -0
  92. package/src/components/tools/FormDraftsView.vue +330 -0
  93. package/src/components/tools/FormVerifyView.vue +206 -0
  94. package/src/components/tools/MoreTools.vue +74 -0
  95. package/src/components/tools/MoreTools@v2.vue +74 -0
  96. package/src/components/tools/Pagination@a.vue +222 -0
  97. package/src/components/tools/Pagination@b.vue +221 -0
  98. package/src/components/tools/index.ts +5 -0
  99. package/src/index.ts +9 -0
  100. package/src/shims-vue.d.ts +5 -0
  101. package/src/store/myui.ts +50 -0
  102. package/tsconfig.json +24 -0
@@ -0,0 +1,386 @@
1
+ <template>
2
+ <div :class="`${frame ? 'b-solid bk-line b-xs r-sm' : ''}`" ui-flex="col xy" style="width: 41em">
3
+ <div class="flex-block" ui-flex="row xy">
4
+ <div class="w-ll flex-fixed" ui-flex="col xy">
5
+ <div ui-date-head="" class="nx-sl mt-ss ny-sm b-solid bk-back" ui-flex="row xm">
6
+ <div ui-flex="row lm" class="o-lm">
7
+ <div ui-btn="@a s none :square" @click="prev(1, { y: -1 })">
8
+ <Icon name="double-arrow-left" />
9
+ </div>
10
+ <div ui-btn="@a s none :square" @click="prev(1, { m: -1 })">
11
+ <Icon name="arrow-left" />
12
+ </div>
13
+ </div>
14
+ <div ui-flex="row cm" class="nx-ss-sub">
15
+ <div ui-flex="row cm" class="nx-ss-sub">
16
+ <p class="mx-ss-sub">
17
+ <b>{{ sta.curr.y }}年</b>
18
+ <b>{{ sta.curr.m }}月</b>
19
+ </p>
20
+ </div>
21
+ </div>
22
+ <div ui-flex="row rm">
23
+ <div v-if="idate(sta.panel).update({ m: 1 }).time < idate(end.panel).time" ui-btn="@a s none :square" @click="next(1, { m: 1 })">
24
+ <Icon name="arrow-right" />
25
+ </div>
26
+ <div v-else ui-btn="@a s none :square" class="o-sl">
27
+ <Icon name="arrow-right" />
28
+ </div>
29
+ <div v-if="idate(sta.panel).update({ y: 1 }).time < idate(end.panel).time" ui-btn="@a s none :square" @click="next(1, { y: 1 })">
30
+ <Icon name="double-arrow-right" />
31
+ </div>
32
+ <div v-else ui-btn="@a s none :square" class="o-sl">
33
+ <Icon name="double-arrow-right" />
34
+ </div>
35
+ </div>
36
+ </div>
37
+ <div ui-date-body="">
38
+ <div class="nb-sm">
39
+ <ul ui-flex="row am" class="fs-xs nx-sm nt-sm">
40
+ <li class="flex-block ac"><span>日</span></li>
41
+ <li class="flex-block ac"><span>一</span></li>
42
+ <li class="flex-block ac"><span>二</span></li>
43
+ <li class="flex-block ac"><span>三</span></li>
44
+ <li class="flex-block ac"><span>四</span></li>
45
+ <li class="flex-block ac"><span>五</span></li>
46
+ <li class="flex-block ac"><span>六</span></li>
47
+ </ul>
48
+ <ul ui-date-days="" ui-flex="col xm" class="flex-wrap nx-sm">
49
+ <li v-for="(week, idx) in sta.curr.days" :key="idx" :ui-date-week="idx + 1" class="flex-block" ui-flex="row am">
50
+ <div v-for="(item, i) in week" :key="i" class="pr flex-block nb-sl" ui-flex="col xy">
51
+ <div
52
+ v-if="item.day"
53
+ :ui-date-day="item.day"
54
+ class="flex-block"
55
+ :class="`${item.range ? 'bg-main-xs' : ''} ${item.sta ? 'r-lt-sl r-lb-sl' : ''} ${item.end ? 'r-rt-sl r-rb-sl' : ''}`"
56
+ ui-flex="col cm"
57
+ @click="change(1, item)"
58
+ >
59
+ <div
60
+ ui-flex="col cm"
61
+ class="r-sm b-solid bk-none b-xs my-ss ux-scale"
62
+ style="width: 1.8em; height: 1.8em"
63
+ :class="`${item.isLastMonth || item.isNextMonth ? 'co-case' : item.holiday ? 'co-risk' : ''} ${
64
+ item.selected ? 'active bg-main-lm co-fore' : 'hover-bg-weak'
65
+ }`"
66
+ >
67
+ <span>{{ item.day }}</span>
68
+ </div>
69
+ </div>
70
+ <div class="pa full-x lh-xs ny-ss ob-no ol-no nowrap s-ml bold" style="transform-origin: 50% 110%" ui-flex="row ct" v-html="extras(item)"></div>
71
+ </div>
72
+ </li>
73
+ </ul>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ <div class="flex-block"></div>
78
+ <div class="w-ll flex-fixed" ui-flex="col xy">
79
+ <div ui-date-head="" class="nx-sl mt-ss ny-sm b-solid bk-back" ui-flex="row xm">
80
+ <div ui-flex="row lm">
81
+ <div v-if="idate(sta.panel).time < idate(end.panel).update({ y: -1 }).time" ui-btn="@a s none :square" @click="prev(2, { y: -1 })">
82
+ <Icon name="double-arrow-left" />
83
+ </div>
84
+ <div v-else ui-btn="@a s none :square" class="o-sl">
85
+ <Icon name="double-arrow-left" />
86
+ </div>
87
+ <div v-if="idate(sta.panel).time < idate(end.panel).update({ m: -1 }).time" ui-btn="@a s none :square" @click="prev(2, { m: -1 })">
88
+ <Icon name="arrow-left" />
89
+ </div>
90
+ <div v-else ui-btn="@a s none :square" class="o-sl">
91
+ <Icon name="arrow-left" />
92
+ </div>
93
+ </div>
94
+ <div ui-flex="row cm" class="nx-ss-sub">
95
+ <div ui-flex="row cm" class="nx-ss-sub">
96
+ <p class="mx-ss-sub">
97
+ <b>{{ end.curr.y }}年</b>
98
+ <b>{{ end.curr.m }}月</b>
99
+ </p>
100
+ </div>
101
+ </div>
102
+ <div ui-flex="row rm" class="o-lm">
103
+ <div ui-btn="@a s none :square" @click="next(2, { m: 1 })">
104
+ <Icon name="arrow-right" />
105
+ </div>
106
+ <div ui-btn="@a s none :square" @click="next(2, { y: 1 })">
107
+ <Icon name="double-arrow-right" />
108
+ </div>
109
+ </div>
110
+ </div>
111
+ <div ui-date-body="">
112
+ <div class="nb-sm">
113
+ <ul ui-flex="row am" class="fs-xs nx-sm nt-sm">
114
+ <li class="flex-block ac"><span>日</span></li>
115
+ <li class="flex-block ac"><span>一</span></li>
116
+ <li class="flex-block ac"><span>二</span></li>
117
+ <li class="flex-block ac"><span>三</span></li>
118
+ <li class="flex-block ac"><span>四</span></li>
119
+ <li class="flex-block ac"><span>五</span></li>
120
+ <li class="flex-block ac"><span>六</span></li>
121
+ </ul>
122
+ <ul ui-date-days="" ui-flex="col xm" class="flex-wrap nx-sm">
123
+ <li v-for="(week, idx) in end.curr.days" :key="idx" :ui-date-week="idx + 1" class="flex-block" ui-flex="row am">
124
+ <div v-for="(item, i) in week" :key="i" class="pr flex-block nb-sl" ui-flex="col xy">
125
+ <div
126
+ v-if="item.day"
127
+ :ui-date-day="item.day"
128
+ class="flex-block"
129
+ :class="`${item.range ? 'bg-main-xs' : ''} ${item.sta ? 'r-lt-sl r-lb-sl' : ''} ${item.end ? 'r-rt-sl r-rb-sl' : ''}`"
130
+ ui-flex="col cm"
131
+ @click="change(2, item)"
132
+ >
133
+ <div
134
+ ui-flex="col cm"
135
+ class="r-sm b-solid bk-none b-xs my-ss ux-scale"
136
+ style="width: 1.8em; height: 1.8em"
137
+ :class="`${item.isLastMonth || item.isNextMonth ? 'co-case' : item.holiday ? 'co-risk' : ''} ${
138
+ item.selected ? 'active bg-main-lm co-fore' : 'hover-bg-weak'
139
+ }`"
140
+ >
141
+ <span>{{ item.day }}</span>
142
+ </div>
143
+ </div>
144
+ <div class="pa full-x lh-xs ny-ss ob-no ol-no nowrap s-ml bold" style="transform-origin: 50% 110%" ui-flex="row ct" v-html="extras(item)"></div>
145
+ </div>
146
+ </li>
147
+ </ul>
148
+ </div>
149
+ </div>
150
+ </div>
151
+ </div>
152
+ <div v-if="tools" ui-date-foot="" ui-flex="row xm" class="nx-sl ny-sl b-solid bk-line-ls bt-xs">
153
+ <div ui-flex="row lm" class="nl-ss">
154
+ <p v-if="sta.value || end.value">
155
+ <span class="nowrap">已选:</span>
156
+ <span>{{ sta.value || '-' }} ~ {{ end.value || '-' }}</span>
157
+ </p>
158
+ <div v-else-if="com.shortcuts?.length" ui-flex="row lm">
159
+ <span class="nowrap">推荐:</span>
160
+ <div class="mr-sm-sub nx-sl-sub ny-ss-sub lh-ss nowrap fs-ss dib-sub" ui-scroll=":x y:hidden">
161
+ <p v-for="(item, idx) in com.shortcuts" :key="idx" class="bg-main-xs co-main r-xl" ui-btn="@a xs none :round" @click="item?.func">{{ item?.text }}</p>
162
+ <p class="bg-main-xs co-main r-xl" ui-btn="@a xs none :round"><Icon class="co-main" name="more" /></p>
163
+ </div>
164
+ </div>
165
+ <div v-else>&nbsp;</div>
166
+ </div>
167
+ <div>
168
+ <button v-if="sta.value" ui-btn="@a xs none" class="co-risk" @click="remove()">清空</button>
169
+ </div>
170
+ </div>
171
+ </div>
172
+ </template>
173
+ <script setup lang="ts">
174
+ import { computed, reactive, watch } from 'vue';
175
+ import { idate, isDateString, isString } from '@fekit/utils';
176
+ import { Icon } from '../basic';
177
+
178
+ // 创建日期
179
+ // const cDate = (date: any = null) => {
180
+ // return isDateString(date) ? new Date(date) : new Date();
181
+ // };
182
+
183
+ // 快捷预设
184
+ const shortcutsList: any = {
185
+ yesterday: {
186
+ text: '昨天',
187
+ func() {
188
+ change(0, { date: idate(new Date().setDate(new Date().getDate() - 1)).format('YYYY-MM-DD') });
189
+ }
190
+ },
191
+ today: {
192
+ text: '今天',
193
+ func() {
194
+ change(0, { date: idate(new Date()).format('YYYY-MM-DD') });
195
+ }
196
+ },
197
+ tomorrow: {
198
+ text: '明天',
199
+ func() {
200
+ change(0, { date: idate(new Date().setDate(new Date().getDate() + 1)).format('YYYY-MM-DD') });
201
+ }
202
+ }
203
+ };
204
+
205
+ const emits: any = defineEmits(['update:modelValue', 'change']);
206
+
207
+ interface PickerRange {
208
+ y?: number;
209
+ m?: number;
210
+ d?: number;
211
+ }
212
+ interface Props {
213
+ modelValue?: Array<string | number>;
214
+ frame: boolean;
215
+ tools?: boolean;
216
+ range?: boolean;
217
+ pickerRange?: PickerRange;
218
+ format?: string;
219
+ picker?: 'date' | 'week' | 'month' | 'quarter';
220
+ holiday?: object;
221
+ shortcuts?: Array<'yesterday' | 'today' | 'tomorrow'>;
222
+ extras?: (item: any) => string;
223
+ }
224
+ const props: any = withDefaults(defineProps<Props>(), {
225
+ // 值
226
+ modelValue: () => [],
227
+ // 是否显示框架
228
+ frame: false,
229
+ // 是否是示工具
230
+ tools: true,
231
+ // 时间范围
232
+ range: true,
233
+ // 面板类型
234
+ picker: 'date',
235
+ // 面板范围
236
+ pickerRange: () => ({ y: 0, m: 1, d: 0 }),
237
+ // 额外内容
238
+ extras: (item: any) => {
239
+ return `<i class="dib o-ms mb-xs r-xl ${item.today ? 'bg-main' : 'bg-none'}" style="width:.6em; height:.6em;"></i>`;
240
+ },
241
+ // 快捷选择
242
+ shortcuts: () => ['yesterday', 'today', 'tomorrow'],
243
+ // 数据格式化
244
+ format: 'YYYY-MM-DD',
245
+ // 节假日
246
+ holiday: () => ({})
247
+ });
248
+
249
+ // 公共数据
250
+ const com: any = reactive({
251
+ // 快捷选择
252
+ shortcuts: computed(() => {
253
+ return props.shortcuts.map((item: any) => {
254
+ return isString(item) ? shortcutsList[item] : item;
255
+ });
256
+ })
257
+ });
258
+
259
+ // 开始数据
260
+ const sta: any = reactive({
261
+ // 面板日期
262
+ panel: '',
263
+ // 值
264
+ value: '',
265
+ // 当前时间计算
266
+ curr: computed(() => {
267
+ const date = idate(sta.panel);
268
+ const days = date.calendar({ group: true, value: [sta.value, end.value] });
269
+ const { y = 0, M: m = 0, d = 0 } = date.attr || {};
270
+ return { days, y, m, d };
271
+ })
272
+ });
273
+
274
+ // 结束数据
275
+ const end: any = reactive({
276
+ panel: '',
277
+ value: '',
278
+ // 当前时间计算
279
+ curr: computed(() => {
280
+ const date = idate(end.panel);
281
+ const days = date.calendar({ group: true, value: [sta.value, end.value] });
282
+ const { y = 0, M: m = 0, d = 0 } = date.attr || {};
283
+ return { days, y, m, d };
284
+ })
285
+ });
286
+
287
+ const init = ([a = '', b = '']: any = []) => {
288
+ console.log(a, b);
289
+ // 开始
290
+ if (a && isDateString(a)) {
291
+ sta.panel = a;
292
+ sta.value = idate(a).format(props.format);
293
+ }
294
+ // 结束
295
+ if (b && isDateString(b)) {
296
+ if (a) {
297
+ if (idate(b) >= idate(a)) {
298
+ if (!b) {
299
+ end.panel = idate(b).update(props.pickerRange).format(props.format);
300
+ }
301
+ end.value = idate(b).format(props.format);
302
+ } else {
303
+ sta.panel = b;
304
+ if (!b) {
305
+ end.panel = idate(a).update(props.pickerRange).format(props.format);
306
+ }
307
+ sta.value = idate(b).format(props.format);
308
+ end.value = idate(a).format(props.format);
309
+ }
310
+ } else {
311
+ sta.panel = b;
312
+ sta.value = idate(b).format(props.format);
313
+ }
314
+ }
315
+ if (!a && !b) {
316
+ sta.panel = idate().format(props.format);
317
+ end.panel = idate().update(props.pickerRange).format(props.format);
318
+ }
319
+ };
320
+
321
+ watch(() => props.modelValue, init, { deep: true, immediate: true });
322
+ watch(
323
+ [() => sta.value, () => end.value],
324
+ ([sta = '', end = '']: any = []) => {
325
+ if ((sta && end) || (!sta && !end)) {
326
+ emits('update:modelValue', [sta, end]);
327
+ }
328
+ },
329
+ { deep: true, immediate: true }
330
+ );
331
+
332
+ // 日期前翻
333
+ const prev = (panel: any = 0, type: any = { m: 1 }) => {
334
+ if (panel === 1) {
335
+ sta.panel = idate(sta.panel).update(type).format('YYYY-MM-DD');
336
+ }
337
+ if (panel === 2) {
338
+ end.panel = idate(end.panel).update(type).format('YYYY-MM-DD');
339
+ }
340
+ };
341
+ // 日期后翻
342
+ const next = (panel: any = 0, type: any = 'm') => {
343
+ if (panel === 1) {
344
+ sta.panel = idate(sta.panel).update(type).format('YYYY-MM-DD');
345
+ }
346
+ if (panel === 2) {
347
+ end.panel = idate(end.panel).update(type).format('YYYY-MM-DD');
348
+ }
349
+ };
350
+
351
+ // 向外通信
352
+ const change = (_panel: any = 0, item: any = '') => {
353
+ // 如果已有值则清空
354
+ if (sta.value && end.value) {
355
+ sta.value = '';
356
+ end.value = '';
357
+ }
358
+
359
+ if (!sta.value) {
360
+ sta.value = idate(item.date).format(props.format);
361
+ } else {
362
+ if (idate(item.date).time < idate(sta.value).time) {
363
+ end.value = idate(sta.value).format(props.format);
364
+ sta.value = idate(item.date).format(props.format);
365
+ } else {
366
+ end.value = idate(item.date).format(props.format);
367
+ }
368
+ }
369
+ // 更新面板
370
+ // if (sta.value) {
371
+ // sta.panel = sta.value;
372
+ // }
373
+ // const { y: sta_y = '', M: sta_m = '' } = idate(sta.panel).attr || {};
374
+ // const { y: end_y = '', M: end_m = '' } = idate(end.value).attr || {};
375
+ // if (end.value && idate(`${end_y}-${end_m}-1`).time > idate(`${sta_y}-${sta_m}-1`).time) {
376
+ // console.log(370, sta.panel, end.value, idate(`${end_y}-${end_m}-1`).time > idate(`${sta_y}-${sta_m}-1`).time);
377
+ // end.panel = end.value;
378
+ // }
379
+ };
380
+
381
+ const remove: any = () => {
382
+ sta.value = '';
383
+ end.value = '';
384
+ init([]);
385
+ };
386
+ </script>
@@ -0,0 +1,229 @@
1
+ <template>
2
+ <div ui-date="@a" class="w-ll" :class="`${frame ? 'b-solid bk-line b-xs r-sm' : ''}`" ui-flex="col xy">
3
+ <div ui-date-head="" class="nx-sl mt-ss ny-sm b-solid bk-back" ui-flex="row xm">
4
+ <div ui-flex="row lm" class="o-lm">
5
+ <div ui-btn="@a s none :square" @click="prev('y')">
6
+ <Icon name="double-arrow-left" />
7
+ </div>
8
+ <div ui-btn="@a s none :square" @click="prev('m')">
9
+ <Icon name="arrow-left" />
10
+ </div>
11
+ </div>
12
+ <div ui-flex="row cm" class="nx-ss-sub">
13
+ <div ui-flex="row cm" class="nx-ss-sub">
14
+ <p class="mx-ss-sub">
15
+ <b>{{ state.curr.y }}年</b>
16
+ <b>{{ state.curr.m }}月</b>
17
+ </p>
18
+ </div>
19
+ </div>
20
+ <div ui-flex="row rm" class="o-lm">
21
+ <div ui-btn="@a s none :square" @click="next('m')">
22
+ <Icon name="arrow-right" />
23
+ </div>
24
+ <div ui-btn="@a s none :square" @click="next('y')">
25
+ <Icon name="double-arrow-right" />
26
+ </div>
27
+ </div>
28
+ </div>
29
+ <div ui-date-body="">
30
+ <div class="nb-sm">
31
+ <ul ui-flex="row am" class="fs-xs nx-sm nt-sm">
32
+ <li class="flex-block ac"><span>日</span></li>
33
+ <li class="flex-block ac"><span>一</span></li>
34
+ <li class="flex-block ac"><span>二</span></li>
35
+ <li class="flex-block ac"><span>三</span></li>
36
+ <li class="flex-block ac"><span>四</span></li>
37
+ <li class="flex-block ac"><span>五</span></li>
38
+ <li class="flex-block ac"><span>六</span></li>
39
+ </ul>
40
+ <ul ui-date-days="" ui-flex="col xm" class="flex-wrap nx-sm">
41
+ <li v-for="(week, idx) in state.curr.days" :key="idx" :ui-date-week="idx + 1" class="flex-block" ui-flex="row am" style="margin-bottom: -0.25em">
42
+ <div v-for="(item, i) in week" :key="i" class="pr flex-block nb-sm" ui-flex="col xy">
43
+ <div
44
+ v-if="item.day"
45
+ :ui-date-day="item.day"
46
+ class="flex-block"
47
+ :class="`${item.range ? 'bg-main-xs' : ''} ${item.sta ? 'r-lt-sl r-lb-sl' : ''} ${item.end ? 'r-rt-sl r-rb-sl' : ''}`"
48
+ ui-flex="col cm"
49
+ @click="change(item)"
50
+ @mouseenter="setRangeValue(item)"
51
+ >
52
+ <div
53
+ ui-flex="col cm"
54
+ class="r-sm b-solid bk-none b-xs my-ss ux-scale"
55
+ style="width: 1.8em; height: 1.8em"
56
+ :class="`${item.isLastMonth || item.isNextMonth ? 'co-idle' : item.isHoliday ? 'co-risk' : ''} ${item.selected ? 'active bg-main-lm co-fore' : 'hover-bg-weak'}`"
57
+ >
58
+ <span>{{ item.day }}</span>
59
+ </div>
60
+ </div>
61
+ <div class="pa full-x lh-xs ny-ss ob-no ol-no nowrap s-ml bold" style="transform-origin: 50% 110%" ui-flex="row ct" v-html="extras(item)"></div>
62
+ </div>
63
+ </li>
64
+ </ul>
65
+ </div>
66
+ </div>
67
+ <div v-if="tools" ui-date-foot="" ui-flex="row xm" class="nx-sl ny-sl b-solid bk-line-mm bt-xs">
68
+ <div ui-flex="row lm" class="nl-ss">
69
+ <p v-if="state.date">
70
+ <span class="nowrap">已选:</span>
71
+ <span>{{ state.value }}</span>
72
+ </p>
73
+ <div v-else-if="state.shortcuts?.length" ui-flex="row lm">
74
+ <span class="nowrap">推荐:</span>
75
+ <div class="mr-sm-sub nx-sl-sub ny-ss-sub lh-ss nowrap fs-ss dib-sub" ui-scroll=":x y:hidden">
76
+ <p v-for="(item, idx) in state.shortcuts" :key="idx" class="bg-main-xs co-main r-xl" ui-btn="@a xs none :round" @click="item?.func">{{ item?.text }}</p>
77
+ <p class="bg-main-xs co-main r-xl" ui-btn="@a xs none :round"><Icon class="co-main" name="more" /></p>
78
+ </div>
79
+ </div>
80
+ <div v-else>&nbsp;</div>
81
+ </div>
82
+ <div>
83
+ <button v-if="state.value" ui-btn="@a xs none" class="co-risk" @click="change('')">清空</button>
84
+ </div>
85
+ </div>
86
+ </div>
87
+ </template>
88
+ <script setup lang="ts">
89
+ import { computed, reactive, watch } from 'vue';
90
+ import { idate, isDateString, isString } from '@fekit/utils';
91
+ import { Icon } from '../basic';
92
+
93
+ // 创建日期
94
+ const cDate = (date: any = null) => {
95
+ return isDateString(date) ? new Date(date) : new Date();
96
+ };
97
+
98
+ // 快捷预设
99
+ const shortcutsList: any = {
100
+ yesterday: {
101
+ text: '昨天',
102
+ func() {
103
+ change({ date: idate(new Date().setDate(new Date().getDate() - 1)).format('YYYY-MM-DD') });
104
+ }
105
+ },
106
+ today: {
107
+ text: '今天',
108
+ func() {
109
+ change({ date: idate(new Date()).format('YYYY-MM-DD') });
110
+ }
111
+ },
112
+ tomorrow: {
113
+ text: '明天',
114
+ func() {
115
+ change({ date: idate(new Date().setDate(new Date().getDate() + 1)).format('YYYY-MM-DD') });
116
+ }
117
+ }
118
+ };
119
+
120
+ const emits: any = defineEmits(['update:modelValue', 'change']);
121
+ interface Props {
122
+ modelValue?: string | number;
123
+ frame: boolean;
124
+ tools?: boolean;
125
+ range?: boolean;
126
+ format?: string;
127
+ picker?: 'date' | 'week' | 'month' | 'quarter';
128
+ holiday?: object;
129
+ shortcuts?: Array<'yesterday' | 'today' | 'tomorrow'>;
130
+ extras?: (item: any) => string;
131
+ rangeValue?: string;
132
+ }
133
+ const props: any = withDefaults(defineProps<Props>(), {
134
+ // 值
135
+ modelValue: '',
136
+ // 是否显示框架
137
+ frame: false,
138
+ // 是否是示工具
139
+ tools: true,
140
+ // 时间范围
141
+ range: false,
142
+ // 面板类型
143
+ picker: 'date',
144
+ // 额外内容
145
+ extras: (item: any) => {
146
+ return `<i class="dib o-ms mb-xs r-xl ${item.today ? 'bg-main' : 'bg-none'}" style="width:.6em; height:.6em;"></i>`;
147
+ },
148
+ // 快捷选择
149
+ shortcuts: () => ['yesterday', 'today', 'tomorrow'],
150
+ // 数据格式化
151
+ format: 'YYYY-MM-DD',
152
+ // 节假日
153
+ holiday: () => ({}),
154
+ // 范围时间
155
+ rangeValue: ''
156
+ });
157
+
158
+ // 内部数据
159
+ const state: any = reactive({
160
+ date: '',
161
+ // 当前时间计算
162
+ curr: computed(() => {
163
+ const date = idate(state.date);
164
+ const days = date.calendar({ group: true, value: [state.value] });
165
+ const { y = 0, M: m = 0, d = 0 } = date.attr || {};
166
+ return { days, y, m, d };
167
+ }),
168
+ // 值
169
+ value: '',
170
+ // 范围时间值
171
+ rangeValue: '',
172
+ // 快捷选择
173
+ shortcuts: computed(() => {
174
+ return props.shortcuts.map((item: any) => {
175
+ return isString(item) ? shortcutsList[item] : item;
176
+ });
177
+ })
178
+ });
179
+
180
+ watch(
181
+ () => props.modelValue,
182
+ (value: any) => {
183
+ state.date = value || '';
184
+ state.value = value || '';
185
+ },
186
+ { deep: true, immediate: true }
187
+ );
188
+ // 范围时间值
189
+ watch(
190
+ () => props.rangeValue,
191
+ (value: any) => {
192
+ state.rangeValue = value;
193
+ },
194
+ { deep: true, immediate: true }
195
+ );
196
+
197
+ // 更新时间
198
+ const upload = (a: any = 'm', b: any = 1) => {
199
+ const date = cDate(state.date);
200
+ if (a === 'm') {
201
+ date.setMonth(date.getMonth() + b);
202
+ } else {
203
+ date.setFullYear(date.getFullYear() + b);
204
+ }
205
+ return idate(date).format(props.format);
206
+ };
207
+
208
+ // 日期前翻
209
+ const prev = (type: any = 'm') => {
210
+ state.date = upload(type, -1);
211
+ };
212
+ // 日期后翻
213
+ const next = (type: any = 'm') => {
214
+ state.date = upload(type, 1);
215
+ };
216
+ // 设置范围时间
217
+ const setRangeValue = (item: any) => {
218
+ if (state.value) {
219
+ state.rangeValue = idate(item.date).format(props.format);
220
+ }
221
+ };
222
+
223
+ // 向外通信
224
+ const change = (item: any) => {
225
+ emits('update:modelValue', item ? idate(item.date).format(props.format) : item);
226
+ emits('change', state.value);
227
+ };
228
+ // 向外通信范围时间
229
+ </script>