@robot-admin/naive-ui-components 0.9.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +82 -76
- package/LICENSE +21 -0
- package/README.md +314 -294
- 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.cjs +1 -1
- package/dist/C_AvatarGroup.css +21 -21
- package/dist/C_AvatarGroup.d.cts +1 -1
- package/dist/C_AvatarGroup.d.ts +1 -1
- package/dist/C_AvatarGroup.js +1 -1
- 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-CmCrLVft.css.map +1 -0
- package/dist/C_Cascade-U6A5AJJb.css.map +1 -0
- package/dist/C_Cascade.css +3 -3
- package/dist/C_Cascade.d.cts +2 -2
- package/dist/C_Cascade.d.ts +2 -2
- 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-B_2ql62V.css.map} +1 -1
- package/dist/{C_Form-D_gwQ7hC.css.map → C_Form-CX-7xsz3.css.map} +1 -1
- package/dist/C_Form.css +223 -223
- package/dist/C_Form.d.cts +2 -2
- package/dist/C_Form.d.ts +2 -2
- 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.d.cts +1 -1
- package/dist/C_Icon.d.ts +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.d.cts +1 -1
- package/dist/C_Language.d.ts +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-27Exh7PM.css.map +1 -0
- package/dist/C_Steps-DU9ZsFrs.css.map +1 -0
- package/dist/C_Steps.css +38 -38
- package/dist/C_Steps.d.cts +1 -1
- package/dist/C_Steps.d.ts +1 -1
- 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 +3 -3
- package/dist/C_Table2.js.map +1 -1
- package/dist/{C_TagsView-DX3LecK1.css.map → C_TagsView-BN8vMRsY.css.map} +1 -1
- package/dist/{C_TagsView-DqOTa8bL.css.map → C_TagsView-s1dnSJAV.css.map} +1 -1
- package/dist/C_TagsView.css +36 -36
- package/dist/C_TagsView.d.cts +1 -1
- package/dist/C_TagsView.d.ts +1 -1
- 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.d.cts +1 -1
- package/dist/C_Theme.d.ts +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.cjs +1 -1
- package/dist/C_Timeline.css +45 -45
- package/dist/C_Timeline.d.cts +1 -1
- package/dist/C_Timeline.d.ts +1 -1
- package/dist/C_Timeline.js +1 -1
- 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 +1 -1
- package/dist/constants3.d.ts +1 -1
- package/dist/constants4.d.ts +2 -2
- package/dist/constants5.d.ts +2 -2
- package/dist/data.d.ts +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.vue.d.ts +1 -1
- package/dist/index10.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 +2 -2
- package/dist/index15.vue.d.ts +29 -9
- package/dist/index16.vue.d.ts +11 -4
- package/dist/index17.vue.d.ts +1 -1
- package/dist/index18.vue.d.ts +3 -3
- package/dist/index2.vue.d.ts +6 -6
- package/dist/index20.vue.d.ts +1 -1
- package/dist/index21.vue.d.ts +3 -3
- package/dist/index22.vue.d.ts +3 -3
- package/dist/index23.vue.d.ts +15 -4
- package/dist/index24.vue.d.ts +13 -4
- package/dist/index25.vue.d.ts +4 -2
- package/dist/index26.vue.d.ts +2 -2
- package/dist/index27.vue.d.ts +3 -3
- package/dist/index28.vue.d.ts +4 -4
- package/dist/index3.vue.d.ts +1 -1
- package/dist/index4.vue.d.ts +4 -4
- package/dist/index6.vue.d.ts +3 -3
- package/dist/index7.vue.d.ts +7 -5
- package/dist/resolver.cjs +1 -1
- package/dist/resolver.cjs.map +1 -1
- package/dist/resolver.d.cts +2 -21
- package/dist/resolver.d.ts +2 -21
- package/dist/resolver.js +1 -1
- package/dist/resolver.js.map +1 -1
- package/dist/style.css +1991 -1991
- package/dist/useCalendarEvents.d.ts +8 -5
- package/dist/useCollapsePanel.d.ts +2 -2
- package/dist/useCropperCore.d.ts +6 -6
- package/dist/useDraggableLayout.d.ts +3 -3
- package/dist/useDynamicFormState.d.ts +31 -3726
- package/dist/useEdgeInteraction.d.ts +2 -2
- package/dist/useFullscreen.d.ts +2 -2
- package/dist/useInfiniteScroll.d.ts +2 -2
- package/dist/useModalEdit.d.ts +6 -6
- package/dist/useQRCode.d.ts +5 -5
- package/dist/useSignatureHistory.d.ts +2 -2
- package/dist/useSplitResize.d.ts +6 -6
- package/dist/useTimeSelection.d.ts +3 -3
- package/dist/useTreeOperations.d.ts +5 -5
- package/dist/useWorkflowValidation.d.ts +3 -3
- package/package.json +12 -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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_AudioPlayer2.js","names":[],"sources":["../src/components/C_AudioPlayer/types.ts","../src/components/C_AudioPlayer/index.vue"],"sourcesContent":["/**\n * @Description: Audio player component type definitions\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\n */\n\n/** Single audio track */\nexport interface AudioTrack {\n /** Unique identifier */\n id: string | number\n /** Track title */\n title: string\n /** Artist / author */\n artist?: string\n /** Audio source URL */\n src: string\n /** Cover image URL */\n cover?: string\n /** Duration in seconds (optional, for static display) */\n duration?: number\n /** Extra data */\n extra?: Record<string, unknown>\n}\n\n/** Component props */\nexport interface AudioPlayerProps {\n /** Playlist */\n tracks: AudioTrack[]\n /** Initial active index */\n initialIndex?: number\n /** Whether to show the playlist panel */\n showPlaylist?: boolean\n /** Whether to show the cover art */\n showCover?: boolean\n /** Whether to auto-play on mount */\n autoplay?: boolean\n /** Playback mode */\n mode?: 'list' | 'loop' | 'single' | 'shuffle'\n /** Theme appearance */\n theme?: 'default' | 'minimal'\n}\n\n/** Default props */\nexport const DEFAULT_AUDIO_PLAYER_PROPS: Partial<AudioPlayerProps> = {\n initialIndex: 0,\n showPlaylist: true,\n showCover: true,\n autoplay: false,\n mode: 'list',\n theme: 'default',\n}\n\n/** Playback mode icon map */\nexport const MODE_ICON_MAP: Record<string, { icon: string; label: string }> = {\n list: { icon: 'mdi:repeat', label: 'List Loop' },\n loop: { icon: 'mdi:repeat-once', label: 'Single Loop' },\n single: { icon: 'mdi:numeric-1-box', label: 'Play Once' },\n shuffle: { icon: 'mdi:shuffle-variant', label: 'Shuffle' },\n}\n\n/** Format seconds to mm:ss */\nexport function formatTime(seconds: number): string {\n if (!Number.isFinite(seconds) || seconds < 0) return '00:00'\n const m = Math.floor(seconds / 60)\n const s = Math.floor(seconds % 60)\n return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`\n}\n","<!--\n * @Description: 音频播放器组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-audio-player\"\n :class=\"{ 'is-minimal': theme === 'minimal' }\"\n >\n <!-- ================ Now Playing ================ -->\n <div class=\"c-audio-player__now-playing\">\n <div\n v-if=\"showCover\"\n class=\"c-audio-player__cover\"\n >\n <img\n v-if=\"currentTrack?.cover\"\n :src=\"currentTrack.cover\"\n :alt=\"currentTrack.title\"\n />\n <C_Icon\n v-else\n name=\"mdi:music-note\"\n class=\"c-audio-player__cover-placeholder\"\n />\n </div>\n <div class=\"c-audio-player__info\">\n <div class=\"c-audio-player__title\">{{\n currentTrack?.title ?? '未选择曲目'\n }}</div>\n <div\n v-if=\"currentTrack?.artist\"\n class=\"c-audio-player__artist\"\n >\n {{ currentTrack.artist }}\n </div>\n </div>\n </div>\n\n <!-- ================ Progress ================ -->\n <div\n v-if=\"theme !== 'minimal'\"\n class=\"c-audio-player__progress\"\n >\n <div\n class=\"c-audio-player__progress-bar\"\n @click=\"seekByClick\"\n >\n <div\n class=\"c-audio-player__progress-fill\"\n :style=\"{ width: `${progressPercent}%` }\"\n />\n </div>\n <div class=\"c-audio-player__time\">\n <span>{{ formatTime(currentTime) }}</span>\n <span>{{ formatTime(totalDuration) }}</span>\n </div>\n </div>\n\n <!-- ================ Controls ================ -->\n <div class=\"c-audio-player__controls\">\n <button\n class=\"c-audio-player__ctrl-btn is-mode\"\n :title=\"currentModeLabel\"\n @click=\"cycleMode\"\n >\n <C_Icon :name=\"currentModeIcon\" />\n </button>\n <button\n class=\"c-audio-player__ctrl-btn is-skip\"\n title=\"上一曲\"\n @click=\"prev\"\n >\n <C_Icon name=\"mdi:skip-previous\" />\n </button>\n <button\n class=\"c-audio-player__ctrl-btn is-play\"\n :title=\"isPlaying ? '暂停' : '播放'\"\n @click=\"togglePlay\"\n >\n <C_Icon :name=\"isPlaying ? 'mdi:pause' : 'mdi:play'\" />\n </button>\n <button\n class=\"c-audio-player__ctrl-btn is-skip\"\n title=\"下一曲\"\n @click=\"next\"\n >\n <C_Icon name=\"mdi:skip-next\" />\n </button>\n <button\n class=\"c-audio-player__ctrl-btn is-mode\"\n title=\"播放列表\"\n @click=\"playlistVisible = !playlistVisible\"\n >\n <C_Icon name=\"mdi:playlist-music\" />\n </button>\n </div>\n\n <!-- ================ Volume ================ -->\n <div\n v-if=\"theme !== 'minimal'\"\n class=\"c-audio-player__volume\"\n >\n <C_Icon\n :name=\"volumeIcon\"\n class=\"c-audio-player__volume-icon\"\n @click=\"toggleMute\"\n />\n <NSlider\n v-model:value=\"volume\"\n :min=\"0\"\n :max=\"100\"\n :step=\"1\"\n class=\"c-audio-player__volume-slider\"\n @update:value=\"handleVolumeChange\"\n />\n </div>\n\n <!-- ================ Playlist ================ -->\n <div\n v-if=\"showPlaylist && playlistVisible && theme !== 'minimal'\"\n class=\"c-audio-player__playlist\"\n >\n <div class=\"c-audio-player__playlist-header\">\n <span>播放列表</span>\n <span>{{ tracks.length }} 首</span>\n </div>\n <div\n v-for=\"(track, idx) in tracks\"\n :key=\"track.id\"\n class=\"c-audio-player__track\"\n :class=\"{ 'is-active': idx === activeIndex }\"\n @click=\"playTrack(idx)\"\n >\n <span class=\"c-audio-player__track-index\">\n <C_Icon\n v-if=\"idx === activeIndex && isPlaying\"\n name=\"mdi:volume-high\"\n />\n <template v-else>{{ idx + 1 }}</template>\n </span>\n <div class=\"c-audio-player__track-info\">\n <div class=\"c-audio-player__track-title\">{{ track.title }}</div>\n <div\n v-if=\"track.artist\"\n class=\"c-audio-player__track-artist\"\n >\n {{ track.artist }}\n </div>\n </div>\n <span\n v-if=\"track.duration\"\n class=\"c-audio-player__track-duration\"\n >\n {{ formatTime(track.duration) }}\n </span>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed, onBeforeUnmount, ref, watch } from 'vue'\n import C_Icon from '../C_Icon/index.vue'\n import {\n DEFAULT_AUDIO_PLAYER_PROPS,\n formatTime,\n MODE_ICON_MAP,\n type AudioPlayerProps,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n tracks: AudioPlayerProps['tracks']\n initialIndex?: number\n showPlaylist?: boolean\n showCover?: boolean\n autoplay?: boolean\n mode?: AudioPlayerProps['mode']\n theme?: AudioPlayerProps['theme']\n }>(),\n {\n initialIndex: DEFAULT_AUDIO_PLAYER_PROPS.initialIndex,\n showPlaylist: DEFAULT_AUDIO_PLAYER_PROPS.showPlaylist,\n showCover: true,\n autoplay: DEFAULT_AUDIO_PLAYER_PROPS.autoplay,\n mode: DEFAULT_AUDIO_PLAYER_PROPS.mode,\n theme: DEFAULT_AUDIO_PLAYER_PROPS.theme,\n }\n )\n\n const emit = defineEmits<{\n play: [index: number]\n pause: []\n ended: [index: number]\n modeChange: [mode: string]\n }>()\n\n // ==================== Audio Core ====================\n\n let audio: HTMLAudioElement | null = null\n\n const activeIndex = ref(props.initialIndex ?? 0)\n const isPlaying = ref(false)\n const currentTime = ref(0)\n const totalDuration = ref(0)\n const volume = ref(70)\n const prevVolume = ref(70)\n const playlistVisible = ref(props.showPlaylist)\n const playMode = ref(props.mode ?? 'list')\n\n const currentTrack = computed(() => props.tracks[activeIndex.value])\n\n const progressPercent = computed(() => {\n if (totalDuration.value === 0) return 0\n return (currentTime.value / totalDuration.value) * 100\n })\n\n const volumeIcon = computed(() => {\n if (volume.value === 0) return 'mdi:volume-off'\n if (volume.value < 40) return 'mdi:volume-low'\n if (volume.value < 70) return 'mdi:volume-medium'\n return 'mdi:volume-high'\n })\n\n const currentModeIcon = computed(\n () => MODE_ICON_MAP[playMode.value]?.icon ?? 'mdi:repeat'\n )\n const currentModeLabel = computed(\n () => MODE_ICON_MAP[playMode.value]?.label ?? '循环'\n )\n\n /** 初始化音频实例 */\n function initAudio() {\n if (audio) {\n audio.pause()\n audio.removeEventListener('timeupdate', onTimeUpdate)\n audio.removeEventListener('loadedmetadata', onMetaLoaded)\n audio.removeEventListener('ended', onEnded)\n }\n const track = currentTrack.value\n if (!track) return\n\n audio = new Audio(track.src)\n audio.volume = volume.value / 100\n audio.addEventListener('timeupdate', onTimeUpdate)\n audio.addEventListener('loadedmetadata', onMetaLoaded)\n audio.addEventListener('ended', onEnded)\n }\n\n /** 播放进度更新回调 */\n function onTimeUpdate() {\n if (audio) currentTime.value = audio.currentTime\n }\n\n /** 音频元数据加载完成回调 */\n function onMetaLoaded() {\n if (audio) totalDuration.value = audio.duration\n }\n\n /** 播放结束回调,根据模式决定下一步 */\n function onEnded() {\n emit('ended', activeIndex.value)\n switch (playMode.value) {\n case 'loop':\n audio?.play().catch(() => {})\n break\n case 'single':\n isPlaying.value = false\n break\n case 'shuffle':\n playTrack(Math.floor(Math.random() * props.tracks.length))\n break\n default: // list\n if (activeIndex.value < props.tracks.length - 1) next()\n else {\n activeIndex.value = 0\n initAudio()\n audio?.play().catch(() => {})\n }\n }\n }\n\n /** 切换播放/暂停 */\n function togglePlay() {\n if (!audio) initAudio()\n if (isPlaying.value) {\n audio?.pause()\n isPlaying.value = false\n emit('pause')\n } else {\n audio?.play().catch(() => {})\n isPlaying.value = true\n emit('play', activeIndex.value)\n }\n }\n\n /** 播放指定索引的曲目 */\n function playTrack(idx: number) {\n activeIndex.value = idx\n initAudio()\n audio?.play().catch(() => {})\n isPlaying.value = true\n emit('play', idx)\n }\n\n /** 上一曲 */\n function prev() {\n const idx =\n activeIndex.value <= 0 ? props.tracks.length - 1 : activeIndex.value - 1\n playTrack(idx)\n }\n\n /** 下一曲 */\n function next() {\n const idx =\n activeIndex.value >= props.tracks.length - 1 ? 0 : activeIndex.value + 1\n playTrack(idx)\n }\n\n /** 点击进度条跳转播放位置 */\n function seekByClick(e: MouseEvent) {\n if (!audio || !totalDuration.value) return\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width))\n audio.currentTime = ratio * totalDuration.value\n currentTime.value = audio.currentTime\n }\n\n /** 处理音量变更 */\n function handleVolumeChange(val: number) {\n volume.value = val\n if (audio) audio.volume = val / 100\n }\n\n /** 切换静音状态 */\n function toggleMute() {\n if (volume.value > 0) {\n prevVolume.value = volume.value\n volume.value = 0\n } else {\n volume.value = prevVolume.value || 70\n }\n if (audio) audio.volume = volume.value / 100\n }\n\n const MODES = ['list', 'loop', 'single', 'shuffle'] as const\n /** 循环切换播放模式 */\n function cycleMode() {\n const idx = MODES.indexOf(playMode.value as (typeof MODES)[number])\n playMode.value = MODES[(idx + 1) % MODES.length]\n emit('modeChange', playMode.value)\n }\n\n // ==================== Lifecycle ====================\n\n watch(\n () => props.tracks,\n () => {\n activeIndex.value = 0\n initAudio()\n }\n )\n\n watch(\n () => props.initialIndex,\n val => {\n if (val !== undefined && val !== activeIndex.value) {\n activeIndex.value = val\n initAudio()\n }\n }\n )\n\n onBeforeUnmount(() => {\n if (audio) {\n audio.pause()\n audio.removeEventListener('timeupdate', onTimeUpdate)\n audio.removeEventListener('loadedmetadata', onMetaLoaded)\n audio.removeEventListener('ended', onEnded)\n audio = null\n }\n })\n\n // 自动播放\n if (props.autoplay && props.tracks.length > 0) {\n playTrack(activeIndex.value)\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"C_AudioPlayer2.js","names":["theme","showCover","showPlaylist","tracks"],"sources":["../src/components/C_AudioPlayer/types.ts","../src/components/C_AudioPlayer/index.vue","../src/components/C_AudioPlayer/index.vue"],"sourcesContent":["/**\n * @Description: Audio player component type definitions\n * Copyright (c) 2026 by CHENY, All Rights Reserved.\n */\n\n/** Single audio track */\nexport interface AudioTrack {\n /** Unique identifier */\n id: string | number\n /** Track title */\n title: string\n /** Artist / author */\n artist?: string\n /** Audio source URL */\n src: string\n /** Cover image URL */\n cover?: string\n /** Duration in seconds (optional, for static display) */\n duration?: number\n /** Extra data */\n extra?: Record<string, unknown>\n}\n\n/** Component props */\nexport interface AudioPlayerProps {\n /** Playlist */\n tracks: AudioTrack[]\n /** Initial active index */\n initialIndex?: number\n /** Whether to show the playlist panel */\n showPlaylist?: boolean\n /** Whether to show the cover art */\n showCover?: boolean\n /** Whether to auto-play on mount */\n autoplay?: boolean\n /** Playback mode */\n mode?: 'list' | 'loop' | 'single' | 'shuffle'\n /** Theme appearance */\n theme?: 'default' | 'minimal'\n}\n\n/** Default props */\nexport const DEFAULT_AUDIO_PLAYER_PROPS: Partial<AudioPlayerProps> = {\n initialIndex: 0,\n showPlaylist: true,\n showCover: true,\n autoplay: false,\n mode: 'list',\n theme: 'default',\n}\n\n/** Playback mode icon map */\nexport const MODE_ICON_MAP: Record<string, { icon: string; label: string }> = {\n list: { icon: 'mdi:repeat', label: 'List Loop' },\n loop: { icon: 'mdi:repeat-once', label: 'Single Loop' },\n single: { icon: 'mdi:numeric-1-box', label: 'Play Once' },\n shuffle: { icon: 'mdi:shuffle-variant', label: 'Shuffle' },\n}\n\n/** Format seconds to mm:ss */\nexport function formatTime(seconds: number): string {\n if (!Number.isFinite(seconds) || seconds < 0) return '00:00'\n const m = Math.floor(seconds / 60)\n const s = Math.floor(seconds % 60)\n return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`\n}\n","<!--\n * @Description: 音频播放器组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-audio-player\"\n :class=\"{ 'is-minimal': theme === 'minimal' }\"\n >\n <!-- ================ Now Playing ================ -->\n <div class=\"c-audio-player__now-playing\">\n <div\n v-if=\"showCover\"\n class=\"c-audio-player__cover\"\n >\n <img\n v-if=\"currentTrack?.cover\"\n :src=\"currentTrack.cover\"\n :alt=\"currentTrack.title\"\n />\n <C_Icon\n v-else\n name=\"mdi:music-note\"\n class=\"c-audio-player__cover-placeholder\"\n />\n </div>\n <div class=\"c-audio-player__info\">\n <div class=\"c-audio-player__title\">{{\n currentTrack?.title ?? '未选择曲目'\n }}</div>\n <div\n v-if=\"currentTrack?.artist\"\n class=\"c-audio-player__artist\"\n >\n {{ currentTrack.artist }}\n </div>\n </div>\n </div>\n\n <!-- ================ Progress ================ -->\n <div\n v-if=\"theme !== 'minimal'\"\n class=\"c-audio-player__progress\"\n >\n <div\n class=\"c-audio-player__progress-bar\"\n @click=\"seekByClick\"\n >\n <div\n class=\"c-audio-player__progress-fill\"\n :style=\"{ width: `${progressPercent}%` }\"\n />\n </div>\n <div class=\"c-audio-player__time\">\n <span>{{ formatTime(currentTime) }}</span>\n <span>{{ formatTime(totalDuration) }}</span>\n </div>\n </div>\n\n <!-- ================ Controls ================ -->\n <div class=\"c-audio-player__controls\">\n <button\n class=\"c-audio-player__ctrl-btn is-mode\"\n :title=\"currentModeLabel\"\n @click=\"cycleMode\"\n >\n <C_Icon :name=\"currentModeIcon\" />\n </button>\n <button\n class=\"c-audio-player__ctrl-btn is-skip\"\n title=\"上一曲\"\n @click=\"prev\"\n >\n <C_Icon name=\"mdi:skip-previous\" />\n </button>\n <button\n class=\"c-audio-player__ctrl-btn is-play\"\n :title=\"isPlaying ? '暂停' : '播放'\"\n @click=\"togglePlay\"\n >\n <C_Icon :name=\"isPlaying ? 'mdi:pause' : 'mdi:play'\" />\n </button>\n <button\n class=\"c-audio-player__ctrl-btn is-skip\"\n title=\"下一曲\"\n @click=\"next\"\n >\n <C_Icon name=\"mdi:skip-next\" />\n </button>\n <button\n class=\"c-audio-player__ctrl-btn is-mode\"\n title=\"播放列表\"\n @click=\"playlistVisible = !playlistVisible\"\n >\n <C_Icon name=\"mdi:playlist-music\" />\n </button>\n </div>\n\n <!-- ================ Volume ================ -->\n <div\n v-if=\"theme !== 'minimal'\"\n class=\"c-audio-player__volume\"\n >\n <C_Icon\n :name=\"volumeIcon\"\n class=\"c-audio-player__volume-icon\"\n @click=\"toggleMute\"\n />\n <NSlider\n v-model:value=\"volume\"\n :min=\"0\"\n :max=\"100\"\n :step=\"1\"\n class=\"c-audio-player__volume-slider\"\n @update:value=\"handleVolumeChange\"\n />\n </div>\n\n <!-- ================ Playlist ================ -->\n <div\n v-if=\"showPlaylist && playlistVisible && theme !== 'minimal'\"\n class=\"c-audio-player__playlist\"\n >\n <div class=\"c-audio-player__playlist-header\">\n <span>播放列表</span>\n <span>{{ tracks.length }} 首</span>\n </div>\n <div\n v-for=\"(track, idx) in tracks\"\n :key=\"track.id\"\n class=\"c-audio-player__track\"\n :class=\"{ 'is-active': idx === activeIndex }\"\n @click=\"playTrack(idx)\"\n >\n <span class=\"c-audio-player__track-index\">\n <C_Icon\n v-if=\"idx === activeIndex && isPlaying\"\n name=\"mdi:volume-high\"\n />\n <template v-else>{{ idx + 1 }}</template>\n </span>\n <div class=\"c-audio-player__track-info\">\n <div class=\"c-audio-player__track-title\">{{ track.title }}</div>\n <div\n v-if=\"track.artist\"\n class=\"c-audio-player__track-artist\"\n >\n {{ track.artist }}\n </div>\n </div>\n <span\n v-if=\"track.duration\"\n class=\"c-audio-player__track-duration\"\n >\n {{ formatTime(track.duration) }}\n </span>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed, onBeforeUnmount, ref, watch } from 'vue'\n import C_Icon from '../C_Icon/index.vue'\n import {\n DEFAULT_AUDIO_PLAYER_PROPS,\n formatTime,\n MODE_ICON_MAP,\n type AudioPlayerProps,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n tracks: AudioPlayerProps['tracks']\n initialIndex?: number\n showPlaylist?: boolean\n showCover?: boolean\n autoplay?: boolean\n mode?: AudioPlayerProps['mode']\n theme?: AudioPlayerProps['theme']\n }>(),\n {\n initialIndex: DEFAULT_AUDIO_PLAYER_PROPS.initialIndex,\n showPlaylist: DEFAULT_AUDIO_PLAYER_PROPS.showPlaylist,\n showCover: true,\n autoplay: DEFAULT_AUDIO_PLAYER_PROPS.autoplay,\n mode: DEFAULT_AUDIO_PLAYER_PROPS.mode,\n theme: DEFAULT_AUDIO_PLAYER_PROPS.theme,\n }\n )\n\n const emit = defineEmits<{\n play: [index: number]\n pause: []\n ended: [index: number]\n modeChange: [mode: string]\n }>()\n\n // ==================== Audio Core ====================\n\n let audio: HTMLAudioElement | null = null\n\n const activeIndex = ref(props.initialIndex ?? 0)\n const isPlaying = ref(false)\n const currentTime = ref(0)\n const totalDuration = ref(0)\n const volume = ref(70)\n const prevVolume = ref(70)\n const playlistVisible = ref(props.showPlaylist)\n const playMode = ref(props.mode ?? 'list')\n\n const currentTrack = computed(() => props.tracks[activeIndex.value])\n\n const progressPercent = computed(() => {\n if (totalDuration.value === 0) return 0\n return (currentTime.value / totalDuration.value) * 100\n })\n\n const volumeIcon = computed(() => {\n if (volume.value === 0) return 'mdi:volume-off'\n if (volume.value < 40) return 'mdi:volume-low'\n if (volume.value < 70) return 'mdi:volume-medium'\n return 'mdi:volume-high'\n })\n\n const currentModeIcon = computed(\n () => MODE_ICON_MAP[playMode.value]?.icon ?? 'mdi:repeat'\n )\n const currentModeLabel = computed(\n () => MODE_ICON_MAP[playMode.value]?.label ?? '循环'\n )\n\n /** 初始化音频实例 */\n function initAudio() {\n if (audio) {\n audio.pause()\n audio.removeEventListener('timeupdate', onTimeUpdate)\n audio.removeEventListener('loadedmetadata', onMetaLoaded)\n audio.removeEventListener('ended', onEnded)\n }\n const track = currentTrack.value\n if (!track) return\n\n audio = new Audio(track.src)\n audio.volume = volume.value / 100\n audio.addEventListener('timeupdate', onTimeUpdate)\n audio.addEventListener('loadedmetadata', onMetaLoaded)\n audio.addEventListener('ended', onEnded)\n }\n\n /** 播放进度更新回调 */\n function onTimeUpdate() {\n if (audio) currentTime.value = audio.currentTime\n }\n\n /** 音频元数据加载完成回调 */\n function onMetaLoaded() {\n if (audio) totalDuration.value = audio.duration\n }\n\n /** 播放结束回调,根据模式决定下一步 */\n function onEnded() {\n emit('ended', activeIndex.value)\n switch (playMode.value) {\n case 'loop':\n audio?.play().catch(() => {})\n break\n case 'single':\n isPlaying.value = false\n break\n case 'shuffle':\n playTrack(Math.floor(Math.random() * props.tracks.length))\n break\n default: // list\n if (activeIndex.value < props.tracks.length - 1) next()\n else {\n activeIndex.value = 0\n initAudio()\n audio?.play().catch(() => {})\n }\n }\n }\n\n /** 切换播放/暂停 */\n function togglePlay() {\n if (!audio) initAudio()\n if (isPlaying.value) {\n audio?.pause()\n isPlaying.value = false\n emit('pause')\n } else {\n audio?.play().catch(() => {})\n isPlaying.value = true\n emit('play', activeIndex.value)\n }\n }\n\n /** 播放指定索引的曲目 */\n function playTrack(idx: number) {\n activeIndex.value = idx\n initAudio()\n audio?.play().catch(() => {})\n isPlaying.value = true\n emit('play', idx)\n }\n\n /** 上一曲 */\n function prev() {\n const idx =\n activeIndex.value <= 0 ? props.tracks.length - 1 : activeIndex.value - 1\n playTrack(idx)\n }\n\n /** 下一曲 */\n function next() {\n const idx =\n activeIndex.value >= props.tracks.length - 1 ? 0 : activeIndex.value + 1\n playTrack(idx)\n }\n\n /** 点击进度条跳转播放位置 */\n function seekByClick(e: MouseEvent) {\n if (!audio || !totalDuration.value) return\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width))\n audio.currentTime = ratio * totalDuration.value\n currentTime.value = audio.currentTime\n }\n\n /** 处理音量变更 */\n function handleVolumeChange(val: number) {\n volume.value = val\n if (audio) audio.volume = val / 100\n }\n\n /** 切换静音状态 */\n function toggleMute() {\n if (volume.value > 0) {\n prevVolume.value = volume.value\n volume.value = 0\n } else {\n volume.value = prevVolume.value || 70\n }\n if (audio) audio.volume = volume.value / 100\n }\n\n const MODES = ['list', 'loop', 'single', 'shuffle'] as const\n /** 循环切换播放模式 */\n function cycleMode() {\n const idx = MODES.indexOf(playMode.value as (typeof MODES)[number])\n playMode.value = MODES[(idx + 1) % MODES.length]\n emit('modeChange', playMode.value)\n }\n\n // ==================== Lifecycle ====================\n\n watch(\n () => props.tracks,\n () => {\n activeIndex.value = 0\n initAudio()\n }\n )\n\n watch(\n () => props.initialIndex,\n val => {\n if (val !== undefined && val !== activeIndex.value) {\n activeIndex.value = val\n initAudio()\n }\n }\n )\n\n onBeforeUnmount(() => {\n if (audio) {\n audio.pause()\n audio.removeEventListener('timeupdate', onTimeUpdate)\n audio.removeEventListener('loadedmetadata', onMetaLoaded)\n audio.removeEventListener('ended', onEnded)\n audio = null\n }\n })\n\n // 自动播放\n if (props.autoplay && props.tracks.length > 0) {\n playTrack(activeIndex.value)\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n","<!--\n * @Description: 音频播放器组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-audio-player\"\n :class=\"{ 'is-minimal': theme === 'minimal' }\"\n >\n <!-- ================ Now Playing ================ -->\n <div class=\"c-audio-player__now-playing\">\n <div\n v-if=\"showCover\"\n class=\"c-audio-player__cover\"\n >\n <img\n v-if=\"currentTrack?.cover\"\n :src=\"currentTrack.cover\"\n :alt=\"currentTrack.title\"\n />\n <C_Icon\n v-else\n name=\"mdi:music-note\"\n class=\"c-audio-player__cover-placeholder\"\n />\n </div>\n <div class=\"c-audio-player__info\">\n <div class=\"c-audio-player__title\">{{\n currentTrack?.title ?? '未选择曲目'\n }}</div>\n <div\n v-if=\"currentTrack?.artist\"\n class=\"c-audio-player__artist\"\n >\n {{ currentTrack.artist }}\n </div>\n </div>\n </div>\n\n <!-- ================ Progress ================ -->\n <div\n v-if=\"theme !== 'minimal'\"\n class=\"c-audio-player__progress\"\n >\n <div\n class=\"c-audio-player__progress-bar\"\n @click=\"seekByClick\"\n >\n <div\n class=\"c-audio-player__progress-fill\"\n :style=\"{ width: `${progressPercent}%` }\"\n />\n </div>\n <div class=\"c-audio-player__time\">\n <span>{{ formatTime(currentTime) }}</span>\n <span>{{ formatTime(totalDuration) }}</span>\n </div>\n </div>\n\n <!-- ================ Controls ================ -->\n <div class=\"c-audio-player__controls\">\n <button\n class=\"c-audio-player__ctrl-btn is-mode\"\n :title=\"currentModeLabel\"\n @click=\"cycleMode\"\n >\n <C_Icon :name=\"currentModeIcon\" />\n </button>\n <button\n class=\"c-audio-player__ctrl-btn is-skip\"\n title=\"上一曲\"\n @click=\"prev\"\n >\n <C_Icon name=\"mdi:skip-previous\" />\n </button>\n <button\n class=\"c-audio-player__ctrl-btn is-play\"\n :title=\"isPlaying ? '暂停' : '播放'\"\n @click=\"togglePlay\"\n >\n <C_Icon :name=\"isPlaying ? 'mdi:pause' : 'mdi:play'\" />\n </button>\n <button\n class=\"c-audio-player__ctrl-btn is-skip\"\n title=\"下一曲\"\n @click=\"next\"\n >\n <C_Icon name=\"mdi:skip-next\" />\n </button>\n <button\n class=\"c-audio-player__ctrl-btn is-mode\"\n title=\"播放列表\"\n @click=\"playlistVisible = !playlistVisible\"\n >\n <C_Icon name=\"mdi:playlist-music\" />\n </button>\n </div>\n\n <!-- ================ Volume ================ -->\n <div\n v-if=\"theme !== 'minimal'\"\n class=\"c-audio-player__volume\"\n >\n <C_Icon\n :name=\"volumeIcon\"\n class=\"c-audio-player__volume-icon\"\n @click=\"toggleMute\"\n />\n <NSlider\n v-model:value=\"volume\"\n :min=\"0\"\n :max=\"100\"\n :step=\"1\"\n class=\"c-audio-player__volume-slider\"\n @update:value=\"handleVolumeChange\"\n />\n </div>\n\n <!-- ================ Playlist ================ -->\n <div\n v-if=\"showPlaylist && playlistVisible && theme !== 'minimal'\"\n class=\"c-audio-player__playlist\"\n >\n <div class=\"c-audio-player__playlist-header\">\n <span>播放列表</span>\n <span>{{ tracks.length }} 首</span>\n </div>\n <div\n v-for=\"(track, idx) in tracks\"\n :key=\"track.id\"\n class=\"c-audio-player__track\"\n :class=\"{ 'is-active': idx === activeIndex }\"\n @click=\"playTrack(idx)\"\n >\n <span class=\"c-audio-player__track-index\">\n <C_Icon\n v-if=\"idx === activeIndex && isPlaying\"\n name=\"mdi:volume-high\"\n />\n <template v-else>{{ idx + 1 }}</template>\n </span>\n <div class=\"c-audio-player__track-info\">\n <div class=\"c-audio-player__track-title\">{{ track.title }}</div>\n <div\n v-if=\"track.artist\"\n class=\"c-audio-player__track-artist\"\n >\n {{ track.artist }}\n </div>\n </div>\n <span\n v-if=\"track.duration\"\n class=\"c-audio-player__track-duration\"\n >\n {{ formatTime(track.duration) }}\n </span>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed, onBeforeUnmount, ref, watch } from 'vue'\n import C_Icon from '../C_Icon/index.vue'\n import {\n DEFAULT_AUDIO_PLAYER_PROPS,\n formatTime,\n MODE_ICON_MAP,\n type AudioPlayerProps,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n tracks: AudioPlayerProps['tracks']\n initialIndex?: number\n showPlaylist?: boolean\n showCover?: boolean\n autoplay?: boolean\n mode?: AudioPlayerProps['mode']\n theme?: AudioPlayerProps['theme']\n }>(),\n {\n initialIndex: DEFAULT_AUDIO_PLAYER_PROPS.initialIndex,\n showPlaylist: DEFAULT_AUDIO_PLAYER_PROPS.showPlaylist,\n showCover: true,\n autoplay: DEFAULT_AUDIO_PLAYER_PROPS.autoplay,\n mode: DEFAULT_AUDIO_PLAYER_PROPS.mode,\n theme: DEFAULT_AUDIO_PLAYER_PROPS.theme,\n }\n )\n\n const emit = defineEmits<{\n play: [index: number]\n pause: []\n ended: [index: number]\n modeChange: [mode: string]\n }>()\n\n // ==================== Audio Core ====================\n\n let audio: HTMLAudioElement | null = null\n\n const activeIndex = ref(props.initialIndex ?? 0)\n const isPlaying = ref(false)\n const currentTime = ref(0)\n const totalDuration = ref(0)\n const volume = ref(70)\n const prevVolume = ref(70)\n const playlistVisible = ref(props.showPlaylist)\n const playMode = ref(props.mode ?? 'list')\n\n const currentTrack = computed(() => props.tracks[activeIndex.value])\n\n const progressPercent = computed(() => {\n if (totalDuration.value === 0) return 0\n return (currentTime.value / totalDuration.value) * 100\n })\n\n const volumeIcon = computed(() => {\n if (volume.value === 0) return 'mdi:volume-off'\n if (volume.value < 40) return 'mdi:volume-low'\n if (volume.value < 70) return 'mdi:volume-medium'\n return 'mdi:volume-high'\n })\n\n const currentModeIcon = computed(\n () => MODE_ICON_MAP[playMode.value]?.icon ?? 'mdi:repeat'\n )\n const currentModeLabel = computed(\n () => MODE_ICON_MAP[playMode.value]?.label ?? '循环'\n )\n\n /** 初始化音频实例 */\n function initAudio() {\n if (audio) {\n audio.pause()\n audio.removeEventListener('timeupdate', onTimeUpdate)\n audio.removeEventListener('loadedmetadata', onMetaLoaded)\n audio.removeEventListener('ended', onEnded)\n }\n const track = currentTrack.value\n if (!track) return\n\n audio = new Audio(track.src)\n audio.volume = volume.value / 100\n audio.addEventListener('timeupdate', onTimeUpdate)\n audio.addEventListener('loadedmetadata', onMetaLoaded)\n audio.addEventListener('ended', onEnded)\n }\n\n /** 播放进度更新回调 */\n function onTimeUpdate() {\n if (audio) currentTime.value = audio.currentTime\n }\n\n /** 音频元数据加载完成回调 */\n function onMetaLoaded() {\n if (audio) totalDuration.value = audio.duration\n }\n\n /** 播放结束回调,根据模式决定下一步 */\n function onEnded() {\n emit('ended', activeIndex.value)\n switch (playMode.value) {\n case 'loop':\n audio?.play().catch(() => {})\n break\n case 'single':\n isPlaying.value = false\n break\n case 'shuffle':\n playTrack(Math.floor(Math.random() * props.tracks.length))\n break\n default: // list\n if (activeIndex.value < props.tracks.length - 1) next()\n else {\n activeIndex.value = 0\n initAudio()\n audio?.play().catch(() => {})\n }\n }\n }\n\n /** 切换播放/暂停 */\n function togglePlay() {\n if (!audio) initAudio()\n if (isPlaying.value) {\n audio?.pause()\n isPlaying.value = false\n emit('pause')\n } else {\n audio?.play().catch(() => {})\n isPlaying.value = true\n emit('play', activeIndex.value)\n }\n }\n\n /** 播放指定索引的曲目 */\n function playTrack(idx: number) {\n activeIndex.value = idx\n initAudio()\n audio?.play().catch(() => {})\n isPlaying.value = true\n emit('play', idx)\n }\n\n /** 上一曲 */\n function prev() {\n const idx =\n activeIndex.value <= 0 ? props.tracks.length - 1 : activeIndex.value - 1\n playTrack(idx)\n }\n\n /** 下一曲 */\n function next() {\n const idx =\n activeIndex.value >= props.tracks.length - 1 ? 0 : activeIndex.value + 1\n playTrack(idx)\n }\n\n /** 点击进度条跳转播放位置 */\n function seekByClick(e: MouseEvent) {\n if (!audio || !totalDuration.value) return\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width))\n audio.currentTime = ratio * totalDuration.value\n currentTime.value = audio.currentTime\n }\n\n /** 处理音量变更 */\n function handleVolumeChange(val: number) {\n volume.value = val\n if (audio) audio.volume = val / 100\n }\n\n /** 切换静音状态 */\n function toggleMute() {\n if (volume.value > 0) {\n prevVolume.value = volume.value\n volume.value = 0\n } else {\n volume.value = prevVolume.value || 70\n }\n if (audio) audio.volume = volume.value / 100\n }\n\n const MODES = ['list', 'loop', 'single', 'shuffle'] as const\n /** 循环切换播放模式 */\n function cycleMode() {\n const idx = MODES.indexOf(playMode.value as (typeof MODES)[number])\n playMode.value = MODES[(idx + 1) % MODES.length]\n emit('modeChange', playMode.value)\n }\n\n // ==================== Lifecycle ====================\n\n watch(\n () => props.tracks,\n () => {\n activeIndex.value = 0\n initAudio()\n }\n )\n\n watch(\n () => props.initialIndex,\n val => {\n if (val !== undefined && val !== activeIndex.value) {\n activeIndex.value = val\n initAudio()\n }\n }\n )\n\n onBeforeUnmount(() => {\n if (audio) {\n audio.pause()\n audio.removeEventListener('timeupdate', onTimeUpdate)\n audio.removeEventListener('loadedmetadata', onMetaLoaded)\n audio.removeEventListener('ended', onEnded)\n audio = null\n }\n })\n\n // 自动播放\n if (props.autoplay && props.tracks.length > 0) {\n playTrack(activeIndex.value)\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_AvatarGroup-
|
|
1
|
+
{"version":3,"file":"C_AvatarGroup-B9d-GJ9c.css","names":[],"sources":["../src/components/C_AvatarGroup/index.vue?vue&type=style&index=0&scoped=e9981c87&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled *//**\n * C_AvatarGroup — 头像组组件样式\n */\n.c-avatar-group[data-v-e9981c87] {\n display: inline-flex;\n align-items: center;\n /* ======================== 单个头像 ======================== */\n /* ---- 头像图片 ---- */\n /* ---- 首字母 fallback ---- */\n /* ---- 状态指示点 ---- */\n /* ======================== 溢出 +N ======================== */\n}\n.c-avatar-group.is-rtl[data-v-e9981c87] {\n flex-direction: row-reverse;\n}\n.c-avatar-group__item[data-v-e9981c87] {\n position: relative;\n flex-shrink: 0;\n border: 2px solid var(--card-color);\n background: var(--card-color);\n transition: transform 0.2s, z-index 0.2s, box-shadow 0.2s;\n cursor: default;\n z-index: 1;\n}\n.c-avatar-group__item.is-circle[data-v-e9981c87] {\n border-radius: 50%;\n}\n.c-avatar-group__item.is-square[data-v-e9981c87] {\n border-radius: 6px;\n}\n.c-avatar-group__item.is-clickable[data-v-e9981c87] {\n cursor: pointer;\n}\n.c-avatar-group__item.is-clickable[data-v-e9981c87]:hover {\n transform: translateY(-3px) scale(1.08);\n z-index: 10;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n}\n.c-avatar-group__item[data-v-e9981c87]:hover {\n z-index: 10;\n}\n.c-avatar-group__img[data-v-e9981c87] {\n display: block;\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n.is-circle .c-avatar-group__img[data-v-e9981c87] {\n border-radius: 50%;\n}\n.is-square .c-avatar-group__img[data-v-e9981c87] {\n border-radius: 4px;\n}\n.c-avatar-group__initials[data-v-e9981c87] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n color: #fff;\n font-weight: 600;\n user-select: none;\n}\n.is-circle .c-avatar-group__initials[data-v-e9981c87] {\n border-radius: 50%;\n}\n.is-square .c-avatar-group__initials[data-v-e9981c87] {\n border-radius: 4px;\n}\n.c-avatar-group__status[data-v-e9981c87] {\n position: absolute;\n bottom: 0;\n right: 0;\n border-radius: 50%;\n border: 2px solid var(--card-color);\n z-index: 2;\n}\n.c-avatar-group__overflow[data-v-e9981c87] {\n position: relative;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--card-color);\n background: color-mix(in srgb, var(--primary-color) 12%, var(--card-color));\n color: var(--primary-color);\n font-weight: 700;\n z-index: 0;\n transition: transform 0.2s, box-shadow 0.2s;\n}\n.c-avatar-group__overflow.is-circle[data-v-e9981c87] {\n border-radius: 50%;\n}\n.c-avatar-group__overflow.is-square[data-v-e9981c87] {\n border-radius: 6px;\n}\n.c-avatar-group__overflow.is-clickable[data-v-e9981c87] {\n cursor: pointer;\n}\n.c-avatar-group__overflow.is-clickable[data-v-e9981c87]:hover {\n transform: translateY(-3px) scale(1.08);\n z-index: 10;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n background: color-mix(in srgb, var(--primary-color) 20%, var(--card-color));\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_AvatarGroup-
|
|
1
|
+
{"version":3,"file":"C_AvatarGroup-SIzxuuZr.css","names":[],"sources":["../src/components/C_AvatarGroup/index.vue?vue&type=style&index=0&scoped=e9981c87&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled *//**\n * C_AvatarGroup — 头像组组件样式\n */\n.c-avatar-group[data-v-e9981c87] {\n display: inline-flex;\n align-items: center;\n /* ======================== 单个头像 ======================== */\n /* ---- 头像图片 ---- */\n /* ---- 首字母 fallback ---- */\n /* ---- 状态指示点 ---- */\n /* ======================== 溢出 +N ======================== */\n}\n.c-avatar-group.is-rtl[data-v-e9981c87] {\n flex-direction: row-reverse;\n}\n.c-avatar-group__item[data-v-e9981c87] {\n position: relative;\n flex-shrink: 0;\n border: 2px solid var(--card-color);\n background: var(--card-color);\n transition: transform 0.2s, z-index 0.2s, box-shadow 0.2s;\n cursor: default;\n z-index: 1;\n}\n.c-avatar-group__item.is-circle[data-v-e9981c87] {\n border-radius: 50%;\n}\n.c-avatar-group__item.is-square[data-v-e9981c87] {\n border-radius: 6px;\n}\n.c-avatar-group__item.is-clickable[data-v-e9981c87] {\n cursor: pointer;\n}\n.c-avatar-group__item.is-clickable[data-v-e9981c87]:hover {\n transform: translateY(-3px) scale(1.08);\n z-index: 10;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n}\n.c-avatar-group__item[data-v-e9981c87]:hover {\n z-index: 10;\n}\n.c-avatar-group__img[data-v-e9981c87] {\n display: block;\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n.is-circle .c-avatar-group__img[data-v-e9981c87] {\n border-radius: 50%;\n}\n.is-square .c-avatar-group__img[data-v-e9981c87] {\n border-radius: 4px;\n}\n.c-avatar-group__initials[data-v-e9981c87] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n color: #fff;\n font-weight: 600;\n user-select: none;\n}\n.is-circle .c-avatar-group__initials[data-v-e9981c87] {\n border-radius: 50%;\n}\n.is-square .c-avatar-group__initials[data-v-e9981c87] {\n border-radius: 4px;\n}\n.c-avatar-group__status[data-v-e9981c87] {\n position: absolute;\n bottom: 0;\n right: 0;\n border-radius: 50%;\n border: 2px solid var(--card-color);\n z-index: 2;\n}\n.c-avatar-group__overflow[data-v-e9981c87] {\n position: relative;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--card-color);\n background: color-mix(in srgb, var(--primary-color) 12%, var(--card-color));\n color: var(--primary-color);\n font-weight: 700;\n z-index: 0;\n transition: transform 0.2s, box-shadow 0.2s;\n}\n.c-avatar-group__overflow.is-circle[data-v-e9981c87] {\n border-radius: 50%;\n}\n.c-avatar-group__overflow.is-square[data-v-e9981c87] {\n border-radius: 6px;\n}\n.c-avatar-group__overflow.is-clickable[data-v-e9981c87] {\n cursor: pointer;\n}\n.c-avatar-group__overflow.is-clickable[data-v-e9981c87]:hover {\n transform: translateY(-3px) scale(1.08);\n z-index: 10;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n background: color-mix(in srgb, var(--primary-color) 20%, var(--card-color));\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
package/dist/C_AvatarGroup.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./C_AvatarGroup.js`);exports.
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./C_AvatarGroup.js`);exports.AVATAR_STATUS_COLOR_MAP=e.r,exports.C_AvatarGroup=e.t,exports.DEFAULT_AVATAR_GROUP_PROPS=e.n,exports.getInitials=e.i,exports.nameToColor=e.a;
|
package/dist/C_AvatarGroup.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* unplugin-vue-components disabled *//**
|
|
2
2
|
* C_AvatarGroup — 头像组组件样式
|
|
3
3
|
*/
|
|
4
|
-
.c-avatar-group[data-v-
|
|
4
|
+
.c-avatar-group[data-v-e9981c87] {
|
|
5
5
|
display: inline-flex;
|
|
6
6
|
align-items: center;
|
|
7
7
|
/* ======================== 单个头像 ======================== */
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
/* ---- 状态指示点 ---- */
|
|
11
11
|
/* ======================== 溢出 +N ======================== */
|
|
12
12
|
}
|
|
13
|
-
.c-avatar-group.is-rtl[data-v-
|
|
13
|
+
.c-avatar-group.is-rtl[data-v-e9981c87] {
|
|
14
14
|
flex-direction: row-reverse;
|
|
15
15
|
}
|
|
16
|
-
.c-avatar-group__item[data-v-
|
|
16
|
+
.c-avatar-group__item[data-v-e9981c87] {
|
|
17
17
|
position: relative;
|
|
18
18
|
flex-shrink: 0;
|
|
19
19
|
border: 2px solid var(--card-color);
|
|
@@ -22,36 +22,36 @@
|
|
|
22
22
|
cursor: default;
|
|
23
23
|
z-index: 1;
|
|
24
24
|
}
|
|
25
|
-
.c-avatar-group__item.is-circle[data-v-
|
|
25
|
+
.c-avatar-group__item.is-circle[data-v-e9981c87] {
|
|
26
26
|
border-radius: 50%;
|
|
27
27
|
}
|
|
28
|
-
.c-avatar-group__item.is-square[data-v-
|
|
28
|
+
.c-avatar-group__item.is-square[data-v-e9981c87] {
|
|
29
29
|
border-radius: 6px;
|
|
30
30
|
}
|
|
31
|
-
.c-avatar-group__item.is-clickable[data-v-
|
|
31
|
+
.c-avatar-group__item.is-clickable[data-v-e9981c87] {
|
|
32
32
|
cursor: pointer;
|
|
33
33
|
}
|
|
34
|
-
.c-avatar-group__item.is-clickable[data-v-
|
|
34
|
+
.c-avatar-group__item.is-clickable[data-v-e9981c87]:hover {
|
|
35
35
|
transform: translateY(-3px) scale(1.08);
|
|
36
36
|
z-index: 10;
|
|
37
37
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
38
38
|
}
|
|
39
|
-
.c-avatar-group__item[data-v-
|
|
39
|
+
.c-avatar-group__item[data-v-e9981c87]:hover {
|
|
40
40
|
z-index: 10;
|
|
41
41
|
}
|
|
42
|
-
.c-avatar-group__img[data-v-
|
|
42
|
+
.c-avatar-group__img[data-v-e9981c87] {
|
|
43
43
|
display: block;
|
|
44
44
|
width: 100%;
|
|
45
45
|
height: 100%;
|
|
46
46
|
object-fit: cover;
|
|
47
47
|
}
|
|
48
|
-
.is-circle .c-avatar-group__img[data-v-
|
|
48
|
+
.is-circle .c-avatar-group__img[data-v-e9981c87] {
|
|
49
49
|
border-radius: 50%;
|
|
50
50
|
}
|
|
51
|
-
.is-square .c-avatar-group__img[data-v-
|
|
51
|
+
.is-square .c-avatar-group__img[data-v-e9981c87] {
|
|
52
52
|
border-radius: 4px;
|
|
53
53
|
}
|
|
54
|
-
.c-avatar-group__initials[data-v-
|
|
54
|
+
.c-avatar-group__initials[data-v-e9981c87] {
|
|
55
55
|
display: flex;
|
|
56
56
|
align-items: center;
|
|
57
57
|
justify-content: center;
|
|
@@ -61,13 +61,13 @@
|
|
|
61
61
|
font-weight: 600;
|
|
62
62
|
user-select: none;
|
|
63
63
|
}
|
|
64
|
-
.is-circle .c-avatar-group__initials[data-v-
|
|
64
|
+
.is-circle .c-avatar-group__initials[data-v-e9981c87] {
|
|
65
65
|
border-radius: 50%;
|
|
66
66
|
}
|
|
67
|
-
.is-square .c-avatar-group__initials[data-v-
|
|
67
|
+
.is-square .c-avatar-group__initials[data-v-e9981c87] {
|
|
68
68
|
border-radius: 4px;
|
|
69
69
|
}
|
|
70
|
-
.c-avatar-group__status[data-v-
|
|
70
|
+
.c-avatar-group__status[data-v-e9981c87] {
|
|
71
71
|
position: absolute;
|
|
72
72
|
bottom: 0;
|
|
73
73
|
right: 0;
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
border: 2px solid var(--card-color);
|
|
76
76
|
z-index: 2;
|
|
77
77
|
}
|
|
78
|
-
.c-avatar-group__overflow[data-v-
|
|
78
|
+
.c-avatar-group__overflow[data-v-e9981c87] {
|
|
79
79
|
position: relative;
|
|
80
80
|
flex-shrink: 0;
|
|
81
81
|
display: flex;
|
|
@@ -88,20 +88,20 @@
|
|
|
88
88
|
z-index: 0;
|
|
89
89
|
transition: transform 0.2s, box-shadow 0.2s;
|
|
90
90
|
}
|
|
91
|
-
.c-avatar-group__overflow.is-circle[data-v-
|
|
91
|
+
.c-avatar-group__overflow.is-circle[data-v-e9981c87] {
|
|
92
92
|
border-radius: 50%;
|
|
93
93
|
}
|
|
94
|
-
.c-avatar-group__overflow.is-square[data-v-
|
|
94
|
+
.c-avatar-group__overflow.is-square[data-v-e9981c87] {
|
|
95
95
|
border-radius: 6px;
|
|
96
96
|
}
|
|
97
|
-
.c-avatar-group__overflow.is-clickable[data-v-
|
|
97
|
+
.c-avatar-group__overflow.is-clickable[data-v-e9981c87] {
|
|
98
98
|
cursor: pointer;
|
|
99
99
|
}
|
|
100
|
-
.c-avatar-group__overflow.is-clickable[data-v-
|
|
100
|
+
.c-avatar-group__overflow.is-clickable[data-v-e9981c87]:hover {
|
|
101
101
|
transform: translateY(-3px) scale(1.08);
|
|
102
102
|
z-index: 10;
|
|
103
103
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
|
|
104
104
|
background: color-mix(in srgb, var(--primary-color) 20%, var(--card-color));
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
/*# sourceMappingURL=C_AvatarGroup-
|
|
107
|
+
/*# sourceMappingURL=C_AvatarGroup-B9d-GJ9c.css.map*/
|
package/dist/C_AvatarGroup.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { a as STATUS_COLOR_MAP, i as DEFAULT_AVATAR_GROUP_PROPS, n as AvatarGroupProps, o as getInitials, r as AvatarItem, s as nameToColor, t as _default } from "./index3.vue.js";
|
|
2
|
-
export { type AvatarGroupProps, type AvatarItem, _default as C_AvatarGroup, DEFAULT_AVATAR_GROUP_PROPS,
|
|
2
|
+
export { STATUS_COLOR_MAP as AVATAR_STATUS_COLOR_MAP, type AvatarGroupProps, type AvatarItem, _default as C_AvatarGroup, DEFAULT_AVATAR_GROUP_PROPS, getInitials, nameToColor };
|
package/dist/C_AvatarGroup.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { a as STATUS_COLOR_MAP, i as DEFAULT_AVATAR_GROUP_PROPS, n as AvatarGroupProps, o as getInitials, r as AvatarItem, s as nameToColor, t as _default } from "./index3.vue.js";
|
|
2
|
-
export { type AvatarGroupProps, type AvatarItem, _default as C_AvatarGroup, DEFAULT_AVATAR_GROUP_PROPS,
|
|
2
|
+
export { STATUS_COLOR_MAP as AVATAR_STATUS_COLOR_MAP, type AvatarGroupProps, type AvatarItem, _default as C_AvatarGroup, DEFAULT_AVATAR_GROUP_PROPS, getInitials, nameToColor };
|
package/dist/C_AvatarGroup.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,i as t,n,r,t as i}from"./C_AvatarGroup2.js";export{i as C_AvatarGroup,n as DEFAULT_AVATAR_GROUP_PROPS,
|
|
1
|
+
import{a as e,i as t,n,r,t as i}from"./C_AvatarGroup2.js";export{r as AVATAR_STATUS_COLOR_MAP,i as C_AvatarGroup,n as DEFAULT_AVATAR_GROUP_PROPS,t as getInitials,e as nameToColor};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_AvatarGroup.js","names":[],"sources":["../src/components/C_AvatarGroup/types.ts","../src/components/C_AvatarGroup/index.vue"],"sourcesContent":["/**\n * @Description: 头像组组件类型定义\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n */\n\n/** 单个头像数据 */\nexport interface AvatarItem {\n /** 唯一标识 */\n id: string | number\n /** 头像图片 URL */\n src?: string\n /** 姓名(用于首字母 fallback 和 tooltip) */\n name: string\n /** 悬浮提示(默认取 name) */\n tooltip?: string\n /** 在线状态 */\n status?: 'online' | 'offline' | 'busy' | 'away'\n /** 额外数据 */\n extra?: Record<string, unknown>\n}\n\n/** 组件 Props */\nexport interface AvatarGroupProps {\n /** 头像数据列表 */\n items: AvatarItem[]\n /** 最多显示数量(超出 +N) */\n max?: number\n /** 头像尺寸 (px) */\n size?: number\n /** 头像间重叠偏移量 (px),负值表示堆叠 */\n overlap?: number\n /** 形状 */\n shape?: 'circle' | 'square'\n /** 是否显示状态指示点 */\n showStatus?: boolean\n /** 是否显示悬浮提示 */\n showTooltip?: boolean\n /** 是否可点击 */\n clickable?: boolean\n /** +N 溢出按钮是否可点击 */\n overflowClickable?: boolean\n /** 堆叠方向 */\n direction?: 'ltr' | 'rtl'\n}\n\n/** 默认 Props */\nexport const DEFAULT_AVATAR_GROUP_PROPS: Partial<AvatarGroupProps> = {\n max: 5,\n size: 40,\n overlap: -10,\n shape: 'circle',\n showStatus: true,\n showTooltip: true,\n clickable: false,\n overflowClickable: true,\n direction: 'ltr',\n}\n\n/** 状态颜色映射 */\nexport const STATUS_COLOR_MAP: Record<string, string> = {\n online: '#18a058',\n offline: '#909399',\n busy: '#e53e3e',\n away: '#f0a020',\n}\n\n/** 从名字中提取首字母 */\nexport function getInitials(name: string): string {\n if (!name) return '?'\n const parts = name.trim().split(/\\s+/)\n if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase()\n // 中文直接取最后一个字\n if (/[\\u4E00-\\u9FFF]/.test(name)) return name.slice(-1)\n return name.slice(0, 2).toUpperCase()\n}\n\n/** 根据名字生成稳定的背景色 */\nexport function nameToColor(name: string): string {\n const palette = [\n '#6366f1',\n '#8b5cf6',\n '#a855f7',\n '#d946ef',\n '#ec4899',\n '#f43f5e',\n '#ef4444',\n '#f97316',\n '#eab308',\n '#84cc16',\n '#22c55e',\n '#14b8a6',\n '#06b6d4',\n '#0ea5e9',\n '#3b82f6',\n '#6d28d9',\n ]\n let hash = 0\n for (let i = 0; i < name.length; i++) {\n hash = name.charCodeAt(i) + ((hash * 31) | 0)\n }\n return palette[Math.abs(hash) % palette.length]\n}\n","<!--\n * @Description: 头像组组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-avatar-group\"\n :class=\"{ 'is-rtl': mergedProps.direction === 'rtl' }\"\n >\n <NTooltip\n v-for=\"(item, idx) in visibleItems\"\n :key=\"item.id\"\n :disabled=\"!mergedProps.showTooltip\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__item\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.clickable },\n ]\"\n :style=\"itemStyle(idx)\"\n @click=\"mergedProps.clickable && emit('itemClick', item)\"\n >\n <img\n v-if=\"item.src\"\n :src=\"item.src\"\n :alt=\"item.name\"\n class=\"c-avatar-group__img\"\n />\n <div\n v-else\n class=\"c-avatar-group__initials\"\n :style=\"{\n background: nameToColor(item.name),\n fontSize: initialsFontSize,\n }\"\n >\n {{ getInitials(item.name) }}\n </div>\n\n <span\n v-if=\"mergedProps.showStatus && item.status\"\n class=\"c-avatar-group__status\"\n :style=\"statusStyle(item.status)\"\n />\n </div>\n </template>\n {{ item.tooltip ?? item.name }}\n </NTooltip>\n\n <!-- 溢出 +N -->\n <NTooltip\n v-if=\"overflowCount > 0\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__overflow\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.overflowClickable },\n ]\"\n :style=\"overflowStyle\"\n @click=\"\n mergedProps.overflowClickable && emit('overflowClick', hiddenItems)\n \"\n >\n +{{ overflowCount }}\n </div>\n </template>\n <div style=\"max-width: 200px\">\n <div\n v-for=\"h in hiddenItems\"\n :key=\"h.id\"\n style=\"line-height: 1.6\"\n >\n {{ h.name }}\n </div>\n </div>\n </NTooltip>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import {\n DEFAULT_AVATAR_GROUP_PROPS,\n getInitials,\n nameToColor,\n STATUS_COLOR_MAP,\n type AvatarGroupProps,\n type AvatarItem,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n items: AvatarGroupProps['items']\n max?: number\n size?: number\n overlap?: number\n shape?: AvatarGroupProps['shape']\n showStatus?: boolean\n showTooltip?: boolean\n clickable?: boolean\n overflowClickable?: boolean\n direction?: AvatarGroupProps['direction']\n }>(),\n {\n max: DEFAULT_AVATAR_GROUP_PROPS.max,\n size: DEFAULT_AVATAR_GROUP_PROPS.size,\n overlap: DEFAULT_AVATAR_GROUP_PROPS.overlap,\n shape: DEFAULT_AVATAR_GROUP_PROPS.shape,\n showStatus: DEFAULT_AVATAR_GROUP_PROPS.showStatus,\n showTooltip: DEFAULT_AVATAR_GROUP_PROPS.showTooltip,\n clickable: DEFAULT_AVATAR_GROUP_PROPS.clickable,\n overflowClickable: DEFAULT_AVATAR_GROUP_PROPS.overflowClickable,\n direction: DEFAULT_AVATAR_GROUP_PROPS.direction,\n }\n )\n\n const emit = defineEmits<{\n itemClick: [item: AvatarItem]\n overflowClick: [hiddenItems: AvatarItem[]]\n }>()\n\n const mergedProps = computed(() => ({\n ...DEFAULT_AVATAR_GROUP_PROPS,\n ...props,\n }))\n\n const visibleItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(0, max) : props.items\n })\n\n const hiddenItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(max) : []\n })\n\n const overflowCount = computed(() => hiddenItems.value.length)\n\n const initialsFontSize = computed(\n () => `${Math.round(mergedProps.value.size! * 0.38)}px`\n )\n\n /** 计算头像项定位样式 */\n function itemStyle(idx: number) {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: idx === 0 ? '0' : `${overlap}px`,\n }\n }\n\n const overflowStyle = computed(() => {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: `${overlap}px`,\n fontSize: `${Math.round(s * 0.32)}px`,\n }\n })\n\n /** 计算状态指示点样式 */\n function statusStyle(status: string) {\n const dotSize = Math.max(8, Math.round(mergedProps.value.size! * 0.24))\n return {\n width: `${dotSize}px`,\n height: `${dotSize}px`,\n backgroundColor: STATUS_COLOR_MAP[status] ?? STATUS_COLOR_MAP.offline,\n }\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"C_AvatarGroup.js","names":[],"sources":["../src/components/C_AvatarGroup/types.ts","../src/components/C_AvatarGroup/index.vue","../src/components/C_AvatarGroup/index.vue"],"sourcesContent":["/**\n * @Description: 头像组组件类型定义\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n */\n\n/** 单个头像数据 */\nexport interface AvatarItem {\n /** 唯一标识 */\n id: string | number\n /** 头像图片 URL */\n src?: string\n /** 姓名(用于首字母 fallback 和 tooltip) */\n name: string\n /** 悬浮提示(默认取 name) */\n tooltip?: string\n /** 在线状态 */\n status?: 'online' | 'offline' | 'busy' | 'away'\n /** 额外数据 */\n extra?: Record<string, unknown>\n}\n\n/** 组件 Props */\nexport interface AvatarGroupProps {\n /** 头像数据列表 */\n items: AvatarItem[]\n /** 最多显示数量(超出 +N) */\n max?: number\n /** 头像尺寸 (px) */\n size?: number\n /** 头像间重叠偏移量 (px),负值表示堆叠 */\n overlap?: number\n /** 形状 */\n shape?: 'circle' | 'square'\n /** 是否显示状态指示点 */\n showStatus?: boolean\n /** 是否显示悬浮提示 */\n showTooltip?: boolean\n /** 是否可点击 */\n clickable?: boolean\n /** +N 溢出按钮是否可点击 */\n overflowClickable?: boolean\n /** 堆叠方向 */\n direction?: 'ltr' | 'rtl'\n}\n\n/** 默认 Props */\nexport const DEFAULT_AVATAR_GROUP_PROPS: Partial<AvatarGroupProps> = {\n max: 5,\n size: 40,\n overlap: -10,\n shape: 'circle',\n showStatus: true,\n showTooltip: true,\n clickable: false,\n overflowClickable: true,\n direction: 'ltr',\n}\n\n/** 状态颜色映射 */\nexport const STATUS_COLOR_MAP: Record<string, string> = {\n online: '#18a058',\n offline: '#909399',\n busy: '#e53e3e',\n away: '#f0a020',\n}\n\n/** 从名字中提取首字母 */\nexport function getInitials(name: string): string {\n if (!name) return '?'\n const parts = name.trim().split(/\\s+/)\n if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase()\n // 中文直接取最后一个字\n if (/[\\u4E00-\\u9FFF]/.test(name)) return name.slice(-1)\n return name.slice(0, 2).toUpperCase()\n}\n\n/** 根据名字生成稳定的背景色 */\nexport function nameToColor(name: string): string {\n const palette = [\n '#6366f1',\n '#8b5cf6',\n '#a855f7',\n '#d946ef',\n '#ec4899',\n '#f43f5e',\n '#ef4444',\n '#f97316',\n '#eab308',\n '#84cc16',\n '#22c55e',\n '#14b8a6',\n '#06b6d4',\n '#0ea5e9',\n '#3b82f6',\n '#6d28d9',\n ]\n let hash = 0\n for (let i = 0; i < name.length; i++) {\n hash = name.charCodeAt(i) + ((hash * 31) | 0)\n }\n return palette[Math.abs(hash) % palette.length]\n}\n","<!--\n * @Description: 头像组组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-avatar-group\"\n :class=\"{ 'is-rtl': mergedProps.direction === 'rtl' }\"\n >\n <NTooltip\n v-for=\"(item, idx) in visibleItems\"\n :key=\"item.id\"\n :disabled=\"!mergedProps.showTooltip\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__item\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.clickable },\n ]\"\n :style=\"itemStyle(idx)\"\n @click=\"mergedProps.clickable && emit('itemClick', item)\"\n >\n <img\n v-if=\"item.src\"\n :src=\"item.src\"\n :alt=\"item.name\"\n class=\"c-avatar-group__img\"\n />\n <div\n v-else\n class=\"c-avatar-group__initials\"\n :style=\"{\n background: nameToColor(item.name),\n fontSize: initialsFontSize,\n }\"\n >\n {{ getInitials(item.name) }}\n </div>\n\n <span\n v-if=\"mergedProps.showStatus && item.status\"\n class=\"c-avatar-group__status\"\n :style=\"statusStyle(item.status)\"\n />\n </div>\n </template>\n {{ item.tooltip ?? item.name }}\n </NTooltip>\n\n <!-- 溢出 +N -->\n <NTooltip\n v-if=\"overflowCount > 0\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__overflow\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.overflowClickable },\n ]\"\n :style=\"overflowStyle\"\n @click=\"\n mergedProps.overflowClickable && emit('overflowClick', hiddenItems)\n \"\n >\n +{{ overflowCount }}\n </div>\n </template>\n <div style=\"max-width: 200px\">\n <div\n v-for=\"h in hiddenItems\"\n :key=\"h.id\"\n style=\"line-height: 1.6\"\n >\n {{ h.name }}\n </div>\n </div>\n </NTooltip>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import {\n DEFAULT_AVATAR_GROUP_PROPS,\n getInitials,\n nameToColor,\n STATUS_COLOR_MAP,\n type AvatarGroupProps,\n type AvatarItem,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n items: AvatarGroupProps['items']\n max?: number\n size?: number\n overlap?: number\n shape?: AvatarGroupProps['shape']\n showStatus?: boolean\n showTooltip?: boolean\n clickable?: boolean\n overflowClickable?: boolean\n direction?: AvatarGroupProps['direction']\n }>(),\n {\n max: DEFAULT_AVATAR_GROUP_PROPS.max,\n size: DEFAULT_AVATAR_GROUP_PROPS.size,\n overlap: DEFAULT_AVATAR_GROUP_PROPS.overlap,\n shape: DEFAULT_AVATAR_GROUP_PROPS.shape,\n showStatus: DEFAULT_AVATAR_GROUP_PROPS.showStatus,\n showTooltip: DEFAULT_AVATAR_GROUP_PROPS.showTooltip,\n clickable: DEFAULT_AVATAR_GROUP_PROPS.clickable,\n overflowClickable: DEFAULT_AVATAR_GROUP_PROPS.overflowClickable,\n direction: DEFAULT_AVATAR_GROUP_PROPS.direction,\n }\n )\n\n const emit = defineEmits<{\n itemClick: [item: AvatarItem]\n overflowClick: [hiddenItems: AvatarItem[]]\n }>()\n\n const mergedProps = computed(() => ({\n ...DEFAULT_AVATAR_GROUP_PROPS,\n ...props,\n }))\n\n const visibleItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(0, max) : props.items\n })\n\n const hiddenItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(max) : []\n })\n\n const overflowCount = computed(() => hiddenItems.value.length)\n\n const initialsFontSize = computed(\n () => `${Math.round(mergedProps.value.size! * 0.38)}px`\n )\n\n /** 计算头像项定位样式 */\n function itemStyle(idx: number) {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: idx === 0 ? '0' : `${overlap}px`,\n }\n }\n\n const overflowStyle = computed(() => {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: `${overlap}px`,\n fontSize: `${Math.round(s * 0.32)}px`,\n }\n })\n\n /** 计算状态指示点样式 */\n function statusStyle(status: string) {\n const dotSize = Math.max(8, Math.round(mergedProps.value.size! * 0.24))\n return {\n width: `${dotSize}px`,\n height: `${dotSize}px`,\n backgroundColor: STATUS_COLOR_MAP[status] ?? STATUS_COLOR_MAP.offline,\n }\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n","<!--\n * @Description: 头像组组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-avatar-group\"\n :class=\"{ 'is-rtl': mergedProps.direction === 'rtl' }\"\n >\n <NTooltip\n v-for=\"(item, idx) in visibleItems\"\n :key=\"item.id\"\n :disabled=\"!mergedProps.showTooltip\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__item\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.clickable },\n ]\"\n :style=\"itemStyle(idx)\"\n @click=\"mergedProps.clickable && emit('itemClick', item)\"\n >\n <img\n v-if=\"item.src\"\n :src=\"item.src\"\n :alt=\"item.name\"\n class=\"c-avatar-group__img\"\n />\n <div\n v-else\n class=\"c-avatar-group__initials\"\n :style=\"{\n background: nameToColor(item.name),\n fontSize: initialsFontSize,\n }\"\n >\n {{ getInitials(item.name) }}\n </div>\n\n <span\n v-if=\"mergedProps.showStatus && item.status\"\n class=\"c-avatar-group__status\"\n :style=\"statusStyle(item.status)\"\n />\n </div>\n </template>\n {{ item.tooltip ?? item.name }}\n </NTooltip>\n\n <!-- 溢出 +N -->\n <NTooltip\n v-if=\"overflowCount > 0\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__overflow\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.overflowClickable },\n ]\"\n :style=\"overflowStyle\"\n @click=\"\n mergedProps.overflowClickable && emit('overflowClick', hiddenItems)\n \"\n >\n +{{ overflowCount }}\n </div>\n </template>\n <div style=\"max-width: 200px\">\n <div\n v-for=\"h in hiddenItems\"\n :key=\"h.id\"\n style=\"line-height: 1.6\"\n >\n {{ h.name }}\n </div>\n </div>\n </NTooltip>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import {\n DEFAULT_AVATAR_GROUP_PROPS,\n getInitials,\n nameToColor,\n STATUS_COLOR_MAP,\n type AvatarGroupProps,\n type AvatarItem,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n items: AvatarGroupProps['items']\n max?: number\n size?: number\n overlap?: number\n shape?: AvatarGroupProps['shape']\n showStatus?: boolean\n showTooltip?: boolean\n clickable?: boolean\n overflowClickable?: boolean\n direction?: AvatarGroupProps['direction']\n }>(),\n {\n max: DEFAULT_AVATAR_GROUP_PROPS.max,\n size: DEFAULT_AVATAR_GROUP_PROPS.size,\n overlap: DEFAULT_AVATAR_GROUP_PROPS.overlap,\n shape: DEFAULT_AVATAR_GROUP_PROPS.shape,\n showStatus: DEFAULT_AVATAR_GROUP_PROPS.showStatus,\n showTooltip: DEFAULT_AVATAR_GROUP_PROPS.showTooltip,\n clickable: DEFAULT_AVATAR_GROUP_PROPS.clickable,\n overflowClickable: DEFAULT_AVATAR_GROUP_PROPS.overflowClickable,\n direction: DEFAULT_AVATAR_GROUP_PROPS.direction,\n }\n )\n\n const emit = defineEmits<{\n itemClick: [item: AvatarItem]\n overflowClick: [hiddenItems: AvatarItem[]]\n }>()\n\n const mergedProps = computed(() => ({\n ...DEFAULT_AVATAR_GROUP_PROPS,\n ...props,\n }))\n\n const visibleItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(0, max) : props.items\n })\n\n const hiddenItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(max) : []\n })\n\n const overflowCount = computed(() => hiddenItems.value.length)\n\n const initialsFontSize = computed(\n () => `${Math.round(mergedProps.value.size! * 0.38)}px`\n )\n\n /** 计算头像项定位样式 */\n function itemStyle(idx: number) {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: idx === 0 ? '0' : `${overlap}px`,\n }\n }\n\n const overflowStyle = computed(() => {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: `${overlap}px`,\n fontSize: `${Math.round(s * 0.32)}px`,\n }\n })\n\n /** 计算状态指示点样式 */\n function statusStyle(status: string) {\n const dotSize = Math.max(8, Math.round(mergedProps.value.size! * 0.24))\n return {\n width: `${dotSize}px`,\n height: `${dotSize}px`,\n backgroundColor: STATUS_COLOR_MAP[status] ?? STATUS_COLOR_MAP.offline,\n }\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n"],"mappings":"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"}
|
package/dist/C_AvatarGroup2.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./export-helper.js";import{Fragment as
|
|
1
|
+
import{t as e}from"./export-helper.js";import{NTooltip as t}from"naive-ui";import{Fragment as n,computed as r,createBlock as i,createCommentVNode as a,createElementBlock as o,createElementVNode as s,createTextVNode as c,defineComponent as l,normalizeClass as u,normalizeStyle as d,openBlock as f,renderList as p,resolveComponent as m,toDisplayString as h,unref as g,withCtx as _}from"vue";const v={max:5,size:40,overlap:-10,shape:`circle`,showStatus:!0,showTooltip:!0,clickable:!1,overflowClickable:!0,direction:`ltr`},y={online:`#18a058`,offline:`#909399`,busy:`#e53e3e`,away:`#f0a020`};function b(e){if(!e)return`?`;let t=e.trim().split(/\s+/);return t.length>=2?(t[0][0]+t[1][0]).toUpperCase():/[\u4E00-\u9FFF]/.test(e)?e.slice(-1):e.slice(0,2).toUpperCase()}function x(e){let t=[`#6366f1`,`#8b5cf6`,`#a855f7`,`#d946ef`,`#ec4899`,`#f43f5e`,`#ef4444`,`#f97316`,`#eab308`,`#84cc16`,`#22c55e`,`#14b8a6`,`#06b6d4`,`#0ea5e9`,`#3b82f6`,`#6d28d9`],n=0;for(let t=0;t<e.length;t++)n=e.charCodeAt(t)+(n*31|0);return t[Math.abs(n)%t.length]}const S=[`onClick`],C=[`src`,`alt`],w={style:{"max-width":`200px`}};var T=e(l({__name:`index`,props:{items:{},max:{default:v.max},size:{default:v.size},overlap:{default:v.overlap},shape:{default:v.shape},showStatus:{type:Boolean,default:v.showStatus},showTooltip:{type:Boolean,default:v.showTooltip},clickable:{type:Boolean,default:v.clickable},overflowClickable:{type:Boolean,default:v.overflowClickable},direction:{default:v.direction}},emits:[`itemClick`,`overflowClick`],setup(e,{emit:l}){let m=e,T=l,E=r(()=>({...v,...m})),D=r(()=>{let e=E.value.max;return m.items.length>e?m.items.slice(0,e):m.items}),O=r(()=>{let e=E.value.max;return m.items.length>e?m.items.slice(e):[]}),k=r(()=>O.value.length),A=r(()=>`${Math.round(E.value.size*.38)}px`);function j(e){let t=E.value.size,n=E.value.overlap;return{width:`${t}px`,height:`${t}px`,marginLeft:e===0?`0`:`${n}px`}}let M=r(()=>{let e=E.value.size,t=E.value.overlap;return{width:`${e}px`,height:`${e}px`,marginLeft:`${t}px`,fontSize:`${Math.round(e*.32)}px`}});function N(e){let t=Math.max(8,Math.round(E.value.size*.24));return{width:`${t}px`,height:`${t}px`,backgroundColor:y[e]??y.offline}}return(e,r)=>{let l=t;return f(),o(`div`,{class:u([`c-avatar-group`,{"is-rtl":E.value.direction===`rtl`}])},[(f(!0),o(n,null,p(D.value,(e,t)=>(f(),i(l,{key:e.id,disabled:!E.value.showTooltip,placement:`top`},{trigger:_(()=>[s(`div`,{class:u([`c-avatar-group__item`,[`is-${E.value.shape}`,{"is-clickable":E.value.clickable}]]),style:d(j(t)),onClick:t=>E.value.clickable&&T(`itemClick`,e)},[e.src?(f(),o(`img`,{key:0,src:e.src,alt:e.name,class:`c-avatar-group__img`},null,8,C)):(f(),o(`div`,{key:1,class:`c-avatar-group__initials`,style:d({background:g(x)(e.name),fontSize:A.value})},h(g(b)(e.name)),5)),E.value.showStatus&&e.status?(f(),o(`span`,{key:2,class:`c-avatar-group__status`,style:d(N(e.status))},null,4)):a(`v-if`,!0)],14,S)]),default:_(()=>[c(` `+h(e.tooltip??e.name),1)]),_:2},1032,[`disabled`]))),128)),a(` 溢出 +N `),k.value>0?(f(),i(l,{key:0,placement:`top`},{trigger:_(()=>[s(`div`,{class:u([`c-avatar-group__overflow`,[`is-${E.value.shape}`,{"is-clickable":E.value.overflowClickable}]]),style:d(M.value),onClick:r[0]||=e=>E.value.overflowClickable&&T(`overflowClick`,O.value)},` +`+h(k.value),7)]),default:_(()=>[s(`div`,w,[(f(!0),o(n,null,p(O.value,e=>(f(),o(`div`,{key:e.id,style:{"line-height":`1.6`}},h(e.name),1))),128))])]),_:1})):a(`v-if`,!0)],2)}}}),[[`__scopeId`,`data-v-e9981c87`]]);export{x as a,b as i,v as n,y as r,T as t};
|
|
2
2
|
//# sourceMappingURL=C_AvatarGroup2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_AvatarGroup2.js","names":[],"sources":["../src/components/C_AvatarGroup/types.ts","../src/components/C_AvatarGroup/index.vue"],"sourcesContent":["/**\n * @Description: 头像组组件类型定义\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n */\n\n/** 单个头像数据 */\nexport interface AvatarItem {\n /** 唯一标识 */\n id: string | number\n /** 头像图片 URL */\n src?: string\n /** 姓名(用于首字母 fallback 和 tooltip) */\n name: string\n /** 悬浮提示(默认取 name) */\n tooltip?: string\n /** 在线状态 */\n status?: 'online' | 'offline' | 'busy' | 'away'\n /** 额外数据 */\n extra?: Record<string, unknown>\n}\n\n/** 组件 Props */\nexport interface AvatarGroupProps {\n /** 头像数据列表 */\n items: AvatarItem[]\n /** 最多显示数量(超出 +N) */\n max?: number\n /** 头像尺寸 (px) */\n size?: number\n /** 头像间重叠偏移量 (px),负值表示堆叠 */\n overlap?: number\n /** 形状 */\n shape?: 'circle' | 'square'\n /** 是否显示状态指示点 */\n showStatus?: boolean\n /** 是否显示悬浮提示 */\n showTooltip?: boolean\n /** 是否可点击 */\n clickable?: boolean\n /** +N 溢出按钮是否可点击 */\n overflowClickable?: boolean\n /** 堆叠方向 */\n direction?: 'ltr' | 'rtl'\n}\n\n/** 默认 Props */\nexport const DEFAULT_AVATAR_GROUP_PROPS: Partial<AvatarGroupProps> = {\n max: 5,\n size: 40,\n overlap: -10,\n shape: 'circle',\n showStatus: true,\n showTooltip: true,\n clickable: false,\n overflowClickable: true,\n direction: 'ltr',\n}\n\n/** 状态颜色映射 */\nexport const STATUS_COLOR_MAP: Record<string, string> = {\n online: '#18a058',\n offline: '#909399',\n busy: '#e53e3e',\n away: '#f0a020',\n}\n\n/** 从名字中提取首字母 */\nexport function getInitials(name: string): string {\n if (!name) return '?'\n const parts = name.trim().split(/\\s+/)\n if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase()\n // 中文直接取最后一个字\n if (/[\\u4E00-\\u9FFF]/.test(name)) return name.slice(-1)\n return name.slice(0, 2).toUpperCase()\n}\n\n/** 根据名字生成稳定的背景色 */\nexport function nameToColor(name: string): string {\n const palette = [\n '#6366f1',\n '#8b5cf6',\n '#a855f7',\n '#d946ef',\n '#ec4899',\n '#f43f5e',\n '#ef4444',\n '#f97316',\n '#eab308',\n '#84cc16',\n '#22c55e',\n '#14b8a6',\n '#06b6d4',\n '#0ea5e9',\n '#3b82f6',\n '#6d28d9',\n ]\n let hash = 0\n for (let i = 0; i < name.length; i++) {\n hash = name.charCodeAt(i) + ((hash * 31) | 0)\n }\n return palette[Math.abs(hash) % palette.length]\n}\n","<!--\n * @Description: 头像组组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-avatar-group\"\n :class=\"{ 'is-rtl': mergedProps.direction === 'rtl' }\"\n >\n <NTooltip\n v-for=\"(item, idx) in visibleItems\"\n :key=\"item.id\"\n :disabled=\"!mergedProps.showTooltip\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__item\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.clickable },\n ]\"\n :style=\"itemStyle(idx)\"\n @click=\"mergedProps.clickable && emit('itemClick', item)\"\n >\n <img\n v-if=\"item.src\"\n :src=\"item.src\"\n :alt=\"item.name\"\n class=\"c-avatar-group__img\"\n />\n <div\n v-else\n class=\"c-avatar-group__initials\"\n :style=\"{\n background: nameToColor(item.name),\n fontSize: initialsFontSize,\n }\"\n >\n {{ getInitials(item.name) }}\n </div>\n\n <span\n v-if=\"mergedProps.showStatus && item.status\"\n class=\"c-avatar-group__status\"\n :style=\"statusStyle(item.status)\"\n />\n </div>\n </template>\n {{ item.tooltip ?? item.name }}\n </NTooltip>\n\n <!-- 溢出 +N -->\n <NTooltip\n v-if=\"overflowCount > 0\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__overflow\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.overflowClickable },\n ]\"\n :style=\"overflowStyle\"\n @click=\"\n mergedProps.overflowClickable && emit('overflowClick', hiddenItems)\n \"\n >\n +{{ overflowCount }}\n </div>\n </template>\n <div style=\"max-width: 200px\">\n <div\n v-for=\"h in hiddenItems\"\n :key=\"h.id\"\n style=\"line-height: 1.6\"\n >\n {{ h.name }}\n </div>\n </div>\n </NTooltip>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import {\n DEFAULT_AVATAR_GROUP_PROPS,\n getInitials,\n nameToColor,\n STATUS_COLOR_MAP,\n type AvatarGroupProps,\n type AvatarItem,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n items: AvatarGroupProps['items']\n max?: number\n size?: number\n overlap?: number\n shape?: AvatarGroupProps['shape']\n showStatus?: boolean\n showTooltip?: boolean\n clickable?: boolean\n overflowClickable?: boolean\n direction?: AvatarGroupProps['direction']\n }>(),\n {\n max: DEFAULT_AVATAR_GROUP_PROPS.max,\n size: DEFAULT_AVATAR_GROUP_PROPS.size,\n overlap: DEFAULT_AVATAR_GROUP_PROPS.overlap,\n shape: DEFAULT_AVATAR_GROUP_PROPS.shape,\n showStatus: DEFAULT_AVATAR_GROUP_PROPS.showStatus,\n showTooltip: DEFAULT_AVATAR_GROUP_PROPS.showTooltip,\n clickable: DEFAULT_AVATAR_GROUP_PROPS.clickable,\n overflowClickable: DEFAULT_AVATAR_GROUP_PROPS.overflowClickable,\n direction: DEFAULT_AVATAR_GROUP_PROPS.direction,\n }\n )\n\n const emit = defineEmits<{\n itemClick: [item: AvatarItem]\n overflowClick: [hiddenItems: AvatarItem[]]\n }>()\n\n const mergedProps = computed(() => ({\n ...DEFAULT_AVATAR_GROUP_PROPS,\n ...props,\n }))\n\n const visibleItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(0, max) : props.items\n })\n\n const hiddenItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(max) : []\n })\n\n const overflowCount = computed(() => hiddenItems.value.length)\n\n const initialsFontSize = computed(\n () => `${Math.round(mergedProps.value.size! * 0.38)}px`\n )\n\n /** 计算头像项定位样式 */\n function itemStyle(idx: number) {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: idx === 0 ? '0' : `${overlap}px`,\n }\n }\n\n const overflowStyle = computed(() => {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: `${overlap}px`,\n fontSize: `${Math.round(s * 0.32)}px`,\n }\n })\n\n /** 计算状态指示点样式 */\n function statusStyle(status: string) {\n const dotSize = Math.max(8, Math.round(mergedProps.value.size! * 0.24))\n return {\n width: `${dotSize}px`,\n height: `${dotSize}px`,\n backgroundColor: STATUS_COLOR_MAP[status] ?? STATUS_COLOR_MAP.offline,\n }\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"C_AvatarGroup2.js","names":[],"sources":["../src/components/C_AvatarGroup/types.ts","../src/components/C_AvatarGroup/index.vue","../src/components/C_AvatarGroup/index.vue"],"sourcesContent":["/**\n * @Description: 头像组组件类型定义\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n */\n\n/** 单个头像数据 */\nexport interface AvatarItem {\n /** 唯一标识 */\n id: string | number\n /** 头像图片 URL */\n src?: string\n /** 姓名(用于首字母 fallback 和 tooltip) */\n name: string\n /** 悬浮提示(默认取 name) */\n tooltip?: string\n /** 在线状态 */\n status?: 'online' | 'offline' | 'busy' | 'away'\n /** 额外数据 */\n extra?: Record<string, unknown>\n}\n\n/** 组件 Props */\nexport interface AvatarGroupProps {\n /** 头像数据列表 */\n items: AvatarItem[]\n /** 最多显示数量(超出 +N) */\n max?: number\n /** 头像尺寸 (px) */\n size?: number\n /** 头像间重叠偏移量 (px),负值表示堆叠 */\n overlap?: number\n /** 形状 */\n shape?: 'circle' | 'square'\n /** 是否显示状态指示点 */\n showStatus?: boolean\n /** 是否显示悬浮提示 */\n showTooltip?: boolean\n /** 是否可点击 */\n clickable?: boolean\n /** +N 溢出按钮是否可点击 */\n overflowClickable?: boolean\n /** 堆叠方向 */\n direction?: 'ltr' | 'rtl'\n}\n\n/** 默认 Props */\nexport const DEFAULT_AVATAR_GROUP_PROPS: Partial<AvatarGroupProps> = {\n max: 5,\n size: 40,\n overlap: -10,\n shape: 'circle',\n showStatus: true,\n showTooltip: true,\n clickable: false,\n overflowClickable: true,\n direction: 'ltr',\n}\n\n/** 状态颜色映射 */\nexport const STATUS_COLOR_MAP: Record<string, string> = {\n online: '#18a058',\n offline: '#909399',\n busy: '#e53e3e',\n away: '#f0a020',\n}\n\n/** 从名字中提取首字母 */\nexport function getInitials(name: string): string {\n if (!name) return '?'\n const parts = name.trim().split(/\\s+/)\n if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase()\n // 中文直接取最后一个字\n if (/[\\u4E00-\\u9FFF]/.test(name)) return name.slice(-1)\n return name.slice(0, 2).toUpperCase()\n}\n\n/** 根据名字生成稳定的背景色 */\nexport function nameToColor(name: string): string {\n const palette = [\n '#6366f1',\n '#8b5cf6',\n '#a855f7',\n '#d946ef',\n '#ec4899',\n '#f43f5e',\n '#ef4444',\n '#f97316',\n '#eab308',\n '#84cc16',\n '#22c55e',\n '#14b8a6',\n '#06b6d4',\n '#0ea5e9',\n '#3b82f6',\n '#6d28d9',\n ]\n let hash = 0\n for (let i = 0; i < name.length; i++) {\n hash = name.charCodeAt(i) + ((hash * 31) | 0)\n }\n return palette[Math.abs(hash) % palette.length]\n}\n","<!--\n * @Description: 头像组组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-avatar-group\"\n :class=\"{ 'is-rtl': mergedProps.direction === 'rtl' }\"\n >\n <NTooltip\n v-for=\"(item, idx) in visibleItems\"\n :key=\"item.id\"\n :disabled=\"!mergedProps.showTooltip\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__item\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.clickable },\n ]\"\n :style=\"itemStyle(idx)\"\n @click=\"mergedProps.clickable && emit('itemClick', item)\"\n >\n <img\n v-if=\"item.src\"\n :src=\"item.src\"\n :alt=\"item.name\"\n class=\"c-avatar-group__img\"\n />\n <div\n v-else\n class=\"c-avatar-group__initials\"\n :style=\"{\n background: nameToColor(item.name),\n fontSize: initialsFontSize,\n }\"\n >\n {{ getInitials(item.name) }}\n </div>\n\n <span\n v-if=\"mergedProps.showStatus && item.status\"\n class=\"c-avatar-group__status\"\n :style=\"statusStyle(item.status)\"\n />\n </div>\n </template>\n {{ item.tooltip ?? item.name }}\n </NTooltip>\n\n <!-- 溢出 +N -->\n <NTooltip\n v-if=\"overflowCount > 0\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__overflow\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.overflowClickable },\n ]\"\n :style=\"overflowStyle\"\n @click=\"\n mergedProps.overflowClickable && emit('overflowClick', hiddenItems)\n \"\n >\n +{{ overflowCount }}\n </div>\n </template>\n <div style=\"max-width: 200px\">\n <div\n v-for=\"h in hiddenItems\"\n :key=\"h.id\"\n style=\"line-height: 1.6\"\n >\n {{ h.name }}\n </div>\n </div>\n </NTooltip>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import {\n DEFAULT_AVATAR_GROUP_PROPS,\n getInitials,\n nameToColor,\n STATUS_COLOR_MAP,\n type AvatarGroupProps,\n type AvatarItem,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n items: AvatarGroupProps['items']\n max?: number\n size?: number\n overlap?: number\n shape?: AvatarGroupProps['shape']\n showStatus?: boolean\n showTooltip?: boolean\n clickable?: boolean\n overflowClickable?: boolean\n direction?: AvatarGroupProps['direction']\n }>(),\n {\n max: DEFAULT_AVATAR_GROUP_PROPS.max,\n size: DEFAULT_AVATAR_GROUP_PROPS.size,\n overlap: DEFAULT_AVATAR_GROUP_PROPS.overlap,\n shape: DEFAULT_AVATAR_GROUP_PROPS.shape,\n showStatus: DEFAULT_AVATAR_GROUP_PROPS.showStatus,\n showTooltip: DEFAULT_AVATAR_GROUP_PROPS.showTooltip,\n clickable: DEFAULT_AVATAR_GROUP_PROPS.clickable,\n overflowClickable: DEFAULT_AVATAR_GROUP_PROPS.overflowClickable,\n direction: DEFAULT_AVATAR_GROUP_PROPS.direction,\n }\n )\n\n const emit = defineEmits<{\n itemClick: [item: AvatarItem]\n overflowClick: [hiddenItems: AvatarItem[]]\n }>()\n\n const mergedProps = computed(() => ({\n ...DEFAULT_AVATAR_GROUP_PROPS,\n ...props,\n }))\n\n const visibleItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(0, max) : props.items\n })\n\n const hiddenItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(max) : []\n })\n\n const overflowCount = computed(() => hiddenItems.value.length)\n\n const initialsFontSize = computed(\n () => `${Math.round(mergedProps.value.size! * 0.38)}px`\n )\n\n /** 计算头像项定位样式 */\n function itemStyle(idx: number) {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: idx === 0 ? '0' : `${overlap}px`,\n }\n }\n\n const overflowStyle = computed(() => {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: `${overlap}px`,\n fontSize: `${Math.round(s * 0.32)}px`,\n }\n })\n\n /** 计算状态指示点样式 */\n function statusStyle(status: string) {\n const dotSize = Math.max(8, Math.round(mergedProps.value.size! * 0.24))\n return {\n width: `${dotSize}px`,\n height: `${dotSize}px`,\n backgroundColor: STATUS_COLOR_MAP[status] ?? STATUS_COLOR_MAP.offline,\n }\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n","<!--\n * @Description: 头像组组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-avatar-group\"\n :class=\"{ 'is-rtl': mergedProps.direction === 'rtl' }\"\n >\n <NTooltip\n v-for=\"(item, idx) in visibleItems\"\n :key=\"item.id\"\n :disabled=\"!mergedProps.showTooltip\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__item\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.clickable },\n ]\"\n :style=\"itemStyle(idx)\"\n @click=\"mergedProps.clickable && emit('itemClick', item)\"\n >\n <img\n v-if=\"item.src\"\n :src=\"item.src\"\n :alt=\"item.name\"\n class=\"c-avatar-group__img\"\n />\n <div\n v-else\n class=\"c-avatar-group__initials\"\n :style=\"{\n background: nameToColor(item.name),\n fontSize: initialsFontSize,\n }\"\n >\n {{ getInitials(item.name) }}\n </div>\n\n <span\n v-if=\"mergedProps.showStatus && item.status\"\n class=\"c-avatar-group__status\"\n :style=\"statusStyle(item.status)\"\n />\n </div>\n </template>\n {{ item.tooltip ?? item.name }}\n </NTooltip>\n\n <!-- 溢出 +N -->\n <NTooltip\n v-if=\"overflowCount > 0\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__overflow\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.overflowClickable },\n ]\"\n :style=\"overflowStyle\"\n @click=\"\n mergedProps.overflowClickable && emit('overflowClick', hiddenItems)\n \"\n >\n +{{ overflowCount }}\n </div>\n </template>\n <div style=\"max-width: 200px\">\n <div\n v-for=\"h in hiddenItems\"\n :key=\"h.id\"\n style=\"line-height: 1.6\"\n >\n {{ h.name }}\n </div>\n </div>\n </NTooltip>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import {\n DEFAULT_AVATAR_GROUP_PROPS,\n getInitials,\n nameToColor,\n STATUS_COLOR_MAP,\n type AvatarGroupProps,\n type AvatarItem,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n items: AvatarGroupProps['items']\n max?: number\n size?: number\n overlap?: number\n shape?: AvatarGroupProps['shape']\n showStatus?: boolean\n showTooltip?: boolean\n clickable?: boolean\n overflowClickable?: boolean\n direction?: AvatarGroupProps['direction']\n }>(),\n {\n max: DEFAULT_AVATAR_GROUP_PROPS.max,\n size: DEFAULT_AVATAR_GROUP_PROPS.size,\n overlap: DEFAULT_AVATAR_GROUP_PROPS.overlap,\n shape: DEFAULT_AVATAR_GROUP_PROPS.shape,\n showStatus: DEFAULT_AVATAR_GROUP_PROPS.showStatus,\n showTooltip: DEFAULT_AVATAR_GROUP_PROPS.showTooltip,\n clickable: DEFAULT_AVATAR_GROUP_PROPS.clickable,\n overflowClickable: DEFAULT_AVATAR_GROUP_PROPS.overflowClickable,\n direction: DEFAULT_AVATAR_GROUP_PROPS.direction,\n }\n )\n\n const emit = defineEmits<{\n itemClick: [item: AvatarItem]\n overflowClick: [hiddenItems: AvatarItem[]]\n }>()\n\n const mergedProps = computed(() => ({\n ...DEFAULT_AVATAR_GROUP_PROPS,\n ...props,\n }))\n\n const visibleItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(0, max) : props.items\n })\n\n const hiddenItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(max) : []\n })\n\n const overflowCount = computed(() => hiddenItems.value.length)\n\n const initialsFontSize = computed(\n () => `${Math.round(mergedProps.value.size! * 0.38)}px`\n )\n\n /** 计算头像项定位样式 */\n function itemStyle(idx: number) {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: idx === 0 ? '0' : `${overlap}px`,\n }\n }\n\n const overflowStyle = computed(() => {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: `${overlap}px`,\n fontSize: `${Math.round(s * 0.32)}px`,\n }\n })\n\n /** 计算状态指示点样式 */\n function statusStyle(status: string) {\n const dotSize = Math.max(8, Math.round(mergedProps.value.size! * 0.24))\n return {\n width: `${dotSize}px`,\n height: `${dotSize}px`,\n backgroundColor: STATUS_COLOR_MAP[status] ?? STATUS_COLOR_MAP.offline,\n }\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_Barcode-
|
|
1
|
+
{"version":3,"file":"C_Barcode-CAU2mFcx.css","names":[],"sources":["../src/components/C_Barcode/index.vue?vue&type=style&index=0&scoped=a8846f89&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.c-barcode[data-v-a8846f89] {\n display: inline-flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n max-width: 100%;\n}\n.c-barcode .barcode-wrapper[data-v-a8846f89] {\n display: inline-block;\n padding: 8px;\n background: #ffffff;\n border-radius: 4px;\n transition: all 0.3s ease;\n overflow: hidden;\n max-width: 100%;\n}\n.c-barcode .barcode-wrapper.with-border[data-v-a8846f89] {\n border: 1px dashed #e0e0e0;\n}\n.c-barcode .barcode-wrapper[data-v-a8846f89]:hover {\n border-color: var(--c-primary, #409eff);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n.c-barcode .barcode-wrapper[data-v-a8846f89] svg {\n max-width: 100%;\n height: auto;\n display: block;\n overflow: visible;\n}\n.c-barcode .barcode-label[data-v-a8846f89] {\n font-size: 14px;\n color: #666;\n text-align: center;\n font-weight: 500;\n word-break: break-all;\n max-width: 100%;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_Barcode-
|
|
1
|
+
{"version":3,"file":"C_Barcode-D2oJaEg3.css","names":[],"sources":["../src/components/C_Barcode/index.vue?vue&type=style&index=0&scoped=a8846f89&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.c-barcode[data-v-a8846f89] {\n display: inline-flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n max-width: 100%;\n}\n.c-barcode .barcode-wrapper[data-v-a8846f89] {\n display: inline-block;\n padding: 8px;\n background: #ffffff;\n border-radius: 4px;\n transition: all 0.3s ease;\n overflow: hidden;\n max-width: 100%;\n}\n.c-barcode .barcode-wrapper.with-border[data-v-a8846f89] {\n border: 1px dashed #e0e0e0;\n}\n.c-barcode .barcode-wrapper[data-v-a8846f89]:hover {\n border-color: var(--c-primary, #409eff);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n.c-barcode .barcode-wrapper[data-v-a8846f89] svg {\n max-width: 100%;\n height: auto;\n display: block;\n overflow: visible;\n}\n.c-barcode .barcode-label[data-v-a8846f89] {\n font-size: 14px;\n color: #666;\n text-align: center;\n font-weight: 500;\n word-break: break-all;\n max-width: 100%;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
package/dist/C_Barcode.css
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/* unplugin-vue-components disabled */.c-barcode[data-v-
|
|
1
|
+
/* unplugin-vue-components disabled */.c-barcode[data-v-a8846f89] {
|
|
2
2
|
display: inline-flex;
|
|
3
3
|
flex-direction: column;
|
|
4
4
|
align-items: center;
|
|
5
5
|
gap: 8px;
|
|
6
6
|
max-width: 100%;
|
|
7
7
|
}
|
|
8
|
-
.c-barcode .barcode-wrapper[data-v-
|
|
8
|
+
.c-barcode .barcode-wrapper[data-v-a8846f89] {
|
|
9
9
|
display: inline-block;
|
|
10
10
|
padding: 8px;
|
|
11
11
|
background: #ffffff;
|
|
@@ -14,20 +14,20 @@
|
|
|
14
14
|
overflow: hidden;
|
|
15
15
|
max-width: 100%;
|
|
16
16
|
}
|
|
17
|
-
.c-barcode .barcode-wrapper.with-border[data-v-
|
|
17
|
+
.c-barcode .barcode-wrapper.with-border[data-v-a8846f89] {
|
|
18
18
|
border: 1px dashed #e0e0e0;
|
|
19
19
|
}
|
|
20
|
-
.c-barcode .barcode-wrapper[data-v-
|
|
20
|
+
.c-barcode .barcode-wrapper[data-v-a8846f89]:hover {
|
|
21
21
|
border-color: var(--c-primary, #409eff);
|
|
22
22
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
23
23
|
}
|
|
24
|
-
.c-barcode .barcode-wrapper[data-v-
|
|
24
|
+
.c-barcode .barcode-wrapper[data-v-a8846f89] svg {
|
|
25
25
|
max-width: 100%;
|
|
26
26
|
height: auto;
|
|
27
27
|
display: block;
|
|
28
28
|
overflow: visible;
|
|
29
29
|
}
|
|
30
|
-
.c-barcode .barcode-label[data-v-
|
|
30
|
+
.c-barcode .barcode-label[data-v-a8846f89] {
|
|
31
31
|
font-size: 14px;
|
|
32
32
|
color: #666;
|
|
33
33
|
text-align: center;
|
|
@@ -36,4 +36,4 @@
|
|
|
36
36
|
max-width: 100%;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
/*# sourceMappingURL=C_Barcode-
|
|
39
|
+
/*# sourceMappingURL=C_Barcode-CAU2mFcx.css.map*/
|
package/dist/C_Barcode.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_Barcode.js","names":[],"sources":["../src/components/C_Barcode/index.vue"],"sourcesContent":["<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2025-12-02\n * @Description: 条形码组件\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div class=\"c-barcode\">\n <div class=\"barcode-wrapper\" :class=\"{ 'with-border': showBorder }\">\n <VueBarcode v-bind=\"barcodeProps\" @error=\"handleError\" />\n </div>\n <div v-if=\"showLabel && label\" class=\"barcode-label\">\n {{ label }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport VueBarcode from \"@chenfengyuan/vue-barcode\";\n\ndefineOptions({ name: \"C_Barcode\" });\n\ninterface Props {\n value: string;\n format?:\n | \"CODE128\"\n | \"CODE39\"\n | \"EAN13\"\n | \"EAN8\"\n | \"UPC\"\n | \"ITF14\"\n | \"MSI\"\n | \"pharmacode\";\n width?: number;\n height?: number;\n showText?: boolean;\n fontSize?: number;\n textPosition?: \"bottom\" | \"top\";\n lineColor?: string;\n background?: string;\n showBorder?: boolean;\n label?: string;\n showLabel?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n format: \"CODE128\",\n width: 2,\n height: 80,\n showText: true,\n fontSize: 20,\n textPosition: \"bottom\",\n lineColor: \"#000000\",\n background: \"#FFFFFF\",\n showBorder: true,\n label: \"\",\n showLabel: false,\n});\n\nconst emit = defineEmits<{\n error: [error: Error];\n}>();\n\nconst barcodeProps = computed(() => ({\n value: props.value,\n format: props.format,\n width: props.width,\n height: props.height,\n displayValue: props.showText,\n fontSize: props.fontSize,\n textPosition: props.textPosition,\n lineColor: props.lineColor,\n background: props.background,\n}));\n\nconst handleError = (error: Error) => {\n console.error(\"条形码生成失败:\", error);\n emit(\"error\", error);\n};\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n"],"mappings":"8lBA+CA,IAAM,EAAQ,EAcR,EAAO,EAIP,GAAA,EAAA,EAAA,eAA+B,CACnC,MAAO,EAAM,MACb,OAAQ,EAAM,OACd,MAAO,EAAM,MACb,OAAQ,EAAM,OACd,aAAc,EAAM,SACpB,SAAU,EAAM,SAChB,aAAc,EAAM,aACpB,UAAW,EAAM,UACjB,WAAY,EAAM,WACnB,EAAE,CAEG,EAAe,GAAiB,CACpC,QAAQ,MAAM,WAAY,EAAM,CAChC,EAAK,QAAS,EAAM,
|
|
1
|
+
{"version":3,"file":"C_Barcode.js","names":["showBorder","showLabel","label"],"sources":["../src/components/C_Barcode/index.vue","../src/components/C_Barcode/index.vue"],"sourcesContent":["<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2025-12-02\n * @Description: 条形码组件\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div class=\"c-barcode\">\n <div class=\"barcode-wrapper\" :class=\"{ 'with-border': showBorder }\">\n <VueBarcode v-bind=\"barcodeProps\" @error=\"handleError\" />\n </div>\n <div v-if=\"showLabel && label\" class=\"barcode-label\">\n {{ label }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport VueBarcode from \"@chenfengyuan/vue-barcode\";\n\ndefineOptions({ name: \"C_Barcode\" });\n\ninterface Props {\n value: string;\n format?:\n | \"CODE128\"\n | \"CODE39\"\n | \"EAN13\"\n | \"EAN8\"\n | \"UPC\"\n | \"ITF14\"\n | \"MSI\"\n | \"pharmacode\";\n width?: number;\n height?: number;\n showText?: boolean;\n fontSize?: number;\n textPosition?: \"bottom\" | \"top\";\n lineColor?: string;\n background?: string;\n showBorder?: boolean;\n label?: string;\n showLabel?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n format: \"CODE128\",\n width: 2,\n height: 80,\n showText: true,\n fontSize: 20,\n textPosition: \"bottom\",\n lineColor: \"#000000\",\n background: \"#FFFFFF\",\n showBorder: true,\n label: \"\",\n showLabel: false,\n});\n\nconst emit = defineEmits<{\n error: [error: Error];\n}>();\n\nconst barcodeProps = computed(() => ({\n value: props.value,\n format: props.format,\n width: props.width,\n height: props.height,\n displayValue: props.showText,\n fontSize: props.fontSize,\n textPosition: props.textPosition,\n lineColor: props.lineColor,\n background: props.background,\n}));\n\nconst handleError = (error: Error) => {\n console.error(\"条形码生成失败:\", error);\n emit(\"error\", error);\n};\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","<!--\n * @Author: ChenYu ycyplus@gmail.com\n * @Date: 2025-12-02\n * @Description: 条形码组件\n * @Migration: naive-ui-components 组件库迁移版本\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div class=\"c-barcode\">\n <div class=\"barcode-wrapper\" :class=\"{ 'with-border': showBorder }\">\n <VueBarcode v-bind=\"barcodeProps\" @error=\"handleError\" />\n </div>\n <div v-if=\"showLabel && label\" class=\"barcode-label\">\n {{ label }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport VueBarcode from \"@chenfengyuan/vue-barcode\";\n\ndefineOptions({ name: \"C_Barcode\" });\n\ninterface Props {\n value: string;\n format?:\n | \"CODE128\"\n | \"CODE39\"\n | \"EAN13\"\n | \"EAN8\"\n | \"UPC\"\n | \"ITF14\"\n | \"MSI\"\n | \"pharmacode\";\n width?: number;\n height?: number;\n showText?: boolean;\n fontSize?: number;\n textPosition?: \"bottom\" | \"top\";\n lineColor?: string;\n background?: string;\n showBorder?: boolean;\n label?: string;\n showLabel?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n format: \"CODE128\",\n width: 2,\n height: 80,\n showText: true,\n fontSize: 20,\n textPosition: \"bottom\",\n lineColor: \"#000000\",\n background: \"#FFFFFF\",\n showBorder: true,\n label: \"\",\n showLabel: false,\n});\n\nconst emit = defineEmits<{\n error: [error: Error];\n}>();\n\nconst barcodeProps = computed(() => ({\n value: props.value,\n format: props.format,\n width: props.width,\n height: props.height,\n displayValue: props.showText,\n fontSize: props.fontSize,\n textPosition: props.textPosition,\n lineColor: props.lineColor,\n background: props.background,\n}));\n\nconst handleError = (error: Error) => {\n console.error(\"条形码生成失败:\", error);\n emit(\"error\", error);\n};\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n"],"mappings":"8lBA+CA,IAAM,EAAQ,EAcR,EAAO,EAIP,GAAA,EAAA,EAAA,eAA+B,CACnC,MAAO,EAAM,MACb,OAAQ,EAAM,OACd,MAAO,EAAM,MACb,OAAQ,EAAM,OACd,aAAc,EAAM,SACpB,SAAU,EAAM,SAChB,aAAc,EAAM,aACpB,UAAW,EAAM,UACjB,WAAY,EAAM,WACnB,EAAE,CAEG,EAAe,GAAiB,CACpC,QAAQ,MAAM,WAAY,EAAM,CAChC,EAAK,QAAS,EAAM,2DChEd,MAPN,EAOM,EAAA,EAAA,EAAA,oBAJE,MAAA,CAFD,OAAA,EAAA,EAAA,gBAAK,CAAC,kBAAiB,CAAA,cAA0BA,EAAAA,WAAU,CAAA,CAAA,CAAA,CAAA,EAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OACL,EAAA,QAAA,EAAA,EAAA,EAAA,YAArC,EAAqC,MAAzB,CAAG,QAAO,EAAW,CAAA,CAAA,KAAA,GAAA,CAAA,CAAA,EAAA,CAE5CC,EAAAA,WAAaC,EAAAA,QAAAA,EAAAA,EAAAA,YAAAA,EAAAA,EAAAA,EAAAA,oBAElB,MAFN,GAAA,EAAA,EAAA,iBACKA,EAAAA,MAAK,CAAA,EAAA,GAAA,EAAA,EAAA,oBAAA,OAAA,GAAA,CAAA,CAAA"}
|
package/dist/C_Barcode2.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./export-helper.js";import{computed as t,createCommentVNode as n,createElementBlock as r,createElementVNode as i,createVNode as a,defineComponent as o,mergeProps as s,normalizeClass as c,openBlock as l,toDisplayString as u,unref as d}from"vue";import f from"@chenfengyuan/vue-barcode";const p={class:`c-barcode`},m={key:0,class:`barcode-label`};var h=e(o({name:`C_Barcode`,__name:`index`,props:{value:{},format:{default:`CODE128`},width:{default:2},height:{default:80},showText:{type:Boolean,default:!0},fontSize:{default:20},textPosition:{default:`bottom`},lineColor:{default:`#000000`},background:{default:`#FFFFFF`},showBorder:{type:Boolean,default:!0},label:{default:``},showLabel:{type:Boolean,default:!1}},emits:[`error`],setup(e,{emit:o}){let h=e,g=o,_=t(()=>({value:h.value,format:h.format,width:h.width,height:h.height,displayValue:h.showText,fontSize:h.fontSize,textPosition:h.textPosition,lineColor:h.lineColor,background:h.background})),v=e=>{console.error(`条形码生成失败:`,e),g(`error`,e)};return(e,t)=>(l(),r(`div`,p,[i(`div`,{class:c([`barcode-wrapper`,{"with-border":e.showBorder}])},[a(d(f),s(_.value,{onError:v}),null,16)],2),e.showLabel&&e.label?(l(),r(`div`,m,u(e.label),1)):n(`v-if`,!0)]))}}),[[`__scopeId`,`data-v-
|
|
1
|
+
import{t as e}from"./export-helper.js";import{computed as t,createCommentVNode as n,createElementBlock as r,createElementVNode as i,createVNode as a,defineComponent as o,mergeProps as s,normalizeClass as c,openBlock as l,toDisplayString as u,unref as d}from"vue";import f from"@chenfengyuan/vue-barcode";const p={class:`c-barcode`},m={key:0,class:`barcode-label`};var h=e(o({name:`C_Barcode`,__name:`index`,props:{value:{},format:{default:`CODE128`},width:{default:2},height:{default:80},showText:{type:Boolean,default:!0},fontSize:{default:20},textPosition:{default:`bottom`},lineColor:{default:`#000000`},background:{default:`#FFFFFF`},showBorder:{type:Boolean,default:!0},label:{default:``},showLabel:{type:Boolean,default:!1}},emits:[`error`],setup(e,{emit:o}){let h=e,g=o,_=t(()=>({value:h.value,format:h.format,width:h.width,height:h.height,displayValue:h.showText,fontSize:h.fontSize,textPosition:h.textPosition,lineColor:h.lineColor,background:h.background})),v=e=>{console.error(`条形码生成失败:`,e),g(`error`,e)};return(e,t)=>(l(),r(`div`,p,[i(`div`,{class:c([`barcode-wrapper`,{"with-border":e.showBorder}])},[a(d(f),s(_.value,{onError:v}),null,16)],2),e.showLabel&&e.label?(l(),r(`div`,m,u(e.label),1)):n(`v-if`,!0)]))}}),[[`__scopeId`,`data-v-a8846f89`]]);export{h as t};
|
|
2
2
|
//# sourceMappingURL=C_Barcode2.js.map
|