@robot-admin/naive-ui-components 0.3.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 (352) hide show
  1. package/README.md +257 -0
  2. package/dist/C_ActionBar-DWN-woTc.css.map +1 -0
  3. package/dist/C_ActionBar.cjs +5 -0
  4. package/dist/C_ActionBar.d.cts +2 -0
  5. package/dist/C_ActionBar.d.ts +2 -0
  6. package/dist/C_ActionBar.js +4 -0
  7. package/dist/C_ActionBar2.js +196 -0
  8. package/dist/C_ActionBar2.js.map +1 -0
  9. package/dist/C_AntV-AFKyK6hH.css.map +1 -0
  10. package/dist/C_AntV.cjs +8 -0
  11. package/dist/C_AntV.d.cts +2 -0
  12. package/dist/C_AntV.d.ts +2 -0
  13. package/dist/C_AntV.js +4 -0
  14. package/dist/C_AntV2.js +3150 -0
  15. package/dist/C_AntV2.js.map +1 -0
  16. package/dist/C_Barcode-P_EFj8dC.css.map +1 -0
  17. package/dist/C_Barcode.cjs +4 -0
  18. package/dist/C_Barcode.d.cts +2 -0
  19. package/dist/C_Barcode.d.ts +2 -0
  20. package/dist/C_Barcode.js +3 -0
  21. package/dist/C_Barcode2.js +68 -0
  22. package/dist/C_Barcode2.js.map +1 -0
  23. package/dist/C_Captcha-C-ef41xw.css.map +1 -0
  24. package/dist/C_Captcha.cjs +4 -0
  25. package/dist/C_Captcha.d.cts +2 -0
  26. package/dist/C_Captcha.d.ts +2 -0
  27. package/dist/C_Captcha.js +3 -0
  28. package/dist/C_Captcha2.js +155 -0
  29. package/dist/C_Captcha2.js.map +1 -0
  30. package/dist/C_Cascade-D9kNsjsV.css.map +1 -0
  31. package/dist/C_Cascade.cjs +4 -0
  32. package/dist/C_Cascade.d.cts +2 -0
  33. package/dist/C_Cascade.d.ts +2 -0
  34. package/dist/C_Cascade.js +3 -0
  35. package/dist/C_Cascade2.js +103 -0
  36. package/dist/C_Cascade2.js.map +1 -0
  37. package/dist/C_City-BCQ4ipiK.css.map +1 -0
  38. package/dist/C_City.cjs +4 -0
  39. package/dist/C_City.d.cts +2 -0
  40. package/dist/C_City.d.ts +2 -0
  41. package/dist/C_City.js +3 -0
  42. package/dist/C_City2.js +841 -0
  43. package/dist/C_City2.js.map +1 -0
  44. package/dist/C_Code-C9kvvEmO.css.map +1 -0
  45. package/dist/C_Code.cjs +5 -0
  46. package/dist/C_Code.d.cts +2 -0
  47. package/dist/C_Code.d.ts +2 -0
  48. package/dist/C_Code.js +4 -0
  49. package/dist/C_Code2.js +346 -0
  50. package/dist/C_Code2.js.map +1 -0
  51. package/dist/C_CollapsePanel-BUJHuYcU.css.map +1 -0
  52. package/dist/C_CollapsePanel.cjs +6 -0
  53. package/dist/C_CollapsePanel.d.cts +2 -0
  54. package/dist/C_CollapsePanel.d.ts +2 -0
  55. package/dist/C_CollapsePanel.js +4 -0
  56. package/dist/C_CollapsePanel2.js +319 -0
  57. package/dist/C_CollapsePanel2.js.map +1 -0
  58. package/dist/C_Cron-yx2Ob4Jl.css.map +1 -0
  59. package/dist/C_Cron.cjs +15 -0
  60. package/dist/C_Cron.d.cts +2 -0
  61. package/dist/C_Cron.d.ts +2 -0
  62. package/dist/C_Cron.js +4 -0
  63. package/dist/C_Cron2.js +1209 -0
  64. package/dist/C_Cron2.js.map +1 -0
  65. package/dist/C_Date.cjs +4 -0
  66. package/dist/C_Date.d.cts +2 -0
  67. package/dist/C_Date.d.ts +2 -0
  68. package/dist/C_Date.js +3 -0
  69. package/dist/C_Date2.js +219 -0
  70. package/dist/C_Date2.js.map +1 -0
  71. package/dist/C_Draggable-C483syRC.css.map +1 -0
  72. package/dist/C_Draggable.cjs +5 -0
  73. package/dist/C_Draggable.d.cts +2 -0
  74. package/dist/C_Draggable.d.ts +2 -0
  75. package/dist/C_Draggable.js +3 -0
  76. package/dist/C_Draggable2.js +295 -0
  77. package/dist/C_Draggable2.js.map +1 -0
  78. package/dist/C_Editor-Bp0SyIEw.css.map +1 -0
  79. package/dist/C_Editor.cjs +4 -0
  80. package/dist/C_Editor.d.cts +2 -0
  81. package/dist/C_Editor.d.ts +2 -0
  82. package/dist/C_Editor.js +3 -0
  83. package/dist/C_Editor2.js +160 -0
  84. package/dist/C_Editor2.js.map +1 -0
  85. package/dist/C_FilePreview-CPqvhoCy.css.map +1 -0
  86. package/dist/C_FilePreview.cjs +6 -0
  87. package/dist/C_FilePreview.d.cts +2 -0
  88. package/dist/C_FilePreview.d.ts +2 -0
  89. package/dist/C_FilePreview.js +3 -0
  90. package/dist/C_FilePreview2.js +1031 -0
  91. package/dist/C_FilePreview2.js.map +1 -0
  92. package/dist/C_Form-Jx7PY3sT.css.map +1 -0
  93. package/dist/C_Form.cjs +15 -0
  94. package/dist/C_Form.d.cts +2 -0
  95. package/dist/C_Form.d.ts +2 -0
  96. package/dist/C_Form.js +4 -0
  97. package/dist/C_Form2.js +2510 -0
  98. package/dist/C_Form2.js.map +1 -0
  99. package/dist/C_FormSearch-DvRgxlRn.css.map +1 -0
  100. package/dist/C_FormSearch.cjs +6 -0
  101. package/dist/C_FormSearch.d.cts +2 -0
  102. package/dist/C_FormSearch.d.ts +2 -0
  103. package/dist/C_FormSearch.js +3 -0
  104. package/dist/C_FormSearch2.js +356 -0
  105. package/dist/C_FormSearch2.js.map +1 -0
  106. package/dist/C_FormulaEditor-DtGkt4T_.css.map +1 -0
  107. package/dist/C_FormulaEditor.cjs +13 -0
  108. package/dist/C_FormulaEditor.d.cts +2 -0
  109. package/dist/C_FormulaEditor.d.ts +2 -0
  110. package/dist/C_FormulaEditor.js +4 -0
  111. package/dist/C_FormulaEditor2.js +1433 -0
  112. package/dist/C_FormulaEditor2.js.map +1 -0
  113. package/dist/C_FullCalendar-BF7H0YIx.css.map +1 -0
  114. package/dist/C_FullCalendar.cjs +9 -0
  115. package/dist/C_FullCalendar.d.cts +2 -0
  116. package/dist/C_FullCalendar.d.ts +2 -0
  117. package/dist/C_FullCalendar.js +3 -0
  118. package/dist/C_FullCalendar2.js +377 -0
  119. package/dist/C_FullCalendar2.js.map +1 -0
  120. package/dist/C_Guide.cjs +4 -0
  121. package/dist/C_Guide.d.cts +2 -0
  122. package/dist/C_Guide.d.ts +2 -0
  123. package/dist/C_Guide.js +3 -0
  124. package/dist/C_Guide2.js +58 -0
  125. package/dist/C_Guide2.js.map +1 -0
  126. package/dist/C_Icon.cjs +4 -0
  127. package/dist/C_Icon.d.cts +2 -0
  128. package/dist/C_Icon.d.ts +2 -0
  129. package/dist/C_Icon.js +3 -0
  130. package/dist/C_Icon2.js +286 -0
  131. package/dist/C_Icon2.js.map +1 -0
  132. package/dist/C_ImageCropper-BVJfUufl.css.map +1 -0
  133. package/dist/C_ImageCropper.cjs +6 -0
  134. package/dist/C_ImageCropper.d.cts +2 -0
  135. package/dist/C_ImageCropper.d.ts +2 -0
  136. package/dist/C_ImageCropper.js +4 -0
  137. package/dist/C_ImageCropper2.js +723 -0
  138. package/dist/C_ImageCropper2.js.map +1 -0
  139. package/dist/C_Language.cjs +4 -0
  140. package/dist/C_Language.d.cts +2 -0
  141. package/dist/C_Language.d.ts +2 -0
  142. package/dist/C_Language.js +3 -0
  143. package/dist/C_Language2.js +72 -0
  144. package/dist/C_Language2.js.map +1 -0
  145. package/dist/C_Map-DpzeuWdX.css.map +1 -0
  146. package/dist/C_Map.cjs +7 -0
  147. package/dist/C_Map.d.cts +2 -0
  148. package/dist/C_Map.d.ts +2 -0
  149. package/dist/C_Map.js +3 -0
  150. package/dist/C_Map2.js +199 -0
  151. package/dist/C_Map2.js.map +1 -0
  152. package/dist/C_Markdown-BEjxknqd.css.map +1 -0
  153. package/dist/C_Markdown.cjs +4 -0
  154. package/dist/C_Markdown.d.cts +2 -0
  155. package/dist/C_Markdown.d.ts +2 -0
  156. package/dist/C_Markdown.js +3 -0
  157. package/dist/C_Markdown2.js +186 -0
  158. package/dist/C_Markdown2.js.map +1 -0
  159. package/dist/C_NotificationCenter-0l3TY2Gn.css.map +1 -0
  160. package/dist/C_NotificationCenter.cjs +20 -0
  161. package/dist/C_NotificationCenter.d.cts +2 -0
  162. package/dist/C_NotificationCenter.d.ts +2 -0
  163. package/dist/C_NotificationCenter.js +4 -0
  164. package/dist/C_NotificationCenter2.js +1383 -0
  165. package/dist/C_NotificationCenter2.js.map +1 -0
  166. package/dist/C_Progress.cjs +4 -0
  167. package/dist/C_Progress.d.cts +2 -0
  168. package/dist/C_Progress.d.ts +2 -0
  169. package/dist/C_Progress.js +3 -0
  170. package/dist/C_Progress2.js +103 -0
  171. package/dist/C_Progress2.js.map +1 -0
  172. package/dist/C_QRCode-DbdiAIPg.css.map +1 -0
  173. package/dist/C_QRCode.cjs +5 -0
  174. package/dist/C_QRCode.d.cts +2 -0
  175. package/dist/C_QRCode.d.ts +2 -0
  176. package/dist/C_QRCode.js +3 -0
  177. package/dist/C_QRCode2.js +218 -0
  178. package/dist/C_QRCode2.js.map +1 -0
  179. package/dist/C_Signature-zhHCbra9.css.map +1 -0
  180. package/dist/C_Signature.cjs +8 -0
  181. package/dist/C_Signature.d.cts +2 -0
  182. package/dist/C_Signature.d.ts +2 -0
  183. package/dist/C_Signature.js +4 -0
  184. package/dist/C_Signature2.js +618 -0
  185. package/dist/C_Signature2.js.map +1 -0
  186. package/dist/C_SplitPane-C6sBsfKY.css.map +1 -0
  187. package/dist/C_SplitPane.cjs +6 -0
  188. package/dist/C_SplitPane.d.cts +2 -0
  189. package/dist/C_SplitPane.d.ts +2 -0
  190. package/dist/C_SplitPane.js +4 -0
  191. package/dist/C_SplitPane2.js +356 -0
  192. package/dist/C_SplitPane2.js.map +1 -0
  193. package/dist/C_Steps-CODHN5Hs.css.map +1 -0
  194. package/dist/C_Steps.cjs +4 -0
  195. package/dist/C_Steps.d.cts +2 -0
  196. package/dist/C_Steps.d.ts +2 -0
  197. package/dist/C_Steps.js +3 -0
  198. package/dist/C_Steps2.js +82 -0
  199. package/dist/C_Steps2.js.map +1 -0
  200. package/dist/C_Table-DSNsntmT.css.map +1 -0
  201. package/dist/C_Table.cjs +19 -0
  202. package/dist/C_Table.d.cts +2 -0
  203. package/dist/C_Table.d.ts +2 -0
  204. package/dist/C_Table.js +5 -0
  205. package/dist/C_Table2.js +3009 -0
  206. package/dist/C_Table2.js.map +1 -0
  207. package/dist/C_Theme.cjs +4 -0
  208. package/dist/C_Theme.d.cts +2 -0
  209. package/dist/C_Theme.d.ts +2 -0
  210. package/dist/C_Theme.js +3 -0
  211. package/dist/C_Theme2.js +60 -0
  212. package/dist/C_Theme2.js.map +1 -0
  213. package/dist/C_Time-BvZLYraL.css.map +1 -0
  214. package/dist/C_Time.cjs +5 -0
  215. package/dist/C_Time.d.cts +2 -0
  216. package/dist/C_Time.d.ts +2 -0
  217. package/dist/C_Time.js +3 -0
  218. package/dist/C_Time2.js +199 -0
  219. package/dist/C_Time2.js.map +1 -0
  220. package/dist/C_Tree-0GDv--jX.css.map +1 -0
  221. package/dist/C_Tree.cjs +7 -0
  222. package/dist/C_Tree.d.cts +2 -0
  223. package/dist/C_Tree.d.ts +2 -0
  224. package/dist/C_Tree.js +4 -0
  225. package/dist/C_Tree2.js +441 -0
  226. package/dist/C_Tree2.js.map +1 -0
  227. package/dist/C_Upload-BXd3YYLx.css.map +1 -0
  228. package/dist/C_Upload.cjs +12 -0
  229. package/dist/C_Upload.d.cts +2 -0
  230. package/dist/C_Upload.d.ts +2 -0
  231. package/dist/C_Upload.js +4 -0
  232. package/dist/C_Upload2.js +1388 -0
  233. package/dist/C_Upload2.js.map +1 -0
  234. package/dist/C_VideoPlayer-DYG3RL0Q.css.map +1 -0
  235. package/dist/C_VideoPlayer.cjs +23 -0
  236. package/dist/C_VideoPlayer.d.cts +2 -0
  237. package/dist/C_VideoPlayer.d.ts +2 -0
  238. package/dist/C_VideoPlayer.js +3 -0
  239. package/dist/C_VideoPlayer2.js +1932 -0
  240. package/dist/C_VideoPlayer2.js.map +1 -0
  241. package/dist/C_VtableGantt-fhItIiHE.css.map +1 -0
  242. package/dist/C_VtableGantt.cjs +6 -0
  243. package/dist/C_VtableGantt.d.cts +2 -0
  244. package/dist/C_VtableGantt.d.ts +2 -0
  245. package/dist/C_VtableGantt.js +4 -0
  246. package/dist/C_VtableGantt2.js +873 -0
  247. package/dist/C_VtableGantt2.js.map +1 -0
  248. package/dist/C_WaterFall-8sQDFXKg.css.map +1 -0
  249. package/dist/C_WaterFall.cjs +13 -0
  250. package/dist/C_WaterFall.d.cts +2 -0
  251. package/dist/C_WaterFall.d.ts +2 -0
  252. package/dist/C_WaterFall.js +3 -0
  253. package/dist/C_WaterFall2.js +365 -0
  254. package/dist/C_WaterFall2.js.map +1 -0
  255. package/dist/C_WorkFlow-J-dyIuh9.css.map +1 -0
  256. package/dist/C_WorkFlow.cjs +8 -0
  257. package/dist/C_WorkFlow.d.cts +2 -0
  258. package/dist/C_WorkFlow.d.ts +2 -0
  259. package/dist/C_WorkFlow.js +4 -0
  260. package/dist/C_WorkFlow2.js +1984 -0
  261. package/dist/C_WorkFlow2.js.map +1 -0
  262. package/dist/chunk.js +22 -0
  263. package/dist/city.js +4817 -0
  264. package/dist/city.js.map +1 -0
  265. package/dist/constants.d.ts +273 -0
  266. package/dist/constants.d.ts.map +1 -0
  267. package/dist/constants2.d.ts +178 -0
  268. package/dist/constants2.d.ts.map +1 -0
  269. package/dist/constants3.d.ts +475 -0
  270. package/dist/constants3.d.ts.map +1 -0
  271. package/dist/constants4.d.ts +430 -0
  272. package/dist/constants4.d.ts.map +1 -0
  273. package/dist/constants5.d.ts +4283 -0
  274. package/dist/constants5.d.ts.map +1 -0
  275. package/dist/data.d.ts +67 -0
  276. package/dist/data.d.ts.map +1 -0
  277. package/dist/export-helper.js +9 -0
  278. package/dist/index.cjs +409 -0
  279. package/dist/index.d.cts +96 -0
  280. package/dist/index.d.cts.map +1 -0
  281. package/dist/index.d.ts +103 -0
  282. package/dist/index.d.ts.map +1 -0
  283. package/dist/index.js +230 -0
  284. package/dist/index.js.map +1 -0
  285. package/dist/index.vue.d.ts +80 -0
  286. package/dist/index.vue.d.ts.map +1 -0
  287. package/dist/index10.vue.d.ts +72 -0
  288. package/dist/index10.vue.d.ts.map +1 -0
  289. package/dist/index11.vue.d.ts +26 -0
  290. package/dist/index11.vue.d.ts.map +1 -0
  291. package/dist/index12.vue.d.ts +81 -0
  292. package/dist/index12.vue.d.ts.map +1 -0
  293. package/dist/index13.vue.d.ts +55 -0
  294. package/dist/index13.vue.d.ts.map +1 -0
  295. package/dist/index14.vue.d.ts +33 -0
  296. package/dist/index14.vue.d.ts.map +1 -0
  297. package/dist/index15.vue.d.ts +18 -0
  298. package/dist/index15.vue.d.ts.map +1 -0
  299. package/dist/index16.vue.d.ts +662 -0
  300. package/dist/index16.vue.d.ts.map +1 -0
  301. package/dist/index2.vue.d.ts +38 -0
  302. package/dist/index2.vue.d.ts.map +1 -0
  303. package/dist/index3.vue.d.ts +45 -0
  304. package/dist/index3.vue.d.ts.map +1 -0
  305. package/dist/index4.vue.d.ts +31 -0
  306. package/dist/index4.vue.d.ts.map +1 -0
  307. package/dist/index5.vue.d.ts +35 -0
  308. package/dist/index5.vue.d.ts.map +1 -0
  309. package/dist/index6.vue.d.ts +48 -0
  310. package/dist/index6.vue.d.ts.map +1 -0
  311. package/dist/index7.vue.d.ts +56 -0
  312. package/dist/index7.vue.d.ts.map +1 -0
  313. package/dist/index8.vue.d.ts +41 -0
  314. package/dist/index8.vue.d.ts.map +1 -0
  315. package/dist/index9.vue.d.ts +30 -0
  316. package/dist/index9.vue.d.ts.map +1 -0
  317. package/dist/storage.js +31 -0
  318. package/dist/storage.js.map +1 -0
  319. package/dist/style.css +7725 -0
  320. package/dist/useCalendarEvents.d.ts +148 -0
  321. package/dist/useCalendarEvents.d.ts.map +1 -0
  322. package/dist/useCollapsePanel.d.ts +132 -0
  323. package/dist/useCollapsePanel.d.ts.map +1 -0
  324. package/dist/useCropperCore.d.ts +102 -0
  325. package/dist/useCropperCore.d.ts.map +1 -0
  326. package/dist/useDraggableLayout.d.ts +194 -0
  327. package/dist/useDraggableLayout.d.ts.map +1 -0
  328. package/dist/useDynamicFormState.d.ts +4248 -0
  329. package/dist/useDynamicFormState.d.ts.map +1 -0
  330. package/dist/useEdgeInteraction.d.ts +7614 -0
  331. package/dist/useEdgeInteraction.d.ts.map +1 -0
  332. package/dist/useFullscreen.d.ts +166 -0
  333. package/dist/useFullscreen.d.ts.map +1 -0
  334. package/dist/useInfiniteScroll.d.ts +169 -0
  335. package/dist/useInfiniteScroll.d.ts.map +1 -0
  336. package/dist/useModalEdit.d.ts +960 -0
  337. package/dist/useModalEdit.d.ts.map +1 -0
  338. package/dist/useQRCode.d.ts +87 -0
  339. package/dist/useQRCode.d.ts.map +1 -0
  340. package/dist/useSearchState.d.ts +180 -0
  341. package/dist/useSearchState.d.ts.map +1 -0
  342. package/dist/useSignatureHistory.d.ts +189 -0
  343. package/dist/useSignatureHistory.d.ts.map +1 -0
  344. package/dist/useSplitResize.d.ts +158 -0
  345. package/dist/useSplitResize.d.ts.map +1 -0
  346. package/dist/useTimeSelection.d.ts +105 -0
  347. package/dist/useTimeSelection.d.ts.map +1 -0
  348. package/dist/useTreeOperations.d.ts +183 -0
  349. package/dist/useTreeOperations.d.ts.map +1 -0
  350. package/dist/useWorkflowValidation.d.ts +1052 -0
  351. package/dist/useWorkflowValidation.d.ts.map +1 -0
  352. package/package.json +342 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"C_Cron2.js","names":["modelValue","computing","nextExecutions","formatDate","formatWeekDay","templates","currentValue","$emit"],"sources":["../src/components/C_Cron/constants.ts","../src/components/C_Cron/composables/useCronParser.ts","../src/components/C_Cron/composables/useCronPreview.ts","../src/components/C_Cron/composables/useCronDescription.ts","../src/components/C_Cron/components/CronFieldEditor.vue","../src/components/C_Cron/components/CronFieldEditor.vue","../src/components/C_Cron/components/CronFieldEditor.vue","../src/components/C_Cron/components/CronPreview.vue","../src/components/C_Cron/components/CronPreview.vue","../src/components/C_Cron/components/CronPreview.vue","../src/components/C_Cron/components/CronTemplates.vue","../src/components/C_Cron/components/CronTemplates.vue","../src/components/C_Cron/components/CronTemplates.vue","../src/components/C_Cron/index.vue","../src/components/C_Cron/index.vue","../src/components/C_Cron/index.vue"],"sourcesContent":["/*\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 表达式编辑器常量\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n */\r\n\r\nimport type {\r\n CronFieldMeta,\r\n CronFieldValue,\r\n CronTemplate,\r\n CronValue,\r\n} from \"./types\";\r\n\r\n/* ─── 字段元数据 ────────────────────────────────── */\r\n\r\nexport const CRON_FIELD_META: CronFieldMeta[] = [\r\n { type: \"second\", label: \"秒\", min: 0, max: 59 },\r\n { type: \"minute\", label: \"分\", min: 0, max: 59 },\r\n { type: \"hour\", label: \"时\", min: 0, max: 23 },\r\n { type: \"day\", label: \"日\", min: 1, max: 31 },\r\n { type: \"month\", label: \"月\", min: 1, max: 12 },\r\n {\r\n type: \"week\",\r\n label: \"周\",\r\n min: 1,\r\n max: 7,\r\n valueLabels: {\r\n 1: \"周日\",\r\n 2: \"周一\",\r\n 3: \"周二\",\r\n 4: \"周三\",\r\n 5: \"周四\",\r\n 6: \"周五\",\r\n 7: \"周六\",\r\n },\r\n },\r\n];\r\n\r\n/* ─── 默认字段值 ────────────────────────────────── */\r\n\r\nexport const DEFAULT_FIELD_VALUE: CronFieldValue = {\r\n mode: \"every\",\r\n rangeStart: 0,\r\n rangeEnd: 0,\r\n stepStart: 0,\r\n stepInterval: 1,\r\n specificValues: [],\r\n};\r\n\r\n/* ─── 默认 Cron 值(每秒执行) ────────────────── */\r\n\r\nexport const DEFAULT_CRON_VALUE: CronValue = {\r\n second: { ...DEFAULT_FIELD_VALUE, rangeEnd: 59 },\r\n minute: { ...DEFAULT_FIELD_VALUE, rangeEnd: 59 },\r\n hour: { ...DEFAULT_FIELD_VALUE, rangeEnd: 23 },\r\n day: { ...DEFAULT_FIELD_VALUE, rangeStart: 1, rangeEnd: 31 },\r\n month: { ...DEFAULT_FIELD_VALUE, rangeStart: 1, rangeEnd: 12 },\r\n week: { ...DEFAULT_FIELD_VALUE, mode: \"none\", rangeStart: 1, rangeEnd: 7 },\r\n};\r\n\r\n/* ─── 默认表达式 ─────────────────────────────────── */\r\n\r\nexport const DEFAULT_CRON_EXPRESSION = \"0 0 0 * * ?\";\r\n\r\n/* ─── 常用模板 ───────────────────────────────────── */\r\n\r\nexport const CRON_TEMPLATES: CronTemplate[] = [\r\n {\r\n label: \"每秒执行\",\r\n value: \"* * * * * ?\",\r\n description: \"每秒执行一次\",\r\n icon: \"mdi:timer-sand\",\r\n },\r\n {\r\n label: \"每分钟执行\",\r\n value: \"0 * * * * ?\",\r\n description: \"每分钟第 0 秒执行\",\r\n icon: \"mdi:clock-outline\",\r\n },\r\n {\r\n label: \"每小时执行\",\r\n value: \"0 0 * * * ?\",\r\n description: \"每小时整点执行\",\r\n icon: \"mdi:clock-time-twelve-outline\",\r\n },\r\n {\r\n label: \"每天 0 点\",\r\n value: \"0 0 0 * * ?\",\r\n description: \"每天凌晨 00:00 执行\",\r\n icon: \"mdi:weather-night\",\r\n },\r\n {\r\n label: \"每天 8:30\",\r\n value: \"0 30 8 * * ?\",\r\n description: \"每天早上 08:30 执行\",\r\n icon: \"mdi:weather-sunny\",\r\n },\r\n {\r\n label: \"每天 12:00\",\r\n value: \"0 0 12 * * ?\",\r\n description: \"每天中午 12:00 执行\",\r\n icon: \"mdi:food\",\r\n },\r\n {\r\n label: \"工作日 9:00\",\r\n value: \"0 0 9 ? * 2-6\",\r\n description: \"周一至周五 09:00 执行\",\r\n icon: \"mdi:briefcase-outline\",\r\n },\r\n {\r\n label: \"每周一 0 点\",\r\n value: \"0 0 0 ? * 2\",\r\n description: \"每周一凌晨 00:00 执行\",\r\n icon: \"mdi:calendar-week\",\r\n },\r\n {\r\n label: \"每月 1 号 0 点\",\r\n value: \"0 0 0 1 * ?\",\r\n description: \"每月 1 号凌晨 00:00 执行\",\r\n icon: \"mdi:calendar-month\",\r\n },\r\n {\r\n label: \"每 5 分钟\",\r\n value: \"0 0/5 * * * ?\",\r\n description: \"每隔 5 分钟执行一次\",\r\n icon: \"mdi:timer-5\",\r\n },\r\n {\r\n label: \"每 30 分钟\",\r\n value: \"0 0/30 * * * ?\",\r\n description: \"每隔 30 分钟执行一次\",\r\n icon: \"mdi:timer-30\",\r\n },\r\n {\r\n label: \"每 2 小时\",\r\n value: \"0 0 0/2 * * ?\",\r\n description: \"每隔 2 小时执行一次\",\r\n icon: \"mdi:timer-2\",\r\n },\r\n];\r\n\r\n/* ─── 月份名称 ───────────────────────────────────── */\r\n\r\nexport const MONTH_LABELS: Record<number, string> = {\r\n 1: \"一月\",\r\n 2: \"二月\",\r\n 3: \"三月\",\r\n 4: \"四月\",\r\n 5: \"五月\",\r\n 6: \"六月\",\r\n 7: \"七月\",\r\n 8: \"八月\",\r\n 9: \"九月\",\r\n 10: \"十月\",\r\n 11: \"十一月\",\r\n 12: \"十二月\",\r\n};\r\n\r\n/* ─── 周名称 ─────────────────────────────────────── */\r\n\r\nexport const WEEK_LABELS: Record<number, string> = {\r\n 1: \"周日\",\r\n 2: \"周一\",\r\n 3: \"周二\",\r\n 4: \"周三\",\r\n 5: \"周四\",\r\n 6: \"周五\",\r\n 7: \"周六\",\r\n};\r\n","/*\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 解析 & 生成引擎\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n */\r\n\r\nimport { ref, computed } from \"vue\";\r\nimport type {\r\n CronFieldMeta,\r\n CronFieldType,\r\n CronFieldValue,\r\n CronValidation,\r\n CronValue,\r\n} from \"../types\";\r\nimport { CRON_FIELD_META, DEFAULT_CRON_VALUE } from \"../constants\";\r\n\r\n/* ─── 字段顺序 ────────────────────────────────── */\r\n\r\nconst FIELD_ORDER: CronFieldType[] = [\r\n \"second\",\r\n \"minute\",\r\n \"hour\",\r\n \"day\",\r\n \"month\",\r\n \"week\",\r\n];\r\n\r\n/**\r\n * Cron 解析 & 生成引擎\r\n */\r\nexport function useCronParser() {\r\n /** 当前 Cron 对象 */\r\n const cronValue = ref<CronValue>(structuredClone(DEFAULT_CRON_VALUE));\r\n\r\n /* ─── 单字段 → 表达式片段 ────────────────────── */\r\n\r\n /** 将单个字段值转为 Cron 表达式片段 */\r\n function fieldToExpression(field: CronFieldValue): string {\r\n switch (field.mode) {\r\n case \"every\":\r\n return \"*\";\r\n case \"range\":\r\n return `${field.rangeStart}-${field.rangeEnd}`;\r\n case \"step\":\r\n return `${field.stepStart}/${field.stepInterval}`;\r\n case \"specific\":\r\n return field.specificValues.length > 0\r\n ? field.specificValues.sort((a, b) => a - b).join(\",\")\r\n : \"*\";\r\n case \"none\":\r\n return \"?\";\r\n default:\r\n return \"*\";\r\n }\r\n }\r\n\r\n /* ─── 表达式片段 → 单字段 ────────────────────── */\r\n\r\n /** 创建默认字段值 */\r\n function createFieldValue(\r\n meta: CronFieldMeta,\r\n mode: CronFieldValue[\"mode\"],\r\n overrides: Partial<CronFieldValue> = {},\r\n ): CronFieldValue {\r\n return {\r\n mode,\r\n rangeStart: meta.min,\r\n rangeEnd: meta.max,\r\n stepStart: meta.min,\r\n stepInterval: 1,\r\n specificValues: [],\r\n ...overrides,\r\n };\r\n }\r\n\r\n /** 解析步进表达式为字段值 */\r\n function parseStepExpr(expr: string, meta: CronFieldMeta): CronFieldValue {\r\n const [start, interval] = expr.split(\"/\").map(Number);\r\n return createFieldValue(meta, \"step\", {\r\n stepStart: isNaN(start) ? meta.min : start,\r\n stepInterval: isNaN(interval) ? 1 : interval,\r\n });\r\n }\r\n\r\n /** 解析范围表达式为字段值 */\r\n function parseRangeExpr(expr: string, meta: CronFieldMeta): CronFieldValue {\r\n const [start, end] = expr.split(\"-\").map(Number);\r\n return createFieldValue(meta, \"range\", {\r\n rangeStart: isNaN(start) ? meta.min : start,\r\n rangeEnd: isNaN(end) ? meta.max : end,\r\n });\r\n }\r\n\r\n /** 将 Cron 表达式片段解析为字段值对象 */\r\n function expressionToField(\r\n expr: string,\r\n type: CronFieldType,\r\n ): CronFieldValue {\r\n const meta = CRON_FIELD_META.find((m) => m.type === type)!;\r\n\r\n if (expr === \"?\") return createFieldValue(meta, \"none\");\r\n if (expr === \"*\") return createFieldValue(meta, \"every\");\r\n if (expr.includes(\"/\")) return parseStepExpr(expr, meta);\r\n if (expr.includes(\"-\") && !expr.includes(\",\"))\r\n return parseRangeExpr(expr, meta);\r\n\r\n /* x,y,z 或单个数字(指定值) */\r\n const values = expr\r\n .split(\",\")\r\n .map(Number)\r\n .filter((n) => !isNaN(n));\r\n if (values.length > 0)\r\n return createFieldValue(meta, \"specific\", { specificValues: values });\r\n\r\n return createFieldValue(meta, \"every\");\r\n }\r\n\r\n /* ─── CronValue → 完整表达式 ────────────────── */\r\n\r\n /** 由 CronValue 生成完整 Cron 表达式 */\r\n function generate(): string {\r\n return FIELD_ORDER.map((type) =>\r\n fieldToExpression(cronValue.value[type]),\r\n ).join(\" \");\r\n }\r\n\r\n /* ─── 完整表达式 → CronValue ────────────────── */\r\n\r\n /** 解析 Cron 表达式字符串为 CronValue */\r\n function parse(expression: string): void {\r\n const parts = expression.trim().split(/\\s+/);\r\n if (parts.length < 6) return;\r\n\r\n FIELD_ORDER.forEach((type, index) => {\r\n cronValue.value[type] = expressionToField(parts[index], type);\r\n });\r\n }\r\n\r\n /* ─── 日/周互斥处理 ─────────────────────────── */\r\n\r\n /** 日/周互斥:修改一方时另一方自动设为 ? */\r\n function handleDayWeekExclusion(changedField: \"day\" | \"week\"): void {\r\n if (changedField === \"day\") {\r\n if (cronValue.value.day.mode !== \"none\") {\r\n cronValue.value.week = { ...cronValue.value.week, mode: \"none\" };\r\n }\r\n } else {\r\n if (cronValue.value.week.mode !== \"none\") {\r\n cronValue.value.day = { ...cronValue.value.day, mode: \"none\" };\r\n }\r\n }\r\n }\r\n\r\n /* ─── 校验 ──────────────────────────────────── */\r\n\r\n /** 校验 Cron 表达式合法性 */\r\n function validate(expression?: string): CronValidation {\r\n const expr = expression ?? generate();\r\n const parts = expr.trim().split(/\\s+/);\r\n\r\n if (parts.length !== 6) {\r\n return {\r\n valid: false,\r\n message: `表达式应包含 6 个字段,当前为 ${parts.length} 个`,\r\n };\r\n }\r\n\r\n /* 日和周必须有一个为 ? */\r\n const dayPart = parts[3];\r\n const weekPart = parts[5];\r\n if (dayPart !== \"?\" && weekPart !== \"?\") {\r\n return {\r\n valid: false,\r\n message: \"日和周不能同时指定,其中一个必须为 ?\",\r\n field: \"day\",\r\n };\r\n }\r\n if (dayPart === \"?\" && weekPart === \"?\") {\r\n return {\r\n valid: false,\r\n message: \"日和周不能同时为 ?,至少指定一个\",\r\n field: \"day\",\r\n };\r\n }\r\n\r\n /* 逐字段校验 */\r\n for (let i = 0; i < FIELD_ORDER.length; i++) {\r\n const type = FIELD_ORDER[i];\r\n const part = parts[i];\r\n const meta = CRON_FIELD_META.find((m) => m.type === type)!;\r\n const result = validateField(part, meta);\r\n if (!result.valid) {\r\n return { ...result, field: type };\r\n }\r\n }\r\n\r\n return { valid: true, message: \"表达式合法\" };\r\n }\r\n\r\n /** 校验步进表达式 */\r\n function validateStep(part: string, meta: CronFieldMeta): CronValidation {\r\n const [s, i] = part.split(\"/\");\r\n const start = s === \"*\" ? meta.min : Number(s);\r\n const interval = Number(i);\r\n if (isNaN(start) || isNaN(interval))\r\n return { valid: false, message: `${meta.label}字段步进格式错误` };\r\n if (start < meta.min || start > meta.max)\r\n return {\r\n valid: false,\r\n message: `${meta.label}字段步进起始值超出范围 (${meta.min}-${meta.max})`,\r\n };\r\n if (interval < 1)\r\n return { valid: false, message: `${meta.label}字段步进间隔必须大于 0` };\r\n return { valid: true, message: \"\" };\r\n }\r\n\r\n /** 校验范围表达式 */\r\n function validateRange(part: string, meta: CronFieldMeta): CronValidation {\r\n const [s, e] = part.split(\"-\").map(Number);\r\n if (isNaN(s) || isNaN(e))\r\n return { valid: false, message: `${meta.label}字段范围格式错误` };\r\n if (s < meta.min || e > meta.max)\r\n return {\r\n valid: false,\r\n message: `${meta.label}字段范围超出 (${meta.min}-${meta.max})`,\r\n };\r\n if (s > e)\r\n return { valid: false, message: `${meta.label}字段范围起始不能大于结束` };\r\n return { valid: true, message: \"\" };\r\n }\r\n\r\n /** 校验指定值表达式 */\r\n function validateSpecific(part: string, meta: CronFieldMeta): CronValidation {\r\n const values = part.split(\",\").map(Number);\r\n if (values.some(isNaN))\r\n return { valid: false, message: `${meta.label}字段包含非数字字符` };\r\n if (values.some((v) => v < meta.min || v > meta.max)) {\r\n return {\r\n valid: false,\r\n message: `${meta.label}字段值超出范围 (${meta.min}-${meta.max})`,\r\n };\r\n }\r\n return { valid: true, message: \"\" };\r\n }\r\n\r\n /** 校验单个字段表达式 */\r\n function validateField(part: string, meta: CronFieldMeta): CronValidation {\r\n if (part === \"*\" || part === \"?\") return { valid: true, message: \"\" };\r\n if (part.includes(\"/\")) return validateStep(part, meta);\r\n if (part.includes(\"-\") && !part.includes(\",\"))\r\n return validateRange(part, meta);\r\n return validateSpecific(part, meta);\r\n }\r\n\r\n /* ─── 计算属性:自动生成表达式 ────────────────── */\r\n\r\n const expression = computed(() => generate());\r\n\r\n /* ─── 校验结果 ──────────────────────────────── */\r\n\r\n const validation = computed(() => validate());\r\n\r\n return {\r\n cronValue,\r\n expression,\r\n validation,\r\n parse,\r\n generate,\r\n validate,\r\n handleDayWeekExclusion,\r\n };\r\n}\r\n","/*\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 执行时间预测\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n */\r\n\r\nimport { ref, watch, type Ref } from 'vue'\r\nimport type { CronValidation } from '../types'\r\n\r\n/**\r\n * 解析 Cron 表达式,预测未来 N 次执行时间\r\n * 纯逻辑实现,不依赖外部库\r\n */\r\nexport function useCronPreview(\r\n expression: Ref<string>,\r\n validation: Ref<CronValidation>,\r\n count: Ref<number>\r\n) {\r\n /** 预测的执行时间列表 */\r\n const nextExecutions = ref<Date[]>([])\r\n\r\n /** 是否正在计算 */\r\n const computing = ref(false)\r\n\r\n /* ─── 匹配检查工具 ─────────────────────────── */\r\n\r\n /** 检查单个值是否匹配 Cron 字段片段 */\r\n function matchesPart(value: number, part: string): boolean {\r\n if (part === '*' || part === '?') return true\r\n\r\n /* 步进 x/y */\r\n if (part.includes('/')) {\r\n const [s, i] = part.split('/')\r\n const start = s === '*' ? 0 : Number(s)\r\n const interval = Number(i)\r\n return value - start >= 0 && (value - start) % interval === 0\r\n }\r\n\r\n /* 范围 x-y */\r\n if (part.includes('-') && !part.includes(',')) {\r\n const [start, end] = part.split('-').map(Number)\r\n return value >= start && value <= end\r\n }\r\n\r\n /* 指定值 x,y,z */\r\n return part.split(',').map(Number).includes(value)\r\n }\r\n\r\n /** 检查日期是否匹配 Cron 表达式 */\r\n function matchesCron(date: Date, parts: string[]): boolean {\r\n if (parts.length !== 6) return false\r\n\r\n const [secPart, minPart, hourPart, dayPart, monthPart, weekPart] = parts\r\n\r\n /* 月 (1-12) */\r\n if (!matchesPart(date.getMonth() + 1, monthPart)) return false\r\n\r\n /* 日/周(互斥) */\r\n if (dayPart !== '?') {\r\n if (!matchesPart(date.getDate(), dayPart)) return false\r\n }\r\n if (weekPart !== '?') {\r\n /* JS: 0=周日, 1=周一… → Cron: 1=周日, 2=周一… */\r\n if (!matchesPart(date.getDay() + 1, weekPart)) return false\r\n }\r\n\r\n /* 时 */\r\n if (!matchesPart(date.getHours(), hourPart)) return false\r\n /* 分 */\r\n if (!matchesPart(date.getMinutes(), minPart)) return false\r\n /* 秒 */\r\n if (!matchesPart(date.getSeconds(), secPart)) return false\r\n\r\n return true\r\n }\r\n\r\n /** 计算未来 N 次执行时间 */\r\n function computeNextExecutions(): Date[] {\r\n const expr = expression.value\r\n if (!expr || !validation.value.valid) return []\r\n\r\n const parts = expr.trim().split(/\\s+/)\r\n if (parts.length !== 6) return []\r\n\r\n const results: Date[] = []\r\n const now = new Date()\r\n const cursor = new Date(now.getTime() + 1000) /* 从下一秒开始 */\r\n cursor.setMilliseconds(0)\r\n\r\n /* 判断是否包含秒级调度(秒字段不是 0) */\r\n const hasSecond = parts[0] !== '0'\r\n const stepMs = hasSecond ? 1000 : 60_000 /* 秒级/分钟级步进 */\r\n\r\n /* 分钟级步进时,对齐到整分(秒归零),否则秒位永远无法匹配 '0' */\r\n if (!hasSecond) {\r\n cursor.setSeconds(0)\r\n if (cursor.getTime() <= now.getTime()) {\r\n cursor.setTime(cursor.getTime() + 60_000)\r\n }\r\n }\r\n\r\n const maxIterations = 525_600 /* 最多遍历 1 年的分钟数 */\r\n const target = count.value\r\n\r\n for (let i = 0; i < maxIterations && results.length < target; i++) {\r\n if (matchesCron(cursor, parts)) {\r\n results.push(new Date(cursor))\r\n }\r\n cursor.setTime(cursor.getTime() + stepMs)\r\n }\r\n\r\n return results\r\n }\r\n\r\n /* ─── 监听表达式变化自动计算 ─────────────────── */\r\n\r\n watch(\r\n [expression, count],\r\n () => {\r\n if (!validation.value.valid) {\r\n nextExecutions.value = []\r\n return\r\n }\r\n computing.value = true\r\n /* 使用 setTimeout 避免阻塞 UI */\r\n setTimeout(() => {\r\n nextExecutions.value = computeNextExecutions()\r\n computing.value = false\r\n }, 0)\r\n },\r\n { immediate: true }\r\n )\r\n\r\n /* ─── 格式化输出 ───────────────────────────── */\r\n\r\n /** 格式化日期为字符串 */\r\n function formatDate(date: Date): string {\r\n const pad = (n: number) => String(n).padStart(2, '0')\r\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`\r\n }\r\n\r\n /** 获取日期的中文星期名称 */\r\n function formatWeekDay(date: Date): string {\r\n const days = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']\r\n return days[date.getDay()]\r\n }\r\n\r\n return {\r\n nextExecutions,\r\n computing,\r\n formatDate,\r\n formatWeekDay,\r\n }\r\n}\r\n","/*\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 中文描述生成\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n */\r\n\r\nimport { computed } from \"vue\";\r\nimport type { Ref } from \"vue\";\r\nimport type { CronValidation } from \"../types\";\r\nimport { MONTH_LABELS, WEEK_LABELS } from \"../constants\";\r\n\r\n/** 获取周名称 */\r\nfunction weekLabel(n: number | string): string {\r\n return WEEK_LABELS[Number(n)] || `周${n}`;\r\n}\r\n\r\n/**\r\n * 将 Cron 表达式自动转换为中文可读描述\r\n */\r\nexport function useCronDescription(\r\n expression: Ref<string>,\r\n validation: Ref<CronValidation>,\r\n) {\r\n /** 中文描述 */\r\n const description = computed(() => {\r\n if (!validation.value.valid) return \"表达式不合法\";\r\n return generateDescription(expression.value);\r\n });\r\n\r\n /* ─── 核心转换 ──────────────────────────────── */\r\n\r\n /** 将完整 Cron 表达式转为中文描述 */\r\n function generateDescription(expr: string): string {\r\n const parts = expr.trim().split(/\\s+/);\r\n if (parts.length !== 6) return \"表达式格式错误\";\r\n\r\n const [sec, min, hour, day, month, week] = parts;\r\n\r\n const fragments: string[] = [];\r\n\r\n /* 月 */\r\n fragments.push(describeMonth(month));\r\n /* 周 or 日 */\r\n if (week !== \"?\") {\r\n fragments.push(describeWeek(week));\r\n } else {\r\n fragments.push(describeDay(day));\r\n }\r\n /* 时 */\r\n fragments.push(describeHour(hour));\r\n /* 分 */\r\n fragments.push(describeMinute(min));\r\n /* 秒 */\r\n fragments.push(describeSecond(sec));\r\n\r\n return fragments.filter(Boolean).join(\" \") + \" 执行\";\r\n }\r\n\r\n /* ─── 各字段描述 ────────────────────────────── */\r\n\r\n /** 描述秒字段 */\r\n function describeSecond(part: string): string {\r\n if (part === \"0\") return \"\";\r\n if (part === \"*\") return \"每秒\";\r\n return describeFieldGeneric(part, \"秒\");\r\n }\r\n\r\n /** 描述分字段 */\r\n function describeMinute(part: string): string {\r\n if (part === \"*\") return \"每分钟\";\r\n if (part === \"0\") return \"\";\r\n return describeFieldGeneric(part, \"分\");\r\n }\r\n\r\n /** 描述时字段 */\r\n function describeHour(part: string): string {\r\n if (part === \"*\") return \"每小时\";\r\n if (/^\\d+$/.test(part)) return `${part.padStart(2, \"0\")}:`;\r\n return describeFieldGeneric(part, \"时\");\r\n }\r\n\r\n /** 描述日字段 */\r\n function describeDay(part: string): string {\r\n if (part === \"*\" || part === \"?\") return \"每天\";\r\n if (/^\\d+$/.test(part)) return `每月 ${part} 号`;\r\n if (part.includes(\"/\")) {\r\n const [s, i] = part.split(\"/\");\r\n return `从 ${s} 号开始每 ${i} 天`;\r\n }\r\n if (part.includes(\"-\")) {\r\n const [s, e] = part.split(\"-\");\r\n return `${s} 号到 ${e} 号`;\r\n }\r\n if (part.includes(\",\")) {\r\n return `每月 ${part} 号`;\r\n }\r\n return \"\";\r\n }\r\n\r\n /** 描述月字段 */\r\n function describeMonth(part: string): string {\r\n if (part === \"*\") return \"\";\r\n if (/^\\d+$/.test(part)) {\r\n const n = Number(part);\r\n return MONTH_LABELS[n] ? `${MONTH_LABELS[n]}` : `${n} 月`;\r\n }\r\n if (part.includes(\"/\")) {\r\n const [s, i] = part.split(\"/\");\r\n return `从 ${s} 月开始每 ${i} 个月`;\r\n }\r\n if (part.includes(\"-\")) {\r\n const [s, e] = part.split(\"-\");\r\n return `${s} 月到 ${e} 月`;\r\n }\r\n if (part.includes(\",\")) {\r\n const months = part\r\n .split(\",\")\r\n .map((n) => MONTH_LABELS[Number(n)] || `${n}月`)\r\n .join(\"、\");\r\n return months;\r\n }\r\n return \"\";\r\n }\r\n\r\n /** 描述周字段 */\r\n function describeWeek(part: string): string {\r\n if (part === \"*\" || part === \"?\") return \"\";\r\n if (/^\\d+$/.test(part)) return `每${weekLabel(part)}`;\r\n if (part.includes(\"/\"))\r\n return `从${weekLabel(part.split(\"/\")[0])}开始每 ${part.split(\"/\")[1]} 天`;\r\n if (part.includes(\"-\"))\r\n return `${weekLabel(part.split(\"-\")[0])}到${weekLabel(part.split(\"-\")[1])}`;\r\n if (part.includes(\",\"))\r\n return `每${part.split(\",\").map(weekLabel).join(\"、\")}`;\r\n return \"\";\r\n }\r\n\r\n /** 通用字段描述 */\r\n function describeFieldGeneric(part: string, unit: string): string {\r\n if (part.includes(\"/\")) {\r\n const [s, i] = part.split(\"/\");\r\n const startDesc = s === \"*\" || s === \"0\" ? \"\" : `从第 ${s} ${unit}开始`;\r\n return `${startDesc}每 ${i} ${unit}`;\r\n }\r\n if (part.includes(\"-\")) {\r\n const [s, e] = part.split(\"-\");\r\n return `${s} ${unit}到 ${e} ${unit}`;\r\n }\r\n if (part.includes(\",\")) {\r\n return `第 ${part} ${unit}`;\r\n }\r\n if (/^\\d+$/.test(part)) {\r\n return `${part.padStart(2, \"0\")}`;\r\n }\r\n return \"\";\r\n }\r\n\r\n return {\r\n description,\r\n };\r\n}\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 字段值网格(始终可见,根据模式自动高亮对应值)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"cron-field-editor\">\r\n <div class=\"cron-field-editor__grid\" :style=\"{ '--cols': gridColumns }\">\r\n <div\r\n v-for=\"item in valueOptions\"\r\n :key=\"item.value\"\r\n class=\"cron-field-editor__cell\"\r\n :class=\"{\r\n 'cron-field-editor__cell--on': highlightedValues.has(item.value),\r\n 'cron-field-editor__cell--pick': modelValue.mode === 'specific',\r\n }\"\r\n @click=\"handleCellClick(item.value)\"\r\n >\r\n {{ item.label }}\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from \"vue\";\r\nimport type { CronFieldMeta, CronFieldValue } from \"../types\";\r\n\r\ninterface Props {\r\n modelValue: CronFieldValue;\r\n meta: CronFieldMeta;\r\n}\r\n\r\nconst props = defineProps<Props>();\r\nconst emit = defineEmits<{\r\n \"update:modelValue\": [value: CronFieldValue];\r\n}>();\r\n\r\n/** 网格列数 */\r\nconst gridColumns = computed(() => {\r\n switch (props.meta.type) {\r\n case \"second\":\r\n case \"minute\":\r\n return 10;\r\n case \"hour\":\r\n return 12;\r\n case \"day\":\r\n return 7;\r\n case \"month\":\r\n return 6;\r\n case \"week\":\r\n return 7;\r\n default:\r\n return 10;\r\n }\r\n});\r\n\r\n/** 可选值列表 */\r\nconst valueOptions = computed(() => {\r\n const items: { value: number; label: string }[] = [];\r\n for (let i = props.meta.min; i <= props.meta.max; i++) {\r\n items.push({\r\n value: i,\r\n label: props.meta.valueLabels?.[i] ?? String(i),\r\n });\r\n }\r\n return items;\r\n});\r\n\r\n/** 根据当前模式计算高亮值集合 */\r\nconst highlightedValues = computed(() => {\r\n const { modelValue: f, meta } = props;\r\n const set = new Set<number>();\r\n switch (f.mode) {\r\n case \"every\":\r\n for (let i = meta.min; i <= meta.max; i++) set.add(i);\r\n break;\r\n case \"none\":\r\n break;\r\n case \"range\":\r\n for (let i = f.rangeStart; i <= f.rangeEnd; i++) set.add(i);\r\n break;\r\n case \"step\":\r\n for (let i = f.stepStart; i <= meta.max; i += f.stepInterval) set.add(i);\r\n break;\r\n case \"specific\":\r\n f.specificValues.forEach((v) => set.add(v));\r\n break;\r\n }\r\n return set;\r\n});\r\n\r\n/** 点击单元格(仅 specific 模式生效) */\r\nfunction handleCellClick(value: number) {\r\n if (props.modelValue.mode !== \"specific\") return;\r\n const current = [...props.modelValue.specificValues];\r\n const idx = current.indexOf(value);\r\n if (idx >= 0) current.splice(idx, 1);\r\n else current.push(value);\r\n emit(\"update:modelValue\", {\r\n ...props.modelValue,\r\n specificValues: current,\r\n });\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.cron-field-editor {\r\n &__grid {\r\n display: grid;\r\n grid-template-columns: repeat(var(--cols, 10), 1fr);\r\n gap: 4px;\r\n }\r\n\r\n &__cell {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 34px;\r\n border-radius: 6px;\r\n font-size: 13px;\r\n font-variant-numeric: tabular-nums;\r\n transition: all var(--c-transition, 0.2s ease);\r\n user-select: none;\r\n color: var(--c-text-2);\r\n\r\n /* 非交互高亮(every / range / step 的视觉反馈) */\r\n &--on:not(&--pick) {\r\n background: color-mix(in srgb, var(--c-primary) 12%, transparent);\r\n color: var(--c-primary);\r\n }\r\n\r\n /* 可交互模式(specific) */\r\n &--pick {\r\n cursor: pointer;\r\n\r\n &:hover:not(.cron-field-editor__cell--on) {\r\n background: var(--c-bg-card);\r\n }\r\n\r\n &.cron-field-editor__cell--on {\r\n background: var(--c-primary);\r\n color: #fff;\r\n font-weight: 600;\r\n }\r\n }\r\n }\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 字段值网格(始终可见,根据模式自动高亮对应值)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"cron-field-editor\">\r\n <div class=\"cron-field-editor__grid\" :style=\"{ '--cols': gridColumns }\">\r\n <div\r\n v-for=\"item in valueOptions\"\r\n :key=\"item.value\"\r\n class=\"cron-field-editor__cell\"\r\n :class=\"{\r\n 'cron-field-editor__cell--on': highlightedValues.has(item.value),\r\n 'cron-field-editor__cell--pick': modelValue.mode === 'specific',\r\n }\"\r\n @click=\"handleCellClick(item.value)\"\r\n >\r\n {{ item.label }}\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from \"vue\";\r\nimport type { CronFieldMeta, CronFieldValue } from \"../types\";\r\n\r\ninterface Props {\r\n modelValue: CronFieldValue;\r\n meta: CronFieldMeta;\r\n}\r\n\r\nconst props = defineProps<Props>();\r\nconst emit = defineEmits<{\r\n \"update:modelValue\": [value: CronFieldValue];\r\n}>();\r\n\r\n/** 网格列数 */\r\nconst gridColumns = computed(() => {\r\n switch (props.meta.type) {\r\n case \"second\":\r\n case \"minute\":\r\n return 10;\r\n case \"hour\":\r\n return 12;\r\n case \"day\":\r\n return 7;\r\n case \"month\":\r\n return 6;\r\n case \"week\":\r\n return 7;\r\n default:\r\n return 10;\r\n }\r\n});\r\n\r\n/** 可选值列表 */\r\nconst valueOptions = computed(() => {\r\n const items: { value: number; label: string }[] = [];\r\n for (let i = props.meta.min; i <= props.meta.max; i++) {\r\n items.push({\r\n value: i,\r\n label: props.meta.valueLabels?.[i] ?? String(i),\r\n });\r\n }\r\n return items;\r\n});\r\n\r\n/** 根据当前模式计算高亮值集合 */\r\nconst highlightedValues = computed(() => {\r\n const { modelValue: f, meta } = props;\r\n const set = new Set<number>();\r\n switch (f.mode) {\r\n case \"every\":\r\n for (let i = meta.min; i <= meta.max; i++) set.add(i);\r\n break;\r\n case \"none\":\r\n break;\r\n case \"range\":\r\n for (let i = f.rangeStart; i <= f.rangeEnd; i++) set.add(i);\r\n break;\r\n case \"step\":\r\n for (let i = f.stepStart; i <= meta.max; i += f.stepInterval) set.add(i);\r\n break;\r\n case \"specific\":\r\n f.specificValues.forEach((v) => set.add(v));\r\n break;\r\n }\r\n return set;\r\n});\r\n\r\n/** 点击单元格(仅 specific 模式生效) */\r\nfunction handleCellClick(value: number) {\r\n if (props.modelValue.mode !== \"specific\") return;\r\n const current = [...props.modelValue.specificValues];\r\n const idx = current.indexOf(value);\r\n if (idx >= 0) current.splice(idx, 1);\r\n else current.push(value);\r\n emit(\"update:modelValue\", {\r\n ...props.modelValue,\r\n specificValues: current,\r\n });\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.cron-field-editor {\r\n &__grid {\r\n display: grid;\r\n grid-template-columns: repeat(var(--cols, 10), 1fr);\r\n gap: 4px;\r\n }\r\n\r\n &__cell {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 34px;\r\n border-radius: 6px;\r\n font-size: 13px;\r\n font-variant-numeric: tabular-nums;\r\n transition: all var(--c-transition, 0.2s ease);\r\n user-select: none;\r\n color: var(--c-text-2);\r\n\r\n /* 非交互高亮(every / range / step 的视觉反馈) */\r\n &--on:not(&--pick) {\r\n background: color-mix(in srgb, var(--c-primary) 12%, transparent);\r\n color: var(--c-primary);\r\n }\r\n\r\n /* 可交互模式(specific) */\r\n &--pick {\r\n cursor: pointer;\r\n\r\n &:hover:not(.cron-field-editor__cell--on) {\r\n background: var(--c-bg-card);\r\n }\r\n\r\n &.cron-field-editor__cell--on {\r\n background: var(--c-primary);\r\n color: #fff;\r\n font-weight: 600;\r\n }\r\n }\r\n }\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 字段值网格(始终可见,根据模式自动高亮对应值)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"cron-field-editor\">\r\n <div class=\"cron-field-editor__grid\" :style=\"{ '--cols': gridColumns }\">\r\n <div\r\n v-for=\"item in valueOptions\"\r\n :key=\"item.value\"\r\n class=\"cron-field-editor__cell\"\r\n :class=\"{\r\n 'cron-field-editor__cell--on': highlightedValues.has(item.value),\r\n 'cron-field-editor__cell--pick': modelValue.mode === 'specific',\r\n }\"\r\n @click=\"handleCellClick(item.value)\"\r\n >\r\n {{ item.label }}\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from \"vue\";\r\nimport type { CronFieldMeta, CronFieldValue } from \"../types\";\r\n\r\ninterface Props {\r\n modelValue: CronFieldValue;\r\n meta: CronFieldMeta;\r\n}\r\n\r\nconst props = defineProps<Props>();\r\nconst emit = defineEmits<{\r\n \"update:modelValue\": [value: CronFieldValue];\r\n}>();\r\n\r\n/** 网格列数 */\r\nconst gridColumns = computed(() => {\r\n switch (props.meta.type) {\r\n case \"second\":\r\n case \"minute\":\r\n return 10;\r\n case \"hour\":\r\n return 12;\r\n case \"day\":\r\n return 7;\r\n case \"month\":\r\n return 6;\r\n case \"week\":\r\n return 7;\r\n default:\r\n return 10;\r\n }\r\n});\r\n\r\n/** 可选值列表 */\r\nconst valueOptions = computed(() => {\r\n const items: { value: number; label: string }[] = [];\r\n for (let i = props.meta.min; i <= props.meta.max; i++) {\r\n items.push({\r\n value: i,\r\n label: props.meta.valueLabels?.[i] ?? String(i),\r\n });\r\n }\r\n return items;\r\n});\r\n\r\n/** 根据当前模式计算高亮值集合 */\r\nconst highlightedValues = computed(() => {\r\n const { modelValue: f, meta } = props;\r\n const set = new Set<number>();\r\n switch (f.mode) {\r\n case \"every\":\r\n for (let i = meta.min; i <= meta.max; i++) set.add(i);\r\n break;\r\n case \"none\":\r\n break;\r\n case \"range\":\r\n for (let i = f.rangeStart; i <= f.rangeEnd; i++) set.add(i);\r\n break;\r\n case \"step\":\r\n for (let i = f.stepStart; i <= meta.max; i += f.stepInterval) set.add(i);\r\n break;\r\n case \"specific\":\r\n f.specificValues.forEach((v) => set.add(v));\r\n break;\r\n }\r\n return set;\r\n});\r\n\r\n/** 点击单元格(仅 specific 模式生效) */\r\nfunction handleCellClick(value: number) {\r\n if (props.modelValue.mode !== \"specific\") return;\r\n const current = [...props.modelValue.specificValues];\r\n const idx = current.indexOf(value);\r\n if (idx >= 0) current.splice(idx, 1);\r\n else current.push(value);\r\n emit(\"update:modelValue\", {\r\n ...props.modelValue,\r\n specificValues: current,\r\n });\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.cron-field-editor {\r\n &__grid {\r\n display: grid;\r\n grid-template-columns: repeat(var(--cols, 10), 1fr);\r\n gap: 4px;\r\n }\r\n\r\n &__cell {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 34px;\r\n border-radius: 6px;\r\n font-size: 13px;\r\n font-variant-numeric: tabular-nums;\r\n transition: all var(--c-transition, 0.2s ease);\r\n user-select: none;\r\n color: var(--c-text-2);\r\n\r\n /* 非交互高亮(every / range / step 的视觉反馈) */\r\n &--on:not(&--pick) {\r\n background: color-mix(in srgb, var(--c-primary) 12%, transparent);\r\n color: var(--c-primary);\r\n }\r\n\r\n /* 可交互模式(specific) */\r\n &--pick {\r\n cursor: pointer;\r\n\r\n &:hover:not(.cron-field-editor__cell--on) {\r\n background: var(--c-bg-card);\r\n }\r\n\r\n &.cron-field-editor__cell--on {\r\n background: var(--c-primary);\r\n color: #fff;\r\n font-weight: 600;\r\n }\r\n }\r\n }\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 执行时间预览(紧凑布局)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"cron-preview\">\r\n <div class=\"cron-preview__header\">\r\n <C_Icon name=\"mdi:calendar-clock\" :size=\"15\" />\r\n <span>未来执行</span>\r\n <NSpin v-if=\"computing\" :size=\"14\" />\r\n </div>\r\n\r\n <NScrollbar style=\"max-height: 220px\">\r\n <div v-if=\"nextExecutions.length > 0\" class=\"cron-preview__list\">\r\n <div\r\n v-for=\"(date, index) in nextExecutions\"\r\n :key=\"index\"\r\n class=\"cron-preview__item\"\r\n >\r\n <span class=\"cron-preview__idx\">{{ index + 1 }}</span>\r\n <span class=\"cron-preview__date\">{{ formatDate(date) }}</span>\r\n <span class=\"cron-preview__week\">{{ formatWeekDay(date) }}</span>\r\n </div>\r\n </div>\r\n <NEmpty v-else size=\"small\" description=\"暂无匹配\" />\r\n </NScrollbar>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport C_Icon from \"../../C_Icon/index.vue\";\r\n\r\ninterface Props {\r\n nextExecutions: Date[];\r\n computing: boolean;\r\n count: number;\r\n formatDate: (date: Date) => string;\r\n formatWeekDay: (date: Date) => string;\r\n}\r\n\r\ndefineProps<Props>();\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.cron-preview {\r\n &__header {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-weight: 600;\r\n font-size: 13px;\r\n margin-bottom: 6px;\r\n color: var(--c-text-1);\r\n }\r\n\r\n &__list {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 2px;\r\n }\r\n\r\n &__item {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n padding: 3px 4px;\r\n border-radius: 4px;\r\n font-size: 12px;\r\n transition: background var(--c-transition, 0.2s ease);\r\n\r\n &:hover {\r\n background: var(--c-bg-card);\r\n }\r\n }\r\n\r\n &__idx {\r\n width: 16px;\r\n text-align: center;\r\n color: var(--c-text-4);\r\n flex-shrink: 0;\r\n font-size: 11px;\r\n }\r\n\r\n &__date {\r\n font-family: \"Courier New\", Courier, monospace;\r\n flex: 1;\r\n font-size: 12px;\r\n }\r\n\r\n &__week {\r\n color: var(--c-text-4);\r\n font-size: 12px;\r\n flex-shrink: 0;\r\n }\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 执行时间预览(紧凑布局)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"cron-preview\">\r\n <div class=\"cron-preview__header\">\r\n <C_Icon name=\"mdi:calendar-clock\" :size=\"15\" />\r\n <span>未来执行</span>\r\n <NSpin v-if=\"computing\" :size=\"14\" />\r\n </div>\r\n\r\n <NScrollbar style=\"max-height: 220px\">\r\n <div v-if=\"nextExecutions.length > 0\" class=\"cron-preview__list\">\r\n <div\r\n v-for=\"(date, index) in nextExecutions\"\r\n :key=\"index\"\r\n class=\"cron-preview__item\"\r\n >\r\n <span class=\"cron-preview__idx\">{{ index + 1 }}</span>\r\n <span class=\"cron-preview__date\">{{ formatDate(date) }}</span>\r\n <span class=\"cron-preview__week\">{{ formatWeekDay(date) }}</span>\r\n </div>\r\n </div>\r\n <NEmpty v-else size=\"small\" description=\"暂无匹配\" />\r\n </NScrollbar>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport C_Icon from \"../../C_Icon/index.vue\";\r\n\r\ninterface Props {\r\n nextExecutions: Date[];\r\n computing: boolean;\r\n count: number;\r\n formatDate: (date: Date) => string;\r\n formatWeekDay: (date: Date) => string;\r\n}\r\n\r\ndefineProps<Props>();\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.cron-preview {\r\n &__header {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-weight: 600;\r\n font-size: 13px;\r\n margin-bottom: 6px;\r\n color: var(--c-text-1);\r\n }\r\n\r\n &__list {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 2px;\r\n }\r\n\r\n &__item {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n padding: 3px 4px;\r\n border-radius: 4px;\r\n font-size: 12px;\r\n transition: background var(--c-transition, 0.2s ease);\r\n\r\n &:hover {\r\n background: var(--c-bg-card);\r\n }\r\n }\r\n\r\n &__idx {\r\n width: 16px;\r\n text-align: center;\r\n color: var(--c-text-4);\r\n flex-shrink: 0;\r\n font-size: 11px;\r\n }\r\n\r\n &__date {\r\n font-family: \"Courier New\", Courier, monospace;\r\n flex: 1;\r\n font-size: 12px;\r\n }\r\n\r\n &__week {\r\n color: var(--c-text-4);\r\n font-size: 12px;\r\n flex-shrink: 0;\r\n }\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 执行时间预览(紧凑布局)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"cron-preview\">\r\n <div class=\"cron-preview__header\">\r\n <C_Icon name=\"mdi:calendar-clock\" :size=\"15\" />\r\n <span>未来执行</span>\r\n <NSpin v-if=\"computing\" :size=\"14\" />\r\n </div>\r\n\r\n <NScrollbar style=\"max-height: 220px\">\r\n <div v-if=\"nextExecutions.length > 0\" class=\"cron-preview__list\">\r\n <div\r\n v-for=\"(date, index) in nextExecutions\"\r\n :key=\"index\"\r\n class=\"cron-preview__item\"\r\n >\r\n <span class=\"cron-preview__idx\">{{ index + 1 }}</span>\r\n <span class=\"cron-preview__date\">{{ formatDate(date) }}</span>\r\n <span class=\"cron-preview__week\">{{ formatWeekDay(date) }}</span>\r\n </div>\r\n </div>\r\n <NEmpty v-else size=\"small\" description=\"暂无匹配\" />\r\n </NScrollbar>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport C_Icon from \"../../C_Icon/index.vue\";\r\n\r\ninterface Props {\r\n nextExecutions: Date[];\r\n computing: boolean;\r\n count: number;\r\n formatDate: (date: Date) => string;\r\n formatWeekDay: (date: Date) => string;\r\n}\r\n\r\ndefineProps<Props>();\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.cron-preview {\r\n &__header {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-weight: 600;\r\n font-size: 13px;\r\n margin-bottom: 6px;\r\n color: var(--c-text-1);\r\n }\r\n\r\n &__list {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 2px;\r\n }\r\n\r\n &__item {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n padding: 3px 4px;\r\n border-radius: 4px;\r\n font-size: 12px;\r\n transition: background var(--c-transition, 0.2s ease);\r\n\r\n &:hover {\r\n background: var(--c-bg-card);\r\n }\r\n }\r\n\r\n &__idx {\r\n width: 16px;\r\n text-align: center;\r\n color: var(--c-text-4);\r\n flex-shrink: 0;\r\n font-size: 11px;\r\n }\r\n\r\n &__date {\r\n font-family: \"Courier New\", Courier, monospace;\r\n flex: 1;\r\n font-size: 12px;\r\n }\r\n\r\n &__week {\r\n color: var(--c-text-4);\r\n font-size: 12px;\r\n flex-shrink: 0;\r\n }\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 常用模板(底部卡片网格)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"cron-templates\">\r\n <div class=\"cron-templates__header\">\r\n <C_Icon name=\"mdi:lightning-bolt\" :size=\"15\" />\r\n <span>常用模板</span>\r\n </div>\r\n\r\n <div class=\"cron-templates__cards\">\r\n <div\r\n v-for=\"template in templates\"\r\n :key=\"template.value\"\r\n class=\"cron-templates__card\"\r\n :class=\"{\r\n 'cron-templates__card--active': template.value === currentValue,\r\n }\"\r\n @click=\"$emit('select', template.value)\"\r\n >\r\n <div class=\"cron-templates__card-name\">{{ template.label }}</div>\r\n <div class=\"cron-templates__card-expr\">{{ template.value }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport C_Icon from \"../../C_Icon/index.vue\";\r\nimport type { CronTemplate } from \"../types\";\r\n\r\ninterface Props {\r\n templates: CronTemplate[];\r\n currentValue: string;\r\n}\r\n\r\ndefineProps<Props>();\r\ndefineEmits<{\r\n select: [value: string];\r\n}>();\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.cron-templates {\r\n &__header {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-weight: 600;\r\n font-size: 13px;\r\n margin-bottom: 10px;\r\n color: var(--c-text-1);\r\n }\r\n\r\n &__cards {\r\n display: grid;\r\n grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));\r\n gap: 8px;\r\n }\r\n\r\n &__card {\r\n padding: 10px 12px;\r\n border-radius: 8px;\r\n border: 1px solid var(--c-border);\r\n cursor: pointer;\r\n transition: all var(--c-transition, 0.2s ease);\r\n\r\n &:hover {\r\n border-color: var(--c-primary);\r\n background: color-mix(in srgb, var(--c-primary) 4%, transparent);\r\n }\r\n\r\n &--active {\r\n border-color: var(--c-primary);\r\n background: color-mix(in srgb, var(--c-primary) 8%, transparent);\r\n }\r\n }\r\n\r\n &__card-name {\r\n font-size: 13px;\r\n font-weight: 500;\r\n line-height: 1.4;\r\n }\r\n\r\n &__card-expr {\r\n font-family: \"Courier New\", Courier, monospace;\r\n font-size: 11px;\r\n color: var(--c-text-4);\r\n margin-top: 2px;\r\n }\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 常用模板(底部卡片网格)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"cron-templates\">\r\n <div class=\"cron-templates__header\">\r\n <C_Icon name=\"mdi:lightning-bolt\" :size=\"15\" />\r\n <span>常用模板</span>\r\n </div>\r\n\r\n <div class=\"cron-templates__cards\">\r\n <div\r\n v-for=\"template in templates\"\r\n :key=\"template.value\"\r\n class=\"cron-templates__card\"\r\n :class=\"{\r\n 'cron-templates__card--active': template.value === currentValue,\r\n }\"\r\n @click=\"$emit('select', template.value)\"\r\n >\r\n <div class=\"cron-templates__card-name\">{{ template.label }}</div>\r\n <div class=\"cron-templates__card-expr\">{{ template.value }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport C_Icon from \"../../C_Icon/index.vue\";\r\nimport type { CronTemplate } from \"../types\";\r\n\r\ninterface Props {\r\n templates: CronTemplate[];\r\n currentValue: string;\r\n}\r\n\r\ndefineProps<Props>();\r\ndefineEmits<{\r\n select: [value: string];\r\n}>();\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.cron-templates {\r\n &__header {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-weight: 600;\r\n font-size: 13px;\r\n margin-bottom: 10px;\r\n color: var(--c-text-1);\r\n }\r\n\r\n &__cards {\r\n display: grid;\r\n grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));\r\n gap: 8px;\r\n }\r\n\r\n &__card {\r\n padding: 10px 12px;\r\n border-radius: 8px;\r\n border: 1px solid var(--c-border);\r\n cursor: pointer;\r\n transition: all var(--c-transition, 0.2s ease);\r\n\r\n &:hover {\r\n border-color: var(--c-primary);\r\n background: color-mix(in srgb, var(--c-primary) 4%, transparent);\r\n }\r\n\r\n &--active {\r\n border-color: var(--c-primary);\r\n background: color-mix(in srgb, var(--c-primary) 8%, transparent);\r\n }\r\n }\r\n\r\n &__card-name {\r\n font-size: 13px;\r\n font-weight: 500;\r\n line-height: 1.4;\r\n }\r\n\r\n &__card-expr {\r\n font-family: \"Courier New\", Courier, monospace;\r\n font-size: 11px;\r\n color: var(--c-text-4);\r\n margin-top: 2px;\r\n }\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 常用模板(底部卡片网格)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"cron-templates\">\r\n <div class=\"cron-templates__header\">\r\n <C_Icon name=\"mdi:lightning-bolt\" :size=\"15\" />\r\n <span>常用模板</span>\r\n </div>\r\n\r\n <div class=\"cron-templates__cards\">\r\n <div\r\n v-for=\"template in templates\"\r\n :key=\"template.value\"\r\n class=\"cron-templates__card\"\r\n :class=\"{\r\n 'cron-templates__card--active': template.value === currentValue,\r\n }\"\r\n @click=\"$emit('select', template.value)\"\r\n >\r\n <div class=\"cron-templates__card-name\">{{ template.label }}</div>\r\n <div class=\"cron-templates__card-expr\">{{ template.value }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport C_Icon from \"../../C_Icon/index.vue\";\r\nimport type { CronTemplate } from \"../types\";\r\n\r\ninterface Props {\r\n templates: CronTemplate[];\r\n currentValue: string;\r\n}\r\n\r\ndefineProps<Props>();\r\ndefineEmits<{\r\n select: [value: string];\r\n}>();\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.cron-templates {\r\n &__header {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-weight: 600;\r\n font-size: 13px;\r\n margin-bottom: 10px;\r\n color: var(--c-text-1);\r\n }\r\n\r\n &__cards {\r\n display: grid;\r\n grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));\r\n gap: 8px;\r\n }\r\n\r\n &__card {\r\n padding: 10px 12px;\r\n border-radius: 8px;\r\n border: 1px solid var(--c-border);\r\n cursor: pointer;\r\n transition: all var(--c-transition, 0.2s ease);\r\n\r\n &:hover {\r\n border-color: var(--c-primary);\r\n background: color-mix(in srgb, var(--c-primary) 4%, transparent);\r\n }\r\n\r\n &--active {\r\n border-color: var(--c-primary);\r\n background: color-mix(in srgb, var(--c-primary) 8%, transparent);\r\n }\r\n }\r\n\r\n &__card-name {\r\n font-size: 13px;\r\n font-weight: 500;\r\n line-height: 1.4;\r\n }\r\n\r\n &__card-expr {\r\n font-family: \"Courier New\", Courier, monospace;\r\n font-size: 11px;\r\n color: var(--c-text-4);\r\n margin-top: 2px;\r\n }\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 表达式编辑器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"c-cron\" :style=\"{ height: containerHeight }\">\r\n <!-- ═══════ 顶部 ═══════ -->\r\n <div class=\"c-cron__header\">\r\n <!-- 标题行 -->\r\n <div class=\"c-cron__title-row\">\r\n <div class=\"c-cron__title\">\r\n <C_Icon name=\"mdi:clock-edit-outline\" :size=\"18\" />\r\n <span>Cron 表达式</span>\r\n </div>\r\n <NTag :type=\"validation.valid ? 'success' : 'error'\" size=\"small\" round>\r\n <template #icon>\r\n <C_Icon\r\n :name=\"validation.valid ? 'mdi:check-circle' : 'mdi:alert-circle'\"\r\n />\r\n </template>\r\n {{ validation.valid ? \"合法\" : \"错误\" }}\r\n </NTag>\r\n </div>\r\n\r\n <!-- 分段式字段选择器 -->\r\n <div class=\"c-cron__segments\">\r\n <div\r\n v-for=\"meta in visibleFields\"\r\n :key=\"meta.type\"\r\n class=\"c-cron__segment\"\r\n :class=\"{\r\n 'c-cron__segment--active': activeField === meta.type,\r\n 'c-cron__segment--wildcard':\r\n fieldExpressions[meta.type] === '*' ||\r\n fieldExpressions[meta.type] === '?',\r\n }\"\r\n @click=\"activeField = meta.type\"\r\n >\r\n <div class=\"c-cron__segment-value\">\r\n {{ fieldExpressions[meta.type] }}\r\n </div>\r\n <div class=\"c-cron__segment-label\">{{ meta.label }}</div>\r\n </div>\r\n </div>\r\n\r\n <!-- 表达式行:输入 + 重置 + 描述 -->\r\n <div class=\"c-cron__expr-row\">\r\n <NInput\r\n :value=\"manualInput\"\r\n :status=\"validation.valid ? undefined : 'error'\"\r\n placeholder=\"秒 分 时 日 月 周\"\r\n :disabled=\"props.disabled\"\r\n font=\"mono\"\r\n size=\"small\"\r\n clearable\r\n class=\"c-cron__expr-input\"\r\n @update:value=\"handleManualInput\"\r\n @blur=\"handleManualBlur\"\r\n @keydown.enter=\"handleManualBlur\"\r\n >\r\n <template #prefix>\r\n <C_Icon name=\"mdi:console\" :size=\"14\" style=\"opacity: 0.4\" />\r\n </template>\r\n </NInput>\r\n <NButton\r\n size=\"small\"\r\n quaternary\r\n :disabled=\"props.disabled\"\r\n @click=\"handleReset\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"mdi:refresh\" />\r\n </template>\r\n </NButton>\r\n <div class=\"c-cron__expr-desc\">\r\n <span v-if=\"validation.valid\" class=\"c-cron__description\">\r\n {{ description }}\r\n </span>\r\n <span v-else class=\"c-cron__error\">\r\n {{ validation.message }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- ═══════ 主内容 ═══════ -->\r\n <div class=\"c-cron__body\">\r\n <!-- 左侧:值网格 -->\r\n <div class=\"c-cron__main\">\r\n <CronFieldEditor\r\n v-for=\"meta in visibleFields\"\r\n v-show=\"activeField === meta.type\"\r\n :key=\"meta.type\"\r\n :model-value=\"cronValue[meta.type]\"\r\n :meta=\"meta\"\r\n @update:model-value=\"(v) => handleFieldChange(meta.type, v)\"\r\n />\r\n </div>\r\n\r\n <!-- 右侧:控制面板 -->\r\n <div class=\"c-cron__panel\">\r\n <NRadioGroup\r\n :value=\"activeFieldValue.mode\"\r\n size=\"small\"\r\n @update:value=\"handleActiveFieldModeChange\"\r\n >\r\n <NRadioButton value=\"every\">\r\n 每{{ activeFieldMeta.label }}\r\n </NRadioButton>\r\n <NRadioButton\r\n v-if=\"activeField === 'day' || activeField === 'week'\"\r\n value=\"none\"\r\n >\r\n 不指定\r\n </NRadioButton>\r\n <NRadioButton value=\"range\">范围</NRadioButton>\r\n <NRadioButton value=\"step\">步进</NRadioButton>\r\n <NRadioButton value=\"specific\">指定</NRadioButton>\r\n </NRadioGroup>\r\n\r\n <!-- 范围配置 -->\r\n <div v-if=\"activeFieldValue.mode === 'range'\" class=\"c-cron__config\">\r\n <div class=\"c-cron__config-row\">\r\n <span>从</span>\r\n <NInputNumber\r\n :value=\"activeFieldValue.rangeStart\"\r\n :min=\"activeFieldMeta.min\"\r\n :max=\"activeFieldMeta.max\"\r\n size=\"small\"\r\n :show-button=\"false\"\r\n class=\"c-cron__config-num\"\r\n @update:value=\"\r\n (v: number | null) =>\r\n handleActiveFieldUpdate({\r\n rangeStart: v ?? activeFieldMeta.min,\r\n })\r\n \"\r\n />\r\n <span>到</span>\r\n <NInputNumber\r\n :value=\"activeFieldValue.rangeEnd\"\r\n :min=\"activeFieldMeta.min\"\r\n :max=\"activeFieldMeta.max\"\r\n size=\"small\"\r\n :show-button=\"false\"\r\n class=\"c-cron__config-num\"\r\n @update:value=\"\r\n (v: number | null) =>\r\n handleActiveFieldUpdate({\r\n rangeEnd: v ?? activeFieldMeta.max,\r\n })\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- 步进配置 -->\r\n <div v-if=\"activeFieldValue.mode === 'step'\" class=\"c-cron__config\">\r\n <div class=\"c-cron__config-row\">\r\n <span>从第</span>\r\n <NInputNumber\r\n :value=\"activeFieldValue.stepStart\"\r\n :min=\"activeFieldMeta.min\"\r\n :max=\"activeFieldMeta.max\"\r\n size=\"small\"\r\n :show-button=\"false\"\r\n class=\"c-cron__config-num\"\r\n @update:value=\"\r\n (v: number | null) =>\r\n handleActiveFieldUpdate({\r\n stepStart: v ?? activeFieldMeta.min,\r\n })\r\n \"\r\n />\r\n <span>{{ activeFieldMeta.label }}起,每</span>\r\n <NInputNumber\r\n :value=\"activeFieldValue.stepInterval\"\r\n :min=\"1\"\r\n :max=\"activeFieldMeta.max - activeFieldMeta.min + 1\"\r\n size=\"small\"\r\n :show-button=\"false\"\r\n class=\"c-cron__config-num\"\r\n @update:value=\"\r\n (v: number | null) =>\r\n handleActiveFieldUpdate({ stepInterval: v ?? 1 })\r\n \"\r\n />\r\n <span>{{ activeFieldMeta.label }}执行</span>\r\n </div>\r\n </div>\r\n\r\n <!-- 指定快捷操作 -->\r\n <div v-if=\"activeFieldValue.mode === 'specific'\" class=\"c-cron__quick\">\r\n <a @click=\"handleSelectAll\">全选</a>\r\n <span class=\"c-cron__quick-sep\">·</span>\r\n <a @click=\"handleClearAll\">清空</a>\r\n <span\r\n v-if=\"activeFieldValue.specificValues.length > 0\"\r\n class=\"c-cron__quick-count\"\r\n >\r\n 已选 {{ activeFieldValue.specificValues.length }}\r\n </span>\r\n </div>\r\n\r\n <!-- 执行预览 -->\r\n <template v-if=\"props.showPreview\">\r\n <div class=\"c-cron__panel-line\" />\r\n <CronPreview\r\n :next-executions=\"nextExecutions\"\r\n :computing=\"computing\"\r\n :count=\"props.previewCount ?? 5\"\r\n :format-date=\"formatDate\"\r\n :format-week-day=\"formatWeekDay\"\r\n />\r\n </template>\r\n </div>\r\n </div>\r\n\r\n <!-- ═══════ 底部模板 ═══════ -->\r\n <div v-if=\"props.showTemplates\" class=\"c-cron__footer\">\r\n <CronTemplates\r\n :templates=\"CRON_TEMPLATES\"\r\n :current-value=\"expression\"\r\n @select=\"handleTemplateSelect\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, watch, onMounted } from \"vue\";\r\nimport type {\r\n CronFieldMode,\r\n CronFieldType,\r\n CronFieldValue,\r\n CronProps,\r\n CronValidation,\r\n} from \"./types\";\r\nimport {\r\n CRON_FIELD_META,\r\n CRON_TEMPLATES,\r\n DEFAULT_CRON_EXPRESSION,\r\n} from \"./constants\";\r\nimport { useCronParser } from \"./composables/useCronParser\";\r\nimport { useCronPreview } from \"./composables/useCronPreview\";\r\nimport { useCronDescription } from \"./composables/useCronDescription\";\r\nimport C_Icon from \"../C_Icon/index.vue\";\r\nimport CronFieldEditor from \"./components/CronFieldEditor.vue\";\r\nimport CronPreview from \"./components/CronPreview.vue\";\r\nimport CronTemplates from \"./components/CronTemplates.vue\";\r\n\r\ndefineOptions({ name: \"C_Cron\" });\r\n\r\n/* ─── Props & Emits ─────────────────────────── */\r\n\r\nconst props = withDefaults(defineProps<CronProps>(), {\r\n modelValue: DEFAULT_CRON_EXPRESSION,\r\n disabled: false,\r\n previewCount: 10,\r\n showTemplates: true,\r\n showPreview: true,\r\n showSecond: true,\r\n height: \"auto\",\r\n});\r\n\r\nconst emit = defineEmits<{\r\n \"update:modelValue\": [value: string];\r\n change: [value: string];\r\n \"validation-change\": [result: CronValidation];\r\n}>();\r\n\r\n/* ─── 组合函数 ──────────────────────────────── */\r\n\r\nconst {\r\n cronValue,\r\n expression,\r\n validation,\r\n parse,\r\n validate,\r\n handleDayWeekExclusion,\r\n} = useCronParser();\r\n\r\nconst previewCount = computed(() => props.previewCount ?? 10);\r\nconst { nextExecutions, computing, formatDate, formatWeekDay } = useCronPreview(\r\n expression,\r\n validation,\r\n previewCount,\r\n);\r\n\r\nconst { description } = useCronDescription(expression, validation);\r\n\r\n/* ─── 本地状态 ──────────────────────────────── */\r\n\r\n/** 手动输入框值(与 expression 解耦,输入完成后同步) */\r\nconst manualInput = ref(props.modelValue || DEFAULT_CRON_EXPRESSION);\r\n\r\n/** 当前激活的字段 Tab */\r\nconst activeField = ref<CronFieldType>(props.showSecond ? \"second\" : \"minute\");\r\n\r\n/* ─── 容器高度 ──────────────────────────────── */\r\n\r\nconst containerHeight = computed(() => {\r\n if (typeof props.height === \"number\") return `${props.height}px`;\r\n return props.height;\r\n});\r\n\r\n/* ─── 可见字段(是否显示秒) ────────────────── */\r\n\r\nconst visibleFields = computed(() => {\r\n return props.showSecond\r\n ? CRON_FIELD_META\r\n : CRON_FIELD_META.filter((m) => m.type !== \"second\");\r\n});\r\n\r\n/* ─── 当前激活字段快捷访问 ─────────────────── */\r\n\r\n/** 当前激活字段元数据 */\r\nconst activeFieldMeta = computed(\r\n () => CRON_FIELD_META.find((m) => m.type === activeField.value)!,\r\n);\r\n\r\n/** 当前激活字段值 */\r\nconst activeFieldValue = computed(() => cronValue.value[activeField.value]);\r\n\r\n/* ─── 分段式表达式(逐字段计算) ────────────── */\r\n\r\n/** 计算单字段表达式文本 */\r\nfunction computeFieldExpr(f: CronFieldValue): string {\r\n switch (f.mode) {\r\n case \"every\":\r\n return \"*\";\r\n case \"none\":\r\n return \"?\";\r\n case \"range\":\r\n return `${f.rangeStart}-${f.rangeEnd}`;\r\n case \"step\":\r\n return `${f.stepStart}/${f.stepInterval}`;\r\n case \"specific\":\r\n return f.specificValues.length > 0\r\n ? [...f.specificValues].sort((a, b) => a - b).join(\",\")\r\n : \"*\";\r\n default:\r\n return \"*\";\r\n }\r\n}\r\n\r\n/** 各字段表达式映射 */\r\nconst fieldExpressions = computed(() => {\r\n const map = {} as Record<CronFieldType, string>;\r\n for (const meta of CRON_FIELD_META) {\r\n map[meta.type] = computeFieldExpr(cronValue.value[meta.type]);\r\n }\r\n return map;\r\n});\r\n\r\n/* ─── 初始化解析 ────────────────────────────── */\r\n\r\nonMounted(() => {\r\n const initial = props.modelValue || DEFAULT_CRON_EXPRESSION;\r\n parse(initial);\r\n manualInput.value = initial;\r\n});\r\n\r\n/* ─── 监听外部 v-model 变更 ─────────────────── */\r\n\r\nwatch(\r\n () => props.modelValue,\r\n (newVal) => {\r\n if (newVal && newVal !== expression.value) {\r\n parse(newVal);\r\n manualInput.value = newVal;\r\n }\r\n },\r\n);\r\n\r\n/* ─── 监听 showSecond 变更 ──────────────────── */\r\n\r\nwatch(\r\n () => props.showSecond,\r\n (show) => {\r\n if (!show && activeField.value === \"second\") {\r\n activeField.value = \"minute\";\r\n }\r\n },\r\n);\r\n\r\n/* ─── 监听内部表达式变更 → 同步到外部 ───────── */\r\n\r\nwatch(expression, (newExpr) => {\r\n manualInput.value = newExpr;\r\n emit(\"update:modelValue\", newExpr);\r\n emit(\"change\", newExpr);\r\n});\r\n\r\n/* ─── 监听校验状态变更 ──────────────────────── */\r\n\r\nwatch(validation, (v) => {\r\n emit(\"validation-change\", v);\r\n});\r\n\r\n/* ─── 字段变更处理 ──────────────────────────── */\r\n\r\n/** 字段编辑变更处理 */\r\nfunction handleFieldChange(type: CronFieldType, value: CronFieldValue) {\r\n cronValue.value[type] = value;\r\n if (type === \"day\" || type === \"week\") {\r\n handleDayWeekExclusion(type);\r\n }\r\n}\r\n\r\n/* ─── 右侧面板操作 ─────────────────────────── */\r\n\r\n/** 切换当前字段模式 */\r\nfunction handleActiveFieldModeChange(mode: CronFieldMode) {\r\n handleFieldChange(activeField.value, {\r\n ...activeFieldValue.value,\r\n mode,\r\n });\r\n}\r\n\r\n/** 更新当前字段属性 */\r\nfunction handleActiveFieldUpdate(partial: Partial<CronFieldValue>) {\r\n handleFieldChange(activeField.value, {\r\n ...activeFieldValue.value,\r\n ...partial,\r\n });\r\n}\r\n\r\n/** 全选当前字段所有值 */\r\nfunction handleSelectAll() {\r\n const { min, max } = activeFieldMeta.value;\r\n const allValues = Array.from({ length: max - min + 1 }, (_, i) => min + i);\r\n handleFieldChange(activeField.value, {\r\n ...activeFieldValue.value,\r\n specificValues: allValues,\r\n });\r\n}\r\n\r\n/** 清空当前字段所有选中值 */\r\nfunction handleClearAll() {\r\n handleFieldChange(activeField.value, {\r\n ...activeFieldValue.value,\r\n specificValues: [],\r\n });\r\n}\r\n\r\n/* ─── 手动输入处理 ──────────────────────────── */\r\n\r\n/** 手动输入更新 */\r\nfunction handleManualInput(value: string) {\r\n manualInput.value = value;\r\n}\r\n\r\n/** 输入框失焦时同步 */\r\nfunction handleManualBlur() {\r\n const trimmed = manualInput.value.trim();\r\n if (trimmed && trimmed !== expression.value) {\r\n parse(trimmed);\r\n }\r\n}\r\n\r\n/* ─── 模板选择 ──────────────────────────────── */\r\n\r\n/** 选择常用模板 */\r\nfunction handleTemplateSelect(expr: string) {\r\n parse(expr);\r\n manualInput.value = expr;\r\n}\r\n\r\n/* ─── 重置 ──────────────────────────────────── */\r\n\r\n/** 重置为初始值 */\r\nfunction handleReset() {\r\n const initial = props.modelValue || DEFAULT_CRON_EXPRESSION;\r\n parse(initial);\r\n manualInput.value = initial;\r\n}\r\n\r\n/* ─── Expose ────────────────────────────────── */\r\n\r\ndefineExpose({\r\n getValue: () => expression.value,\r\n setValue: (expr: string) => {\r\n parse(expr);\r\n manualInput.value = expr;\r\n },\r\n reset: handleReset,\r\n validate: () => validate(),\r\n});\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 表达式编辑器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"c-cron\" :style=\"{ height: containerHeight }\">\r\n <!-- ═══════ 顶部 ═══════ -->\r\n <div class=\"c-cron__header\">\r\n <!-- 标题行 -->\r\n <div class=\"c-cron__title-row\">\r\n <div class=\"c-cron__title\">\r\n <C_Icon name=\"mdi:clock-edit-outline\" :size=\"18\" />\r\n <span>Cron 表达式</span>\r\n </div>\r\n <NTag :type=\"validation.valid ? 'success' : 'error'\" size=\"small\" round>\r\n <template #icon>\r\n <C_Icon\r\n :name=\"validation.valid ? 'mdi:check-circle' : 'mdi:alert-circle'\"\r\n />\r\n </template>\r\n {{ validation.valid ? \"合法\" : \"错误\" }}\r\n </NTag>\r\n </div>\r\n\r\n <!-- 分段式字段选择器 -->\r\n <div class=\"c-cron__segments\">\r\n <div\r\n v-for=\"meta in visibleFields\"\r\n :key=\"meta.type\"\r\n class=\"c-cron__segment\"\r\n :class=\"{\r\n 'c-cron__segment--active': activeField === meta.type,\r\n 'c-cron__segment--wildcard':\r\n fieldExpressions[meta.type] === '*' ||\r\n fieldExpressions[meta.type] === '?',\r\n }\"\r\n @click=\"activeField = meta.type\"\r\n >\r\n <div class=\"c-cron__segment-value\">\r\n {{ fieldExpressions[meta.type] }}\r\n </div>\r\n <div class=\"c-cron__segment-label\">{{ meta.label }}</div>\r\n </div>\r\n </div>\r\n\r\n <!-- 表达式行:输入 + 重置 + 描述 -->\r\n <div class=\"c-cron__expr-row\">\r\n <NInput\r\n :value=\"manualInput\"\r\n :status=\"validation.valid ? undefined : 'error'\"\r\n placeholder=\"秒 分 时 日 月 周\"\r\n :disabled=\"props.disabled\"\r\n font=\"mono\"\r\n size=\"small\"\r\n clearable\r\n class=\"c-cron__expr-input\"\r\n @update:value=\"handleManualInput\"\r\n @blur=\"handleManualBlur\"\r\n @keydown.enter=\"handleManualBlur\"\r\n >\r\n <template #prefix>\r\n <C_Icon name=\"mdi:console\" :size=\"14\" style=\"opacity: 0.4\" />\r\n </template>\r\n </NInput>\r\n <NButton\r\n size=\"small\"\r\n quaternary\r\n :disabled=\"props.disabled\"\r\n @click=\"handleReset\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"mdi:refresh\" />\r\n </template>\r\n </NButton>\r\n <div class=\"c-cron__expr-desc\">\r\n <span v-if=\"validation.valid\" class=\"c-cron__description\">\r\n {{ description }}\r\n </span>\r\n <span v-else class=\"c-cron__error\">\r\n {{ validation.message }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- ═══════ 主内容 ═══════ -->\r\n <div class=\"c-cron__body\">\r\n <!-- 左侧:值网格 -->\r\n <div class=\"c-cron__main\">\r\n <CronFieldEditor\r\n v-for=\"meta in visibleFields\"\r\n v-show=\"activeField === meta.type\"\r\n :key=\"meta.type\"\r\n :model-value=\"cronValue[meta.type]\"\r\n :meta=\"meta\"\r\n @update:model-value=\"(v) => handleFieldChange(meta.type, v)\"\r\n />\r\n </div>\r\n\r\n <!-- 右侧:控制面板 -->\r\n <div class=\"c-cron__panel\">\r\n <NRadioGroup\r\n :value=\"activeFieldValue.mode\"\r\n size=\"small\"\r\n @update:value=\"handleActiveFieldModeChange\"\r\n >\r\n <NRadioButton value=\"every\">\r\n 每{{ activeFieldMeta.label }}\r\n </NRadioButton>\r\n <NRadioButton\r\n v-if=\"activeField === 'day' || activeField === 'week'\"\r\n value=\"none\"\r\n >\r\n 不指定\r\n </NRadioButton>\r\n <NRadioButton value=\"range\">范围</NRadioButton>\r\n <NRadioButton value=\"step\">步进</NRadioButton>\r\n <NRadioButton value=\"specific\">指定</NRadioButton>\r\n </NRadioGroup>\r\n\r\n <!-- 范围配置 -->\r\n <div v-if=\"activeFieldValue.mode === 'range'\" class=\"c-cron__config\">\r\n <div class=\"c-cron__config-row\">\r\n <span>从</span>\r\n <NInputNumber\r\n :value=\"activeFieldValue.rangeStart\"\r\n :min=\"activeFieldMeta.min\"\r\n :max=\"activeFieldMeta.max\"\r\n size=\"small\"\r\n :show-button=\"false\"\r\n class=\"c-cron__config-num\"\r\n @update:value=\"\r\n (v: number | null) =>\r\n handleActiveFieldUpdate({\r\n rangeStart: v ?? activeFieldMeta.min,\r\n })\r\n \"\r\n />\r\n <span>到</span>\r\n <NInputNumber\r\n :value=\"activeFieldValue.rangeEnd\"\r\n :min=\"activeFieldMeta.min\"\r\n :max=\"activeFieldMeta.max\"\r\n size=\"small\"\r\n :show-button=\"false\"\r\n class=\"c-cron__config-num\"\r\n @update:value=\"\r\n (v: number | null) =>\r\n handleActiveFieldUpdate({\r\n rangeEnd: v ?? activeFieldMeta.max,\r\n })\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- 步进配置 -->\r\n <div v-if=\"activeFieldValue.mode === 'step'\" class=\"c-cron__config\">\r\n <div class=\"c-cron__config-row\">\r\n <span>从第</span>\r\n <NInputNumber\r\n :value=\"activeFieldValue.stepStart\"\r\n :min=\"activeFieldMeta.min\"\r\n :max=\"activeFieldMeta.max\"\r\n size=\"small\"\r\n :show-button=\"false\"\r\n class=\"c-cron__config-num\"\r\n @update:value=\"\r\n (v: number | null) =>\r\n handleActiveFieldUpdate({\r\n stepStart: v ?? activeFieldMeta.min,\r\n })\r\n \"\r\n />\r\n <span>{{ activeFieldMeta.label }}起,每</span>\r\n <NInputNumber\r\n :value=\"activeFieldValue.stepInterval\"\r\n :min=\"1\"\r\n :max=\"activeFieldMeta.max - activeFieldMeta.min + 1\"\r\n size=\"small\"\r\n :show-button=\"false\"\r\n class=\"c-cron__config-num\"\r\n @update:value=\"\r\n (v: number | null) =>\r\n handleActiveFieldUpdate({ stepInterval: v ?? 1 })\r\n \"\r\n />\r\n <span>{{ activeFieldMeta.label }}执行</span>\r\n </div>\r\n </div>\r\n\r\n <!-- 指定快捷操作 -->\r\n <div v-if=\"activeFieldValue.mode === 'specific'\" class=\"c-cron__quick\">\r\n <a @click=\"handleSelectAll\">全选</a>\r\n <span class=\"c-cron__quick-sep\">·</span>\r\n <a @click=\"handleClearAll\">清空</a>\r\n <span\r\n v-if=\"activeFieldValue.specificValues.length > 0\"\r\n class=\"c-cron__quick-count\"\r\n >\r\n 已选 {{ activeFieldValue.specificValues.length }}\r\n </span>\r\n </div>\r\n\r\n <!-- 执行预览 -->\r\n <template v-if=\"props.showPreview\">\r\n <div class=\"c-cron__panel-line\" />\r\n <CronPreview\r\n :next-executions=\"nextExecutions\"\r\n :computing=\"computing\"\r\n :count=\"props.previewCount ?? 5\"\r\n :format-date=\"formatDate\"\r\n :format-week-day=\"formatWeekDay\"\r\n />\r\n </template>\r\n </div>\r\n </div>\r\n\r\n <!-- ═══════ 底部模板 ═══════ -->\r\n <div v-if=\"props.showTemplates\" class=\"c-cron__footer\">\r\n <CronTemplates\r\n :templates=\"CRON_TEMPLATES\"\r\n :current-value=\"expression\"\r\n @select=\"handleTemplateSelect\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, watch, onMounted } from \"vue\";\r\nimport type {\r\n CronFieldMode,\r\n CronFieldType,\r\n CronFieldValue,\r\n CronProps,\r\n CronValidation,\r\n} from \"./types\";\r\nimport {\r\n CRON_FIELD_META,\r\n CRON_TEMPLATES,\r\n DEFAULT_CRON_EXPRESSION,\r\n} from \"./constants\";\r\nimport { useCronParser } from \"./composables/useCronParser\";\r\nimport { useCronPreview } from \"./composables/useCronPreview\";\r\nimport { useCronDescription } from \"./composables/useCronDescription\";\r\nimport C_Icon from \"../C_Icon/index.vue\";\r\nimport CronFieldEditor from \"./components/CronFieldEditor.vue\";\r\nimport CronPreview from \"./components/CronPreview.vue\";\r\nimport CronTemplates from \"./components/CronTemplates.vue\";\r\n\r\ndefineOptions({ name: \"C_Cron\" });\r\n\r\n/* ─── Props & Emits ─────────────────────────── */\r\n\r\nconst props = withDefaults(defineProps<CronProps>(), {\r\n modelValue: DEFAULT_CRON_EXPRESSION,\r\n disabled: false,\r\n previewCount: 10,\r\n showTemplates: true,\r\n showPreview: true,\r\n showSecond: true,\r\n height: \"auto\",\r\n});\r\n\r\nconst emit = defineEmits<{\r\n \"update:modelValue\": [value: string];\r\n change: [value: string];\r\n \"validation-change\": [result: CronValidation];\r\n}>();\r\n\r\n/* ─── 组合函数 ──────────────────────────────── */\r\n\r\nconst {\r\n cronValue,\r\n expression,\r\n validation,\r\n parse,\r\n validate,\r\n handleDayWeekExclusion,\r\n} = useCronParser();\r\n\r\nconst previewCount = computed(() => props.previewCount ?? 10);\r\nconst { nextExecutions, computing, formatDate, formatWeekDay } = useCronPreview(\r\n expression,\r\n validation,\r\n previewCount,\r\n);\r\n\r\nconst { description } = useCronDescription(expression, validation);\r\n\r\n/* ─── 本地状态 ──────────────────────────────── */\r\n\r\n/** 手动输入框值(与 expression 解耦,输入完成后同步) */\r\nconst manualInput = ref(props.modelValue || DEFAULT_CRON_EXPRESSION);\r\n\r\n/** 当前激活的字段 Tab */\r\nconst activeField = ref<CronFieldType>(props.showSecond ? \"second\" : \"minute\");\r\n\r\n/* ─── 容器高度 ──────────────────────────────── */\r\n\r\nconst containerHeight = computed(() => {\r\n if (typeof props.height === \"number\") return `${props.height}px`;\r\n return props.height;\r\n});\r\n\r\n/* ─── 可见字段(是否显示秒) ────────────────── */\r\n\r\nconst visibleFields = computed(() => {\r\n return props.showSecond\r\n ? CRON_FIELD_META\r\n : CRON_FIELD_META.filter((m) => m.type !== \"second\");\r\n});\r\n\r\n/* ─── 当前激活字段快捷访问 ─────────────────── */\r\n\r\n/** 当前激活字段元数据 */\r\nconst activeFieldMeta = computed(\r\n () => CRON_FIELD_META.find((m) => m.type === activeField.value)!,\r\n);\r\n\r\n/** 当前激活字段值 */\r\nconst activeFieldValue = computed(() => cronValue.value[activeField.value]);\r\n\r\n/* ─── 分段式表达式(逐字段计算) ────────────── */\r\n\r\n/** 计算单字段表达式文本 */\r\nfunction computeFieldExpr(f: CronFieldValue): string {\r\n switch (f.mode) {\r\n case \"every\":\r\n return \"*\";\r\n case \"none\":\r\n return \"?\";\r\n case \"range\":\r\n return `${f.rangeStart}-${f.rangeEnd}`;\r\n case \"step\":\r\n return `${f.stepStart}/${f.stepInterval}`;\r\n case \"specific\":\r\n return f.specificValues.length > 0\r\n ? [...f.specificValues].sort((a, b) => a - b).join(\",\")\r\n : \"*\";\r\n default:\r\n return \"*\";\r\n }\r\n}\r\n\r\n/** 各字段表达式映射 */\r\nconst fieldExpressions = computed(() => {\r\n const map = {} as Record<CronFieldType, string>;\r\n for (const meta of CRON_FIELD_META) {\r\n map[meta.type] = computeFieldExpr(cronValue.value[meta.type]);\r\n }\r\n return map;\r\n});\r\n\r\n/* ─── 初始化解析 ────────────────────────────── */\r\n\r\nonMounted(() => {\r\n const initial = props.modelValue || DEFAULT_CRON_EXPRESSION;\r\n parse(initial);\r\n manualInput.value = initial;\r\n});\r\n\r\n/* ─── 监听外部 v-model 变更 ─────────────────── */\r\n\r\nwatch(\r\n () => props.modelValue,\r\n (newVal) => {\r\n if (newVal && newVal !== expression.value) {\r\n parse(newVal);\r\n manualInput.value = newVal;\r\n }\r\n },\r\n);\r\n\r\n/* ─── 监听 showSecond 变更 ──────────────────── */\r\n\r\nwatch(\r\n () => props.showSecond,\r\n (show) => {\r\n if (!show && activeField.value === \"second\") {\r\n activeField.value = \"minute\";\r\n }\r\n },\r\n);\r\n\r\n/* ─── 监听内部表达式变更 → 同步到外部 ───────── */\r\n\r\nwatch(expression, (newExpr) => {\r\n manualInput.value = newExpr;\r\n emit(\"update:modelValue\", newExpr);\r\n emit(\"change\", newExpr);\r\n});\r\n\r\n/* ─── 监听校验状态变更 ──────────────────────── */\r\n\r\nwatch(validation, (v) => {\r\n emit(\"validation-change\", v);\r\n});\r\n\r\n/* ─── 字段变更处理 ──────────────────────────── */\r\n\r\n/** 字段编辑变更处理 */\r\nfunction handleFieldChange(type: CronFieldType, value: CronFieldValue) {\r\n cronValue.value[type] = value;\r\n if (type === \"day\" || type === \"week\") {\r\n handleDayWeekExclusion(type);\r\n }\r\n}\r\n\r\n/* ─── 右侧面板操作 ─────────────────────────── */\r\n\r\n/** 切换当前字段模式 */\r\nfunction handleActiveFieldModeChange(mode: CronFieldMode) {\r\n handleFieldChange(activeField.value, {\r\n ...activeFieldValue.value,\r\n mode,\r\n });\r\n}\r\n\r\n/** 更新当前字段属性 */\r\nfunction handleActiveFieldUpdate(partial: Partial<CronFieldValue>) {\r\n handleFieldChange(activeField.value, {\r\n ...activeFieldValue.value,\r\n ...partial,\r\n });\r\n}\r\n\r\n/** 全选当前字段所有值 */\r\nfunction handleSelectAll() {\r\n const { min, max } = activeFieldMeta.value;\r\n const allValues = Array.from({ length: max - min + 1 }, (_, i) => min + i);\r\n handleFieldChange(activeField.value, {\r\n ...activeFieldValue.value,\r\n specificValues: allValues,\r\n });\r\n}\r\n\r\n/** 清空当前字段所有选中值 */\r\nfunction handleClearAll() {\r\n handleFieldChange(activeField.value, {\r\n ...activeFieldValue.value,\r\n specificValues: [],\r\n });\r\n}\r\n\r\n/* ─── 手动输入处理 ──────────────────────────── */\r\n\r\n/** 手动输入更新 */\r\nfunction handleManualInput(value: string) {\r\n manualInput.value = value;\r\n}\r\n\r\n/** 输入框失焦时同步 */\r\nfunction handleManualBlur() {\r\n const trimmed = manualInput.value.trim();\r\n if (trimmed && trimmed !== expression.value) {\r\n parse(trimmed);\r\n }\r\n}\r\n\r\n/* ─── 模板选择 ──────────────────────────────── */\r\n\r\n/** 选择常用模板 */\r\nfunction handleTemplateSelect(expr: string) {\r\n parse(expr);\r\n manualInput.value = expr;\r\n}\r\n\r\n/* ─── 重置 ──────────────────────────────────── */\r\n\r\n/** 重置为初始值 */\r\nfunction handleReset() {\r\n const initial = props.modelValue || DEFAULT_CRON_EXPRESSION;\r\n parse(initial);\r\n manualInput.value = initial;\r\n}\r\n\r\n/* ─── Expose ────────────────────────────────── */\r\n\r\ndefineExpose({\r\n getValue: () => expression.value,\r\n setValue: (expr: string) => {\r\n parse(expr);\r\n manualInput.value = expr;\r\n },\r\n reset: handleReset,\r\n validate: () => validate(),\r\n});\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2026-02-25\r\n * @Description: Cron 表达式编辑器组件\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\r\n-->\r\n\r\n<template>\r\n <div class=\"c-cron\" :style=\"{ height: containerHeight }\">\r\n <!-- ═══════ 顶部 ═══════ -->\r\n <div class=\"c-cron__header\">\r\n <!-- 标题行 -->\r\n <div class=\"c-cron__title-row\">\r\n <div class=\"c-cron__title\">\r\n <C_Icon name=\"mdi:clock-edit-outline\" :size=\"18\" />\r\n <span>Cron 表达式</span>\r\n </div>\r\n <NTag :type=\"validation.valid ? 'success' : 'error'\" size=\"small\" round>\r\n <template #icon>\r\n <C_Icon\r\n :name=\"validation.valid ? 'mdi:check-circle' : 'mdi:alert-circle'\"\r\n />\r\n </template>\r\n {{ validation.valid ? \"合法\" : \"错误\" }}\r\n </NTag>\r\n </div>\r\n\r\n <!-- 分段式字段选择器 -->\r\n <div class=\"c-cron__segments\">\r\n <div\r\n v-for=\"meta in visibleFields\"\r\n :key=\"meta.type\"\r\n class=\"c-cron__segment\"\r\n :class=\"{\r\n 'c-cron__segment--active': activeField === meta.type,\r\n 'c-cron__segment--wildcard':\r\n fieldExpressions[meta.type] === '*' ||\r\n fieldExpressions[meta.type] === '?',\r\n }\"\r\n @click=\"activeField = meta.type\"\r\n >\r\n <div class=\"c-cron__segment-value\">\r\n {{ fieldExpressions[meta.type] }}\r\n </div>\r\n <div class=\"c-cron__segment-label\">{{ meta.label }}</div>\r\n </div>\r\n </div>\r\n\r\n <!-- 表达式行:输入 + 重置 + 描述 -->\r\n <div class=\"c-cron__expr-row\">\r\n <NInput\r\n :value=\"manualInput\"\r\n :status=\"validation.valid ? undefined : 'error'\"\r\n placeholder=\"秒 分 时 日 月 周\"\r\n :disabled=\"props.disabled\"\r\n font=\"mono\"\r\n size=\"small\"\r\n clearable\r\n class=\"c-cron__expr-input\"\r\n @update:value=\"handleManualInput\"\r\n @blur=\"handleManualBlur\"\r\n @keydown.enter=\"handleManualBlur\"\r\n >\r\n <template #prefix>\r\n <C_Icon name=\"mdi:console\" :size=\"14\" style=\"opacity: 0.4\" />\r\n </template>\r\n </NInput>\r\n <NButton\r\n size=\"small\"\r\n quaternary\r\n :disabled=\"props.disabled\"\r\n @click=\"handleReset\"\r\n >\r\n <template #icon>\r\n <C_Icon name=\"mdi:refresh\" />\r\n </template>\r\n </NButton>\r\n <div class=\"c-cron__expr-desc\">\r\n <span v-if=\"validation.valid\" class=\"c-cron__description\">\r\n {{ description }}\r\n </span>\r\n <span v-else class=\"c-cron__error\">\r\n {{ validation.message }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- ═══════ 主内容 ═══════ -->\r\n <div class=\"c-cron__body\">\r\n <!-- 左侧:值网格 -->\r\n <div class=\"c-cron__main\">\r\n <CronFieldEditor\r\n v-for=\"meta in visibleFields\"\r\n v-show=\"activeField === meta.type\"\r\n :key=\"meta.type\"\r\n :model-value=\"cronValue[meta.type]\"\r\n :meta=\"meta\"\r\n @update:model-value=\"(v) => handleFieldChange(meta.type, v)\"\r\n />\r\n </div>\r\n\r\n <!-- 右侧:控制面板 -->\r\n <div class=\"c-cron__panel\">\r\n <NRadioGroup\r\n :value=\"activeFieldValue.mode\"\r\n size=\"small\"\r\n @update:value=\"handleActiveFieldModeChange\"\r\n >\r\n <NRadioButton value=\"every\">\r\n 每{{ activeFieldMeta.label }}\r\n </NRadioButton>\r\n <NRadioButton\r\n v-if=\"activeField === 'day' || activeField === 'week'\"\r\n value=\"none\"\r\n >\r\n 不指定\r\n </NRadioButton>\r\n <NRadioButton value=\"range\">范围</NRadioButton>\r\n <NRadioButton value=\"step\">步进</NRadioButton>\r\n <NRadioButton value=\"specific\">指定</NRadioButton>\r\n </NRadioGroup>\r\n\r\n <!-- 范围配置 -->\r\n <div v-if=\"activeFieldValue.mode === 'range'\" class=\"c-cron__config\">\r\n <div class=\"c-cron__config-row\">\r\n <span>从</span>\r\n <NInputNumber\r\n :value=\"activeFieldValue.rangeStart\"\r\n :min=\"activeFieldMeta.min\"\r\n :max=\"activeFieldMeta.max\"\r\n size=\"small\"\r\n :show-button=\"false\"\r\n class=\"c-cron__config-num\"\r\n @update:value=\"\r\n (v: number | null) =>\r\n handleActiveFieldUpdate({\r\n rangeStart: v ?? activeFieldMeta.min,\r\n })\r\n \"\r\n />\r\n <span>到</span>\r\n <NInputNumber\r\n :value=\"activeFieldValue.rangeEnd\"\r\n :min=\"activeFieldMeta.min\"\r\n :max=\"activeFieldMeta.max\"\r\n size=\"small\"\r\n :show-button=\"false\"\r\n class=\"c-cron__config-num\"\r\n @update:value=\"\r\n (v: number | null) =>\r\n handleActiveFieldUpdate({\r\n rangeEnd: v ?? activeFieldMeta.max,\r\n })\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- 步进配置 -->\r\n <div v-if=\"activeFieldValue.mode === 'step'\" class=\"c-cron__config\">\r\n <div class=\"c-cron__config-row\">\r\n <span>从第</span>\r\n <NInputNumber\r\n :value=\"activeFieldValue.stepStart\"\r\n :min=\"activeFieldMeta.min\"\r\n :max=\"activeFieldMeta.max\"\r\n size=\"small\"\r\n :show-button=\"false\"\r\n class=\"c-cron__config-num\"\r\n @update:value=\"\r\n (v: number | null) =>\r\n handleActiveFieldUpdate({\r\n stepStart: v ?? activeFieldMeta.min,\r\n })\r\n \"\r\n />\r\n <span>{{ activeFieldMeta.label }}起,每</span>\r\n <NInputNumber\r\n :value=\"activeFieldValue.stepInterval\"\r\n :min=\"1\"\r\n :max=\"activeFieldMeta.max - activeFieldMeta.min + 1\"\r\n size=\"small\"\r\n :show-button=\"false\"\r\n class=\"c-cron__config-num\"\r\n @update:value=\"\r\n (v: number | null) =>\r\n handleActiveFieldUpdate({ stepInterval: v ?? 1 })\r\n \"\r\n />\r\n <span>{{ activeFieldMeta.label }}执行</span>\r\n </div>\r\n </div>\r\n\r\n <!-- 指定快捷操作 -->\r\n <div v-if=\"activeFieldValue.mode === 'specific'\" class=\"c-cron__quick\">\r\n <a @click=\"handleSelectAll\">全选</a>\r\n <span class=\"c-cron__quick-sep\">·</span>\r\n <a @click=\"handleClearAll\">清空</a>\r\n <span\r\n v-if=\"activeFieldValue.specificValues.length > 0\"\r\n class=\"c-cron__quick-count\"\r\n >\r\n 已选 {{ activeFieldValue.specificValues.length }}\r\n </span>\r\n </div>\r\n\r\n <!-- 执行预览 -->\r\n <template v-if=\"props.showPreview\">\r\n <div class=\"c-cron__panel-line\" />\r\n <CronPreview\r\n :next-executions=\"nextExecutions\"\r\n :computing=\"computing\"\r\n :count=\"props.previewCount ?? 5\"\r\n :format-date=\"formatDate\"\r\n :format-week-day=\"formatWeekDay\"\r\n />\r\n </template>\r\n </div>\r\n </div>\r\n\r\n <!-- ═══════ 底部模板 ═══════ -->\r\n <div v-if=\"props.showTemplates\" class=\"c-cron__footer\">\r\n <CronTemplates\r\n :templates=\"CRON_TEMPLATES\"\r\n :current-value=\"expression\"\r\n @select=\"handleTemplateSelect\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, watch, onMounted } from \"vue\";\r\nimport type {\r\n CronFieldMode,\r\n CronFieldType,\r\n CronFieldValue,\r\n CronProps,\r\n CronValidation,\r\n} from \"./types\";\r\nimport {\r\n CRON_FIELD_META,\r\n CRON_TEMPLATES,\r\n DEFAULT_CRON_EXPRESSION,\r\n} from \"./constants\";\r\nimport { useCronParser } from \"./composables/useCronParser\";\r\nimport { useCronPreview } from \"./composables/useCronPreview\";\r\nimport { useCronDescription } from \"./composables/useCronDescription\";\r\nimport C_Icon from \"../C_Icon/index.vue\";\r\nimport CronFieldEditor from \"./components/CronFieldEditor.vue\";\r\nimport CronPreview from \"./components/CronPreview.vue\";\r\nimport CronTemplates from \"./components/CronTemplates.vue\";\r\n\r\ndefineOptions({ name: \"C_Cron\" });\r\n\r\n/* ─── Props & Emits ─────────────────────────── */\r\n\r\nconst props = withDefaults(defineProps<CronProps>(), {\r\n modelValue: DEFAULT_CRON_EXPRESSION,\r\n disabled: false,\r\n previewCount: 10,\r\n showTemplates: true,\r\n showPreview: true,\r\n showSecond: true,\r\n height: \"auto\",\r\n});\r\n\r\nconst emit = defineEmits<{\r\n \"update:modelValue\": [value: string];\r\n change: [value: string];\r\n \"validation-change\": [result: CronValidation];\r\n}>();\r\n\r\n/* ─── 组合函数 ──────────────────────────────── */\r\n\r\nconst {\r\n cronValue,\r\n expression,\r\n validation,\r\n parse,\r\n validate,\r\n handleDayWeekExclusion,\r\n} = useCronParser();\r\n\r\nconst previewCount = computed(() => props.previewCount ?? 10);\r\nconst { nextExecutions, computing, formatDate, formatWeekDay } = useCronPreview(\r\n expression,\r\n validation,\r\n previewCount,\r\n);\r\n\r\nconst { description } = useCronDescription(expression, validation);\r\n\r\n/* ─── 本地状态 ──────────────────────────────── */\r\n\r\n/** 手动输入框值(与 expression 解耦,输入完成后同步) */\r\nconst manualInput = ref(props.modelValue || DEFAULT_CRON_EXPRESSION);\r\n\r\n/** 当前激活的字段 Tab */\r\nconst activeField = ref<CronFieldType>(props.showSecond ? \"second\" : \"minute\");\r\n\r\n/* ─── 容器高度 ──────────────────────────────── */\r\n\r\nconst containerHeight = computed(() => {\r\n if (typeof props.height === \"number\") return `${props.height}px`;\r\n return props.height;\r\n});\r\n\r\n/* ─── 可见字段(是否显示秒) ────────────────── */\r\n\r\nconst visibleFields = computed(() => {\r\n return props.showSecond\r\n ? CRON_FIELD_META\r\n : CRON_FIELD_META.filter((m) => m.type !== \"second\");\r\n});\r\n\r\n/* ─── 当前激活字段快捷访问 ─────────────────── */\r\n\r\n/** 当前激活字段元数据 */\r\nconst activeFieldMeta = computed(\r\n () => CRON_FIELD_META.find((m) => m.type === activeField.value)!,\r\n);\r\n\r\n/** 当前激活字段值 */\r\nconst activeFieldValue = computed(() => cronValue.value[activeField.value]);\r\n\r\n/* ─── 分段式表达式(逐字段计算) ────────────── */\r\n\r\n/** 计算单字段表达式文本 */\r\nfunction computeFieldExpr(f: CronFieldValue): string {\r\n switch (f.mode) {\r\n case \"every\":\r\n return \"*\";\r\n case \"none\":\r\n return \"?\";\r\n case \"range\":\r\n return `${f.rangeStart}-${f.rangeEnd}`;\r\n case \"step\":\r\n return `${f.stepStart}/${f.stepInterval}`;\r\n case \"specific\":\r\n return f.specificValues.length > 0\r\n ? [...f.specificValues].sort((a, b) => a - b).join(\",\")\r\n : \"*\";\r\n default:\r\n return \"*\";\r\n }\r\n}\r\n\r\n/** 各字段表达式映射 */\r\nconst fieldExpressions = computed(() => {\r\n const map = {} as Record<CronFieldType, string>;\r\n for (const meta of CRON_FIELD_META) {\r\n map[meta.type] = computeFieldExpr(cronValue.value[meta.type]);\r\n }\r\n return map;\r\n});\r\n\r\n/* ─── 初始化解析 ────────────────────────────── */\r\n\r\nonMounted(() => {\r\n const initial = props.modelValue || DEFAULT_CRON_EXPRESSION;\r\n parse(initial);\r\n manualInput.value = initial;\r\n});\r\n\r\n/* ─── 监听外部 v-model 变更 ─────────────────── */\r\n\r\nwatch(\r\n () => props.modelValue,\r\n (newVal) => {\r\n if (newVal && newVal !== expression.value) {\r\n parse(newVal);\r\n manualInput.value = newVal;\r\n }\r\n },\r\n);\r\n\r\n/* ─── 监听 showSecond 变更 ──────────────────── */\r\n\r\nwatch(\r\n () => props.showSecond,\r\n (show) => {\r\n if (!show && activeField.value === \"second\") {\r\n activeField.value = \"minute\";\r\n }\r\n },\r\n);\r\n\r\n/* ─── 监听内部表达式变更 → 同步到外部 ───────── */\r\n\r\nwatch(expression, (newExpr) => {\r\n manualInput.value = newExpr;\r\n emit(\"update:modelValue\", newExpr);\r\n emit(\"change\", newExpr);\r\n});\r\n\r\n/* ─── 监听校验状态变更 ──────────────────────── */\r\n\r\nwatch(validation, (v) => {\r\n emit(\"validation-change\", v);\r\n});\r\n\r\n/* ─── 字段变更处理 ──────────────────────────── */\r\n\r\n/** 字段编辑变更处理 */\r\nfunction handleFieldChange(type: CronFieldType, value: CronFieldValue) {\r\n cronValue.value[type] = value;\r\n if (type === \"day\" || type === \"week\") {\r\n handleDayWeekExclusion(type);\r\n }\r\n}\r\n\r\n/* ─── 右侧面板操作 ─────────────────────────── */\r\n\r\n/** 切换当前字段模式 */\r\nfunction handleActiveFieldModeChange(mode: CronFieldMode) {\r\n handleFieldChange(activeField.value, {\r\n ...activeFieldValue.value,\r\n mode,\r\n });\r\n}\r\n\r\n/** 更新当前字段属性 */\r\nfunction handleActiveFieldUpdate(partial: Partial<CronFieldValue>) {\r\n handleFieldChange(activeField.value, {\r\n ...activeFieldValue.value,\r\n ...partial,\r\n });\r\n}\r\n\r\n/** 全选当前字段所有值 */\r\nfunction handleSelectAll() {\r\n const { min, max } = activeFieldMeta.value;\r\n const allValues = Array.from({ length: max - min + 1 }, (_, i) => min + i);\r\n handleFieldChange(activeField.value, {\r\n ...activeFieldValue.value,\r\n specificValues: allValues,\r\n });\r\n}\r\n\r\n/** 清空当前字段所有选中值 */\r\nfunction handleClearAll() {\r\n handleFieldChange(activeField.value, {\r\n ...activeFieldValue.value,\r\n specificValues: [],\r\n });\r\n}\r\n\r\n/* ─── 手动输入处理 ──────────────────────────── */\r\n\r\n/** 手动输入更新 */\r\nfunction handleManualInput(value: string) {\r\n manualInput.value = value;\r\n}\r\n\r\n/** 输入框失焦时同步 */\r\nfunction handleManualBlur() {\r\n const trimmed = manualInput.value.trim();\r\n if (trimmed && trimmed !== expression.value) {\r\n parse(trimmed);\r\n }\r\n}\r\n\r\n/* ─── 模板选择 ──────────────────────────────── */\r\n\r\n/** 选择常用模板 */\r\nfunction handleTemplateSelect(expr: string) {\r\n parse(expr);\r\n manualInput.value = expr;\r\n}\r\n\r\n/* ─── 重置 ──────────────────────────────────── */\r\n\r\n/** 重置为初始值 */\r\nfunction handleReset() {\r\n const initial = props.modelValue || DEFAULT_CRON_EXPRESSION;\r\n parse(initial);\r\n manualInput.value = initial;\r\n}\r\n\r\n/* ─── Expose ────────────────────────────────── */\r\n\r\ndefineExpose({\r\n getValue: () => expression.value,\r\n setValue: (expr: string) => {\r\n parse(expr);\r\n manualInput.value = expr;\r\n },\r\n reset: handleReset,\r\n validate: () => validate(),\r\n});\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n@use \"./index.scss\";\r\n</style>\r\n"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_C_Date = require('./C_Date.js');
3
+
4
+ exports.C_Date = require_C_Date.C_Date_default;
@@ -0,0 +1,2 @@
1
+ import { t as _default } from "./index7.vue.js";
2
+ export { _default as C_Date };
@@ -0,0 +1,2 @@
1
+ import { t as _default } from "./index7.vue.js";
2
+ export { _default as C_Date };
package/dist/C_Date.js ADDED
@@ -0,0 +1,3 @@
1
+ import { t as C_Date_default } from "./C_Date2.js";
2
+
3
+ export { C_Date_default as C_Date };
@@ -0,0 +1,219 @@
1
+ import { createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, mergeProps, openBlock, ref, unref, watch } from "vue";
2
+ import { NDatePicker } from "naive-ui";
3
+
4
+ //#region src/components/C_Date/index.vue?vue&type=script&setup=true&lang.ts
5
+ const _hoisted_1 = { class: "inline-block" };
6
+ const _hoisted_2 = {
7
+ key: 4,
8
+ class: "inline-block"
9
+ };
10
+ const _hoisted_3 = { class: "flex gap-2.5 items-center" };
11
+ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
12
+ name: "C_Date",
13
+ __name: "index",
14
+ props: {
15
+ mode: { default: "date" },
16
+ placeholder: { default: "" },
17
+ startPlaceholder: { default: "" },
18
+ endPlaceholder: { default: "" },
19
+ disabled: {
20
+ type: Boolean,
21
+ default: false
22
+ },
23
+ disabledBeforeToday: {
24
+ type: Boolean,
25
+ default: false
26
+ },
27
+ disabledAfterToday: {
28
+ type: Boolean,
29
+ default: false
30
+ },
31
+ valueFormat: { default: "yyyy-MM-dd" },
32
+ startDateProps: { default: () => ({}) },
33
+ endDateProps: { default: () => ({}) }
34
+ },
35
+ emits: [
36
+ "update:singleDate",
37
+ "update:singleDateTime",
38
+ "update:dateRange",
39
+ "update:dateTimeRange",
40
+ "update:smartRange",
41
+ "change"
42
+ ],
43
+ setup(__props, { expose: __expose, emit: __emit }) {
44
+ const props = __props;
45
+ const emits = __emit;
46
+ const singleDate = ref(null);
47
+ const singleDateTime = ref(null);
48
+ const dateRange = ref(null);
49
+ const dateTimeRange = ref(null);
50
+ const startDate = ref(null);
51
+ const endDate = ref(null);
52
+ const endDateDisabled = ref(true);
53
+ const getTodayTimestamp = () => {
54
+ const today = /* @__PURE__ */ new Date();
55
+ today.setHours(0, 0, 0, 0);
56
+ return today.getTime();
57
+ };
58
+ const singleDisabledDate = (timestamp) => {
59
+ const todayTimestamp = getTodayTimestamp();
60
+ if (props.disabledBeforeToday && timestamp < todayTimestamp) return true;
61
+ if (props.disabledAfterToday && timestamp > todayTimestamp) return true;
62
+ return false;
63
+ };
64
+ const endDisabledDate = (timestamp) => {
65
+ if (!startDate.value) return true;
66
+ if (timestamp < startDate.value) return true;
67
+ return singleDisabledDate(timestamp);
68
+ };
69
+ const handleSingleDateChange = (value) => {
70
+ emits("update:singleDate", value);
71
+ emits("change", value);
72
+ };
73
+ const handleSingleDateTimeChange = (value) => {
74
+ emits("update:singleDateTime", value);
75
+ emits("change", value);
76
+ };
77
+ const handleDateRangeChange = (value) => {
78
+ emits("update:dateRange", value);
79
+ emits("change", value);
80
+ };
81
+ const handleDateTimeRangeChange = (value) => {
82
+ emits("update:dateTimeRange", value);
83
+ emits("change", value);
84
+ };
85
+ watch(() => [startDate.value, endDate.value], ([startVal, endVal]) => {
86
+ if (!startVal) {
87
+ endDate.value = null;
88
+ endDateDisabled.value = true;
89
+ return;
90
+ }
91
+ if (startVal) endDateDisabled.value = false;
92
+ if (startVal && endVal) {
93
+ const rangeValue = [startVal, endVal];
94
+ emits("update:smartRange", rangeValue);
95
+ emits("change", rangeValue);
96
+ }
97
+ }, { deep: true });
98
+ __expose({
99
+ singleDate,
100
+ singleDateTime,
101
+ dateRange,
102
+ dateTimeRange,
103
+ startDate,
104
+ endDate,
105
+ clearAll: () => {
106
+ singleDate.value = null;
107
+ singleDateTime.value = null;
108
+ dateRange.value = null;
109
+ dateTimeRange.value = null;
110
+ startDate.value = null;
111
+ endDate.value = null;
112
+ endDateDisabled.value = true;
113
+ }
114
+ });
115
+ return (_ctx, _cache) => {
116
+ return openBlock(), createElementBlock("div", _hoisted_1, [_ctx.mode === "date" ? (openBlock(), createBlock(unref(NDatePicker), mergeProps({
117
+ key: 0,
118
+ value: singleDate.value,
119
+ "onUpdate:value": _cache[0] || (_cache[0] = ($event) => singleDate.value = $event),
120
+ type: "date",
121
+ placeholder: _ctx.placeholder || "请选择日期",
122
+ disabled: _ctx.disabled,
123
+ "is-date-disabled": singleDisabledDate,
124
+ "value-format": _ctx.valueFormat,
125
+ clearable: ""
126
+ }, _ctx.$attrs, { "onUpdate:value": handleSingleDateChange }), null, 16, [
127
+ "value",
128
+ "placeholder",
129
+ "disabled",
130
+ "value-format"
131
+ ])) : _ctx.mode === "datetime" ? (openBlock(), createBlock(unref(NDatePicker), mergeProps({
132
+ key: 1,
133
+ value: singleDateTime.value,
134
+ "onUpdate:value": _cache[1] || (_cache[1] = ($event) => singleDateTime.value = $event),
135
+ type: "datetime",
136
+ placeholder: _ctx.placeholder || "请选择日期时间",
137
+ disabled: _ctx.disabled,
138
+ "is-date-disabled": singleDisabledDate,
139
+ "value-format": _ctx.valueFormat,
140
+ clearable: ""
141
+ }, _ctx.$attrs, { "onUpdate:value": handleSingleDateTimeChange }), null, 16, [
142
+ "value",
143
+ "placeholder",
144
+ "disabled",
145
+ "value-format"
146
+ ])) : _ctx.mode === "daterange" ? (openBlock(), createBlock(unref(NDatePicker), mergeProps({
147
+ key: 2,
148
+ value: dateRange.value,
149
+ "onUpdate:value": _cache[2] || (_cache[2] = ($event) => dateRange.value = $event),
150
+ type: "daterange",
151
+ "start-placeholder": _ctx.startPlaceholder || "开始日期",
152
+ "end-placeholder": _ctx.endPlaceholder || "结束日期",
153
+ disabled: _ctx.disabled,
154
+ "is-date-disabled": singleDisabledDate,
155
+ "value-format": _ctx.valueFormat,
156
+ clearable: ""
157
+ }, _ctx.$attrs, { "onUpdate:value": handleDateRangeChange }), null, 16, [
158
+ "value",
159
+ "start-placeholder",
160
+ "end-placeholder",
161
+ "disabled",
162
+ "value-format"
163
+ ])) : _ctx.mode === "datetimerange" ? (openBlock(), createBlock(unref(NDatePicker), mergeProps({
164
+ key: 3,
165
+ value: dateTimeRange.value,
166
+ "onUpdate:value": _cache[3] || (_cache[3] = ($event) => dateTimeRange.value = $event),
167
+ type: "datetimerange",
168
+ "start-placeholder": _ctx.startPlaceholder || "开始日期时间",
169
+ "end-placeholder": _ctx.endPlaceholder || "结束日期时间",
170
+ disabled: _ctx.disabled,
171
+ "is-date-disabled": singleDisabledDate,
172
+ "value-format": _ctx.valueFormat,
173
+ clearable: ""
174
+ }, _ctx.$attrs, { "onUpdate:value": handleDateTimeRangeChange }), null, 16, [
175
+ "value",
176
+ "start-placeholder",
177
+ "end-placeholder",
178
+ "disabled",
179
+ "value-format"
180
+ ])) : _ctx.mode === "smart-range" ? (openBlock(), createElementBlock("div", _hoisted_2, [createElementVNode("div", _hoisted_3, [createVNode(unref(NDatePicker), mergeProps({
181
+ class: "flex-1",
182
+ value: startDate.value,
183
+ "onUpdate:value": _cache[4] || (_cache[4] = ($event) => startDate.value = $event),
184
+ type: "date",
185
+ placeholder: _ctx.startPlaceholder || "请选择开始日期",
186
+ "is-date-disabled": singleDisabledDate,
187
+ "value-format": _ctx.valueFormat,
188
+ clearable: ""
189
+ }, _ctx.startDateProps), null, 16, [
190
+ "value",
191
+ "placeholder",
192
+ "value-format"
193
+ ]), createVNode(unref(NDatePicker), mergeProps({
194
+ class: "flex-1",
195
+ value: endDate.value,
196
+ "onUpdate:value": _cache[5] || (_cache[5] = ($event) => endDate.value = $event),
197
+ type: "date",
198
+ placeholder: _ctx.endPlaceholder || "请选择结束日期",
199
+ disabled: endDateDisabled.value,
200
+ "is-date-disabled": endDisabledDate,
201
+ "value-format": _ctx.valueFormat,
202
+ clearable: ""
203
+ }, _ctx.endDateProps), null, 16, [
204
+ "value",
205
+ "placeholder",
206
+ "disabled",
207
+ "value-format"
208
+ ])])])) : createCommentVNode("v-if", true)]);
209
+ };
210
+ }
211
+ });
212
+
213
+ //#endregion
214
+ //#region src/components/C_Date/index.vue
215
+ var C_Date_default = index_vue_vue_type_script_setup_true_lang_default;
216
+
217
+ //#endregion
218
+ export { C_Date_default as t };
219
+ //# sourceMappingURL=C_Date2.js.map