@robot-admin/naive-ui-components 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/C_ActionBar-BAcfOfRw.css.map +1 -0
- package/dist/C_ActionBar-DG2HW7t5.css.map +1 -0
- package/dist/C_ActionBar.css +47 -47
- package/dist/C_ActionBar.js.map +1 -1
- package/dist/C_ActionBar2.js +1 -1
- package/dist/C_ActionBar2.js.map +1 -1
- package/dist/{C_AntV-BY8jqqmi.css.map → C_AntV-D_jTK8oZ.css.map} +1 -1
- package/dist/{C_AntV-BbkHc-_a.css.map → C_AntV-DanTAq22.css.map} +1 -1
- package/dist/C_AntV.css +79 -79
- package/dist/C_AntV.js.map +1 -1
- package/dist/C_AntV2.js +3 -3
- package/dist/C_AntV2.js.map +1 -1
- package/dist/{C_AudioPlayer-DKRIGhi7.css.map → C_AudioPlayer-BnYIJXPD.css.map} +1 -1
- package/dist/{C_AudioPlayer-DlB6eNsa.css.map → C_AudioPlayer-ldTy9Y34.css.map} +1 -1
- package/dist/C_AudioPlayer.css +47 -47
- package/dist/C_AudioPlayer.js.map +1 -1
- package/dist/C_AudioPlayer2.js +1 -1
- package/dist/C_AudioPlayer2.js.map +1 -1
- package/dist/{C_AvatarGroup-D02zci-i.css.map → C_AvatarGroup-B9d-GJ9c.css.map} +1 -1
- package/dist/{C_AvatarGroup-DatHaUlY.css.map → C_AvatarGroup-SIzxuuZr.css.map} +1 -1
- package/dist/C_AvatarGroup.css +21 -21
- package/dist/C_AvatarGroup.js.map +1 -1
- package/dist/C_AvatarGroup2.js +1 -1
- package/dist/C_AvatarGroup2.js.map +1 -1
- package/dist/{C_Barcode-DYDRDe2O.css.map → C_Barcode-CAU2mFcx.css.map} +1 -1
- package/dist/{C_Barcode-muJdc_O4.css.map → C_Barcode-D2oJaEg3.css.map} +1 -1
- package/dist/C_Barcode.css +7 -7
- package/dist/C_Barcode.js.map +1 -1
- package/dist/C_Barcode2.js +1 -1
- package/dist/C_Barcode2.js.map +1 -1
- package/dist/C_Breadcrumb.js.map +1 -1
- package/dist/C_Breadcrumb2.js +1 -1
- package/dist/C_Breadcrumb2.js.map +1 -1
- package/dist/{C_Captcha-9_hk6VmY.css.map → C_Captcha-B3yrtG7t.css.map} +1 -1
- package/dist/{C_Captcha-MtASlJ0f.css.map → C_Captcha-D4hDdWDu.css.map} +1 -1
- package/dist/C_Captcha.css +19 -19
- package/dist/C_Captcha.js.map +1 -1
- package/dist/C_Captcha2.js +1 -1
- package/dist/C_Captcha2.js.map +1 -1
- package/dist/C_Cascade-BE7t1OX5.css.map +1 -0
- package/dist/C_Cascade-CpDiau1y.css.map +1 -0
- package/dist/C_Cascade.css +3 -3
- package/dist/C_Cascade.js.map +1 -1
- package/dist/C_Cascade2.js +1 -1
- package/dist/C_Cascade2.js.map +1 -1
- package/dist/{C_Chat-Csjz_BFw.css.map → C_Chat-CF1SU7mc.css.map} +1 -1
- package/dist/{C_Chat-DO1ZBA_0.css.map → C_Chat-DeUv6uuI.css.map} +1 -1
- package/dist/C_Chat.css +65 -65
- package/dist/C_Chat.js.map +1 -1
- package/dist/C_Chat2.js +1 -1
- package/dist/C_Chat2.js.map +1 -1
- package/dist/{C_City-Bam08Qv3.css.map → C_City-DdkX6u64.css.map} +1 -1
- package/dist/{C_City-Bb3W-KaN.css.map → C_City-iP-dIvui.css.map} +1 -1
- package/dist/C_City.css +29 -29
- package/dist/C_City.js.map +1 -1
- package/dist/C_City2.js +1 -1
- package/dist/C_City2.js.map +1 -1
- package/dist/C_Code-BWmJMNS7.css.map +1 -0
- package/dist/C_Code-k14vjgVl.css.map +1 -0
- package/dist/C_Code.css +3 -3
- package/dist/C_Code.js.map +1 -1
- package/dist/C_Code2.js +1 -1
- package/dist/C_Code2.js.map +1 -1
- package/dist/{C_CollapsePanel-CWkFCqNQ.css.map → C_CollapsePanel-BSKcWSmY.css.map} +1 -1
- package/dist/{C_CollapsePanel-pcVJA_4z.css.map → C_CollapsePanel-DRvRq8tB.css.map} +1 -1
- package/dist/C_CollapsePanel.css +35 -35
- package/dist/C_CollapsePanel.js.map +1 -1
- package/dist/C_CollapsePanel2.js +1 -1
- package/dist/C_CollapsePanel2.js.map +1 -1
- package/dist/{C_ContextMenu-B3Cgz_wJ.css.map → C_ContextMenu-Bn_uhJSo.css.map} +1 -1
- package/dist/{C_ContextMenu-u1LixF3_.css.map → C_ContextMenu-C9iuxG2n.css.map} +1 -1
- package/dist/C_ContextMenu.css +17 -17
- package/dist/C_ContextMenu.js.map +1 -1
- package/dist/C_ContextMenu2.js +1 -1
- package/dist/C_ContextMenu2.js.map +1 -1
- package/dist/{C_Cron-Civir5-I.css.map → C_Cron-BIQ2By9v.css.map} +1 -1
- package/dist/{C_Cron-iw3qpMsy.css.map → C_Cron-BNSAGD6A.css.map} +1 -1
- package/dist/C_Cron.css +57 -57
- package/dist/C_Cron.js.map +1 -1
- package/dist/C_Cron2.js +1 -1
- package/dist/C_Cron2.js.map +1 -1
- package/dist/C_Date.js.map +1 -1
- package/dist/C_Date2.js +1 -1
- package/dist/C_Date2.js.map +1 -1
- package/dist/{C_Draggable-BCjIvIwT.css.map → C_Draggable-BDAbk4s5.css.map} +1 -1
- package/dist/{C_Draggable-DwkSlCOS.css.map → C_Draggable-UhfDLXop.css.map} +1 -1
- package/dist/C_Draggable.css +46 -46
- package/dist/C_Draggable.js.map +1 -1
- package/dist/C_Draggable2.js +1 -1
- package/dist/C_Draggable2.js.map +1 -1
- package/dist/{C_Editor-BfjjYQ9B.css.map → C_Editor-CZOaChru.css.map} +1 -1
- package/dist/{C_Editor-Do2StvoJ.css.map → C_Editor-kJAQq5z6.css.map} +1 -1
- package/dist/C_Editor.css +14 -14
- package/dist/C_Editor.js.map +1 -1
- package/dist/C_Editor2.js +1 -1
- package/dist/C_Editor2.js.map +1 -1
- package/dist/{C_FilePreview-BhcbiXsV.css.map → C_FilePreview-Bs_omgJS.css.map} +1 -1
- package/dist/{C_FilePreview-DJudcIbW.css.map → C_FilePreview-DbwoyF2j.css.map} +1 -1
- package/dist/C_FilePreview.css +91 -91
- package/dist/C_FilePreview.js.map +1 -1
- package/dist/C_FilePreview2.js +1 -1
- package/dist/C_FilePreview2.js.map +1 -1
- package/dist/{C_Form-BtcAPIRi.css.map → C_Form-SCq-DZaZ.css.map} +1 -1
- package/dist/{C_Form-D_gwQ7hC.css.map → C_Form-mcd1nKvF.css.map} +1 -1
- package/dist/C_Form.css +223 -223
- package/dist/C_Form.js.map +1 -1
- package/dist/C_Form2.js +1 -1
- package/dist/C_Form2.js.map +1 -1
- package/dist/{C_FormSearch-Bi4XYjjk.css.map → C_FormSearch-C3F8peAY.css.map} +1 -1
- package/dist/{C_FormSearch-DUGOoX0u.css.map → C_FormSearch-qW56bJPo.css.map} +1 -1
- package/dist/C_FormSearch.css +45 -45
- package/dist/C_FormSearch.js.map +1 -1
- package/dist/C_FormSearch2.js +1 -1
- package/dist/C_FormSearch2.js.map +1 -1
- package/dist/{C_FormulaEditor-CJk3SSUJ.css.map → C_FormulaEditor-ChOvDbsZ.css.map} +1 -1
- package/dist/{C_FormulaEditor-Cy7mjfVO.css.map → C_FormulaEditor-mfiIUDY4.css.map} +1 -1
- package/dist/C_FormulaEditor.css +78 -78
- package/dist/C_FormulaEditor.js.map +1 -1
- package/dist/C_FormulaEditor2.js +1 -1
- package/dist/C_FormulaEditor2.js.map +1 -1
- package/dist/C_FullCalendar-C2nsqrgS.css.map +1 -0
- package/dist/C_FullCalendar-DdFtXVhy.css.map +1 -0
- package/dist/C_FullCalendar.css +2 -2
- package/dist/C_FullCalendar.js.map +1 -1
- package/dist/C_FullCalendar2.js +1 -1
- package/dist/C_FullCalendar2.js.map +1 -1
- package/dist/{C_GlobalSearch-B6wK3m3k.css.map → C_GlobalSearch-Dq4Wo01K.css.map} +1 -1
- package/dist/{C_GlobalSearch-DoPjldFm.css.map → C_GlobalSearch-RB7J43gu.css.map} +1 -1
- package/dist/C_GlobalSearch.css +112 -112
- package/dist/C_GlobalSearch.js.map +1 -1
- package/dist/C_GlobalSearch2.js +1 -1
- package/dist/C_GlobalSearch2.js.map +1 -1
- package/dist/C_Guide.js.map +1 -1
- package/dist/C_Guide2.js +1 -1
- package/dist/C_Guide2.js.map +1 -1
- package/dist/C_Icon.js.map +1 -1
- package/dist/C_Icon2.js.map +1 -1
- package/dist/{C_ImageCropper-BqZpkZfU.css.map → C_ImageCropper-CdTX2nxU.css.map} +1 -1
- package/dist/{C_ImageCropper-CylwGuzS.css.map → C_ImageCropper-ilOqPklJ.css.map} +1 -1
- package/dist/C_ImageCropper.css +23 -23
- package/dist/C_ImageCropper.js.map +1 -1
- package/dist/C_ImageCropper2.js +1 -1
- package/dist/C_ImageCropper2.js.map +1 -1
- package/dist/C_Language.js.map +1 -1
- package/dist/C_Language2.js +1 -1
- package/dist/C_Language2.js.map +1 -1
- package/dist/{C_Login-BkdnkBKX.css.map → C_Login-B3qYkLrN.css.map} +1 -1
- package/dist/{C_Login-VkMM6OJ2.css.map → C_Login-xMI1_ojE.css.map} +1 -1
- package/dist/C_Login.css +72 -72
- package/dist/C_Login.js.map +1 -1
- package/dist/C_Login2.js +1 -1
- package/dist/C_Login2.js.map +1 -1
- package/dist/{C_Map-DNnBcY70.css.map → C_Map-CWMMN58_.css.map} +1 -1
- package/dist/{C_Map-LEXIx6zM.css.map → C_Map-xSR2H-9o.css.map} +1 -1
- package/dist/C_Map.css +4 -4
- package/dist/C_Map.js.map +1 -1
- package/dist/C_Map2.js +1 -1
- package/dist/C_Map2.js.map +1 -1
- package/dist/{C_Markdown-DwmI0_0Q.css.map → C_Markdown-C7lTVJ1S.css.map} +1 -1
- package/dist/{C_Markdown-k0794RW0.css.map → C_Markdown-CZDm_baQ.css.map} +1 -1
- package/dist/C_Markdown.css +33 -33
- package/dist/C_Markdown.js.map +1 -1
- package/dist/C_Markdown2.js +1 -1
- package/dist/C_Markdown2.js.map +1 -1
- package/dist/C_Menu.js.map +1 -1
- package/dist/C_Menu2.js +1 -1
- package/dist/C_Menu2.js.map +1 -1
- package/dist/{C_NotificationCenter-DT6fQ79O.css.map → C_NotificationCenter-D7GGGWg7.css.map} +1 -1
- package/dist/{C_NotificationCenter-DbgBiyqB.css.map → C_NotificationCenter-SSmeHA45.css.map} +1 -1
- package/dist/C_NotificationCenter.css +89 -89
- package/dist/C_NotificationCenter.js.map +1 -1
- package/dist/C_NotificationCenter2.js +1 -1
- package/dist/C_NotificationCenter2.js.map +1 -1
- package/dist/C_OrgChart.js.map +1 -1
- package/dist/C_OrgChart2.js.map +1 -1
- package/dist/C_Progress.js.map +1 -1
- package/dist/C_Progress2.js +1 -1
- package/dist/C_Progress2.js.map +1 -1
- package/dist/{C_QRCode-CFNTda_1.css.map → C_QRCode-B_1lHUdx.css.map} +1 -1
- package/dist/{C_QRCode-CmWr9lK-.css.map → C_QRCode-CuQRYu0s.css.map} +1 -1
- package/dist/C_QRCode.css +9 -9
- package/dist/C_QRCode.js.map +1 -1
- package/dist/C_QRCode2.js +1 -1
- package/dist/C_QRCode2.js.map +1 -1
- package/dist/{C_Signature-BDx4ctsE.css.map → C_Signature-Bp-RBpAl.css.map} +1 -1
- package/dist/{C_Signature-Bz_uNbwv.css.map → C_Signature-Cb2VW1ok.css.map} +1 -1
- package/dist/C_Signature.css +15 -15
- package/dist/C_Signature.js.map +1 -1
- package/dist/C_Signature2.js +1 -1
- package/dist/C_Signature2.js.map +1 -1
- package/dist/C_Skeleton.js.map +1 -1
- package/dist/C_Skeleton2.js.map +1 -1
- package/dist/{C_SplitPane-BOwr1C7K.css.map → C_SplitPane-CgGWYsRE.css.map} +1 -1
- package/dist/{C_SplitPane-N-a_D-7F.css.map → C_SplitPane-DGf6WEeR.css.map} +1 -1
- package/dist/C_SplitPane.css +31 -31
- package/dist/C_SplitPane.js.map +1 -1
- package/dist/C_SplitPane2.js +1 -1
- package/dist/C_SplitPane2.js.map +1 -1
- package/dist/C_Steps-Buyg7Axn.css.map +1 -0
- package/dist/C_Steps-DNY91VbQ.css.map +1 -0
- package/dist/C_Steps.css +38 -38
- package/dist/C_Steps.js.map +1 -1
- package/dist/C_Steps2.js +1 -1
- package/dist/C_Steps2.js.map +1 -1
- package/dist/{C_Table-BcM5LqAM.css.map → C_Table--kbQaaBv.css.map} +1 -1
- package/dist/{C_Table-HATVoq1F.css.map → C_Table-D631kdXC.css.map} +1 -1
- package/dist/C_Table.css +104 -104
- package/dist/C_Table.js.map +1 -1
- package/dist/C_Table2.js +2 -2
- package/dist/C_Table2.js.map +1 -1
- package/dist/{C_TagsView-DX3LecK1.css.map → C_TagsView-COjGNM9h.css.map} +1 -1
- package/dist/{C_TagsView-DqOTa8bL.css.map → C_TagsView-zUDj9S06.css.map} +1 -1
- package/dist/C_TagsView.css +36 -36
- package/dist/C_TagsView.js.map +1 -1
- package/dist/C_TagsView2.js +1 -1
- package/dist/C_TagsView2.js.map +1 -1
- package/dist/C_Theme.js.map +1 -1
- package/dist/C_Theme2.js +1 -1
- package/dist/C_Theme2.js.map +1 -1
- package/dist/C_Time-BQ9PGy8B.css.map +1 -0
- package/dist/C_Time-CO73krC6.css.map +1 -0
- package/dist/C_Time.css +5 -5
- package/dist/C_Time.js.map +1 -1
- package/dist/C_Time2.js +1 -1
- package/dist/C_Time2.js.map +1 -1
- package/dist/{C_Timeline-BKkimrZx.css.map → C_Timeline-4rk0Dzgn.css.map} +1 -1
- package/dist/{C_Timeline-DTuSCX6p.css.map → C_Timeline-DdESmqwL.css.map} +1 -1
- package/dist/C_Timeline.css +45 -45
- package/dist/C_Timeline.js.map +1 -1
- package/dist/C_Timeline2.js +1 -1
- package/dist/C_Timeline2.js.map +1 -1
- package/dist/{C_Transfer-BOB6OBqS.css.map → C_Transfer-B-vjvhjI.css.map} +1 -1
- package/dist/{C_Transfer-Dpq7ezWC.css.map → C_Transfer-EzdHzZNv.css.map} +1 -1
- package/dist/C_Transfer.css +31 -31
- package/dist/C_Transfer.js.map +1 -1
- package/dist/C_Transfer2.js +1 -1
- package/dist/C_Transfer2.js.map +1 -1
- package/dist/{C_Tree-D98nX9qT.css.map → C_Tree-CsXgGfhn.css.map} +1 -1
- package/dist/{C_Tree-ulfm7b-P.css.map → C_Tree-P7eRpnOa.css.map} +1 -1
- package/dist/C_Tree.css +33 -33
- package/dist/C_Tree.js.map +1 -1
- package/dist/C_Tree2.js +1 -1
- package/dist/C_Tree2.js.map +1 -1
- package/dist/{C_Upload-BR9fg5r4.css.map → C_Upload-CHjiVVh7.css.map} +1 -1
- package/dist/{C_Upload-CPqf74Ea.css.map → C_Upload-DE3OLsZD.css.map} +1 -1
- package/dist/C_Upload.css +50 -50
- package/dist/C_Upload.js.map +1 -1
- package/dist/C_Upload2.js +2 -2
- package/dist/C_Upload2.js.map +1 -1
- package/dist/{C_VideoPlayer-4J96tKfK.css.map → C_VideoPlayer-CnaNOFtW.css.map} +1 -1
- package/dist/{C_VideoPlayer-D35seHkm.css.map → C_VideoPlayer-cnP88zNV.css.map} +1 -1
- package/dist/C_VideoPlayer.css +68 -68
- package/dist/C_VideoPlayer.js.map +1 -1
- package/dist/C_VideoPlayer2.js +3 -3
- package/dist/C_VideoPlayer2.js.map +1 -1
- package/dist/{C_VtableGantt-C2lxFmWg.css.map → C_VtableGantt-CZlJgvpC.css.map} +1 -1
- package/dist/{C_VtableGantt-Dwnkw_WL.css.map → C_VtableGantt-DKfQkql0.css.map} +1 -1
- package/dist/C_VtableGantt.css +15 -15
- package/dist/C_VtableGantt.js.map +1 -1
- package/dist/C_VtableGantt2.js +1 -1
- package/dist/C_VtableGantt2.js.map +1 -1
- package/dist/{C_WaterFall-C4HDqf-a.css.map → C_WaterFall-BJ_39ext.css.map} +1 -1
- package/dist/{C_WaterFall-HWB-gPON.css.map → C_WaterFall-cYc1vntE.css.map} +1 -1
- package/dist/C_WaterFall.css +16 -16
- package/dist/C_WaterFall.js.map +1 -1
- package/dist/C_WaterFall2.js +1 -1
- package/dist/C_WaterFall2.js.map +1 -1
- package/dist/{C_WorkFlow-2hJfvvTK.css.map → C_WorkFlow-BFzRGGhJ.css.map} +1 -1
- package/dist/{C_WorkFlow-DHoNjl8-.css.map → C_WorkFlow-DSyCOvRp.css.map} +1 -1
- package/dist/C_WorkFlow.css +193 -193
- package/dist/C_WorkFlow.js.map +1 -1
- package/dist/C_WorkFlow2.js +1 -1
- package/dist/C_WorkFlow2.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants2.d.ts +2 -2
- package/dist/constants3.d.ts +1 -1
- package/dist/constants4.d.ts +1 -1
- package/dist/constants5.d.ts +2 -2
- package/dist/data.d.ts +1 -1
- package/dist/index.vue.d.ts +2 -2
- package/dist/index11.vue.d.ts +2 -2
- package/dist/index12.vue.d.ts +1 -1
- package/dist/index13.vue.d.ts +2 -2
- package/dist/index14.vue.d.ts +3 -3
- package/dist/index15.vue.d.ts +6 -6
- package/dist/index17.vue.d.ts +1 -1
- package/dist/index18.vue.d.ts +2 -2
- package/dist/index2.vue.d.ts +6 -6
- package/dist/index20.vue.d.ts +1 -1
- package/dist/index21.vue.d.ts +2 -2
- package/dist/index22.vue.d.ts +2 -2
- package/dist/index24.vue.d.ts +1 -1
- package/dist/index26.vue.d.ts +3 -3
- package/dist/index27.vue.d.ts +1 -1
- package/dist/index28.vue.d.ts +2 -2
- package/dist/index3.vue.d.ts +2 -2
- package/dist/index4.vue.d.ts +2 -2
- package/dist/index6.vue.d.ts +3 -3
- package/dist/style.css +1991 -1991
- package/dist/useCalendarEvents.d.ts +1 -1
- package/dist/useCollapsePanel.d.ts +3 -3
- package/dist/useCropperCore.d.ts +4 -4
- package/dist/useDraggableLayout.d.ts +2 -2
- package/dist/useDynamicFormState.d.ts +13 -13
- package/dist/useEdgeInteraction.d.ts +1 -1
- package/dist/useInfiniteScroll.d.ts +3 -3
- package/dist/useModalEdit.d.ts +3 -3
- package/dist/useQRCode.d.ts +3 -3
- package/dist/useSignatureHistory.d.ts +1 -1
- package/dist/useSplitResize.d.ts +5 -5
- package/dist/useTimeSelection.d.ts +2 -2
- package/dist/useTreeOperations.d.ts +4 -4
- package/dist/useWorkflowValidation.d.ts +4 -4
- package/package.json +4 -7
- package/dist/C_ActionBar-DYG0Yf3A.css.map +0 -1
- package/dist/C_ActionBar-MAjRhqcI.css.map +0 -1
- package/dist/C_Cascade-Dq0S5Jkm.css.map +0 -1
- package/dist/C_Cascade-IUUHIh7r.css.map +0 -1
- package/dist/C_Code-BFi5xxnM.css.map +0 -1
- package/dist/C_Code-CZ7yfnri.css.map +0 -1
- package/dist/C_FullCalendar-BQA0OjGB.css.map +0 -1
- package/dist/C_FullCalendar-ChJUosAi.css.map +0 -1
- package/dist/C_Steps-Bk1krgiR.css.map +0 -1
- package/dist/C_Steps-Dn2CMpy1.css.map +0 -1
- package/dist/C_Time-BzyQVvTS.css.map +0 -1
- package/dist/C_Time-DmpKLQHc.css.map +0 -1
- package/dist/themes/glass-morphism.css +0 -1
package/dist/C_Cron.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_Cron.js","names":[],"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/CronPreview.vue","../src/components/C_Cron/components/CronTemplates.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-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","<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2026-02-25\n * @Description: Cron 表达式编辑器组件\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\n-->\n\n<template>\n <div class=\"c-cron\" :style=\"{ height: containerHeight }\">\n <!-- ═══════ 顶部 ═══════ -->\n <div class=\"c-cron__header\">\n <!-- 标题行 -->\n <div class=\"c-cron__title-row\">\n <div class=\"c-cron__title\">\n <C_Icon name=\"mdi:clock-edit-outline\" :size=\"18\" />\n <span>Cron 表达式</span>\n </div>\n <NTag :type=\"validation.valid ? 'success' : 'error'\" size=\"small\" round>\n <template #icon>\n <C_Icon\n :name=\"validation.valid ? 'mdi:check-circle' : 'mdi:alert-circle'\"\n />\n </template>\n {{ validation.valid ? \"合法\" : \"错误\" }}\n </NTag>\n </div>\n\n <!-- 分段式字段选择器 -->\n <div class=\"c-cron__segments\">\n <div\n v-for=\"meta in visibleFields\"\n :key=\"meta.type\"\n class=\"c-cron__segment\"\n :class=\"{\n 'c-cron__segment--active': activeField === meta.type,\n 'c-cron__segment--wildcard':\n fieldExpressions[meta.type] === '*' ||\n fieldExpressions[meta.type] === '?',\n }\"\n @click=\"activeField = meta.type\"\n >\n <div class=\"c-cron__segment-value\">\n {{ fieldExpressions[meta.type] }}\n </div>\n <div class=\"c-cron__segment-label\">{{ meta.label }}</div>\n </div>\n </div>\n\n <!-- 表达式行:输入 + 重置 + 描述 -->\n <div class=\"c-cron__expr-row\">\n <NInput\n :value=\"manualInput\"\n :status=\"validation.valid ? undefined : 'error'\"\n placeholder=\"秒 分 时 日 月 周\"\n :disabled=\"props.disabled\"\n font=\"mono\"\n size=\"small\"\n clearable\n class=\"c-cron__expr-input\"\n @update:value=\"handleManualInput\"\n @blur=\"handleManualBlur\"\n @keydown.enter=\"handleManualBlur\"\n >\n <template #prefix>\n <C_Icon name=\"mdi:console\" :size=\"14\" style=\"opacity: 0.4\" />\n </template>\n </NInput>\n <NButton\n size=\"small\"\n quaternary\n :disabled=\"props.disabled\"\n @click=\"handleReset\"\n >\n <template #icon>\n <C_Icon name=\"mdi:refresh\" />\n </template>\n </NButton>\n <div class=\"c-cron__expr-desc\">\n <span v-if=\"validation.valid\" class=\"c-cron__description\">\n {{ description }}\n </span>\n <span v-else class=\"c-cron__error\">\n {{ validation.message }}\n </span>\n </div>\n </div>\n </div>\n\n <!-- ═══════ 主内容 ═══════ -->\n <div class=\"c-cron__body\">\n <!-- 左侧:值网格 -->\n <div class=\"c-cron__main\">\n <CronFieldEditor\n v-for=\"meta in visibleFields\"\n v-show=\"activeField === meta.type\"\n :key=\"meta.type\"\n :model-value=\"cronValue[meta.type]\"\n :meta=\"meta\"\n @update:model-value=\"(v) => handleFieldChange(meta.type, v)\"\n />\n </div>\n\n <!-- 右侧:控制面板 -->\n <div class=\"c-cron__panel\">\n <NRadioGroup\n :value=\"activeFieldValue.mode\"\n size=\"small\"\n @update:value=\"handleActiveFieldModeChange\"\n >\n <NRadioButton value=\"every\">\n 每{{ activeFieldMeta.label }}\n </NRadioButton>\n <NRadioButton\n v-if=\"activeField === 'day' || activeField === 'week'\"\n value=\"none\"\n >\n 不指定\n </NRadioButton>\n <NRadioButton value=\"range\">范围</NRadioButton>\n <NRadioButton value=\"step\">步进</NRadioButton>\n <NRadioButton value=\"specific\">指定</NRadioButton>\n </NRadioGroup>\n\n <!-- 范围配置 -->\n <div v-if=\"activeFieldValue.mode === 'range'\" class=\"c-cron__config\">\n <div class=\"c-cron__config-row\">\n <span>从</span>\n <NInputNumber\n :value=\"activeFieldValue.rangeStart\"\n :min=\"activeFieldMeta.min\"\n :max=\"activeFieldMeta.max\"\n size=\"small\"\n :show-button=\"false\"\n class=\"c-cron__config-num\"\n @update:value=\"\n (v: number | null) =>\n handleActiveFieldUpdate({\n rangeStart: v ?? activeFieldMeta.min,\n })\n \"\n />\n <span>到</span>\n <NInputNumber\n :value=\"activeFieldValue.rangeEnd\"\n :min=\"activeFieldMeta.min\"\n :max=\"activeFieldMeta.max\"\n size=\"small\"\n :show-button=\"false\"\n class=\"c-cron__config-num\"\n @update:value=\"\n (v: number | null) =>\n handleActiveFieldUpdate({\n rangeEnd: v ?? activeFieldMeta.max,\n })\n \"\n />\n </div>\n </div>\n\n <!-- 步进配置 -->\n <div v-if=\"activeFieldValue.mode === 'step'\" class=\"c-cron__config\">\n <div class=\"c-cron__config-row\">\n <span>从第</span>\n <NInputNumber\n :value=\"activeFieldValue.stepStart\"\n :min=\"activeFieldMeta.min\"\n :max=\"activeFieldMeta.max\"\n size=\"small\"\n :show-button=\"false\"\n class=\"c-cron__config-num\"\n @update:value=\"\n (v: number | null) =>\n handleActiveFieldUpdate({\n stepStart: v ?? activeFieldMeta.min,\n })\n \"\n />\n <span>{{ activeFieldMeta.label }}起,每</span>\n <NInputNumber\n :value=\"activeFieldValue.stepInterval\"\n :min=\"1\"\n :max=\"activeFieldMeta.max - activeFieldMeta.min + 1\"\n size=\"small\"\n :show-button=\"false\"\n class=\"c-cron__config-num\"\n @update:value=\"\n (v: number | null) =>\n handleActiveFieldUpdate({ stepInterval: v ?? 1 })\n \"\n />\n <span>{{ activeFieldMeta.label }}执行</span>\n </div>\n </div>\n\n <!-- 指定快捷操作 -->\n <div v-if=\"activeFieldValue.mode === 'specific'\" class=\"c-cron__quick\">\n <a @click=\"handleSelectAll\">全选</a>\n <span class=\"c-cron__quick-sep\">·</span>\n <a @click=\"handleClearAll\">清空</a>\n <span\n v-if=\"activeFieldValue.specificValues.length > 0\"\n class=\"c-cron__quick-count\"\n >\n 已选 {{ activeFieldValue.specificValues.length }}\n </span>\n </div>\n\n <!-- 执行预览 -->\n <template v-if=\"props.showPreview\">\n <div class=\"c-cron__panel-line\" />\n <CronPreview\n :next-executions=\"nextExecutions\"\n :computing=\"computing\"\n :count=\"props.previewCount ?? 5\"\n :format-date=\"formatDate\"\n :format-week-day=\"formatWeekDay\"\n />\n </template>\n </div>\n </div>\n\n <!-- ═══════ 底部模板 ═══════ -->\n <div v-if=\"props.showTemplates\" class=\"c-cron__footer\">\n <CronTemplates\n :templates=\"CRON_TEMPLATES\"\n :current-value=\"expression\"\n @select=\"handleTemplateSelect\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted } from \"vue\";\nimport type {\n CronFieldMode,\n CronFieldType,\n CronFieldValue,\n CronProps,\n CronValidation,\n} from \"./types\";\nimport {\n CRON_FIELD_META,\n CRON_TEMPLATES,\n DEFAULT_CRON_EXPRESSION,\n} from \"./constants\";\nimport { useCronParser } from \"./composables/useCronParser\";\nimport { useCronPreview } from \"./composables/useCronPreview\";\nimport { useCronDescription } from \"./composables/useCronDescription\";\nimport C_Icon from \"../C_Icon/index.vue\";\nimport CronFieldEditor from \"./components/CronFieldEditor.vue\";\nimport CronPreview from \"./components/CronPreview.vue\";\nimport CronTemplates from \"./components/CronTemplates.vue\";\n\ndefineOptions({ name: \"C_Cron\" });\n\n/* ─── Props & Emits ─────────────────────────── */\n\nconst props = withDefaults(defineProps<CronProps>(), {\n modelValue: DEFAULT_CRON_EXPRESSION,\n disabled: false,\n previewCount: 10,\n showTemplates: true,\n showPreview: true,\n showSecond: true,\n height: \"auto\",\n});\n\nconst emit = defineEmits<{\n \"update:modelValue\": [value: string];\n change: [value: string];\n \"validation-change\": [result: CronValidation];\n}>();\n\n/* ─── 组合函数 ──────────────────────────────── */\n\nconst {\n cronValue,\n expression,\n validation,\n parse,\n validate,\n handleDayWeekExclusion,\n} = useCronParser();\n\nconst previewCount = computed(() => props.previewCount ?? 10);\nconst { nextExecutions, computing, formatDate, formatWeekDay } = useCronPreview(\n expression,\n validation,\n previewCount,\n);\n\nconst { description } = useCronDescription(expression, validation);\n\n/* ─── 本地状态 ──────────────────────────────── */\n\n/** 手动输入框值(与 expression 解耦,输入完成后同步) */\nconst manualInput = ref(props.modelValue || DEFAULT_CRON_EXPRESSION);\n\n/** 当前激活的字段 Tab */\nconst activeField = ref<CronFieldType>(props.showSecond ? \"second\" : \"minute\");\n\n/* ─── 容器高度 ──────────────────────────────── */\n\nconst containerHeight = computed(() => {\n if (typeof props.height === \"number\") return `${props.height}px`;\n return props.height;\n});\n\n/* ─── 可见字段(是否显示秒) ────────────────── */\n\nconst visibleFields = computed(() => {\n return props.showSecond\n ? CRON_FIELD_META\n : CRON_FIELD_META.filter((m) => m.type !== \"second\");\n});\n\n/* ─── 当前激活字段快捷访问 ─────────────────── */\n\n/** 当前激活字段元数据 */\nconst activeFieldMeta = computed(\n () => CRON_FIELD_META.find((m) => m.type === activeField.value)!,\n);\n\n/** 当前激活字段值 */\nconst activeFieldValue = computed(() => cronValue.value[activeField.value]);\n\n/* ─── 分段式表达式(逐字段计算) ────────────── */\n\n/** 计算单字段表达式文本 */\nfunction computeFieldExpr(f: CronFieldValue): string {\n switch (f.mode) {\n case \"every\":\n return \"*\";\n case \"none\":\n return \"?\";\n case \"range\":\n return `${f.rangeStart}-${f.rangeEnd}`;\n case \"step\":\n return `${f.stepStart}/${f.stepInterval}`;\n case \"specific\":\n return f.specificValues.length > 0\n ? [...f.specificValues].sort((a, b) => a - b).join(\",\")\n : \"*\";\n default:\n return \"*\";\n }\n}\n\n/** 各字段表达式映射 */\nconst fieldExpressions = computed(() => {\n const map = {} as Record<CronFieldType, string>;\n for (const meta of CRON_FIELD_META) {\n map[meta.type] = computeFieldExpr(cronValue.value[meta.type]);\n }\n return map;\n});\n\n/* ─── 初始化解析 ────────────────────────────── */\n\nonMounted(() => {\n const initial = props.modelValue || DEFAULT_CRON_EXPRESSION;\n parse(initial);\n manualInput.value = initial;\n});\n\n/* ─── 监听外部 v-model 变更 ─────────────────── */\n\nwatch(\n () => props.modelValue,\n (newVal) => {\n if (newVal && newVal !== expression.value) {\n parse(newVal);\n manualInput.value = newVal;\n }\n },\n);\n\n/* ─── 监听 showSecond 变更 ──────────────────── */\n\nwatch(\n () => props.showSecond,\n (show) => {\n if (!show && activeField.value === \"second\") {\n activeField.value = \"minute\";\n }\n },\n);\n\n/* ─── 监听内部表达式变更 → 同步到外部 ───────── */\n\nwatch(expression, (newExpr) => {\n manualInput.value = newExpr;\n emit(\"update:modelValue\", newExpr);\n emit(\"change\", newExpr);\n});\n\n/* ─── 监听校验状态变更 ──────────────────────── */\n\nwatch(validation, (v) => {\n emit(\"validation-change\", v);\n});\n\n/* ─── 字段变更处理 ──────────────────────────── */\n\n/** 字段编辑变更处理 */\nfunction handleFieldChange(type: CronFieldType, value: CronFieldValue) {\n cronValue.value[type] = value;\n if (type === \"day\" || type === \"week\") {\n handleDayWeekExclusion(type);\n }\n}\n\n/* ─── 右侧面板操作 ─────────────────────────── */\n\n/** 切换当前字段模式 */\nfunction handleActiveFieldModeChange(mode: CronFieldMode) {\n handleFieldChange(activeField.value, {\n ...activeFieldValue.value,\n mode,\n });\n}\n\n/** 更新当前字段属性 */\nfunction handleActiveFieldUpdate(partial: Partial<CronFieldValue>) {\n handleFieldChange(activeField.value, {\n ...activeFieldValue.value,\n ...partial,\n });\n}\n\n/** 全选当前字段所有值 */\nfunction handleSelectAll() {\n const { min, max } = activeFieldMeta.value;\n const allValues = Array.from({ length: max - min + 1 }, (_, i) => min + i);\n handleFieldChange(activeField.value, {\n ...activeFieldValue.value,\n specificValues: allValues,\n });\n}\n\n/** 清空当前字段所有选中值 */\nfunction handleClearAll() {\n handleFieldChange(activeField.value, {\n ...activeFieldValue.value,\n specificValues: [],\n });\n}\n\n/* ─── 手动输入处理 ──────────────────────────── */\n\n/** 手动输入更新 */\nfunction handleManualInput(value: string) {\n manualInput.value = value;\n}\n\n/** 输入框失焦时同步 */\nfunction handleManualBlur() {\n const trimmed = manualInput.value.trim();\n if (trimmed && trimmed !== expression.value) {\n parse(trimmed);\n }\n}\n\n/* ─── 模板选择 ──────────────────────────────── */\n\n/** 选择常用模板 */\nfunction handleTemplateSelect(expr: string) {\n parse(expr);\n manualInput.value = expr;\n}\n\n/* ─── 重置 ──────────────────────────────────── */\n\n/** 重置为初始值 */\nfunction handleReset() {\n const initial = props.modelValue || DEFAULT_CRON_EXPRESSION;\n parse(initial);\n manualInput.value = initial;\n}\n\n/* ─── Expose ────────────────────────────────── */\n\ndefineExpose({\n getValue: () => expression.value,\n setValue: (expr: string) => {\n parse(expr);\n manualInput.value = expr;\n },\n reset: handleReset,\n validate: () => validate(),\n});\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"C_Cron.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/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/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-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","<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2026-02-25\n * @Description: Cron 表达式编辑器组件\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\n-->\n\n<template>\n <div class=\"c-cron\" :style=\"{ height: containerHeight }\">\n <!-- ═══════ 顶部 ═══════ -->\n <div class=\"c-cron__header\">\n <!-- 标题行 -->\n <div class=\"c-cron__title-row\">\n <div class=\"c-cron__title\">\n <C_Icon name=\"mdi:clock-edit-outline\" :size=\"18\" />\n <span>Cron 表达式</span>\n </div>\n <NTag :type=\"validation.valid ? 'success' : 'error'\" size=\"small\" round>\n <template #icon>\n <C_Icon\n :name=\"validation.valid ? 'mdi:check-circle' : 'mdi:alert-circle'\"\n />\n </template>\n {{ validation.valid ? \"合法\" : \"错误\" }}\n </NTag>\n </div>\n\n <!-- 分段式字段选择器 -->\n <div class=\"c-cron__segments\">\n <div\n v-for=\"meta in visibleFields\"\n :key=\"meta.type\"\n class=\"c-cron__segment\"\n :class=\"{\n 'c-cron__segment--active': activeField === meta.type,\n 'c-cron__segment--wildcard':\n fieldExpressions[meta.type] === '*' ||\n fieldExpressions[meta.type] === '?',\n }\"\n @click=\"activeField = meta.type\"\n >\n <div class=\"c-cron__segment-value\">\n {{ fieldExpressions[meta.type] }}\n </div>\n <div class=\"c-cron__segment-label\">{{ meta.label }}</div>\n </div>\n </div>\n\n <!-- 表达式行:输入 + 重置 + 描述 -->\n <div class=\"c-cron__expr-row\">\n <NInput\n :value=\"manualInput\"\n :status=\"validation.valid ? undefined : 'error'\"\n placeholder=\"秒 分 时 日 月 周\"\n :disabled=\"props.disabled\"\n font=\"mono\"\n size=\"small\"\n clearable\n class=\"c-cron__expr-input\"\n @update:value=\"handleManualInput\"\n @blur=\"handleManualBlur\"\n @keydown.enter=\"handleManualBlur\"\n >\n <template #prefix>\n <C_Icon name=\"mdi:console\" :size=\"14\" style=\"opacity: 0.4\" />\n </template>\n </NInput>\n <NButton\n size=\"small\"\n quaternary\n :disabled=\"props.disabled\"\n @click=\"handleReset\"\n >\n <template #icon>\n <C_Icon name=\"mdi:refresh\" />\n </template>\n </NButton>\n <div class=\"c-cron__expr-desc\">\n <span v-if=\"validation.valid\" class=\"c-cron__description\">\n {{ description }}\n </span>\n <span v-else class=\"c-cron__error\">\n {{ validation.message }}\n </span>\n </div>\n </div>\n </div>\n\n <!-- ═══════ 主内容 ═══════ -->\n <div class=\"c-cron__body\">\n <!-- 左侧:值网格 -->\n <div class=\"c-cron__main\">\n <CronFieldEditor\n v-for=\"meta in visibleFields\"\n v-show=\"activeField === meta.type\"\n :key=\"meta.type\"\n :model-value=\"cronValue[meta.type]\"\n :meta=\"meta\"\n @update:model-value=\"(v) => handleFieldChange(meta.type, v)\"\n />\n </div>\n\n <!-- 右侧:控制面板 -->\n <div class=\"c-cron__panel\">\n <NRadioGroup\n :value=\"activeFieldValue.mode\"\n size=\"small\"\n @update:value=\"handleActiveFieldModeChange\"\n >\n <NRadioButton value=\"every\">\n 每{{ activeFieldMeta.label }}\n </NRadioButton>\n <NRadioButton\n v-if=\"activeField === 'day' || activeField === 'week'\"\n value=\"none\"\n >\n 不指定\n </NRadioButton>\n <NRadioButton value=\"range\">范围</NRadioButton>\n <NRadioButton value=\"step\">步进</NRadioButton>\n <NRadioButton value=\"specific\">指定</NRadioButton>\n </NRadioGroup>\n\n <!-- 范围配置 -->\n <div v-if=\"activeFieldValue.mode === 'range'\" class=\"c-cron__config\">\n <div class=\"c-cron__config-row\">\n <span>从</span>\n <NInputNumber\n :value=\"activeFieldValue.rangeStart\"\n :min=\"activeFieldMeta.min\"\n :max=\"activeFieldMeta.max\"\n size=\"small\"\n :show-button=\"false\"\n class=\"c-cron__config-num\"\n @update:value=\"\n (v: number | null) =>\n handleActiveFieldUpdate({\n rangeStart: v ?? activeFieldMeta.min,\n })\n \"\n />\n <span>到</span>\n <NInputNumber\n :value=\"activeFieldValue.rangeEnd\"\n :min=\"activeFieldMeta.min\"\n :max=\"activeFieldMeta.max\"\n size=\"small\"\n :show-button=\"false\"\n class=\"c-cron__config-num\"\n @update:value=\"\n (v: number | null) =>\n handleActiveFieldUpdate({\n rangeEnd: v ?? activeFieldMeta.max,\n })\n \"\n />\n </div>\n </div>\n\n <!-- 步进配置 -->\n <div v-if=\"activeFieldValue.mode === 'step'\" class=\"c-cron__config\">\n <div class=\"c-cron__config-row\">\n <span>从第</span>\n <NInputNumber\n :value=\"activeFieldValue.stepStart\"\n :min=\"activeFieldMeta.min\"\n :max=\"activeFieldMeta.max\"\n size=\"small\"\n :show-button=\"false\"\n class=\"c-cron__config-num\"\n @update:value=\"\n (v: number | null) =>\n handleActiveFieldUpdate({\n stepStart: v ?? activeFieldMeta.min,\n })\n \"\n />\n <span>{{ activeFieldMeta.label }}起,每</span>\n <NInputNumber\n :value=\"activeFieldValue.stepInterval\"\n :min=\"1\"\n :max=\"activeFieldMeta.max - activeFieldMeta.min + 1\"\n size=\"small\"\n :show-button=\"false\"\n class=\"c-cron__config-num\"\n @update:value=\"\n (v: number | null) =>\n handleActiveFieldUpdate({ stepInterval: v ?? 1 })\n \"\n />\n <span>{{ activeFieldMeta.label }}执行</span>\n </div>\n </div>\n\n <!-- 指定快捷操作 -->\n <div v-if=\"activeFieldValue.mode === 'specific'\" class=\"c-cron__quick\">\n <a @click=\"handleSelectAll\">全选</a>\n <span class=\"c-cron__quick-sep\">·</span>\n <a @click=\"handleClearAll\">清空</a>\n <span\n v-if=\"activeFieldValue.specificValues.length > 0\"\n class=\"c-cron__quick-count\"\n >\n 已选 {{ activeFieldValue.specificValues.length }}\n </span>\n </div>\n\n <!-- 执行预览 -->\n <template v-if=\"props.showPreview\">\n <div class=\"c-cron__panel-line\" />\n <CronPreview\n :next-executions=\"nextExecutions\"\n :computing=\"computing\"\n :count=\"props.previewCount ?? 5\"\n :format-date=\"formatDate\"\n :format-week-day=\"formatWeekDay\"\n />\n </template>\n </div>\n </div>\n\n <!-- ═══════ 底部模板 ═══════ -->\n <div v-if=\"props.showTemplates\" class=\"c-cron__footer\">\n <CronTemplates\n :templates=\"CRON_TEMPLATES\"\n :current-value=\"expression\"\n @select=\"handleTemplateSelect\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted } from \"vue\";\nimport type {\n CronFieldMode,\n CronFieldType,\n CronFieldValue,\n CronProps,\n CronValidation,\n} from \"./types\";\nimport {\n CRON_FIELD_META,\n CRON_TEMPLATES,\n DEFAULT_CRON_EXPRESSION,\n} from \"./constants\";\nimport { useCronParser } from \"./composables/useCronParser\";\nimport { useCronPreview } from \"./composables/useCronPreview\";\nimport { useCronDescription } from \"./composables/useCronDescription\";\nimport C_Icon from \"../C_Icon/index.vue\";\nimport CronFieldEditor from \"./components/CronFieldEditor.vue\";\nimport CronPreview from \"./components/CronPreview.vue\";\nimport CronTemplates from \"./components/CronTemplates.vue\";\n\ndefineOptions({ name: \"C_Cron\" });\n\n/* ─── Props & Emits ─────────────────────────── */\n\nconst props = withDefaults(defineProps<CronProps>(), {\n modelValue: DEFAULT_CRON_EXPRESSION,\n disabled: false,\n previewCount: 10,\n showTemplates: true,\n showPreview: true,\n showSecond: true,\n height: \"auto\",\n});\n\nconst emit = defineEmits<{\n \"update:modelValue\": [value: string];\n change: [value: string];\n \"validation-change\": [result: CronValidation];\n}>();\n\n/* ─── 组合函数 ──────────────────────────────── */\n\nconst {\n cronValue,\n expression,\n validation,\n parse,\n validate,\n handleDayWeekExclusion,\n} = useCronParser();\n\nconst previewCount = computed(() => props.previewCount ?? 10);\nconst { nextExecutions, computing, formatDate, formatWeekDay } = useCronPreview(\n expression,\n validation,\n previewCount,\n);\n\nconst { description } = useCronDescription(expression, validation);\n\n/* ─── 本地状态 ──────────────────────────────── */\n\n/** 手动输入框值(与 expression 解耦,输入完成后同步) */\nconst manualInput = ref(props.modelValue || DEFAULT_CRON_EXPRESSION);\n\n/** 当前激活的字段 Tab */\nconst activeField = ref<CronFieldType>(props.showSecond ? \"second\" : \"minute\");\n\n/* ─── 容器高度 ──────────────────────────────── */\n\nconst containerHeight = computed(() => {\n if (typeof props.height === \"number\") return `${props.height}px`;\n return props.height;\n});\n\n/* ─── 可见字段(是否显示秒) ────────────────── */\n\nconst visibleFields = computed(() => {\n return props.showSecond\n ? CRON_FIELD_META\n : CRON_FIELD_META.filter((m) => m.type !== \"second\");\n});\n\n/* ─── 当前激活字段快捷访问 ─────────────────── */\n\n/** 当前激活字段元数据 */\nconst activeFieldMeta = computed(\n () => CRON_FIELD_META.find((m) => m.type === activeField.value)!,\n);\n\n/** 当前激活字段值 */\nconst activeFieldValue = computed(() => cronValue.value[activeField.value]);\n\n/* ─── 分段式表达式(逐字段计算) ────────────── */\n\n/** 计算单字段表达式文本 */\nfunction computeFieldExpr(f: CronFieldValue): string {\n switch (f.mode) {\n case \"every\":\n return \"*\";\n case \"none\":\n return \"?\";\n case \"range\":\n return `${f.rangeStart}-${f.rangeEnd}`;\n case \"step\":\n return `${f.stepStart}/${f.stepInterval}`;\n case \"specific\":\n return f.specificValues.length > 0\n ? [...f.specificValues].sort((a, b) => a - b).join(\",\")\n : \"*\";\n default:\n return \"*\";\n }\n}\n\n/** 各字段表达式映射 */\nconst fieldExpressions = computed(() => {\n const map = {} as Record<CronFieldType, string>;\n for (const meta of CRON_FIELD_META) {\n map[meta.type] = computeFieldExpr(cronValue.value[meta.type]);\n }\n return map;\n});\n\n/* ─── 初始化解析 ────────────────────────────── */\n\nonMounted(() => {\n const initial = props.modelValue || DEFAULT_CRON_EXPRESSION;\n parse(initial);\n manualInput.value = initial;\n});\n\n/* ─── 监听外部 v-model 变更 ─────────────────── */\n\nwatch(\n () => props.modelValue,\n (newVal) => {\n if (newVal && newVal !== expression.value) {\n parse(newVal);\n manualInput.value = newVal;\n }\n },\n);\n\n/* ─── 监听 showSecond 变更 ──────────────────── */\n\nwatch(\n () => props.showSecond,\n (show) => {\n if (!show && activeField.value === \"second\") {\n activeField.value = \"minute\";\n }\n },\n);\n\n/* ─── 监听内部表达式变更 → 同步到外部 ───────── */\n\nwatch(expression, (newExpr) => {\n manualInput.value = newExpr;\n emit(\"update:modelValue\", newExpr);\n emit(\"change\", newExpr);\n});\n\n/* ─── 监听校验状态变更 ──────────────────────── */\n\nwatch(validation, (v) => {\n emit(\"validation-change\", v);\n});\n\n/* ─── 字段变更处理 ──────────────────────────── */\n\n/** 字段编辑变更处理 */\nfunction handleFieldChange(type: CronFieldType, value: CronFieldValue) {\n cronValue.value[type] = value;\n if (type === \"day\" || type === \"week\") {\n handleDayWeekExclusion(type);\n }\n}\n\n/* ─── 右侧面板操作 ─────────────────────────── */\n\n/** 切换当前字段模式 */\nfunction handleActiveFieldModeChange(mode: CronFieldMode) {\n handleFieldChange(activeField.value, {\n ...activeFieldValue.value,\n mode,\n });\n}\n\n/** 更新当前字段属性 */\nfunction handleActiveFieldUpdate(partial: Partial<CronFieldValue>) {\n handleFieldChange(activeField.value, {\n ...activeFieldValue.value,\n ...partial,\n });\n}\n\n/** 全选当前字段所有值 */\nfunction handleSelectAll() {\n const { min, max } = activeFieldMeta.value;\n const allValues = Array.from({ length: max - min + 1 }, (_, i) => min + i);\n handleFieldChange(activeField.value, {\n ...activeFieldValue.value,\n specificValues: allValues,\n });\n}\n\n/** 清空当前字段所有选中值 */\nfunction handleClearAll() {\n handleFieldChange(activeField.value, {\n ...activeFieldValue.value,\n specificValues: [],\n });\n}\n\n/* ─── 手动输入处理 ──────────────────────────── */\n\n/** 手动输入更新 */\nfunction handleManualInput(value: string) {\n manualInput.value = value;\n}\n\n/** 输入框失焦时同步 */\nfunction handleManualBlur() {\n const trimmed = manualInput.value.trim();\n if (trimmed && trimmed !== expression.value) {\n parse(trimmed);\n }\n}\n\n/* ─── 模板选择 ──────────────────────────────── */\n\n/** 选择常用模板 */\nfunction handleTemplateSelect(expr: string) {\n parse(expr);\n manualInput.value = expr;\n}\n\n/* ─── 重置 ──────────────────────────────────── */\n\n/** 重置为初始值 */\nfunction handleReset() {\n const initial = props.modelValue || DEFAULT_CRON_EXPRESSION;\n parse(initial);\n manualInput.value = initial;\n}\n\n/* ─── Expose ────────────────────────────────── */\n\ndefineExpose({\n getValue: () => expression.value,\n setValue: (expr: string) => {\n parse(expr);\n manualInput.value = expr;\n },\n reset: handleReset,\n validate: () => validate(),\n});\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2026-02-25\n * @Description: Cron 表达式编辑器组件\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\n-->\n\n<template>\n <div class=\"c-cron\" :style=\"{ height: containerHeight }\">\n <!-- ═══════ 顶部 ═══════ -->\n <div class=\"c-cron__header\">\n <!-- 标题行 -->\n <div class=\"c-cron__title-row\">\n <div class=\"c-cron__title\">\n <C_Icon name=\"mdi:clock-edit-outline\" :size=\"18\" />\n <span>Cron 表达式</span>\n </div>\n <NTag :type=\"validation.valid ? 'success' : 'error'\" size=\"small\" round>\n <template #icon>\n <C_Icon\n :name=\"validation.valid ? 'mdi:check-circle' : 'mdi:alert-circle'\"\n />\n </template>\n {{ validation.valid ? \"合法\" : \"错误\" }}\n </NTag>\n </div>\n\n <!-- 分段式字段选择器 -->\n <div class=\"c-cron__segments\">\n <div\n v-for=\"meta in visibleFields\"\n :key=\"meta.type\"\n class=\"c-cron__segment\"\n :class=\"{\n 'c-cron__segment--active': activeField === meta.type,\n 'c-cron__segment--wildcard':\n fieldExpressions[meta.type] === '*' ||\n fieldExpressions[meta.type] === '?',\n }\"\n @click=\"activeField = meta.type\"\n >\n <div class=\"c-cron__segment-value\">\n {{ fieldExpressions[meta.type] }}\n </div>\n <div class=\"c-cron__segment-label\">{{ meta.label }}</div>\n </div>\n </div>\n\n <!-- 表达式行:输入 + 重置 + 描述 -->\n <div class=\"c-cron__expr-row\">\n <NInput\n :value=\"manualInput\"\n :status=\"validation.valid ? undefined : 'error'\"\n placeholder=\"秒 分 时 日 月 周\"\n :disabled=\"props.disabled\"\n font=\"mono\"\n size=\"small\"\n clearable\n class=\"c-cron__expr-input\"\n @update:value=\"handleManualInput\"\n @blur=\"handleManualBlur\"\n @keydown.enter=\"handleManualBlur\"\n >\n <template #prefix>\n <C_Icon name=\"mdi:console\" :size=\"14\" style=\"opacity: 0.4\" />\n </template>\n </NInput>\n <NButton\n size=\"small\"\n quaternary\n :disabled=\"props.disabled\"\n @click=\"handleReset\"\n >\n <template #icon>\n <C_Icon name=\"mdi:refresh\" />\n </template>\n </NButton>\n <div class=\"c-cron__expr-desc\">\n <span v-if=\"validation.valid\" class=\"c-cron__description\">\n {{ description }}\n </span>\n <span v-else class=\"c-cron__error\">\n {{ validation.message }}\n </span>\n </div>\n </div>\n </div>\n\n <!-- ═══════ 主内容 ═══════ -->\n <div class=\"c-cron__body\">\n <!-- 左侧:值网格 -->\n <div class=\"c-cron__main\">\n <CronFieldEditor\n v-for=\"meta in visibleFields\"\n v-show=\"activeField === meta.type\"\n :key=\"meta.type\"\n :model-value=\"cronValue[meta.type]\"\n :meta=\"meta\"\n @update:model-value=\"(v) => handleFieldChange(meta.type, v)\"\n />\n </div>\n\n <!-- 右侧:控制面板 -->\n <div class=\"c-cron__panel\">\n <NRadioGroup\n :value=\"activeFieldValue.mode\"\n size=\"small\"\n @update:value=\"handleActiveFieldModeChange\"\n >\n <NRadioButton value=\"every\">\n 每{{ activeFieldMeta.label }}\n </NRadioButton>\n <NRadioButton\n v-if=\"activeField === 'day' || activeField === 'week'\"\n value=\"none\"\n >\n 不指定\n </NRadioButton>\n <NRadioButton value=\"range\">范围</NRadioButton>\n <NRadioButton value=\"step\">步进</NRadioButton>\n <NRadioButton value=\"specific\">指定</NRadioButton>\n </NRadioGroup>\n\n <!-- 范围配置 -->\n <div v-if=\"activeFieldValue.mode === 'range'\" class=\"c-cron__config\">\n <div class=\"c-cron__config-row\">\n <span>从</span>\n <NInputNumber\n :value=\"activeFieldValue.rangeStart\"\n :min=\"activeFieldMeta.min\"\n :max=\"activeFieldMeta.max\"\n size=\"small\"\n :show-button=\"false\"\n class=\"c-cron__config-num\"\n @update:value=\"\n (v: number | null) =>\n handleActiveFieldUpdate({\n rangeStart: v ?? activeFieldMeta.min,\n })\n \"\n />\n <span>到</span>\n <NInputNumber\n :value=\"activeFieldValue.rangeEnd\"\n :min=\"activeFieldMeta.min\"\n :max=\"activeFieldMeta.max\"\n size=\"small\"\n :show-button=\"false\"\n class=\"c-cron__config-num\"\n @update:value=\"\n (v: number | null) =>\n handleActiveFieldUpdate({\n rangeEnd: v ?? activeFieldMeta.max,\n })\n \"\n />\n </div>\n </div>\n\n <!-- 步进配置 -->\n <div v-if=\"activeFieldValue.mode === 'step'\" class=\"c-cron__config\">\n <div class=\"c-cron__config-row\">\n <span>从第</span>\n <NInputNumber\n :value=\"activeFieldValue.stepStart\"\n :min=\"activeFieldMeta.min\"\n :max=\"activeFieldMeta.max\"\n size=\"small\"\n :show-button=\"false\"\n class=\"c-cron__config-num\"\n @update:value=\"\n (v: number | null) =>\n handleActiveFieldUpdate({\n stepStart: v ?? activeFieldMeta.min,\n })\n \"\n />\n <span>{{ activeFieldMeta.label }}起,每</span>\n <NInputNumber\n :value=\"activeFieldValue.stepInterval\"\n :min=\"1\"\n :max=\"activeFieldMeta.max - activeFieldMeta.min + 1\"\n size=\"small\"\n :show-button=\"false\"\n class=\"c-cron__config-num\"\n @update:value=\"\n (v: number | null) =>\n handleActiveFieldUpdate({ stepInterval: v ?? 1 })\n \"\n />\n <span>{{ activeFieldMeta.label }}执行</span>\n </div>\n </div>\n\n <!-- 指定快捷操作 -->\n <div v-if=\"activeFieldValue.mode === 'specific'\" class=\"c-cron__quick\">\n <a @click=\"handleSelectAll\">全选</a>\n <span class=\"c-cron__quick-sep\">·</span>\n <a @click=\"handleClearAll\">清空</a>\n <span\n v-if=\"activeFieldValue.specificValues.length > 0\"\n class=\"c-cron__quick-count\"\n >\n 已选 {{ activeFieldValue.specificValues.length }}\n </span>\n </div>\n\n <!-- 执行预览 -->\n <template v-if=\"props.showPreview\">\n <div class=\"c-cron__panel-line\" />\n <CronPreview\n :next-executions=\"nextExecutions\"\n :computing=\"computing\"\n :count=\"props.previewCount ?? 5\"\n :format-date=\"formatDate\"\n :format-week-day=\"formatWeekDay\"\n />\n </template>\n </div>\n </div>\n\n <!-- ═══════ 底部模板 ═══════ -->\n <div v-if=\"props.showTemplates\" class=\"c-cron__footer\">\n <CronTemplates\n :templates=\"CRON_TEMPLATES\"\n :current-value=\"expression\"\n @select=\"handleTemplateSelect\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted } from \"vue\";\nimport type {\n CronFieldMode,\n CronFieldType,\n CronFieldValue,\n CronProps,\n CronValidation,\n} from \"./types\";\nimport {\n CRON_FIELD_META,\n CRON_TEMPLATES,\n DEFAULT_CRON_EXPRESSION,\n} from \"./constants\";\nimport { useCronParser } from \"./composables/useCronParser\";\nimport { useCronPreview } from \"./composables/useCronPreview\";\nimport { useCronDescription } from \"./composables/useCronDescription\";\nimport C_Icon from \"../C_Icon/index.vue\";\nimport CronFieldEditor from \"./components/CronFieldEditor.vue\";\nimport CronPreview from \"./components/CronPreview.vue\";\nimport CronTemplates from \"./components/CronTemplates.vue\";\n\ndefineOptions({ name: \"C_Cron\" });\n\n/* ─── Props & Emits ─────────────────────────── */\n\nconst props = withDefaults(defineProps<CronProps>(), {\n modelValue: DEFAULT_CRON_EXPRESSION,\n disabled: false,\n previewCount: 10,\n showTemplates: true,\n showPreview: true,\n showSecond: true,\n height: \"auto\",\n});\n\nconst emit = defineEmits<{\n \"update:modelValue\": [value: string];\n change: [value: string];\n \"validation-change\": [result: CronValidation];\n}>();\n\n/* ─── 组合函数 ──────────────────────────────── */\n\nconst {\n cronValue,\n expression,\n validation,\n parse,\n validate,\n handleDayWeekExclusion,\n} = useCronParser();\n\nconst previewCount = computed(() => props.previewCount ?? 10);\nconst { nextExecutions, computing, formatDate, formatWeekDay } = useCronPreview(\n expression,\n validation,\n previewCount,\n);\n\nconst { description } = useCronDescription(expression, validation);\n\n/* ─── 本地状态 ──────────────────────────────── */\n\n/** 手动输入框值(与 expression 解耦,输入完成后同步) */\nconst manualInput = ref(props.modelValue || DEFAULT_CRON_EXPRESSION);\n\n/** 当前激活的字段 Tab */\nconst activeField = ref<CronFieldType>(props.showSecond ? \"second\" : \"minute\");\n\n/* ─── 容器高度 ──────────────────────────────── */\n\nconst containerHeight = computed(() => {\n if (typeof props.height === \"number\") return `${props.height}px`;\n return props.height;\n});\n\n/* ─── 可见字段(是否显示秒) ────────────────── */\n\nconst visibleFields = computed(() => {\n return props.showSecond\n ? CRON_FIELD_META\n : CRON_FIELD_META.filter((m) => m.type !== \"second\");\n});\n\n/* ─── 当前激活字段快捷访问 ─────────────────── */\n\n/** 当前激活字段元数据 */\nconst activeFieldMeta = computed(\n () => CRON_FIELD_META.find((m) => m.type === activeField.value)!,\n);\n\n/** 当前激活字段值 */\nconst activeFieldValue = computed(() => cronValue.value[activeField.value]);\n\n/* ─── 分段式表达式(逐字段计算) ────────────── */\n\n/** 计算单字段表达式文本 */\nfunction computeFieldExpr(f: CronFieldValue): string {\n switch (f.mode) {\n case \"every\":\n return \"*\";\n case \"none\":\n return \"?\";\n case \"range\":\n return `${f.rangeStart}-${f.rangeEnd}`;\n case \"step\":\n return `${f.stepStart}/${f.stepInterval}`;\n case \"specific\":\n return f.specificValues.length > 0\n ? [...f.specificValues].sort((a, b) => a - b).join(\",\")\n : \"*\";\n default:\n return \"*\";\n }\n}\n\n/** 各字段表达式映射 */\nconst fieldExpressions = computed(() => {\n const map = {} as Record<CronFieldType, string>;\n for (const meta of CRON_FIELD_META) {\n map[meta.type] = computeFieldExpr(cronValue.value[meta.type]);\n }\n return map;\n});\n\n/* ─── 初始化解析 ────────────────────────────── */\n\nonMounted(() => {\n const initial = props.modelValue || DEFAULT_CRON_EXPRESSION;\n parse(initial);\n manualInput.value = initial;\n});\n\n/* ─── 监听外部 v-model 变更 ─────────────────── */\n\nwatch(\n () => props.modelValue,\n (newVal) => {\n if (newVal && newVal !== expression.value) {\n parse(newVal);\n manualInput.value = newVal;\n }\n },\n);\n\n/* ─── 监听 showSecond 变更 ──────────────────── */\n\nwatch(\n () => props.showSecond,\n (show) => {\n if (!show && activeField.value === \"second\") {\n activeField.value = \"minute\";\n }\n },\n);\n\n/* ─── 监听内部表达式变更 → 同步到外部 ───────── */\n\nwatch(expression, (newExpr) => {\n manualInput.value = newExpr;\n emit(\"update:modelValue\", newExpr);\n emit(\"change\", newExpr);\n});\n\n/* ─── 监听校验状态变更 ──────────────────────── */\n\nwatch(validation, (v) => {\n emit(\"validation-change\", v);\n});\n\n/* ─── 字段变更处理 ──────────────────────────── */\n\n/** 字段编辑变更处理 */\nfunction handleFieldChange(type: CronFieldType, value: CronFieldValue) {\n cronValue.value[type] = value;\n if (type === \"day\" || type === \"week\") {\n handleDayWeekExclusion(type);\n }\n}\n\n/* ─── 右侧面板操作 ─────────────────────────── */\n\n/** 切换当前字段模式 */\nfunction handleActiveFieldModeChange(mode: CronFieldMode) {\n handleFieldChange(activeField.value, {\n ...activeFieldValue.value,\n mode,\n });\n}\n\n/** 更新当前字段属性 */\nfunction handleActiveFieldUpdate(partial: Partial<CronFieldValue>) {\n handleFieldChange(activeField.value, {\n ...activeFieldValue.value,\n ...partial,\n });\n}\n\n/** 全选当前字段所有值 */\nfunction handleSelectAll() {\n const { min, max } = activeFieldMeta.value;\n const allValues = Array.from({ length: max - min + 1 }, (_, i) => min + i);\n handleFieldChange(activeField.value, {\n ...activeFieldValue.value,\n specificValues: allValues,\n });\n}\n\n/** 清空当前字段所有选中值 */\nfunction handleClearAll() {\n handleFieldChange(activeField.value, {\n ...activeFieldValue.value,\n specificValues: [],\n });\n}\n\n/* ─── 手动输入处理 ──────────────────────────── */\n\n/** 手动输入更新 */\nfunction handleManualInput(value: string) {\n manualInput.value = value;\n}\n\n/** 输入框失焦时同步 */\nfunction handleManualBlur() {\n const trimmed = manualInput.value.trim();\n if (trimmed && trimmed !== expression.value) {\n parse(trimmed);\n }\n}\n\n/* ─── 模板选择 ──────────────────────────────── */\n\n/** 选择常用模板 */\nfunction handleTemplateSelect(expr: string) {\n parse(expr);\n manualInput.value = expr;\n}\n\n/* ─── 重置 ──────────────────────────────────── */\n\n/** 重置为初始值 */\nfunction handleReset() {\n const initial = props.modelValue || DEFAULT_CRON_EXPRESSION;\n parse(initial);\n manualInput.value = initial;\n}\n\n/* ─── Expose ────────────────────────────────── */\n\ndefineExpose({\n getValue: () => expression.value,\n setValue: (expr: string) => {\n parse(expr);\n manualInput.value = expr;\n },\n reset: handleReset,\n validate: () => validate(),\n});\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n"],"mappings":"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"}
|
package/dist/C_Cron2.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./C_Icon2.js";import{t}from"./export-helper.js";import{Fragment as n,computed as r,createBlock as i,createCommentVNode as a,createElementBlock as o,createElementVNode as s,createTextVNode as c,createVNode as l,defineComponent as u,normalizeClass as d,normalizeStyle as f,onMounted as p,openBlock as m,ref as h,renderList as g,resolveComponent as _,toDisplayString as v,unref as y,vShow as ee,watch as b,withCtx as x,withDirectives as te,withKeys as ne}from"vue";const S=[{type:`second`,label:`秒`,min:0,max:59},{type:`minute`,label:`分`,min:0,max:59},{type:`hour`,label:`时`,min:0,max:23},{type:`day`,label:`日`,min:1,max:31},{type:`month`,label:`月`,min:1,max:12},{type:`week`,label:`周`,min:1,max:7,valueLabels:{1:`周日`,2:`周一`,3:`周二`,4:`周三`,5:`周四`,6:`周五`,7:`周六`}}],C={mode:`every`,rangeStart:0,rangeEnd:0,stepStart:0,stepInterval:1,specificValues:[]},w={second:{...C,rangeEnd:59},minute:{...C,rangeEnd:59},hour:{...C,rangeEnd:23},day:{...C,rangeStart:1,rangeEnd:31},month:{...C,rangeStart:1,rangeEnd:12},week:{...C,mode:`none`,rangeStart:1,rangeEnd:7}},T=`0 0 0 * * ?`,E=[{label:`每秒执行`,value:`* * * * * ?`,description:`每秒执行一次`,icon:`mdi:timer-sand`},{label:`每分钟执行`,value:`0 * * * * ?`,description:`每分钟第 0 秒执行`,icon:`mdi:clock-outline`},{label:`每小时执行`,value:`0 0 * * * ?`,description:`每小时整点执行`,icon:`mdi:clock-time-twelve-outline`},{label:`每天 0 点`,value:`0 0 0 * * ?`,description:`每天凌晨 00:00 执行`,icon:`mdi:weather-night`},{label:`每天 8:30`,value:`0 30 8 * * ?`,description:`每天早上 08:30 执行`,icon:`mdi:weather-sunny`},{label:`每天 12:00`,value:`0 0 12 * * ?`,description:`每天中午 12:00 执行`,icon:`mdi:food`},{label:`工作日 9:00`,value:`0 0 9 ? * 2-6`,description:`周一至周五 09:00 执行`,icon:`mdi:briefcase-outline`},{label:`每周一 0 点`,value:`0 0 0 ? * 2`,description:`每周一凌晨 00:00 执行`,icon:`mdi:calendar-week`},{label:`每月 1 号 0 点`,value:`0 0 0 1 * ?`,description:`每月 1 号凌晨 00:00 执行`,icon:`mdi:calendar-month`},{label:`每 5 分钟`,value:`0 0/5 * * * ?`,description:`每隔 5 分钟执行一次`,icon:`mdi:timer-5`},{label:`每 30 分钟`,value:`0 0/30 * * * ?`,description:`每隔 30 分钟执行一次`,icon:`mdi:timer-30`},{label:`每 2 小时`,value:`0 0 0/2 * * ?`,description:`每隔 2 小时执行一次`,icon:`mdi:timer-2`}],D={1:`一月`,2:`二月`,3:`三月`,4:`四月`,5:`五月`,6:`六月`,7:`七月`,8:`八月`,9:`九月`,10:`十月`,11:`十一月`,12:`十二月`},O={1:`周日`,2:`周一`,3:`周二`,4:`周三`,5:`周四`,6:`周五`,7:`周六`},k=[`second`,`minute`,`hour`,`day`,`month`,`week`];function A(){let e=h(structuredClone(w));function t(e){switch(e.mode){case`every`:return`*`;case`range`:return`${e.rangeStart}-${e.rangeEnd}`;case`step`:return`${e.stepStart}/${e.stepInterval}`;case`specific`:return e.specificValues.length>0?e.specificValues.sort((e,t)=>e-t).join(`,`):`*`;case`none`:return`?`;default:return`*`}}function n(e,t,n={}){return{mode:t,rangeStart:e.min,rangeEnd:e.max,stepStart:e.min,stepInterval:1,specificValues:[],...n}}function i(e,t){let[r,i]=e.split(`/`).map(Number);return n(t,`step`,{stepStart:isNaN(r)?t.min:r,stepInterval:isNaN(i)?1:i})}function a(e,t){let[r,i]=e.split(`-`).map(Number);return n(t,`range`,{rangeStart:isNaN(r)?t.min:r,rangeEnd:isNaN(i)?t.max:i})}function o(e,t){let r=S.find(e=>e.type===t);if(e===`?`)return n(r,`none`);if(e===`*`)return n(r,`every`);if(e.includes(`/`))return i(e,r);if(e.includes(`-`)&&!e.includes(`,`))return a(e,r);let o=e.split(`,`).map(Number).filter(e=>!isNaN(e));return o.length>0?n(r,`specific`,{specificValues:o}):n(r,`every`)}function s(){return k.map(n=>t(e.value[n])).join(` `)}function c(t){let n=t.trim().split(/\s+/);n.length<6||k.forEach((t,r)=>{e.value[t]=o(n[r],t)})}function l(t){t===`day`?e.value.day.mode!==`none`&&(e.value.week={...e.value.week,mode:`none`}):e.value.week.mode!==`none`&&(e.value.day={...e.value.day,mode:`none`})}function u(e){let t=(e??s()).trim().split(/\s+/);if(t.length!==6)return{valid:!1,message:`表达式应包含 6 个字段,当前为 ${t.length} 个`};let n=t[3],r=t[5];if(n!==`?`&&r!==`?`)return{valid:!1,message:`日和周不能同时指定,其中一个必须为 ?`,field:`day`};if(n===`?`&&r===`?`)return{valid:!1,message:`日和周不能同时为 ?,至少指定一个`,field:`day`};for(let e=0;e<k.length;e++){let n=k[e],r=t[e],i=m(r,S.find(e=>e.type===n));if(!i.valid)return{...i,field:n}}return{valid:!0,message:`表达式合法`}}function d(e,t){let[n,r]=e.split(`/`),i=n===`*`?t.min:Number(n),a=Number(r);return isNaN(i)||isNaN(a)?{valid:!1,message:`${t.label}字段步进格式错误`}:i<t.min||i>t.max?{valid:!1,message:`${t.label}字段步进起始值超出范围 (${t.min}-${t.max})`}:a<1?{valid:!1,message:`${t.label}字段步进间隔必须大于 0`}:{valid:!0,message:``}}function f(e,t){let[n,r]=e.split(`-`).map(Number);return isNaN(n)||isNaN(r)?{valid:!1,message:`${t.label}字段范围格式错误`}:n<t.min||r>t.max?{valid:!1,message:`${t.label}字段范围超出 (${t.min}-${t.max})`}:n>r?{valid:!1,message:`${t.label}字段范围起始不能大于结束`}:{valid:!0,message:``}}function p(e,t){let n=e.split(`,`).map(Number);return n.some(isNaN)?{valid:!1,message:`${t.label}字段包含非数字字符`}:n.some(e=>e<t.min||e>t.max)?{valid:!1,message:`${t.label}字段值超出范围 (${t.min}-${t.max})`}:{valid:!0,message:``}}function m(e,t){return e===`*`||e===`?`?{valid:!0,message:``}:e.includes(`/`)?d(e,t):e.includes(`-`)&&!e.includes(`,`)?f(e,t):p(e,t)}return{cronValue:e,expression:r(()=>s()),validation:r(()=>u()),parse:c,generate:s,validate:u,handleDayWeekExclusion:l}}function j(e,t,n){let r=h([]),i=h(!1);function a(e,t){if(t===`*`||t===`?`)return!0;if(t.includes(`/`)){let[n,r]=t.split(`/`),i=n===`*`?0:Number(n),a=Number(r);return e-i>=0&&(e-i)%a===0}if(t.includes(`-`)&&!t.includes(`,`)){let[n,r]=t.split(`-`).map(Number);return e>=n&&e<=r}return t.split(`,`).map(Number).includes(e)}function o(e,t){if(t.length!==6)return!1;let[n,r,i,o,s,c]=t;return!(!a(e.getMonth()+1,s)||o!==`?`&&!a(e.getDate(),o)||c!==`?`&&!a(e.getDay()+1,c)||!a(e.getHours(),i)||!a(e.getMinutes(),r)||!a(e.getSeconds(),n))}function s(){let r=e.value;if(!r||!t.value.valid)return[];let i=r.trim().split(/\s+/);if(i.length!==6)return[];let a=[],s=new Date,c=new Date(s.getTime()+1e3);c.setMilliseconds(0);let l=i[0]!==`0`,u=l?1e3:6e4;l||(c.setSeconds(0),c.getTime()<=s.getTime()&&c.setTime(c.getTime()+6e4));let d=n.value;for(let e=0;e<525600&&a.length<d;e++)o(c,i)&&a.push(new Date(c)),c.setTime(c.getTime()+u);return a}b([e,n],()=>{if(!t.value.valid){r.value=[];return}i.value=!0,setTimeout(()=>{r.value=s(),i.value=!1},0)},{immediate:!0});function c(e){let t=e=>String(e).padStart(2,`0`);return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())} ${t(e.getHours())}:${t(e.getMinutes())}:${t(e.getSeconds())}`}function l(e){return[`周日`,`周一`,`周二`,`周三`,`周四`,`周五`,`周六`][e.getDay()]}return{nextExecutions:r,computing:i,formatDate:c,formatWeekDay:l}}function M(e){return O[Number(e)]||`周${e}`}function N(e,t){let n=r(()=>t.value.valid?i(e.value):`表达式不合法`);function i(e){let t=e.trim().split(/\s+/);if(t.length!==6)return`表达式格式错误`;let[n,r,i,d,f,p]=t,m=[];return m.push(l(f)),p===`?`?m.push(c(d)):m.push(u(p)),m.push(s(i)),m.push(o(r)),m.push(a(n)),m.filter(Boolean).join(` `)+` 执行`}function a(e){return e===`0`?``:e===`*`?`每秒`:d(e,`秒`)}function o(e){return e===`*`?`每分钟`:e===`0`?``:d(e,`分`)}function s(e){return e===`*`?`每小时`:/^\d+$/.test(e)?`${e.padStart(2,`0`)}:`:d(e,`时`)}function c(e){if(e===`*`||e===`?`)return`每天`;if(/^\d+$/.test(e))return`每月 ${e} 号`;if(e.includes(`/`)){let[t,n]=e.split(`/`);return`从 ${t} 号开始每 ${n} 天`}if(e.includes(`-`)){let[t,n]=e.split(`-`);return`${t} 号到 ${n} 号`}return e.includes(`,`)?`每月 ${e} 号`:``}function l(e){if(e===`*`)return``;if(/^\d+$/.test(e)){let t=Number(e);return D[t]?`${D[t]}`:`${t} 月`}if(e.includes(`/`)){let[t,n]=e.split(`/`);return`从 ${t} 月开始每 ${n} 个月`}if(e.includes(`-`)){let[t,n]=e.split(`-`);return`${t} 月到 ${n} 月`}return e.includes(`,`)?e.split(`,`).map(e=>D[Number(e)]||`${e}月`).join(`、`):``}function u(e){return e===`*`||e===`?`?``:/^\d+$/.test(e)?`每${M(e)}`:e.includes(`/`)?`从${M(e.split(`/`)[0])}开始每 ${e.split(`/`)[1]} 天`:e.includes(`-`)?`${M(e.split(`-`)[0])}到${M(e.split(`-`)[1])}`:e.includes(`,`)?`每${e.split(`,`).map(M).join(`、`)}`:``}function d(e,t){if(e.includes(`/`)){let[n,r]=e.split(`/`);return`${n===`*`||n===`0`?``:`从第 ${n} ${t}开始`}每 ${r} ${t}`}if(e.includes(`-`)){let[n,r]=e.split(`-`);return`${n} ${t}到 ${r} ${t}`}return e.includes(`,`)?`第 ${e} ${t}`:/^\d+$/.test(e)?`${e.padStart(2,`0`)}`:``}return{description:n}}const P={class:`cron-field-editor`},F=[`onClick`];var re=t(u({__name:`CronFieldEditor`,props:{modelValue:{},meta:{}},emits:[`update:modelValue`],setup(e,{emit:t}){let i=e,a=t,c=r(()=>{switch(i.meta.type){case`second`:case`minute`:return 10;case`hour`:return 12;case`day`:return 7;case`month`:return 6;case`week`:return 7;default:return 10}}),l=r(()=>{let e=[];for(let t=i.meta.min;t<=i.meta.max;t++)e.push({value:t,label:i.meta.valueLabels?.[t]??String(t)});return e}),u=r(()=>{let{modelValue:e,meta:t}=i,n=new Set;switch(e.mode){case`every`:for(let e=t.min;e<=t.max;e++)n.add(e);break;case`none`:break;case`range`:for(let t=e.rangeStart;t<=e.rangeEnd;t++)n.add(t);break;case`step`:for(let r=e.stepStart;r<=t.max;r+=e.stepInterval)n.add(r);break;case`specific`:e.specificValues.forEach(e=>n.add(e));break}return n});function p(e){if(i.modelValue.mode!==`specific`)return;let t=[...i.modelValue.specificValues],n=t.indexOf(e);n>=0?t.splice(n,1):t.push(e),a(`update:modelValue`,{...i.modelValue,specificValues:t})}return(e,t)=>(m(),o(`div`,P,[s(`div`,{class:`cron-field-editor__grid`,style:f({"--cols":c.value})},[(m(!0),o(n,null,g(l.value,t=>(m(),o(`div`,{key:t.value,class:d([`cron-field-editor__cell`,{"cron-field-editor__cell--on":u.value.has(t.value),"cron-field-editor__cell--pick":e.modelValue.mode===`specific`}]),onClick:e=>p(t.value)},v(t.label),11,F))),128))],4)]))}}),[[`__scopeId`,`data-v-769c51fe`]]);const I={class:`cron-preview`},L={class:`cron-preview__header`},R={key:0,class:`cron-preview__list`},z={class:`cron-preview__idx`},B={class:`cron-preview__date`},V={class:`cron-preview__week`};var ie=t(u({__name:`CronPreview`,props:{nextExecutions:{},computing:{type:Boolean},count:{},formatDate:{type:Function},formatWeekDay:{type:Function}},setup(t){return(t,r)=>{let c=_(`NSpin`),u=_(`NEmpty`),d=_(`NScrollbar`);return m(),o(`div`,I,[s(`div`,L,[l(e,{name:`mdi:calendar-clock`,size:15}),r[0]||=s(`span`,null,`未来执行`,-1),t.computing?(m(),i(c,{key:0,size:14})):a(`v-if`,!0)]),l(d,{style:{"max-height":`220px`}},{default:x(()=>[t.nextExecutions.length>0?(m(),o(`div`,R,[(m(!0),o(n,null,g(t.nextExecutions,(e,n)=>(m(),o(`div`,{key:n,class:`cron-preview__item`},[s(`span`,z,v(n+1),1),s(`span`,B,v(t.formatDate(e)),1),s(`span`,V,v(t.formatWeekDay(e)),1)]))),128))])):(m(),i(u,{key:1,size:`small`,description:`暂无匹配`}))]),_:1})])}}}),[[`__scopeId`,`data-v-570ad3fb`]]);const H={class:`cron-templates`},U={class:`cron-templates__header`},W={class:`cron-templates__cards`},G=[`onClick`],K={class:`cron-templates__card-name`},q={class:`cron-templates__card-expr`};var ae=t(u({__name:`CronTemplates`,props:{templates:{},currentValue:{}},emits:[`select`],setup(t){return(t,r)=>(m(),o(`div`,H,[s(`div`,U,[l(e,{name:`mdi:lightning-bolt`,size:15}),r[0]||=s(`span`,null,`常用模板`,-1)]),s(`div`,W,[(m(!0),o(n,null,g(t.templates,e=>(m(),o(`div`,{key:e.value,class:d([`cron-templates__card`,{"cron-templates__card--active":e.value===t.currentValue}]),onClick:n=>t.$emit(`select`,e.value)},[s(`div`,K,v(e.label),1),s(`div`,q,v(e.value),1)],10,G))),128))])]))}}),[[`__scopeId`,`data-v-5190cefc`]]);const oe={class:`c-cron__header`},se={class:`c-cron__title-row`},ce={class:`c-cron__title`},le={class:`c-cron__segments`},ue=[`onClick`],de={class:`c-cron__segment-value`},fe={class:`c-cron__segment-label`},pe={class:`c-cron__expr-row`},me={class:`c-cron__expr-desc`},he={key:0,class:`c-cron__description`},ge={key:1,class:`c-cron__error`},_e={class:`c-cron__body`},ve={class:`c-cron__main`},ye={class:`c-cron__panel`},be={key:0,class:`c-cron__config`},xe={class:`c-cron__config-row`},Se={key:1,class:`c-cron__config`},Ce={class:`c-cron__config-row`},we={key:2,class:`c-cron__quick`},Te={key:0,class:`c-cron__quick-count`},Ee={key:0,class:`c-cron__footer`};var J=t(u({name:`C_Cron`,__name:`index`,props:{modelValue:{default:T},disabled:{type:Boolean,default:!1},previewCount:{default:10},showTemplates:{type:Boolean,default:!0},showPreview:{type:Boolean,default:!0},showSecond:{type:Boolean,default:!0},height:{default:`auto`}},emits:[`update:modelValue`,`change`,`validation-change`],setup(t,{expose:u,emit:C}){let w=t,D=C,{cronValue:O,expression:k,validation:M,parse:P,validate:F,handleDayWeekExclusion:I}=A(),{nextExecutions:L,computing:R,formatDate:z,formatWeekDay:B}=j(k,M,r(()=>w.previewCount??10)),{description:V}=N(k,M),H=h(w.modelValue||T),U=h(w.showSecond?`second`:`minute`),W=r(()=>typeof w.height==`number`?`${w.height}px`:w.height),G=r(()=>w.showSecond?S:S.filter(e=>e.type!==`second`)),K=r(()=>S.find(e=>e.type===U.value)),q=r(()=>O.value[U.value]);function J(e){switch(e.mode){case`every`:return`*`;case`none`:return`?`;case`range`:return`${e.rangeStart}-${e.rangeEnd}`;case`step`:return`${e.stepStart}/${e.stepInterval}`;case`specific`:return e.specificValues.length>0?[...e.specificValues].sort((e,t)=>e-t).join(`,`):`*`;default:return`*`}}let Y=r(()=>{let e={};for(let t of S)e[t.type]=J(O.value[t.type]);return e});p(()=>{let e=w.modelValue||T;P(e),H.value=e}),b(()=>w.modelValue,e=>{e&&e!==k.value&&(P(e),H.value=e)}),b(()=>w.showSecond,e=>{!e&&U.value===`second`&&(U.value=`minute`)}),b(k,e=>{H.value=e,D(`update:modelValue`,e),D(`change`,e)}),b(M,e=>{D(`validation-change`,e)});function X(e,t){O.value[e]=t,(e===`day`||e===`week`)&&I(e)}function De(e){X(U.value,{...q.value,mode:e})}function Z(e){X(U.value,{...q.value,...e})}function Oe(){let{min:e,max:t}=K.value,n=Array.from({length:t-e+1},(t,n)=>e+n);X(U.value,{...q.value,specificValues:n})}function ke(){X(U.value,{...q.value,specificValues:[]})}function Ae(e){H.value=e}function Q(){let e=H.value.trim();e&&e!==k.value&&P(e)}function je(e){P(e),H.value=e}function $(){let e=w.modelValue||T;P(e),H.value=e}return u({getValue:()=>k.value,setValue:e=>{P(e),H.value=e},reset:$,validate:()=>F()}),(t,r)=>{let u=_(`NTag`),p=_(`NInput`),h=_(`NButton`),b=_(`NRadioButton`),S=_(`NRadioGroup`),C=_(`NInputNumber`);return m(),o(`div`,{class:`c-cron`,style:f({height:W.value})},[a(` ═══════ 顶部 ═══════ `),s(`div`,oe,[a(` 标题行 `),s(`div`,se,[s(`div`,ce,[l(e,{name:`mdi:clock-edit-outline`,size:18}),r[4]||=s(`span`,null,`Cron 表达式`,-1)]),l(u,{type:y(M).valid?`success`:`error`,size:`small`,round:``},{icon:x(()=>[l(e,{name:y(M).valid?`mdi:check-circle`:`mdi:alert-circle`},null,8,[`name`])]),default:x(()=>[c(` `+v(y(M).valid?`合法`:`错误`),1)]),_:1},8,[`type`])]),a(` 分段式字段选择器 `),s(`div`,le,[(m(!0),o(n,null,g(G.value,e=>(m(),o(`div`,{key:e.type,class:d([`c-cron__segment`,{"c-cron__segment--active":U.value===e.type,"c-cron__segment--wildcard":Y.value[e.type]===`*`||Y.value[e.type]===`?`}]),onClick:t=>U.value=e.type},[s(`div`,de,v(Y.value[e.type]),1),s(`div`,fe,v(e.label),1)],10,ue))),128))]),a(` 表达式行:输入 + 重置 + 描述 `),s(`div`,pe,[l(p,{value:H.value,status:y(M).valid?void 0:`error`,placeholder:`秒 分 时 日 月 周`,disabled:w.disabled,font:`mono`,size:`small`,clearable:``,class:`c-cron__expr-input`,"onUpdate:value":Ae,onBlur:Q,onKeydown:ne(Q,[`enter`])},{prefix:x(()=>[l(e,{name:`mdi:console`,size:14,style:{opacity:`0.4`}})]),_:1},8,[`value`,`status`,`disabled`]),l(h,{size:`small`,quaternary:``,disabled:w.disabled,onClick:$},{icon:x(()=>[l(e,{name:`mdi:refresh`})]),_:1},8,[`disabled`]),s(`div`,me,[y(M).valid?(m(),o(`span`,he,v(y(V)),1)):(m(),o(`span`,ge,v(y(M).message),1))])])]),a(` ═══════ 主内容 ═══════ `),s(`div`,_e,[a(` 左侧:值网格 `),s(`div`,ve,[(m(!0),o(n,null,g(G.value,e=>te((m(),i(re,{key:e.type,"model-value":y(O)[e.type],meta:e,"onUpdate:modelValue":t=>X(e.type,t)},null,8,[`model-value`,`meta`,`onUpdate:modelValue`])),[[ee,U.value===e.type]])),128))]),a(` 右侧:控制面板 `),s(`div`,ye,[l(S,{value:q.value.mode,size:`small`,"onUpdate:value":De},{default:x(()=>[l(b,{value:`every`},{default:x(()=>[c(` 每`+v(K.value.label),1)]),_:1}),U.value===`day`||U.value===`week`?(m(),i(b,{key:0,value:`none`},{default:x(()=>r[5]||=[c(` 不指定 `,-1)]),_:1,__:[5]})):a(`v-if`,!0),l(b,{value:`range`},{default:x(()=>r[6]||=[c(`范围`,-1)]),_:1,__:[6]}),l(b,{value:`step`},{default:x(()=>r[7]||=[c(`步进`,-1)]),_:1,__:[7]}),l(b,{value:`specific`},{default:x(()=>r[8]||=[c(`指定`,-1)]),_:1,__:[8]})]),_:1},8,[`value`]),a(` 范围配置 `),q.value.mode===`range`?(m(),o(`div`,be,[s(`div`,xe,[r[9]||=s(`span`,null,`从`,-1),l(C,{value:q.value.rangeStart,min:K.value.min,max:K.value.max,size:`small`,"show-button":!1,class:`c-cron__config-num`,"onUpdate:value":r[0]||=e=>Z({rangeStart:e??K.value.min})},null,8,[`value`,`min`,`max`]),r[10]||=s(`span`,null,`到`,-1),l(C,{value:q.value.rangeEnd,min:K.value.min,max:K.value.max,size:`small`,"show-button":!1,class:`c-cron__config-num`,"onUpdate:value":r[1]||=e=>Z({rangeEnd:e??K.value.max})},null,8,[`value`,`min`,`max`])])])):a(`v-if`,!0),a(` 步进配置 `),q.value.mode===`step`?(m(),o(`div`,Se,[s(`div`,Ce,[r[11]||=s(`span`,null,`从第`,-1),l(C,{value:q.value.stepStart,min:K.value.min,max:K.value.max,size:`small`,"show-button":!1,class:`c-cron__config-num`,"onUpdate:value":r[2]||=e=>Z({stepStart:e??K.value.min})},null,8,[`value`,`min`,`max`]),s(`span`,null,v(K.value.label)+`起,每`,1),l(C,{value:q.value.stepInterval,min:1,max:K.value.max-K.value.min+1,size:`small`,"show-button":!1,class:`c-cron__config-num`,"onUpdate:value":r[3]||=e=>Z({stepInterval:e??1})},null,8,[`value`,`max`]),s(`span`,null,v(K.value.label)+`执行`,1)])])):a(`v-if`,!0),a(` 指定快捷操作 `),q.value.mode===`specific`?(m(),o(`div`,we,[s(`a`,{onClick:Oe},`全选`),r[12]||=s(`span`,{class:`c-cron__quick-sep`},`·`,-1),s(`a`,{onClick:ke},`清空`),q.value.specificValues.length>0?(m(),o(`span`,Te,` 已选 `+v(q.value.specificValues.length),1)):a(`v-if`,!0)])):a(`v-if`,!0),a(` 执行预览 `),w.showPreview?(m(),o(n,{key:3},[r[13]||=s(`div`,{class:`c-cron__panel-line`},null,-1),l(ie,{"next-executions":y(L),computing:y(R),count:w.previewCount??5,"format-date":y(z),"format-week-day":y(B)},null,8,[`next-executions`,`computing`,`count`,`format-date`,`format-week-day`])],64)):a(`v-if`,!0)])]),a(` ═══════ 底部模板 ═══════ `),w.showTemplates?(m(),o(`div`,Ee,[l(ae,{templates:y(E),"current-value":y(k),onSelect:je},null,8,[`templates`,`current-value`])])):a(`v-if`,!0)],4)}}}),[[`__scopeId`,`data-v-e9b95547`]]);export{S as a,w as c,O as d,A as i,C as l,N as n,E as o,j as r,T as s,J as t,D as u};
|
|
1
|
+
import{t as e}from"./C_Icon2.js";import{t}from"./export-helper.js";import{NButton as n,NEmpty as r,NInput as i,NInputNumber as a,NRadioButton as o,NRadioGroup as s,NScrollbar as c,NSpin as l,NTag as u}from"naive-ui";import{Fragment as d,computed as f,createBlock as p,createCommentVNode as m,createElementBlock as h,createElementVNode as g,createTextVNode as _,createVNode as v,defineComponent as y,normalizeClass as b,normalizeStyle as x,onMounted as S,openBlock as C,ref as w,renderList as T,resolveComponent as E,toDisplayString as D,unref as O,vShow as ee,watch as k,withCtx as A,withDirectives as te,withKeys as ne}from"vue";const j=[{type:`second`,label:`秒`,min:0,max:59},{type:`minute`,label:`分`,min:0,max:59},{type:`hour`,label:`时`,min:0,max:23},{type:`day`,label:`日`,min:1,max:31},{type:`month`,label:`月`,min:1,max:12},{type:`week`,label:`周`,min:1,max:7,valueLabels:{1:`周日`,2:`周一`,3:`周二`,4:`周三`,5:`周四`,6:`周五`,7:`周六`}}],M={mode:`every`,rangeStart:0,rangeEnd:0,stepStart:0,stepInterval:1,specificValues:[]},N={second:{...M,rangeEnd:59},minute:{...M,rangeEnd:59},hour:{...M,rangeEnd:23},day:{...M,rangeStart:1,rangeEnd:31},month:{...M,rangeStart:1,rangeEnd:12},week:{...M,mode:`none`,rangeStart:1,rangeEnd:7}},P=`0 0 0 * * ?`,F=[{label:`每秒执行`,value:`* * * * * ?`,description:`每秒执行一次`,icon:`mdi:timer-sand`},{label:`每分钟执行`,value:`0 * * * * ?`,description:`每分钟第 0 秒执行`,icon:`mdi:clock-outline`},{label:`每小时执行`,value:`0 0 * * * ?`,description:`每小时整点执行`,icon:`mdi:clock-time-twelve-outline`},{label:`每天 0 点`,value:`0 0 0 * * ?`,description:`每天凌晨 00:00 执行`,icon:`mdi:weather-night`},{label:`每天 8:30`,value:`0 30 8 * * ?`,description:`每天早上 08:30 执行`,icon:`mdi:weather-sunny`},{label:`每天 12:00`,value:`0 0 12 * * ?`,description:`每天中午 12:00 执行`,icon:`mdi:food`},{label:`工作日 9:00`,value:`0 0 9 ? * 2-6`,description:`周一至周五 09:00 执行`,icon:`mdi:briefcase-outline`},{label:`每周一 0 点`,value:`0 0 0 ? * 2`,description:`每周一凌晨 00:00 执行`,icon:`mdi:calendar-week`},{label:`每月 1 号 0 点`,value:`0 0 0 1 * ?`,description:`每月 1 号凌晨 00:00 执行`,icon:`mdi:calendar-month`},{label:`每 5 分钟`,value:`0 0/5 * * * ?`,description:`每隔 5 分钟执行一次`,icon:`mdi:timer-5`},{label:`每 30 分钟`,value:`0 0/30 * * * ?`,description:`每隔 30 分钟执行一次`,icon:`mdi:timer-30`},{label:`每 2 小时`,value:`0 0 0/2 * * ?`,description:`每隔 2 小时执行一次`,icon:`mdi:timer-2`}],I={1:`一月`,2:`二月`,3:`三月`,4:`四月`,5:`五月`,6:`六月`,7:`七月`,8:`八月`,9:`九月`,10:`十月`,11:`十一月`,12:`十二月`},L={1:`周日`,2:`周一`,3:`周二`,4:`周三`,5:`周四`,6:`周五`,7:`周六`},R=[`second`,`minute`,`hour`,`day`,`month`,`week`];function z(){let e=w(structuredClone(N));function t(e){switch(e.mode){case`every`:return`*`;case`range`:return`${e.rangeStart}-${e.rangeEnd}`;case`step`:return`${e.stepStart}/${e.stepInterval}`;case`specific`:return e.specificValues.length>0?e.specificValues.sort((e,t)=>e-t).join(`,`):`*`;case`none`:return`?`;default:return`*`}}function n(e,t,n={}){return{mode:t,rangeStart:e.min,rangeEnd:e.max,stepStart:e.min,stepInterval:1,specificValues:[],...n}}function r(e,t){let[r,i]=e.split(`/`).map(Number);return n(t,`step`,{stepStart:isNaN(r)?t.min:r,stepInterval:isNaN(i)?1:i})}function i(e,t){let[r,i]=e.split(`-`).map(Number);return n(t,`range`,{rangeStart:isNaN(r)?t.min:r,rangeEnd:isNaN(i)?t.max:i})}function a(e,t){let a=j.find(e=>e.type===t);if(e===`?`)return n(a,`none`);if(e===`*`)return n(a,`every`);if(e.includes(`/`))return r(e,a);if(e.includes(`-`)&&!e.includes(`,`))return i(e,a);let o=e.split(`,`).map(Number).filter(e=>!isNaN(e));return o.length>0?n(a,`specific`,{specificValues:o}):n(a,`every`)}function o(){return R.map(n=>t(e.value[n])).join(` `)}function s(t){let n=t.trim().split(/\s+/);n.length<6||R.forEach((t,r)=>{e.value[t]=a(n[r],t)})}function c(t){t===`day`?e.value.day.mode!==`none`&&(e.value.week={...e.value.week,mode:`none`}):e.value.week.mode!==`none`&&(e.value.day={...e.value.day,mode:`none`})}function l(e){let t=(e??o()).trim().split(/\s+/);if(t.length!==6)return{valid:!1,message:`表达式应包含 6 个字段,当前为 ${t.length} 个`};let n=t[3],r=t[5];if(n!==`?`&&r!==`?`)return{valid:!1,message:`日和周不能同时指定,其中一个必须为 ?`,field:`day`};if(n===`?`&&r===`?`)return{valid:!1,message:`日和周不能同时为 ?,至少指定一个`,field:`day`};for(let e=0;e<R.length;e++){let n=R[e],r=t[e],i=m(r,j.find(e=>e.type===n));if(!i.valid)return{...i,field:n}}return{valid:!0,message:`表达式合法`}}function u(e,t){let[n,r]=e.split(`/`),i=n===`*`?t.min:Number(n),a=Number(r);return isNaN(i)||isNaN(a)?{valid:!1,message:`${t.label}字段步进格式错误`}:i<t.min||i>t.max?{valid:!1,message:`${t.label}字段步进起始值超出范围 (${t.min}-${t.max})`}:a<1?{valid:!1,message:`${t.label}字段步进间隔必须大于 0`}:{valid:!0,message:``}}function d(e,t){let[n,r]=e.split(`-`).map(Number);return isNaN(n)||isNaN(r)?{valid:!1,message:`${t.label}字段范围格式错误`}:n<t.min||r>t.max?{valid:!1,message:`${t.label}字段范围超出 (${t.min}-${t.max})`}:n>r?{valid:!1,message:`${t.label}字段范围起始不能大于结束`}:{valid:!0,message:``}}function p(e,t){let n=e.split(`,`).map(Number);return n.some(isNaN)?{valid:!1,message:`${t.label}字段包含非数字字符`}:n.some(e=>e<t.min||e>t.max)?{valid:!1,message:`${t.label}字段值超出范围 (${t.min}-${t.max})`}:{valid:!0,message:``}}function m(e,t){return e===`*`||e===`?`?{valid:!0,message:``}:e.includes(`/`)?u(e,t):e.includes(`-`)&&!e.includes(`,`)?d(e,t):p(e,t)}return{cronValue:e,expression:f(()=>o()),validation:f(()=>l()),parse:s,generate:o,validate:l,handleDayWeekExclusion:c}}function B(e,t,n){let r=w([]),i=w(!1);function a(e,t){if(t===`*`||t===`?`)return!0;if(t.includes(`/`)){let[n,r]=t.split(`/`),i=n===`*`?0:Number(n),a=Number(r);return e-i>=0&&(e-i)%a===0}if(t.includes(`-`)&&!t.includes(`,`)){let[n,r]=t.split(`-`).map(Number);return e>=n&&e<=r}return t.split(`,`).map(Number).includes(e)}function o(e,t){if(t.length!==6)return!1;let[n,r,i,o,s,c]=t;return!(!a(e.getMonth()+1,s)||o!==`?`&&!a(e.getDate(),o)||c!==`?`&&!a(e.getDay()+1,c)||!a(e.getHours(),i)||!a(e.getMinutes(),r)||!a(e.getSeconds(),n))}function s(){let r=e.value;if(!r||!t.value.valid)return[];let i=r.trim().split(/\s+/);if(i.length!==6)return[];let a=[],s=new Date,c=new Date(s.getTime()+1e3);c.setMilliseconds(0);let l=i[0]!==`0`,u=l?1e3:6e4;l||(c.setSeconds(0),c.getTime()<=s.getTime()&&c.setTime(c.getTime()+6e4));let d=n.value;for(let e=0;e<525600&&a.length<d;e++)o(c,i)&&a.push(new Date(c)),c.setTime(c.getTime()+u);return a}k([e,n],()=>{if(!t.value.valid){r.value=[];return}i.value=!0,setTimeout(()=>{r.value=s(),i.value=!1},0)},{immediate:!0});function c(e){let t=e=>String(e).padStart(2,`0`);return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())} ${t(e.getHours())}:${t(e.getMinutes())}:${t(e.getSeconds())}`}function l(e){return[`周日`,`周一`,`周二`,`周三`,`周四`,`周五`,`周六`][e.getDay()]}return{nextExecutions:r,computing:i,formatDate:c,formatWeekDay:l}}function V(e){return L[Number(e)]||`周${e}`}function H(e,t){let n=f(()=>t.value.valid?r(e.value):`表达式不合法`);function r(e){let t=e.trim().split(/\s+/);if(t.length!==6)return`表达式格式错误`;let[n,r,u,d,f,p]=t,m=[];return m.push(c(f)),p===`?`?m.push(s(d)):m.push(l(p)),m.push(o(u)),m.push(a(r)),m.push(i(n)),m.filter(Boolean).join(` `)+` 执行`}function i(e){return e===`0`?``:e===`*`?`每秒`:u(e,`秒`)}function a(e){return e===`*`?`每分钟`:e===`0`?``:u(e,`分`)}function o(e){return e===`*`?`每小时`:/^\d+$/.test(e)?`${e.padStart(2,`0`)}:`:u(e,`时`)}function s(e){if(e===`*`||e===`?`)return`每天`;if(/^\d+$/.test(e))return`每月 ${e} 号`;if(e.includes(`/`)){let[t,n]=e.split(`/`);return`从 ${t} 号开始每 ${n} 天`}if(e.includes(`-`)){let[t,n]=e.split(`-`);return`${t} 号到 ${n} 号`}return e.includes(`,`)?`每月 ${e} 号`:``}function c(e){if(e===`*`)return``;if(/^\d+$/.test(e)){let t=Number(e);return I[t]?`${I[t]}`:`${t} 月`}if(e.includes(`/`)){let[t,n]=e.split(`/`);return`从 ${t} 月开始每 ${n} 个月`}if(e.includes(`-`)){let[t,n]=e.split(`-`);return`${t} 月到 ${n} 月`}return e.includes(`,`)?e.split(`,`).map(e=>I[Number(e)]||`${e}月`).join(`、`):``}function l(e){return e===`*`||e===`?`?``:/^\d+$/.test(e)?`每${V(e)}`:e.includes(`/`)?`从${V(e.split(`/`)[0])}开始每 ${e.split(`/`)[1]} 天`:e.includes(`-`)?`${V(e.split(`-`)[0])}到${V(e.split(`-`)[1])}`:e.includes(`,`)?`每${e.split(`,`).map(V).join(`、`)}`:``}function u(e,t){if(e.includes(`/`)){let[n,r]=e.split(`/`);return`${n===`*`||n===`0`?``:`从第 ${n} ${t}开始`}每 ${r} ${t}`}if(e.includes(`-`)){let[n,r]=e.split(`-`);return`${n} ${t}到 ${r} ${t}`}return e.includes(`,`)?`第 ${e} ${t}`:/^\d+$/.test(e)?`${e.padStart(2,`0`)}`:``}return{description:n}}const U={class:`cron-field-editor`},W=[`onClick`];var re=t(y({__name:`CronFieldEditor`,props:{modelValue:{},meta:{}},emits:[`update:modelValue`],setup(e,{emit:t}){let n=e,r=t,i=f(()=>{switch(n.meta.type){case`second`:case`minute`:return 10;case`hour`:return 12;case`day`:return 7;case`month`:return 6;case`week`:return 7;default:return 10}}),a=f(()=>{let e=[];for(let t=n.meta.min;t<=n.meta.max;t++)e.push({value:t,label:n.meta.valueLabels?.[t]??String(t)});return e}),o=f(()=>{let{modelValue:e,meta:t}=n,r=new Set;switch(e.mode){case`every`:for(let e=t.min;e<=t.max;e++)r.add(e);break;case`none`:break;case`range`:for(let t=e.rangeStart;t<=e.rangeEnd;t++)r.add(t);break;case`step`:for(let n=e.stepStart;n<=t.max;n+=e.stepInterval)r.add(n);break;case`specific`:e.specificValues.forEach(e=>r.add(e));break}return r});function s(e){if(n.modelValue.mode!==`specific`)return;let t=[...n.modelValue.specificValues],i=t.indexOf(e);i>=0?t.splice(i,1):t.push(e),r(`update:modelValue`,{...n.modelValue,specificValues:t})}return(e,t)=>(C(),h(`div`,U,[g(`div`,{class:`cron-field-editor__grid`,style:x({"--cols":i.value})},[(C(!0),h(d,null,T(a.value,t=>(C(),h(`div`,{key:t.value,class:b([`cron-field-editor__cell`,{"cron-field-editor__cell--on":o.value.has(t.value),"cron-field-editor__cell--pick":e.modelValue.mode===`specific`}]),onClick:e=>s(t.value)},D(t.label),11,W))),128))],4)]))}}),[[`__scopeId`,`data-v-e6fa8e5b`]]);const G={class:`cron-preview`},ie={class:`cron-preview__header`},K={key:0,class:`cron-preview__list`},q={class:`cron-preview__idx`},ae={class:`cron-preview__date`},J={class:`cron-preview__week`};var oe=t(y({__name:`CronPreview`,props:{nextExecutions:{},computing:{type:Boolean},count:{},formatDate:{type:Function},formatWeekDay:{type:Function}},setup(t){return(t,n)=>{let i=l,a=r,o=c;return C(),h(`div`,G,[g(`div`,ie,[v(e,{name:`mdi:calendar-clock`,size:15}),n[0]||=g(`span`,null,`未来执行`,-1),t.computing?(C(),p(i,{key:0,size:14})):m(`v-if`,!0)]),v(o,{style:{"max-height":`220px`}},{default:A(()=>[t.nextExecutions.length>0?(C(),h(`div`,K,[(C(!0),h(d,null,T(t.nextExecutions,(e,n)=>(C(),h(`div`,{key:n,class:`cron-preview__item`},[g(`span`,q,D(n+1),1),g(`span`,ae,D(t.formatDate(e)),1),g(`span`,J,D(t.formatWeekDay(e)),1)]))),128))])):(C(),p(a,{key:1,size:`small`,description:`暂无匹配`}))]),_:1})])}}}),[[`__scopeId`,`data-v-a695bb32`]]);const Y={class:`cron-templates`},X={class:`cron-templates__header`},se={class:`cron-templates__cards`},Z=[`onClick`],Q={class:`cron-templates__card-name`},ce={class:`cron-templates__card-expr`};var le=t(y({__name:`CronTemplates`,props:{templates:{},currentValue:{}},emits:[`select`],setup(t){return(t,n)=>(C(),h(`div`,Y,[g(`div`,X,[v(e,{name:`mdi:lightning-bolt`,size:15}),n[0]||=g(`span`,null,`常用模板`,-1)]),g(`div`,se,[(C(!0),h(d,null,T(t.templates,e=>(C(),h(`div`,{key:e.value,class:b([`cron-templates__card`,{"cron-templates__card--active":e.value===t.currentValue}]),onClick:n=>t.$emit(`select`,e.value)},[g(`div`,Q,D(e.label),1),g(`div`,ce,D(e.value),1)],10,Z))),128))])]))}}),[[`__scopeId`,`data-v-fe320f38`]]);const ue={class:`c-cron__header`},de={class:`c-cron__title-row`},fe={class:`c-cron__title`},pe={class:`c-cron__segments`},me=[`onClick`],he={class:`c-cron__segment-value`},ge={class:`c-cron__segment-label`},_e={class:`c-cron__expr-row`},ve={class:`c-cron__expr-desc`},ye={key:0,class:`c-cron__description`},be={key:1,class:`c-cron__error`},xe={class:`c-cron__body`},Se={class:`c-cron__main`},Ce={class:`c-cron__panel`},we={key:0,class:`c-cron__config`},Te={class:`c-cron__config-row`},Ee={key:1,class:`c-cron__config`},De={class:`c-cron__config-row`},Oe={key:2,class:`c-cron__quick`},ke={key:0,class:`c-cron__quick-count`},Ae={key:0,class:`c-cron__footer`};var $=t(y({name:`C_Cron`,__name:`index`,props:{modelValue:{default:P},disabled:{type:Boolean,default:!1},previewCount:{default:10},showTemplates:{type:Boolean,default:!0},showPreview:{type:Boolean,default:!0},showSecond:{type:Boolean,default:!0},height:{default:`auto`}},emits:[`update:modelValue`,`change`,`validation-change`],setup(t,{expose:r,emit:c}){let l=t,y=c,{cronValue:E,expression:M,validation:N,parse:I,validate:L,handleDayWeekExclusion:R}=z(),{nextExecutions:V,computing:U,formatDate:W,formatWeekDay:G}=B(M,N,f(()=>l.previewCount??10)),{description:ie}=H(M,N),K=w(l.modelValue||P),q=w(l.showSecond?`second`:`minute`),ae=f(()=>typeof l.height==`number`?`${l.height}px`:l.height),J=f(()=>l.showSecond?j:j.filter(e=>e.type!==`second`)),Y=f(()=>j.find(e=>e.type===q.value)),X=f(()=>E.value[q.value]);function se(e){switch(e.mode){case`every`:return`*`;case`none`:return`?`;case`range`:return`${e.rangeStart}-${e.rangeEnd}`;case`step`:return`${e.stepStart}/${e.stepInterval}`;case`specific`:return e.specificValues.length>0?[...e.specificValues].sort((e,t)=>e-t).join(`,`):`*`;default:return`*`}}let Z=f(()=>{let e={};for(let t of j)e[t.type]=se(E.value[t.type]);return e});S(()=>{let e=l.modelValue||P;I(e),K.value=e}),k(()=>l.modelValue,e=>{e&&e!==M.value&&(I(e),K.value=e)}),k(()=>l.showSecond,e=>{!e&&q.value===`second`&&(q.value=`minute`)}),k(M,e=>{K.value=e,y(`update:modelValue`,e),y(`change`,e)}),k(N,e=>{y(`validation-change`,e)});function Q(e,t){E.value[e]=t,(e===`day`||e===`week`)&&R(e)}function ce(e){Q(q.value,{...X.value,mode:e})}function $(e){Q(q.value,{...X.value,...e})}function je(){let{min:e,max:t}=Y.value,n=Array.from({length:t-e+1},(t,n)=>e+n);Q(q.value,{...X.value,specificValues:n})}function Me(){Q(q.value,{...X.value,specificValues:[]})}function Ne(e){K.value=e}function Pe(){let e=K.value.trim();e&&e!==M.value&&I(e)}function Fe(e){I(e),K.value=e}function Ie(){let e=l.modelValue||P;I(e),K.value=e}return r({getValue:()=>M.value,setValue:e=>{I(e),K.value=e},reset:Ie,validate:()=>L()}),(t,r)=>{let c=u,f=i,y=n,S=o,w=s,k=a;return C(),h(`div`,{class:`c-cron`,style:x({height:ae.value})},[m(` ═══════ 顶部 ═══════ `),g(`div`,ue,[m(` 标题行 `),g(`div`,de,[g(`div`,fe,[v(e,{name:`mdi:clock-edit-outline`,size:18}),r[4]||=g(`span`,null,`Cron 表达式`,-1)]),v(c,{type:O(N).valid?`success`:`error`,size:`small`,round:``},{icon:A(()=>[v(e,{name:O(N).valid?`mdi:check-circle`:`mdi:alert-circle`},null,8,[`name`])]),default:A(()=>[_(` `+D(O(N).valid?`合法`:`错误`),1)]),_:1},8,[`type`])]),m(` 分段式字段选择器 `),g(`div`,pe,[(C(!0),h(d,null,T(J.value,e=>(C(),h(`div`,{key:e.type,class:b([`c-cron__segment`,{"c-cron__segment--active":q.value===e.type,"c-cron__segment--wildcard":Z.value[e.type]===`*`||Z.value[e.type]===`?`}]),onClick:t=>q.value=e.type},[g(`div`,he,D(Z.value[e.type]),1),g(`div`,ge,D(e.label),1)],10,me))),128))]),m(` 表达式行:输入 + 重置 + 描述 `),g(`div`,_e,[v(f,{value:K.value,status:O(N).valid?void 0:`error`,placeholder:`秒 分 时 日 月 周`,disabled:l.disabled,font:`mono`,size:`small`,clearable:``,class:`c-cron__expr-input`,"onUpdate:value":Ne,onBlur:Pe,onKeydown:ne(Pe,[`enter`])},{prefix:A(()=>[v(e,{name:`mdi:console`,size:14,style:{opacity:`0.4`}})]),_:1},8,[`value`,`status`,`disabled`]),v(y,{size:`small`,quaternary:``,disabled:l.disabled,onClick:Ie},{icon:A(()=>[v(e,{name:`mdi:refresh`})]),_:1},8,[`disabled`]),g(`div`,ve,[O(N).valid?(C(),h(`span`,ye,D(O(ie)),1)):(C(),h(`span`,be,D(O(N).message),1))])])]),m(` ═══════ 主内容 ═══════ `),g(`div`,xe,[m(` 左侧:值网格 `),g(`div`,Se,[(C(!0),h(d,null,T(J.value,e=>te((C(),p(re,{key:e.type,"model-value":O(E)[e.type],meta:e,"onUpdate:modelValue":t=>Q(e.type,t)},null,8,[`model-value`,`meta`,`onUpdate:modelValue`])),[[ee,q.value===e.type]])),128))]),m(` 右侧:控制面板 `),g(`div`,Ce,[v(w,{value:X.value.mode,size:`small`,"onUpdate:value":ce},{default:A(()=>[v(S,{value:`every`},{default:A(()=>[_(` 每`+D(Y.value.label),1)]),_:1}),q.value===`day`||q.value===`week`?(C(),p(S,{key:0,value:`none`},{default:A(()=>r[5]||=[_(` 不指定 `,-1)]),_:1,__:[5]})):m(`v-if`,!0),v(S,{value:`range`},{default:A(()=>r[6]||=[_(`范围`,-1)]),_:1,__:[6]}),v(S,{value:`step`},{default:A(()=>r[7]||=[_(`步进`,-1)]),_:1,__:[7]}),v(S,{value:`specific`},{default:A(()=>r[8]||=[_(`指定`,-1)]),_:1,__:[8]})]),_:1},8,[`value`]),m(` 范围配置 `),X.value.mode===`range`?(C(),h(`div`,we,[g(`div`,Te,[r[9]||=g(`span`,null,`从`,-1),v(k,{value:X.value.rangeStart,min:Y.value.min,max:Y.value.max,size:`small`,"show-button":!1,class:`c-cron__config-num`,"onUpdate:value":r[0]||=e=>$({rangeStart:e??Y.value.min})},null,8,[`value`,`min`,`max`]),r[10]||=g(`span`,null,`到`,-1),v(k,{value:X.value.rangeEnd,min:Y.value.min,max:Y.value.max,size:`small`,"show-button":!1,class:`c-cron__config-num`,"onUpdate:value":r[1]||=e=>$({rangeEnd:e??Y.value.max})},null,8,[`value`,`min`,`max`])])])):m(`v-if`,!0),m(` 步进配置 `),X.value.mode===`step`?(C(),h(`div`,Ee,[g(`div`,De,[r[11]||=g(`span`,null,`从第`,-1),v(k,{value:X.value.stepStart,min:Y.value.min,max:Y.value.max,size:`small`,"show-button":!1,class:`c-cron__config-num`,"onUpdate:value":r[2]||=e=>$({stepStart:e??Y.value.min})},null,8,[`value`,`min`,`max`]),g(`span`,null,D(Y.value.label)+`起,每`,1),v(k,{value:X.value.stepInterval,min:1,max:Y.value.max-Y.value.min+1,size:`small`,"show-button":!1,class:`c-cron__config-num`,"onUpdate:value":r[3]||=e=>$({stepInterval:e??1})},null,8,[`value`,`max`]),g(`span`,null,D(Y.value.label)+`执行`,1)])])):m(`v-if`,!0),m(` 指定快捷操作 `),X.value.mode===`specific`?(C(),h(`div`,Oe,[g(`a`,{onClick:je},`全选`),r[12]||=g(`span`,{class:`c-cron__quick-sep`},`·`,-1),g(`a`,{onClick:Me},`清空`),X.value.specificValues.length>0?(C(),h(`span`,ke,` 已选 `+D(X.value.specificValues.length),1)):m(`v-if`,!0)])):m(`v-if`,!0),m(` 执行预览 `),l.showPreview?(C(),h(d,{key:3},[r[13]||=g(`div`,{class:`c-cron__panel-line`},null,-1),v(oe,{"next-executions":O(V),computing:O(U),count:l.previewCount??5,"format-date":O(W),"format-week-day":O(G)},null,8,[`next-executions`,`computing`,`count`,`format-date`,`format-week-day`])],64)):m(`v-if`,!0)])]),m(` ═══════ 底部模板 ═══════ `),l.showTemplates?(C(),h(`div`,Ae,[v(le,{templates:O(F),"current-value":O(M),onSelect:Fe},null,8,[`templates`,`current-value`])])):m(`v-if`,!0)],4)}}}),[[`__scopeId`,`data-v-06e7be26`]]);export{j as a,N as c,L as d,z as i,M as l,H as n,F as o,B as r,P as s,$ as t,I as u};
|
|
2
2
|
//# sourceMappingURL=C_Cron2.js.map
|