foucui 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/dist/components/QiuCanvasKit/QiuCanvasEditor.vue.d.ts +3 -1
  2. package/dist/components/QiuCanvasKit/components/DataModulesPanel.vue.d.ts +1 -0
  3. package/dist/components/QiuTable/index.vue.d.ts +12 -12
  4. package/dist/foucui.css +1 -1
  5. package/dist/foucui.js +7476 -7373
  6. package/dist/foucui.umd.cjs +19 -19
  7. package/package.json +23 -13
  8. package/components/QiuAffix/index.vue +0 -186
  9. package/components/QiuAlert/index.vue +0 -208
  10. package/components/QiuAnchor/context.ts +0 -18
  11. package/components/QiuAnchor/index.vue +0 -180
  12. package/components/QiuAnchorLink/index.vue +0 -67
  13. package/components/QiuApp/index.vue +0 -9
  14. package/components/QiuAutocomplete/index.vue +0 -408
  15. package/components/QiuAvatar/index.vue +0 -140
  16. package/components/QiuBacktop/index.vue +0 -121
  17. package/components/QiuBadge/api/index.ts +0 -389
  18. package/components/QiuBadge/components/BadgeImagePickerDialog.vue +0 -243
  19. package/components/QiuBadge/components/BadgeLibraryManagerDialog.vue +0 -30
  20. package/components/QiuBadge/components/BadgeLibraryPanel.vue +0 -182
  21. package/components/QiuBadge/composables/useTableHostHeight.ts +0 -53
  22. package/components/QiuBadge/index.ts +0 -18
  23. package/components/QiuBadge/shared/BadgeTemplateRenderer.vue +0 -32
  24. package/components/QiuBadge/shared/assetUrl.ts +0 -26
  25. package/components/QiuBadge/shared/badgeTemplate.ts +0 -309
  26. package/components/QiuBadge/utils/chinaAreaData.ts +0 -44
  27. package/components/QiuBadge/utils/hostRegion.ts +0 -22
  28. package/components/QiuBadge/utils/pca-code.json +0 -1
  29. package/components/QiuBadge/utils/pdfFromElement.ts +0 -348
  30. package/components/QiuBadge/views/BadgeLibraryView.vue +0 -32
  31. package/components/QiuBadge/views/BadgeManageView.vue +0 -1364
  32. package/components/QiuBadge/views/BadgeTemplateEditorView.vue +0 -10
  33. package/components/QiuBadge/views/BadgeTemplateListView.vue +0 -229
  34. package/components/QiuBadge/views/DeskLabelTemplateListView.vue +0 -227
  35. package/components/QiuBadge/views/DeskLabelView.vue +0 -683
  36. package/components/QiuBadgeDot/index.vue +0 -87
  37. package/components/QiuButton/index.vue +0 -247
  38. package/components/QiuButtonGroup/index.vue +0 -63
  39. package/components/QiuCanvasKit/QiuCanvasEditor.vue +0 -5503
  40. package/components/QiuCanvasKit/QiuCanvasRenderer.vue +0 -348
  41. package/components/QiuCanvasKit/assetUrl.ts +0 -11
  42. package/components/QiuCanvasKit/components/DataModulesPanel.vue +0 -352
  43. package/components/QiuCanvasKit/export/html.ts +0 -132
  44. package/components/QiuCanvasKit/export/pdf.ts +0 -48
  45. package/components/QiuCanvasKit/export/png.ts +0 -50
  46. package/components/QiuCanvasKit/index.ts +0 -20
  47. package/components/QiuCanvasKit/modules/badgeCompat.ts +0 -84
  48. package/components/QiuCanvasKit/modules/dataRegistry.ts +0 -207
  49. package/components/QiuCanvasKit/modules/merge.ts +0 -71
  50. package/components/QiuCanvasKit/presets/badge.ts +0 -67
  51. package/components/QiuCanvasKit/presets/banner.ts +0 -79
  52. package/components/QiuCanvasKit/types.ts +0 -138
  53. package/components/QiuCard/index.vue +0 -104
  54. package/components/QiuCarousel/context.ts +0 -16
  55. package/components/QiuCarousel/index.vue +0 -343
  56. package/components/QiuCarouselItem/index.vue +0 -47
  57. package/components/QiuCascader/index.vue +0 -879
  58. package/components/QiuCascader/types.ts +0 -48
  59. package/components/QiuCheckbox/QiuCheckboxGroup.vue +0 -78
  60. package/components/QiuCheckbox/index.vue +0 -231
  61. package/components/QiuCheckbox/types.ts +0 -8
  62. package/components/QiuCode/index.vue +0 -64
  63. package/components/QiuCol/col.scss +0 -55
  64. package/components/QiuCol/index.vue +0 -64
  65. package/components/QiuCollapse/context.ts +0 -10
  66. package/components/QiuCollapse/index.vue +0 -70
  67. package/components/QiuCollapseItem/index.vue +0 -167
  68. package/components/QiuColorField/index.vue +0 -296
  69. package/components/QiuColorPicker/README.md +0 -118
  70. package/components/QiuColorPicker/index.vue +0 -60
  71. package/components/QiuColorfulCard/index.vue +0 -101
  72. package/components/QiuCombobox/index.vue +0 -277
  73. package/components/QiuConfigProvider/index.vue +0 -31
  74. package/components/QiuContextMenu/index.vue +0 -209
  75. package/components/QiuDate/index.vue +0 -1134
  76. package/components/QiuDescriptions/context.ts +0 -20
  77. package/components/QiuDescriptions/index.vue +0 -115
  78. package/components/QiuDescriptionsItem/index.vue +0 -103
  79. package/components/QiuDialog/index.vue +0 -828
  80. package/components/QiuDigitalCard/index.vue +0 -159
  81. package/components/QiuDivider/index.vue +0 -185
  82. package/components/QiuDot/index.vue +0 -83
  83. package/components/QiuDrawer/index.vue +0 -350
  84. package/components/QiuDropdown/QiuDropdownItem.vue +0 -74
  85. package/components/QiuDropdown/QiuDropdownMenu.vue +0 -22
  86. package/components/QiuDropdown/context.ts +0 -9
  87. package/components/QiuDropdown/index.vue +0 -189
  88. package/components/QiuEmpty/index.vue +0 -73
  89. package/components/QiuForm/index.vue +0 -172
  90. package/components/QiuForm/types.ts +0 -39
  91. package/components/QiuFormItem/index.vue +0 -276
  92. package/components/QiuFullscreen/index.vue +0 -11
  93. package/components/QiuGrid/index.vue +0 -408
  94. package/components/QiuHoverCard/index.vue +0 -192
  95. package/components/QiuIcon/index.vue +0 -117
  96. package/components/QiuIconPicker/iconify.libraries.ts +0 -182
  97. package/components/QiuIconPicker/icons.catalog.ts +0 -3072
  98. package/components/QiuIconPicker/index.vue +0 -488
  99. package/components/QiuImage/index.vue +0 -177
  100. package/components/QiuInput/index.vue +0 -328
  101. package/components/QiuInputNumber/index.vue +0 -295
  102. package/components/QiuInputOtp/index.vue +0 -190
  103. package/components/QiuKbd/index.vue +0 -57
  104. package/components/QiuLayoutContainer/index.vue +0 -50
  105. package/components/QiuLinkPreview/index.vue +0 -224
  106. package/components/QiuLoading/index.ts +0 -176
  107. package/components/QiuLoading/spinner.vue +0 -820
  108. package/components/QiuLoading/types.ts +0 -44
  109. package/components/QiuMention/index.vue +0 -299
  110. package/components/QiuMenu/QiuMenuRoot.vue +0 -241
  111. package/components/QiuMenu/components/QiuMenuItem.vue +0 -340
  112. package/components/QiuMenu/components/QiuSubMenu.vue +0 -504
  113. package/components/QiuMenu/context.ts +0 -21
  114. package/components/QiuMenu/index.vue +0 -43
  115. package/components/QiuMenuNav/QiuMenuNavItem.vue +0 -100
  116. package/components/QiuMenuNav/QiuMenuNavSub.vue +0 -120
  117. package/components/QiuMenuNav/context.ts +0 -14
  118. package/components/QiuMenuNav/index.vue +0 -148
  119. package/components/QiuMsg/QiuMsgItem.vue +0 -180
  120. package/components/QiuMsg/index.ts +0 -158
  121. package/components/QiuMsg/types.ts +0 -23
  122. package/components/QiuMsgBox/index.ts +0 -147
  123. package/components/QiuNotification/QiuNotificationItem.vue +0 -168
  124. package/components/QiuNotification/index.ts +0 -155
  125. package/components/QiuNotification/types.ts +0 -14
  126. package/components/QiuPage/index.vue +0 -12
  127. package/components/QiuPageHeader/index.vue +0 -115
  128. package/components/QiuPageMain/index.vue +0 -78
  129. package/components/QiuPagination/index.vue +0 -421
  130. package/components/QiuPasswordStrength/index.vue +0 -101
  131. package/components/QiuPopconfirm/index.vue +0 -196
  132. package/components/QiuPopover/index.vue +0 -277
  133. package/components/QiuProgress/index.vue +0 -235
  134. package/components/QiuQrcode/index.vue +0 -302
  135. package/components/QiuQueryForm/components/QiuQueryFormBottomPanel.vue +0 -13
  136. package/components/QiuQueryForm/components/QiuQueryFormLeftPanel.vue +0 -37
  137. package/components/QiuQueryForm/components/QiuQueryFormRightPanel.vue +0 -37
  138. package/components/QiuQueryForm/components/QiuQueryFormTopPanel.vue +0 -13
  139. package/components/QiuQueryForm/index.vue +0 -117
  140. package/components/QiuRadio/QiuRadioGroup.vue +0 -75
  141. package/components/QiuRadio/index.vue +0 -191
  142. package/components/QiuRadio/types.ts +0 -9
  143. package/components/QiuRate/index.vue +0 -184
  144. package/components/QiuRefresh/index.vue +0 -32
  145. package/components/QiuResult/index.vue +0 -103
  146. package/components/QiuRow/index.vue +0 -60
  147. package/components/QiuRow/types.ts +0 -5
  148. package/components/QiuScrollbar/index.vue +0 -107
  149. package/components/QiuSearchBar/index.vue +0 -154
  150. package/components/QiuSegmented/index.vue +0 -120
  151. package/components/QiuSelect/QiuOption.vue +0 -93
  152. package/components/QiuSelect/index.vue +0 -452
  153. package/components/QiuSelect/types.ts +0 -15
  154. package/components/QiuSkeleton/index.vue +0 -78
  155. package/components/QiuSlider/index.vue +0 -266
  156. package/components/QiuSpace/index.vue +0 -95
  157. package/components/QiuSparkline/index.vue +0 -92
  158. package/components/QiuStatistic/index.vue +0 -4
  159. package/components/QiuStatistics/index.vue +0 -123
  160. package/components/QiuStep/index.vue +0 -220
  161. package/components/QiuSteps/context.ts +0 -25
  162. package/components/QiuSteps/index.vue +0 -84
  163. package/components/QiuSwitch/index.vue +0 -145
  164. package/components/QiuTabBar/index.vue +0 -218
  165. package/components/QiuTabBar/types.ts +0 -19
  166. package/components/QiuTabPane/index.vue +0 -82
  167. package/components/QiuTable/columns.ts +0 -16
  168. package/components/QiuTable/export.ts +0 -102
  169. package/components/QiuTable/index.ts +0 -24
  170. package/components/QiuTable/index.vue +0 -3503
  171. package/components/QiuTable/registry.ts +0 -75
  172. package/components/QiuTable/styles/table.scss +0 -1230
  173. package/components/QiuTable/types.ts +0 -413
  174. package/components/QiuTable/useArea.ts +0 -202
  175. package/components/QiuTable/useColumns.ts +0 -325
  176. package/components/QiuTable/useEdit.ts +0 -136
  177. package/components/QiuTable/useExtras.ts +0 -115
  178. package/components/QiuTable/useHistory.ts +0 -77
  179. package/components/QiuTable/useMerge.ts +0 -105
  180. package/components/QiuTable/useResize.ts +0 -86
  181. package/components/QiuTable/useScrollSync.ts +0 -152
  182. package/components/QiuTable/useVirtual.ts +0 -97
  183. package/components/QiuTable/utils.ts +0 -165
  184. package/components/QiuTableColumn/index.vue +0 -101
  185. package/components/QiuTag/index.vue +0 -143
  186. package/components/QiuText/index.vue +0 -99
  187. package/components/QiuTime/index.vue +0 -548
  188. package/components/QiuTimeAgo/index.vue +0 -103
  189. package/components/QiuTimeline/index.vue +0 -54
  190. package/components/QiuTimelineItem/index.vue +0 -140
  191. package/components/QiuTips/index.vue +0 -323
  192. package/components/QiuTooltip/index.vue +0 -237
  193. package/components/QiuTransfer/index.vue +0 -277
  194. package/components/QiuTree/QiuTreeNode.vue +0 -146
  195. package/components/QiuTree/index.vue +0 -143
  196. package/components/QiuTree/types.ts +0 -30
  197. package/components/QiuTreeSelect/index.vue +0 -259
  198. package/components/QiuTrend/index.vue +0 -92
  199. package/components/QiuUpload/index.vue +0 -628
  200. package/components/QiuUploadCrop/index.vue +0 -1267
  201. package/components/QiuWatermark/index.vue +0 -121
  202. package/components/useBodyScrollLock.ts +0 -28
  203. package/dist/components/QiuBadge/utils/pca-code.json.d.ts +0 -3
  204. package/plugins/qiu.ts +0 -83
  205. package/plugins/shortcuts.ts +0 -69
  206. package/src/bridge/@/api/media.ts +0 -8
  207. package/src/bridge/@/api/notice.ts +0 -5
  208. package/src/bridge/@/config/index.ts +0 -38
  209. package/src/bridge/@/config/media.config.ts +0 -37
  210. package/src/bridge/@/config/security.config.ts +0 -8
  211. package/src/bridge/@/i18n/index.ts +0 -6
  212. package/src/bridge/@/store/modules/bing.ts +0 -9
  213. package/src/bridge/@/store/modules/errorLog.ts +0 -9
  214. package/src/bridge/@/store/modules/media.ts +0 -10
  215. package/src/bridge/@/store/modules/routes.ts +0 -10
  216. package/src/bridge/@/store/modules/settings.ts +0 -9
  217. package/src/bridge/@/store/modules/tabs.ts +0 -9
  218. package/src/bridge/@/store/modules/user.ts +0 -9
  219. package/src/bridge/@/utils/convertToCamelCase.ts +0 -11
  220. package/src/bridge/@/utils/index.ts +0 -9
  221. package/src/bridge/@/utils/pageTitle.ts +0 -4
  222. package/src/bridge/@/utils/routes.ts +0 -14
  223. package/src/bridge/@/utils/validate.ts +0 -17
  224. package/src/bridge/@qiu/plugins/shortcuts.ts +0 -3
  225. package/src/i18n.ts +0 -8
  226. package/src/icons/qiu-logo.svg +0 -1
  227. package/styles/dark.scss +0 -194
  228. package/styles/normalize.css +0 -349
  229. package/styles/plain.scss +0 -423
  230. package/styles/qiu-tokens.scss +0 -40
  231. package/styles/qiu.scss +0 -1149
  232. package/styles/technology.scss +0 -452
  233. package/styles/var.scss +0 -382
  234. package/styles/variables.scss +0 -77
@@ -1,1134 +0,0 @@
1
- <template>
2
- <div
3
- ref="rootRef"
4
- class="qiu-date"
5
- :class="[
6
- `qiu-date--${type}`,
7
- { 'is-disabled': disabled, 'is-focused': panelVisible },
8
- ]"
9
- >
10
- <div class="qiu-date__editor" @click="togglePanel">
11
- <template v-if="isRange">
12
- <input
13
- class="qiu-date__input"
14
- :value="displayStartText"
15
- :placeholder="startPlaceholder || startPlaceholderFallback"
16
- readonly
17
- :disabled="disabled"
18
- />
19
- <span class="qiu-date__separator">{{ rangeSeparator }}</span>
20
- <input
21
- class="qiu-date__input"
22
- :value="displayEndText"
23
- :placeholder="endPlaceholder || endPlaceholderFallback"
24
- readonly
25
- :disabled="disabled"
26
- />
27
- </template>
28
- <input
29
- v-else
30
- class="qiu-date__input qiu-date__input--single"
31
- :value="singleText"
32
- :placeholder="placeholder || singlePlaceholderFallback"
33
- readonly
34
- :disabled="disabled"
35
- />
36
- <button
37
- v-if="clearable && hasValue && !disabled"
38
- type="button"
39
- class="qiu-date__clear"
40
- @click.stop="clearValue"
41
- >
42
- ×
43
- </button>
44
- <qiu-icon icon="calendar-line" class="qiu-date__icon" />
45
- </div>
46
-
47
- <Teleport to="body">
48
- <Transition name="qiu-date-fade">
49
- <div
50
- v-if="panelVisible"
51
- ref="panelRef"
52
- class="qiu-date-panel"
53
- :class="[
54
- popperClass,
55
- {
56
- 'qiu-date-panel--lunar': showLunar && panelUnit === 'date',
57
- 'qiu-date-panel--range': isRange,
58
- [`qiu-date-panel--${panelUnit}`]: true,
59
- },
60
- ]"
61
- :style="panelStyle"
62
- @mousedown.prevent
63
- >
64
- <div class="qiu-date-panel__body" :class="{ 'is-range': isRange }">
65
- <!-- 左面板 / 单面板 -->
66
- <div class="qiu-date-panel__side">
67
- <div class="qiu-date-panel__header">
68
- <button type="button" class="qiu-date-panel__nav" @click="navLeft(-1)">‹</button>
69
- <span class="qiu-date-panel__title">{{ leftTitle }}</span>
70
- <button type="button" class="qiu-date-panel__nav" @click="navLeft(1)">›</button>
71
- </div>
72
-
73
- <template v-if="panelUnit === 'date'">
74
- <div class="qiu-date-panel__weeks">
75
- <span v-for="w in weekLabels" :key="w" class="qiu-date-panel__week">{{ w }}</span>
76
- </div>
77
- <div class="qiu-date-panel__grid qiu-date-panel__grid--day">
78
- <button
79
- v-for="cell in leftDayCells"
80
- :key="`l-${cell.key}`"
81
- type="button"
82
- class="qiu-date-panel__cell"
83
- :class="cellClass(cell)"
84
- :disabled="cell.disabled"
85
- @click="pickOnSide('start', cell)"
86
- >
87
- <div
88
- class="qiu-date__cell"
89
- :class="{ 'is-selected': cell.selected, 'is-today': cell.isToday }"
90
- >
91
- <span class="qiu-date__solar">{{ cell.day }}</span>
92
- <span
93
- v-if="showLunar"
94
- class="qiu-date__lunar"
95
- :class="{ 'is-festival': cell.lunar.festival }"
96
- >
97
- {{ cell.lunar.label }}
98
- </span>
99
- </div>
100
- </button>
101
- </div>
102
- </template>
103
-
104
- <div v-else-if="panelUnit === 'month'" class="qiu-date-panel__grid qiu-date-panel__grid--month">
105
- <button
106
- v-for="cell in leftMonthCells"
107
- :key="`lm-${cell.key}`"
108
- type="button"
109
- class="qiu-date-panel__cell qiu-date-panel__cell--month"
110
- :class="cellClass(cell)"
111
- :disabled="cell.disabled"
112
- @click="pickOnSide('start', cell)"
113
- >
114
- <div class="qiu-date__cell" :class="{ 'is-selected': cell.selected }">
115
- <span class="qiu-date__solar">{{ cell.label }}</span>
116
- </div>
117
- </button>
118
- </div>
119
-
120
- <div v-else class="qiu-date-panel__grid qiu-date-panel__grid--year">
121
- <button
122
- v-for="cell in leftYearCells"
123
- :key="`ly-${cell.key}`"
124
- type="button"
125
- class="qiu-date-panel__cell qiu-date-panel__cell--year"
126
- :class="cellClass(cell)"
127
- :disabled="cell.disabled"
128
- @click="pickOnSide('start', cell)"
129
- >
130
- <div class="qiu-date__cell" :class="{ 'is-selected': cell.selected }">
131
- <span class="qiu-date__solar">{{ cell.label }}</span>
132
- </div>
133
- </button>
134
- </div>
135
- </div>
136
-
137
- <!-- 右面板(区间) -->
138
- <div v-if="isRange" class="qiu-date-panel__side">
139
- <div class="qiu-date-panel__header">
140
- <button type="button" class="qiu-date-panel__nav" @click="navRight(-1)">‹</button>
141
- <span class="qiu-date-panel__title">{{ rightTitle }}</span>
142
- <button type="button" class="qiu-date-panel__nav" @click="navRight(1)">›</button>
143
- </div>
144
-
145
- <template v-if="panelUnit === 'date'">
146
- <div class="qiu-date-panel__weeks">
147
- <span v-for="w in weekLabels" :key="`r-${w}`" class="qiu-date-panel__week">{{ w }}</span>
148
- </div>
149
- <div class="qiu-date-panel__grid qiu-date-panel__grid--day">
150
- <button
151
- v-for="cell in rightDayCells"
152
- :key="`r-${cell.key}`"
153
- type="button"
154
- class="qiu-date-panel__cell"
155
- :class="cellClass(cell)"
156
- :disabled="cell.disabled"
157
- @click="pickOnSide('end', cell)"
158
- >
159
- <div
160
- class="qiu-date__cell"
161
- :class="{ 'is-selected': cell.selected, 'is-today': cell.isToday }"
162
- >
163
- <span class="qiu-date__solar">{{ cell.day }}</span>
164
- <span
165
- v-if="showLunar"
166
- class="qiu-date__lunar"
167
- :class="{ 'is-festival': cell.lunar.festival }"
168
- >
169
- {{ cell.lunar.label }}
170
- </span>
171
- </div>
172
- </button>
173
- </div>
174
- </template>
175
-
176
- <div v-else-if="panelUnit === 'month'" class="qiu-date-panel__grid qiu-date-panel__grid--month">
177
- <button
178
- v-for="cell in rightMonthCells"
179
- :key="`rm-${cell.key}`"
180
- type="button"
181
- class="qiu-date-panel__cell qiu-date-panel__cell--month"
182
- :class="cellClass(cell)"
183
- :disabled="cell.disabled"
184
- @click="pickOnSide('end', cell)"
185
- >
186
- <div class="qiu-date__cell" :class="{ 'is-selected': cell.selected }">
187
- <span class="qiu-date__solar">{{ cell.label }}</span>
188
- </div>
189
- </button>
190
- </div>
191
-
192
- <div v-else class="qiu-date-panel__grid qiu-date-panel__grid--year">
193
- <button
194
- v-for="cell in rightYearCells"
195
- :key="`ry-${cell.key}`"
196
- type="button"
197
- class="qiu-date-panel__cell qiu-date-panel__cell--year"
198
- :class="cellClass(cell)"
199
- :disabled="cell.disabled"
200
- @click="pickOnSide('end', cell)"
201
- >
202
- <div class="qiu-date__cell" :class="{ 'is-selected': cell.selected }">
203
- <span class="qiu-date__solar">{{ cell.label }}</span>
204
- </div>
205
- </button>
206
- </div>
207
- </div>
208
- </div>
209
-
210
- <div v-if="isRange" class="qiu-date-panel__footer">
211
- <button type="button" class="qiu-date-panel__btn qiu-date-panel__btn--text" @click="onCancel">
212
- 取消
213
- </button>
214
- <button
215
- type="button"
216
- class="qiu-date-panel__btn qiu-date-panel__btn--primary"
217
- :disabled="!canConfirm"
218
- @click="onConfirm"
219
- >
220
- 确定
221
- </button>
222
- </div>
223
- </div>
224
- </Transition>
225
- </Teleport>
226
- </div>
227
- </template>
228
-
229
- <script lang="ts" setup>
230
- /**
231
- * QiuDate — 纯自研日历面板 + 中国农历
232
- * 区间模式:左右双面板 + 联动纠偏 + 确定/取消(参考 el-date-picker)
233
- */
234
- import { Solar } from 'lunar-javascript'
235
-
236
- defineOptions({ name: 'QiuDate' })
237
-
238
- type PanelUnit = 'date' | 'month' | 'year'
239
- type Side = 'start' | 'end'
240
-
241
- const props = withDefaults(
242
- defineProps<{
243
- modelValue?: any
244
- showLunar?: boolean
245
- type?: string
246
- placeholder?: string
247
- startPlaceholder?: string
248
- endPlaceholder?: string
249
- format?: string
250
- valueFormat?: string
251
- disabled?: boolean
252
- clearable?: boolean
253
- size?: 'large' | 'default' | 'small'
254
- editable?: boolean
255
- readonly?: boolean
256
- rangeSeparator?: string
257
- disabledDate?: (date: Date) => boolean
258
- shortcuts?: any[]
259
- teleported?: boolean
260
- popperClass?: string
261
- }>(),
262
- {
263
- showLunar: true,
264
- type: 'date',
265
- clearable: true,
266
- editable: true,
267
- rangeSeparator: '至',
268
- }
269
- )
270
-
271
- const emit = defineEmits<{
272
- 'update:modelValue': [any]
273
- change: [any]
274
- 'calendar-change': [any]
275
- 'visible-change': [boolean]
276
- 'panel-change': [any]
277
- }>()
278
-
279
- const rootRef = ref<HTMLElement | null>(null)
280
- const panelRef = ref<HTMLElement | null>(null)
281
- const panelVisible = ref(false)
282
- const panelStyle = ref<Record<string, string>>({})
283
-
284
- const leftYear = ref(new Date().getFullYear())
285
- const leftMonth = ref(new Date().getMonth())
286
- const rightYear = ref(new Date().getFullYear())
287
- const rightMonth = ref(new Date().getMonth())
288
- /** 年份面板十年起点 */
289
- const leftDecade = ref(Math.floor(new Date().getFullYear() / 10) * 10)
290
- const rightDecade = ref(Math.floor(new Date().getFullYear() / 10) * 10 + 10)
291
-
292
- const draftStart = ref<Date | null>(null)
293
- const draftEnd = ref<Date | null>(null)
294
-
295
- const weekLabels = ['日', '一', '二', '三', '四', '五', '六']
296
- const monthLabels = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
297
-
298
- const panelUnit = computed<PanelUnit>(() => {
299
- const t = props.type || 'date'
300
- if (t === 'year' || t === 'yearrange') return 'year'
301
- if (t === 'month' || t === 'monthrange') return 'month'
302
- return 'date'
303
- })
304
-
305
- const isRange = computed(() =>
306
- ['daterange', 'datetimerange', 'monthrange', 'yearrange'].includes(props.type || '')
307
- )
308
-
309
- const resolveDateFormats = (type: string) => {
310
- switch (type) {
311
- case 'datetime':
312
- case 'datetimerange':
313
- return { format: 'YYYY-MM-DD HH:mm:ss', valueFormat: 'YYYY-MM-DD HH:mm:ss' }
314
- case 'month':
315
- case 'monthrange':
316
- return { format: 'YYYY-MM', valueFormat: 'YYYY-MM' }
317
- case 'year':
318
- case 'yearrange':
319
- return { format: 'YYYY', valueFormat: 'YYYY' }
320
- default:
321
- return { format: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD' }
322
- }
323
- }
324
-
325
- const valueFormat = computed(
326
- () => props.valueFormat || resolveDateFormats(props.type || 'date').valueFormat
327
- )
328
- const displayFormat = computed(
329
- () => props.format || resolveDateFormats(props.type || 'date').format
330
- )
331
-
332
- const startPlaceholderFallback = computed(() => {
333
- if (panelUnit.value === 'year') return '开始年份'
334
- if (panelUnit.value === 'month') return '开始月份'
335
- return '开始日期'
336
- })
337
- const endPlaceholderFallback = computed(() => {
338
- if (panelUnit.value === 'year') return '结束年份'
339
- if (panelUnit.value === 'month') return '结束月份'
340
- return '结束日期'
341
- })
342
- const singlePlaceholderFallback = computed(() => {
343
- if (panelUnit.value === 'year') return '选择年份'
344
- if (panelUnit.value === 'month') return '选择月份'
345
- return '选择日期'
346
- })
347
-
348
- const pad = (n: number) => String(n).padStart(2, '0')
349
-
350
- const formatDate = (d: Date | null, fmt: string) => {
351
- if (!d) return ''
352
- return fmt
353
- .replace('YYYY', String(d.getFullYear()))
354
- .replace('MM', pad(d.getMonth() + 1))
355
- .replace('DD', pad(d.getDate()))
356
- }
357
-
358
- const parseValue = (v: any): Date | null => {
359
- if (!v && v !== 0) return null
360
- if (v instanceof Date) return Number.isNaN(v.getTime()) ? null : v
361
- const s = String(v).trim()
362
- if (!s) return null
363
- let m = s.match(/^(\d{4})-(\d{2})-(\d{2})/)
364
- if (m) return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]))
365
- m = s.match(/^(\d{4})-(\d{2})$/)
366
- if (m) return new Date(Number(m[1]), Number(m[2]) - 1, 1)
367
- m = s.match(/^(\d{4})$/)
368
- if (m) return new Date(Number(m[1]), 0, 1)
369
- return null
370
- }
371
-
372
- const parseRange = (v: any): [Date | null, Date | null] => {
373
- if (!Array.isArray(v)) return [null, null]
374
- return [parseValue(v[0]), parseValue(v[1])]
375
- }
376
-
377
- const toOutput = (d: Date) => formatDate(d, valueFormat.value)
378
-
379
- const dayStart = (d: Date) => new Date(d.getFullYear(), d.getMonth(), d.getDate())
380
- const monthStart = (d: Date) => new Date(d.getFullYear(), d.getMonth(), 1)
381
- const yearStart = (d: Date) => new Date(d.getFullYear(), 0, 1)
382
-
383
- const normalizeUnit = (d: Date) => {
384
- if (panelUnit.value === 'year') return yearStart(d)
385
- if (panelUnit.value === 'month') return monthStart(d)
386
- return dayStart(d)
387
- }
388
-
389
- const unitTime = (d: Date) => normalizeUnit(d).getTime()
390
-
391
- const sameUnit = (a: Date | null, b: Date | null) => !!a && !!b && unitTime(a) === unitTime(b)
392
-
393
- const addMonths = (d: Date, n: number) => {
394
- const next = new Date(d.getFullYear(), d.getMonth() + n, 1)
395
- if (panelUnit.value === 'date') {
396
- const day = d.getDate()
397
- const max = new Date(next.getFullYear(), next.getMonth() + 1, 0).getDate()
398
- next.setDate(Math.min(day, max))
399
- }
400
- return normalizeUnit(next)
401
- }
402
-
403
- const addYears = (d: Date, n: number) => {
404
- const next = new Date(d)
405
- next.setFullYear(d.getFullYear() + n)
406
- return normalizeUnit(next)
407
- }
408
-
409
- const shiftEndForward = (start: Date) =>
410
- panelUnit.value === 'year' ? addYears(start, 1) : addMonths(start, 1)
411
-
412
- const shiftStartBackward = (end: Date) =>
413
- panelUnit.value === 'year' ? addYears(end, -1) : addMonths(end, -1)
414
-
415
- const singleDate = computed(() => (isRange.value ? null : parseValue(props.modelValue)))
416
- const rangeDates = computed((): [Date | null, Date | null] =>
417
- isRange.value ? parseRange(props.modelValue) : [null, null]
418
- )
419
-
420
- const activeStart = computed(() => (panelVisible.value && isRange.value ? draftStart.value : rangeDates.value[0]))
421
- const activeEnd = computed(() => (panelVisible.value && isRange.value ? draftEnd.value : rangeDates.value[1]))
422
-
423
- const singleText = computed(() => formatDate(singleDate.value, displayFormat.value))
424
- const displayStartText = computed(() =>
425
- formatDate(panelVisible.value ? draftStart.value : rangeDates.value[0], displayFormat.value)
426
- )
427
- const displayEndText = computed(() =>
428
- formatDate(panelVisible.value ? draftEnd.value : rangeDates.value[1], displayFormat.value)
429
- )
430
-
431
- const hasValue = computed(() => {
432
- if (isRange.value) return !!(rangeDates.value[0] || rangeDates.value[1])
433
- return !!singleDate.value
434
- })
435
-
436
- const canConfirm = computed(() => !!(draftStart.value && draftEnd.value))
437
-
438
- const leftTitle = computed(() => {
439
- if (panelUnit.value === 'year') return `${leftDecade.value}年 - ${leftDecade.value + 9}年`
440
- if (panelUnit.value === 'month') return `${leftYear.value}年`
441
- return `${leftYear.value}年 ${leftMonth.value + 1}月`
442
- })
443
-
444
- const rightTitle = computed(() => {
445
- if (panelUnit.value === 'year') return `${rightDecade.value}年 - ${rightDecade.value + 9}年`
446
- if (panelUnit.value === 'month') return `${rightYear.value}年`
447
- return `${rightYear.value}年 ${rightMonth.value + 1}月`
448
- })
449
-
450
- const lunarCache = new Map<string, { label: string; festival?: string }>()
451
-
452
- const lunarOfDate = (d: Date) => {
453
- try {
454
- const key = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`
455
- if (lunarCache.has(key)) return lunarCache.get(key)!
456
- const solar = Solar.fromYmd(d.getFullYear(), d.getMonth() + 1, d.getDate())
457
- const lunar = solar.getLunar()
458
- const festivals = [...lunar.getFestivals(), ...solar.getFestivals()]
459
- const jieQi = lunar.getJieQi()
460
- let label = lunar.getDayInChinese()
461
- let festival = ''
462
- if (festivals.length) {
463
- festival = festivals[0]
464
- label = festival
465
- } else if (jieQi) {
466
- festival = jieQi
467
- label = jieQi
468
- } else if (lunar.getDay() === 1) {
469
- label = lunar.getMonthInChinese() + '月'
470
- }
471
- const info = { label, festival: festival || undefined }
472
- lunarCache.set(key, info)
473
- return info
474
- } catch {
475
- return { label: '' }
476
- }
477
- }
478
-
479
- const isToday = (d: Date) => {
480
- const n = new Date()
481
- return d.getFullYear() === n.getFullYear() && d.getMonth() === n.getMonth() && d.getDate() === n.getDate()
482
- }
483
-
484
- const inRangeUnit = (d: Date, start: Date | null, end: Date | null) => {
485
- if (!start || !end) return false
486
- const t = unitTime(d)
487
- const a = unitTime(start)
488
- const b = unitTime(end)
489
- const lo = Math.min(a, b)
490
- const hi = Math.max(a, b)
491
- return t >= lo && t <= hi
492
- }
493
-
494
- const rangeStateOf = (date: Date) => {
495
- const s = isRange.value ? activeStart.value : null
496
- const e = isRange.value ? activeEnd.value : null
497
- if (isRange.value) {
498
- if (sameUnit(date, s) && sameUnit(date, e)) return 'start-date end-date'
499
- if (sameUnit(date, s)) return 'start-date'
500
- if (sameUnit(date, e)) return 'end-date'
501
- if (inRangeUnit(date, s, e)) return 'in-range'
502
- return ''
503
- }
504
- return ''
505
- }
506
-
507
- const buildDayCells = (y: number, m: number) => {
508
- const first = new Date(y, m, 1)
509
- const startOffset = first.getDay()
510
- const daysInMonth = new Date(y, m + 1, 0).getDate()
511
- const cells: any[] = []
512
-
513
- const push = (date: Date, inMonth: boolean) => {
514
- const disabled = props.disabledDate?.(date) ?? false
515
- const selected = isRange.value
516
- ? sameUnit(date, activeStart.value) || sameUnit(date, activeEnd.value)
517
- : sameUnit(date, singleDate.value)
518
- cells.push({
519
- key: `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`,
520
- date: normalizeUnit(date),
521
- day: date.getDate(),
522
- label: String(date.getDate()),
523
- inMonth,
524
- disabled,
525
- selected,
526
- rangeState: rangeStateOf(date),
527
- isToday: isToday(date),
528
- lunar: lunarOfDate(date),
529
- })
530
- }
531
-
532
- for (let i = 0; i < startOffset; i++) {
533
- push(new Date(y, m, -startOffset + i + 1), false)
534
- }
535
- for (let day = 1; day <= daysInMonth; day++) {
536
- push(new Date(y, m, day), true)
537
- }
538
- while (cells.length % 7 !== 0) {
539
- const last = cells[cells.length - 1].date as Date
540
- push(new Date(last.getFullYear(), last.getMonth(), last.getDate() + 1), false)
541
- }
542
- return cells
543
- }
544
-
545
- const buildMonthCells = (y: number) =>
546
- monthLabels.map((label, i) => {
547
- const date = new Date(y, i, 1)
548
- const disabled = props.disabledDate?.(date) ?? false
549
- const selected = isRange.value
550
- ? sameUnit(date, activeStart.value) || sameUnit(date, activeEnd.value)
551
- : sameUnit(date, singleDate.value)
552
- return {
553
- key: `${y}-${i}`,
554
- date: normalizeUnit(date),
555
- label,
556
- day: i + 1,
557
- inMonth: true,
558
- disabled,
559
- selected,
560
- rangeState: rangeStateOf(date),
561
- isToday: false,
562
- lunar: { label: '' },
563
- }
564
- })
565
-
566
- const buildYearCells = (decade: number) =>
567
- Array.from({ length: 10 }, (_, i) => {
568
- const y = decade + i
569
- const date = new Date(y, 0, 1)
570
- const disabled = props.disabledDate?.(date) ?? false
571
- const selected = isRange.value
572
- ? sameUnit(date, activeStart.value) || sameUnit(date, activeEnd.value)
573
- : sameUnit(date, singleDate.value)
574
- return {
575
- key: `y-${y}`,
576
- date: normalizeUnit(date),
577
- label: String(y),
578
- day: y,
579
- inMonth: true,
580
- disabled,
581
- selected,
582
- rangeState: rangeStateOf(date),
583
- isToday: false,
584
- lunar: { label: '' },
585
- }
586
- })
587
-
588
- const leftDayCells = computed(() => buildDayCells(leftYear.value, leftMonth.value))
589
- const rightDayCells = computed(() => buildDayCells(rightYear.value, rightMonth.value))
590
- const leftMonthCells = computed(() => buildMonthCells(leftYear.value))
591
- const rightMonthCells = computed(() => buildMonthCells(rightYear.value))
592
- const leftYearCells = computed(() => buildYearCells(leftDecade.value))
593
- const rightYearCells = computed(() => buildYearCells(rightDecade.value))
594
-
595
- const cellClass = (cell: any) => {
596
- const rs = String(cell.rangeState || '')
597
- return {
598
- 'is-other-month': !cell.inMonth,
599
- 'is-disabled': cell.disabled,
600
- 'is-selected': cell.selected,
601
- 'is-today': cell.isToday,
602
- 'in-range': rs.includes('in-range'),
603
- 'start-date': rs.includes('start-date'),
604
- 'end-date': rs.includes('end-date'),
605
- }
606
- }
607
-
608
- const syncRightViewAfterLeft = () => {
609
- if (panelUnit.value === 'date') {
610
- let y = leftYear.value
611
- let m = leftMonth.value + 1
612
- if (m > 11) {
613
- m = 0
614
- y += 1
615
- }
616
- rightYear.value = y
617
- rightMonth.value = m
618
- } else if (panelUnit.value === 'month') {
619
- rightYear.value = leftYear.value + 1
620
- } else {
621
- rightDecade.value = leftDecade.value + 10
622
- }
623
- }
624
-
625
- const syncLeftViewFromStart = (d: Date) => {
626
- leftYear.value = d.getFullYear()
627
- leftMonth.value = d.getMonth()
628
- leftDecade.value = Math.floor(d.getFullYear() / 10) * 10
629
- }
630
-
631
- const syncRightViewFromEnd = (d: Date) => {
632
- rightYear.value = d.getFullYear()
633
- rightMonth.value = d.getMonth()
634
- rightDecade.value = Math.floor(d.getFullYear() / 10) * 10
635
- }
636
-
637
- const updatePanelPosition = () => {
638
- const root = rootRef.value
639
- const panel = panelRef.value
640
- if (!root) return
641
- const rect = root.getBoundingClientRect()
642
- const panelW = panel?.offsetWidth || (isRange.value ? 640 : 322)
643
- const panelH = panel?.offsetHeight || 360
644
- let top = rect.bottom + 4
645
- let left = rect.left
646
- if (left + panelW > window.innerWidth - 8) {
647
- left = Math.max(8, window.innerWidth - panelW - 8)
648
- }
649
- if (top + panelH > window.innerHeight - 8) {
650
- top = Math.max(8, rect.top - panelH - 4)
651
- }
652
- panelStyle.value = {
653
- position: 'fixed',
654
- top: `${Math.max(8, top)}px`,
655
- left: `${Math.max(8, left)}px`,
656
- zIndex: '4000',
657
- }
658
- }
659
-
660
- const openPanel = async () => {
661
- if (props.disabled) return
662
-
663
- // 先按触发器定位,避免面板以空 style 落在页面左上角
664
- updatePanelPosition()
665
- panelVisible.value = true
666
- emit('visible-change', true)
667
-
668
- if (isRange.value) {
669
- const [s, e] = rangeDates.value
670
- draftStart.value = s ? normalizeUnit(s) : null
671
- draftEnd.value = e ? normalizeUnit(e) : null
672
- const anchorStart = draftStart.value || new Date()
673
- const anchorEnd = draftEnd.value || shiftEndForward(normalizeUnit(anchorStart))
674
- syncLeftViewFromStart(anchorStart)
675
- syncRightViewFromEnd(anchorEnd)
676
- // 保证右面板不早于左面板视图
677
- if (panelUnit.value === 'date') {
678
- const leftKey = leftYear.value * 12 + leftMonth.value
679
- const rightKey = rightYear.value * 12 + rightMonth.value
680
- if (rightKey <= leftKey) syncRightViewAfterLeft()
681
- } else if (panelUnit.value === 'month') {
682
- if (rightYear.value <= leftYear.value) rightYear.value = leftYear.value + 1
683
- } else if (rightDecade.value <= leftDecade.value) {
684
- rightDecade.value = leftDecade.value + 10
685
- }
686
- } else {
687
- const anchor = singleDate.value || new Date()
688
- syncLeftViewFromStart(anchor)
689
- }
690
-
691
- await nextTick()
692
- requestAnimationFrame(() => {
693
- updatePanelPosition()
694
- requestAnimationFrame(() => updatePanelPosition())
695
- })
696
- emit('panel-change', [leftYear.value, leftMonth.value])
697
- }
698
-
699
- const closePanel = () => {
700
- if (!panelVisible.value) return
701
- panelVisible.value = false
702
- draftStart.value = null
703
- draftEnd.value = null
704
- emit('visible-change', false)
705
- }
706
-
707
- const togglePanel = () => {
708
- if (panelVisible.value) closePanel()
709
- else openPanel()
710
- }
711
-
712
- const navLeft = (dir: number) => {
713
- if (panelUnit.value === 'date') {
714
- let m = leftMonth.value + dir
715
- let y = leftYear.value
716
- if (m < 0) {
717
- m = 11
718
- y -= 1
719
- } else if (m > 11) {
720
- m = 0
721
- y += 1
722
- }
723
- leftYear.value = y
724
- leftMonth.value = m
725
- } else if (panelUnit.value === 'month') {
726
- leftYear.value += dir
727
- } else {
728
- leftDecade.value += dir * 10
729
- }
730
- emit('panel-change', [leftYear.value, leftMonth.value])
731
- }
732
-
733
- const navRight = (dir: number) => {
734
- if (panelUnit.value === 'date') {
735
- let m = rightMonth.value + dir
736
- let y = rightYear.value
737
- if (m < 0) {
738
- m = 11
739
- y -= 1
740
- } else if (m > 11) {
741
- m = 0
742
- y += 1
743
- }
744
- rightYear.value = y
745
- rightMonth.value = m
746
- } else if (panelUnit.value === 'month') {
747
- rightYear.value += dir
748
- } else {
749
- rightDecade.value += dir * 10
750
- }
751
- emit('panel-change', [rightYear.value, rightMonth.value])
752
- }
753
-
754
- const emitChange = (val: any) => {
755
- emit('update:modelValue', val)
756
- emit('change', val)
757
- emit('calendar-change', val)
758
- }
759
-
760
- const pickOnSide = (side: Side, cell: any) => {
761
- if (cell.disabled) return
762
- const d = normalizeUnit(cell.date as Date)
763
-
764
- if (!isRange.value) {
765
- emitChange(toOutput(d))
766
- closePanel()
767
- return
768
- }
769
-
770
- if (side === 'start') {
771
- draftStart.value = d
772
- if (draftEnd.value && unitTime(d) > unitTime(draftEnd.value)) {
773
- draftEnd.value = shiftEndForward(d)
774
- syncRightViewFromEnd(draftEnd.value)
775
- }
776
- } else {
777
- draftEnd.value = d
778
- if (draftStart.value && unitTime(d) < unitTime(draftStart.value)) {
779
- draftStart.value = shiftStartBackward(d)
780
- syncLeftViewFromStart(draftStart.value)
781
- }
782
- }
783
- }
784
-
785
- const onConfirm = () => {
786
- if (!draftStart.value || !draftEnd.value) return
787
- let s = draftStart.value
788
- let e = draftEnd.value
789
- if (unitTime(s) > unitTime(e)) {
790
- e = shiftEndForward(s)
791
- }
792
- emitChange([toOutput(s), toOutput(e)])
793
- closePanel()
794
- }
795
-
796
- /** 取消 = 空选并关闭(参考 el-date-picker 清空语义) */
797
- const onCancel = () => {
798
- draftStart.value = null
799
- draftEnd.value = null
800
- emitChange([])
801
- closePanel()
802
- }
803
-
804
- const clearValue = () => {
805
- emitChange(isRange.value ? [] : '')
806
- }
807
-
808
- const onDocClick = (e: MouseEvent) => {
809
- if (!panelVisible.value) return
810
- const t = e.target as Node
811
- if (rootRef.value?.contains(t) || panelRef.value?.contains(t)) return
812
- // 点外部:丢弃未确认草稿,保留原值
813
- closePanel()
814
- }
815
-
816
- watch(panelVisible, (v) => {
817
- if (v) {
818
- document.addEventListener('click', onDocClick, true)
819
- window.addEventListener('scroll', updatePanelPosition, true)
820
- window.addEventListener('resize', updatePanelPosition)
821
- } else {
822
- document.removeEventListener('click', onDocClick, true)
823
- window.removeEventListener('scroll', updatePanelPosition, true)
824
- window.removeEventListener('resize', updatePanelPosition)
825
- }
826
- })
827
-
828
- onBeforeUnmount(() => {
829
- document.removeEventListener('click', onDocClick, true)
830
- window.removeEventListener('scroll', updatePanelPosition, true)
831
- window.removeEventListener('resize', updatePanelPosition)
832
- })
833
- </script>
834
-
835
- <style lang="scss">
836
- .qiu-date {
837
- display: inline-flex;
838
- min-width: 220px;
839
-
840
- &--daterange,
841
- &--datetimerange,
842
- &--monthrange,
843
- &--yearrange {
844
- min-width: 280px;
845
- }
846
-
847
- &__editor {
848
- display: flex;
849
- flex: 1;
850
- gap: 4px;
851
- align-items: center;
852
- min-height: 32px;
853
- padding: 0 8px;
854
- cursor: pointer;
855
- background: var(--qiu-bg-color, #fff);
856
- border: 1px solid var(--qiu-border-color, #dcdfe6);
857
- border-radius: var(--qiu-border-radius-base, 4px);
858
- transition: border-color 0.2s ease;
859
-
860
- &:hover,
861
- .is-focused & {
862
- border-color: var(--qiu-color-primary, #409eff);
863
- }
864
- }
865
-
866
- &__input {
867
- flex: 1;
868
- min-width: 0;
869
- padding: 0;
870
- font-size: 14px;
871
- color: var(--qiu-text-color-primary, #303133);
872
- cursor: pointer;
873
- background: transparent;
874
- border: 0;
875
- outline: none;
876
-
877
- &--single {
878
- width: 100%;
879
- }
880
- }
881
-
882
- &__separator {
883
- flex-shrink: 0;
884
- font-size: 13px;
885
- color: var(--qiu-text-color-secondary, #909399);
886
- }
887
-
888
- &__clear {
889
- flex-shrink: 0;
890
- padding: 0 4px;
891
- font-size: 16px;
892
- line-height: 1;
893
- color: var(--qiu-text-color-secondary, #909399);
894
- cursor: pointer;
895
- background: transparent;
896
- border: 0;
897
- }
898
-
899
- &__icon {
900
- flex-shrink: 0;
901
- font-size: 16px;
902
- color: var(--qiu-text-color-secondary, #909399);
903
- }
904
- }
905
-
906
- .qiu-date-panel {
907
- position: fixed;
908
- top: 0;
909
- left: 0;
910
- width: 322px;
911
- padding: 12px;
912
- background: var(--qiu-bg-color-overlay, #fff);
913
- border: 1px solid var(--qiu-border-color-light, #e4e7ed);
914
- border-radius: 8px;
915
- box-shadow: var(--qiu-box-shadow-light, 0 2px 12px rgb(0 0 0 / 10%));
916
- z-index: 4000;
917
-
918
- &--range {
919
- width: auto;
920
- max-width: calc(100vw - 16px);
921
- }
922
-
923
- &__body {
924
- display: flex;
925
- gap: 0;
926
-
927
- &.is-range .qiu-date-panel__side + .qiu-date-panel__side {
928
- margin-left: 12px;
929
- padding-left: 12px;
930
- border-left: 1px solid var(--qiu-border-color-lighter, #ebeef5);
931
- }
932
- }
933
-
934
- &__side {
935
- width: 298px;
936
- }
937
-
938
- &__header {
939
- display: flex;
940
- align-items: center;
941
- justify-content: space-between;
942
- margin-bottom: 8px;
943
- }
944
-
945
- &__title {
946
- font-size: 14px;
947
- font-weight: 600;
948
- color: var(--qiu-text-color-primary, #303133);
949
- }
950
-
951
- &__nav {
952
- width: 28px;
953
- height: 28px;
954
- font-size: 18px;
955
- line-height: 1;
956
- color: var(--qiu-text-color-regular, #606266);
957
- cursor: pointer;
958
- background: transparent;
959
- border: 0;
960
- border-radius: 4px;
961
-
962
- &:hover {
963
- color: var(--qiu-color-primary, #409eff);
964
- background: var(--qiu-fill-color-light, #f5f7fa);
965
- }
966
- }
967
-
968
- &__weeks {
969
- display: grid;
970
- grid-template-columns: repeat(7, 1fr);
971
- margin-bottom: 4px;
972
- }
973
-
974
- &__week {
975
- font-size: 12px;
976
- line-height: 28px;
977
- color: var(--qiu-text-color-secondary, #909399);
978
- text-align: center;
979
- }
980
-
981
- &__grid {
982
- display: grid;
983
- gap: 2px 0;
984
-
985
- &--day {
986
- grid-template-columns: repeat(7, 1fr);
987
- }
988
-
989
- &--month,
990
- &--year {
991
- grid-template-columns: repeat(3, 1fr);
992
- gap: 8px;
993
- padding: 8px 0 4px;
994
- }
995
- }
996
-
997
- &__cell {
998
- height: auto;
999
- padding: 3px 0;
1000
- cursor: pointer;
1001
- background: transparent;
1002
- border: 0;
1003
-
1004
- &.is-disabled {
1005
- cursor: not-allowed;
1006
- opacity: 0.4;
1007
- }
1008
-
1009
- &.is-other-month .qiu-date__solar {
1010
- color: var(--qiu-text-color-placeholder, #c0c4cc);
1011
- }
1012
-
1013
- &--month .qiu-date__cell,
1014
- &--year .qiu-date__cell {
1015
- min-height: 40px;
1016
- }
1017
- }
1018
-
1019
- &__footer {
1020
- display: flex;
1021
- gap: 8px;
1022
- justify-content: flex-end;
1023
- padding-top: 10px;
1024
- margin-top: 8px;
1025
- border-top: 1px solid var(--qiu-border-color-lighter, #ebeef5);
1026
- }
1027
-
1028
- &__btn {
1029
- min-width: 60px;
1030
- height: 28px;
1031
- padding: 0 12px;
1032
- font-size: 13px;
1033
- cursor: pointer;
1034
- border-radius: 4px;
1035
- border: 1px solid var(--qiu-border-color, #dcdfe6);
1036
- background: var(--qiu-bg-color, #fff);
1037
- color: var(--qiu-text-color-regular, #606266);
1038
-
1039
- &:disabled {
1040
- cursor: not-allowed;
1041
- opacity: 0.5;
1042
- }
1043
-
1044
- &--text {
1045
- border-color: transparent;
1046
- background: transparent;
1047
- }
1048
-
1049
- &--primary {
1050
- color: #fff;
1051
- background: var(--qiu-color-primary, #409eff);
1052
- border-color: var(--qiu-color-primary, #409eff);
1053
- }
1054
- }
1055
-
1056
- .qiu-date__cell {
1057
- display: flex;
1058
- flex-direction: column;
1059
- align-items: center;
1060
- justify-content: center;
1061
- width: 100%;
1062
- min-height: 32px;
1063
- line-height: 1.15;
1064
- border-radius: 4px;
1065
- }
1066
-
1067
- .qiu-date__solar {
1068
- font-size: 13px;
1069
- font-weight: 500;
1070
- color: var(--qiu-text-color-primary, #303133);
1071
- }
1072
-
1073
- .qiu-date__lunar {
1074
- margin-top: 2px;
1075
- font-size: 10px;
1076
- color: var(--qiu-text-color-secondary, #909399);
1077
- transform: scale(0.92);
1078
-
1079
- &.is-festival {
1080
- color: var(--qiu-color-danger, #f56c6c);
1081
- }
1082
- }
1083
-
1084
- &--lunar .qiu-date__cell {
1085
- min-height: 48px;
1086
- }
1087
-
1088
- .qiu-date-panel__cell.in-range:not(.start-date):not(.end-date) .qiu-date__cell {
1089
- color: var(--qiu-color-primary, #409eff);
1090
- background-color: var(--qiu-color-primary-light-8, #ecf5ff) !important;
1091
- border-radius: 6px;
1092
- box-shadow: inset 0 0 0 1px var(--qiu-color-primary-light-5, #b3d8ff);
1093
- }
1094
-
1095
- .qiu-date-panel__cell.start-date .qiu-date__cell,
1096
- .qiu-date-panel__cell.end-date .qiu-date__cell,
1097
- .qiu-date-panel__cell.is-selected .qiu-date__cell {
1098
- color: #fff;
1099
- background-color: var(--qiu-color-primary, #409eff) !important;
1100
- border-radius: 6px;
1101
- }
1102
-
1103
- .qiu-date-panel__cell.start-date .qiu-date__solar,
1104
- .qiu-date-panel__cell.start-date .qiu-date__lunar,
1105
- .qiu-date-panel__cell.end-date .qiu-date__solar,
1106
- .qiu-date-panel__cell.end-date .qiu-date__lunar,
1107
- .qiu-date-panel__cell.is-selected .qiu-date__solar,
1108
- .qiu-date-panel__cell.is-selected .qiu-date__lunar {
1109
- color: #fff !important;
1110
- }
1111
-
1112
- .qiu-date-panel__cell.is-today:not(.start-date):not(.end-date):not(.is-selected):not(.in-range)
1113
- .qiu-date__solar {
1114
- font-weight: 700;
1115
- color: var(--qiu-color-primary, #409eff);
1116
- }
1117
-
1118
- .qiu-date-panel__cell:not(.is-disabled):hover:not(.start-date):not(.end-date):not(.is-selected)
1119
- .qiu-date__cell {
1120
- background: var(--qiu-fill-color-light, #f5f7fa);
1121
- }
1122
- }
1123
-
1124
- .qiu-date-fade-enter-active,
1125
- .qiu-date-fade-leave-active {
1126
- transition: opacity 0.15s ease, transform 0.15s ease;
1127
- }
1128
-
1129
- .qiu-date-fade-enter-from,
1130
- .qiu-date-fade-leave-to {
1131
- opacity: 0;
1132
- transform: translateY(-4px);
1133
- }
1134
- </style>