@robot-admin/naive-ui-components 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/C_ActionBar-BAcfOfRw.css.map +1 -0
- package/dist/C_ActionBar-DG2HW7t5.css.map +1 -0
- package/dist/C_ActionBar.css +47 -47
- package/dist/C_ActionBar.js.map +1 -1
- package/dist/C_ActionBar2.js +1 -1
- package/dist/C_ActionBar2.js.map +1 -1
- package/dist/{C_AntV-BY8jqqmi.css.map → C_AntV-D_jTK8oZ.css.map} +1 -1
- package/dist/{C_AntV-BbkHc-_a.css.map → C_AntV-DanTAq22.css.map} +1 -1
- package/dist/C_AntV.css +79 -79
- package/dist/C_AntV.js.map +1 -1
- package/dist/C_AntV2.js +3 -3
- package/dist/C_AntV2.js.map +1 -1
- package/dist/{C_AudioPlayer-DKRIGhi7.css.map → C_AudioPlayer-BnYIJXPD.css.map} +1 -1
- package/dist/{C_AudioPlayer-DlB6eNsa.css.map → C_AudioPlayer-ldTy9Y34.css.map} +1 -1
- package/dist/C_AudioPlayer.css +47 -47
- package/dist/C_AudioPlayer.js.map +1 -1
- package/dist/C_AudioPlayer2.js +1 -1
- package/dist/C_AudioPlayer2.js.map +1 -1
- package/dist/{C_AvatarGroup-D02zci-i.css.map → C_AvatarGroup-B9d-GJ9c.css.map} +1 -1
- package/dist/{C_AvatarGroup-DatHaUlY.css.map → C_AvatarGroup-SIzxuuZr.css.map} +1 -1
- package/dist/C_AvatarGroup.css +21 -21
- package/dist/C_AvatarGroup.js.map +1 -1
- package/dist/C_AvatarGroup2.js +1 -1
- package/dist/C_AvatarGroup2.js.map +1 -1
- package/dist/{C_Barcode-DYDRDe2O.css.map → C_Barcode-CAU2mFcx.css.map} +1 -1
- package/dist/{C_Barcode-muJdc_O4.css.map → C_Barcode-D2oJaEg3.css.map} +1 -1
- package/dist/C_Barcode.css +7 -7
- package/dist/C_Barcode.js.map +1 -1
- package/dist/C_Barcode2.js +1 -1
- package/dist/C_Barcode2.js.map +1 -1
- package/dist/C_Breadcrumb.js.map +1 -1
- package/dist/C_Breadcrumb2.js +1 -1
- package/dist/C_Breadcrumb2.js.map +1 -1
- package/dist/{C_Captcha-9_hk6VmY.css.map → C_Captcha-B3yrtG7t.css.map} +1 -1
- package/dist/{C_Captcha-MtASlJ0f.css.map → C_Captcha-D4hDdWDu.css.map} +1 -1
- package/dist/C_Captcha.css +19 -19
- package/dist/C_Captcha.js.map +1 -1
- package/dist/C_Captcha2.js +1 -1
- package/dist/C_Captcha2.js.map +1 -1
- package/dist/C_Cascade-BE7t1OX5.css.map +1 -0
- package/dist/C_Cascade-CpDiau1y.css.map +1 -0
- package/dist/C_Cascade.css +3 -3
- package/dist/C_Cascade.js.map +1 -1
- package/dist/C_Cascade2.js +1 -1
- package/dist/C_Cascade2.js.map +1 -1
- package/dist/{C_Chat-Csjz_BFw.css.map → C_Chat-CF1SU7mc.css.map} +1 -1
- package/dist/{C_Chat-DO1ZBA_0.css.map → C_Chat-DeUv6uuI.css.map} +1 -1
- package/dist/C_Chat.css +65 -65
- package/dist/C_Chat.js.map +1 -1
- package/dist/C_Chat2.js +1 -1
- package/dist/C_Chat2.js.map +1 -1
- package/dist/{C_City-Bam08Qv3.css.map → C_City-DdkX6u64.css.map} +1 -1
- package/dist/{C_City-Bb3W-KaN.css.map → C_City-iP-dIvui.css.map} +1 -1
- package/dist/C_City.css +29 -29
- package/dist/C_City.js.map +1 -1
- package/dist/C_City2.js +1 -1
- package/dist/C_City2.js.map +1 -1
- package/dist/C_Code-BWmJMNS7.css.map +1 -0
- package/dist/C_Code-k14vjgVl.css.map +1 -0
- package/dist/C_Code.css +3 -3
- package/dist/C_Code.js.map +1 -1
- package/dist/C_Code2.js +1 -1
- package/dist/C_Code2.js.map +1 -1
- package/dist/{C_CollapsePanel-CWkFCqNQ.css.map → C_CollapsePanel-BSKcWSmY.css.map} +1 -1
- package/dist/{C_CollapsePanel-pcVJA_4z.css.map → C_CollapsePanel-DRvRq8tB.css.map} +1 -1
- package/dist/C_CollapsePanel.css +35 -35
- package/dist/C_CollapsePanel.js.map +1 -1
- package/dist/C_CollapsePanel2.js +1 -1
- package/dist/C_CollapsePanel2.js.map +1 -1
- package/dist/{C_ContextMenu-B3Cgz_wJ.css.map → C_ContextMenu-Bn_uhJSo.css.map} +1 -1
- package/dist/{C_ContextMenu-u1LixF3_.css.map → C_ContextMenu-C9iuxG2n.css.map} +1 -1
- package/dist/C_ContextMenu.css +17 -17
- package/dist/C_ContextMenu.js.map +1 -1
- package/dist/C_ContextMenu2.js +1 -1
- package/dist/C_ContextMenu2.js.map +1 -1
- package/dist/{C_Cron-Civir5-I.css.map → C_Cron-BIQ2By9v.css.map} +1 -1
- package/dist/{C_Cron-iw3qpMsy.css.map → C_Cron-BNSAGD6A.css.map} +1 -1
- package/dist/C_Cron.css +57 -57
- package/dist/C_Cron.js.map +1 -1
- package/dist/C_Cron2.js +1 -1
- package/dist/C_Cron2.js.map +1 -1
- package/dist/C_Date.js.map +1 -1
- package/dist/C_Date2.js +1 -1
- package/dist/C_Date2.js.map +1 -1
- package/dist/{C_Draggable-BCjIvIwT.css.map → C_Draggable-BDAbk4s5.css.map} +1 -1
- package/dist/{C_Draggable-DwkSlCOS.css.map → C_Draggable-UhfDLXop.css.map} +1 -1
- package/dist/C_Draggable.css +46 -46
- package/dist/C_Draggable.js.map +1 -1
- package/dist/C_Draggable2.js +1 -1
- package/dist/C_Draggable2.js.map +1 -1
- package/dist/{C_Editor-BfjjYQ9B.css.map → C_Editor-CZOaChru.css.map} +1 -1
- package/dist/{C_Editor-Do2StvoJ.css.map → C_Editor-kJAQq5z6.css.map} +1 -1
- package/dist/C_Editor.css +14 -14
- package/dist/C_Editor.js.map +1 -1
- package/dist/C_Editor2.js +1 -1
- package/dist/C_Editor2.js.map +1 -1
- package/dist/{C_FilePreview-BhcbiXsV.css.map → C_FilePreview-Bs_omgJS.css.map} +1 -1
- package/dist/{C_FilePreview-DJudcIbW.css.map → C_FilePreview-DbwoyF2j.css.map} +1 -1
- package/dist/C_FilePreview.css +91 -91
- package/dist/C_FilePreview.js.map +1 -1
- package/dist/C_FilePreview2.js +1 -1
- package/dist/C_FilePreview2.js.map +1 -1
- package/dist/{C_Form-BtcAPIRi.css.map → C_Form-SCq-DZaZ.css.map} +1 -1
- package/dist/{C_Form-D_gwQ7hC.css.map → C_Form-mcd1nKvF.css.map} +1 -1
- package/dist/C_Form.css +223 -223
- package/dist/C_Form.js.map +1 -1
- package/dist/C_Form2.js +1 -1
- package/dist/C_Form2.js.map +1 -1
- package/dist/{C_FormSearch-Bi4XYjjk.css.map → C_FormSearch-C3F8peAY.css.map} +1 -1
- package/dist/{C_FormSearch-DUGOoX0u.css.map → C_FormSearch-qW56bJPo.css.map} +1 -1
- package/dist/C_FormSearch.css +45 -45
- package/dist/C_FormSearch.js.map +1 -1
- package/dist/C_FormSearch2.js +1 -1
- package/dist/C_FormSearch2.js.map +1 -1
- package/dist/{C_FormulaEditor-CJk3SSUJ.css.map → C_FormulaEditor-ChOvDbsZ.css.map} +1 -1
- package/dist/{C_FormulaEditor-Cy7mjfVO.css.map → C_FormulaEditor-mfiIUDY4.css.map} +1 -1
- package/dist/C_FormulaEditor.css +78 -78
- package/dist/C_FormulaEditor.js.map +1 -1
- package/dist/C_FormulaEditor2.js +1 -1
- package/dist/C_FormulaEditor2.js.map +1 -1
- package/dist/C_FullCalendar-C2nsqrgS.css.map +1 -0
- package/dist/C_FullCalendar-DdFtXVhy.css.map +1 -0
- package/dist/C_FullCalendar.css +2 -2
- package/dist/C_FullCalendar.js.map +1 -1
- package/dist/C_FullCalendar2.js +1 -1
- package/dist/C_FullCalendar2.js.map +1 -1
- package/dist/{C_GlobalSearch-B6wK3m3k.css.map → C_GlobalSearch-Dq4Wo01K.css.map} +1 -1
- package/dist/{C_GlobalSearch-DoPjldFm.css.map → C_GlobalSearch-RB7J43gu.css.map} +1 -1
- package/dist/C_GlobalSearch.css +112 -112
- package/dist/C_GlobalSearch.js.map +1 -1
- package/dist/C_GlobalSearch2.js +1 -1
- package/dist/C_GlobalSearch2.js.map +1 -1
- package/dist/C_Guide.js.map +1 -1
- package/dist/C_Guide2.js +1 -1
- package/dist/C_Guide2.js.map +1 -1
- package/dist/C_Icon.js.map +1 -1
- package/dist/C_Icon2.js.map +1 -1
- package/dist/{C_ImageCropper-BqZpkZfU.css.map → C_ImageCropper-CdTX2nxU.css.map} +1 -1
- package/dist/{C_ImageCropper-CylwGuzS.css.map → C_ImageCropper-ilOqPklJ.css.map} +1 -1
- package/dist/C_ImageCropper.css +23 -23
- package/dist/C_ImageCropper.js.map +1 -1
- package/dist/C_ImageCropper2.js +1 -1
- package/dist/C_ImageCropper2.js.map +1 -1
- package/dist/C_Language.js.map +1 -1
- package/dist/C_Language2.js +1 -1
- package/dist/C_Language2.js.map +1 -1
- package/dist/{C_Login-BkdnkBKX.css.map → C_Login-B3qYkLrN.css.map} +1 -1
- package/dist/{C_Login-VkMM6OJ2.css.map → C_Login-xMI1_ojE.css.map} +1 -1
- package/dist/C_Login.css +72 -72
- package/dist/C_Login.js.map +1 -1
- package/dist/C_Login2.js +1 -1
- package/dist/C_Login2.js.map +1 -1
- package/dist/{C_Map-DNnBcY70.css.map → C_Map-CWMMN58_.css.map} +1 -1
- package/dist/{C_Map-LEXIx6zM.css.map → C_Map-xSR2H-9o.css.map} +1 -1
- package/dist/C_Map.css +4 -4
- package/dist/C_Map.js.map +1 -1
- package/dist/C_Map2.js +1 -1
- package/dist/C_Map2.js.map +1 -1
- package/dist/{C_Markdown-DwmI0_0Q.css.map → C_Markdown-C7lTVJ1S.css.map} +1 -1
- package/dist/{C_Markdown-k0794RW0.css.map → C_Markdown-CZDm_baQ.css.map} +1 -1
- package/dist/C_Markdown.css +33 -33
- package/dist/C_Markdown.js.map +1 -1
- package/dist/C_Markdown2.js +1 -1
- package/dist/C_Markdown2.js.map +1 -1
- package/dist/C_Menu.js.map +1 -1
- package/dist/C_Menu2.js +1 -1
- package/dist/C_Menu2.js.map +1 -1
- package/dist/{C_NotificationCenter-DT6fQ79O.css.map → C_NotificationCenter-D7GGGWg7.css.map} +1 -1
- package/dist/{C_NotificationCenter-DbgBiyqB.css.map → C_NotificationCenter-SSmeHA45.css.map} +1 -1
- package/dist/C_NotificationCenter.css +89 -89
- package/dist/C_NotificationCenter.js.map +1 -1
- package/dist/C_NotificationCenter2.js +1 -1
- package/dist/C_NotificationCenter2.js.map +1 -1
- package/dist/C_OrgChart.js.map +1 -1
- package/dist/C_OrgChart2.js.map +1 -1
- package/dist/C_Progress.js.map +1 -1
- package/dist/C_Progress2.js +1 -1
- package/dist/C_Progress2.js.map +1 -1
- package/dist/{C_QRCode-CFNTda_1.css.map → C_QRCode-B_1lHUdx.css.map} +1 -1
- package/dist/{C_QRCode-CmWr9lK-.css.map → C_QRCode-CuQRYu0s.css.map} +1 -1
- package/dist/C_QRCode.css +9 -9
- package/dist/C_QRCode.js.map +1 -1
- package/dist/C_QRCode2.js +1 -1
- package/dist/C_QRCode2.js.map +1 -1
- package/dist/{C_Signature-BDx4ctsE.css.map → C_Signature-Bp-RBpAl.css.map} +1 -1
- package/dist/{C_Signature-Bz_uNbwv.css.map → C_Signature-Cb2VW1ok.css.map} +1 -1
- package/dist/C_Signature.css +15 -15
- package/dist/C_Signature.js.map +1 -1
- package/dist/C_Signature2.js +1 -1
- package/dist/C_Signature2.js.map +1 -1
- package/dist/C_Skeleton.js.map +1 -1
- package/dist/C_Skeleton2.js.map +1 -1
- package/dist/{C_SplitPane-BOwr1C7K.css.map → C_SplitPane-CgGWYsRE.css.map} +1 -1
- package/dist/{C_SplitPane-N-a_D-7F.css.map → C_SplitPane-DGf6WEeR.css.map} +1 -1
- package/dist/C_SplitPane.css +31 -31
- package/dist/C_SplitPane.js.map +1 -1
- package/dist/C_SplitPane2.js +1 -1
- package/dist/C_SplitPane2.js.map +1 -1
- package/dist/C_Steps-Buyg7Axn.css.map +1 -0
- package/dist/C_Steps-DNY91VbQ.css.map +1 -0
- package/dist/C_Steps.css +38 -38
- package/dist/C_Steps.js.map +1 -1
- package/dist/C_Steps2.js +1 -1
- package/dist/C_Steps2.js.map +1 -1
- package/dist/{C_Table-BcM5LqAM.css.map → C_Table--kbQaaBv.css.map} +1 -1
- package/dist/{C_Table-HATVoq1F.css.map → C_Table-D631kdXC.css.map} +1 -1
- package/dist/C_Table.css +104 -104
- package/dist/C_Table.js.map +1 -1
- package/dist/C_Table2.js +2 -2
- package/dist/C_Table2.js.map +1 -1
- package/dist/{C_TagsView-DX3LecK1.css.map → C_TagsView-COjGNM9h.css.map} +1 -1
- package/dist/{C_TagsView-DqOTa8bL.css.map → C_TagsView-zUDj9S06.css.map} +1 -1
- package/dist/C_TagsView.css +36 -36
- package/dist/C_TagsView.js.map +1 -1
- package/dist/C_TagsView2.js +1 -1
- package/dist/C_TagsView2.js.map +1 -1
- package/dist/C_Theme.js.map +1 -1
- package/dist/C_Theme2.js +1 -1
- package/dist/C_Theme2.js.map +1 -1
- package/dist/C_Time-BQ9PGy8B.css.map +1 -0
- package/dist/C_Time-CO73krC6.css.map +1 -0
- package/dist/C_Time.css +5 -5
- package/dist/C_Time.js.map +1 -1
- package/dist/C_Time2.js +1 -1
- package/dist/C_Time2.js.map +1 -1
- package/dist/{C_Timeline-BKkimrZx.css.map → C_Timeline-4rk0Dzgn.css.map} +1 -1
- package/dist/{C_Timeline-DTuSCX6p.css.map → C_Timeline-DdESmqwL.css.map} +1 -1
- package/dist/C_Timeline.css +45 -45
- package/dist/C_Timeline.js.map +1 -1
- package/dist/C_Timeline2.js +1 -1
- package/dist/C_Timeline2.js.map +1 -1
- package/dist/{C_Transfer-BOB6OBqS.css.map → C_Transfer-B-vjvhjI.css.map} +1 -1
- package/dist/{C_Transfer-Dpq7ezWC.css.map → C_Transfer-EzdHzZNv.css.map} +1 -1
- package/dist/C_Transfer.css +31 -31
- package/dist/C_Transfer.js.map +1 -1
- package/dist/C_Transfer2.js +1 -1
- package/dist/C_Transfer2.js.map +1 -1
- package/dist/{C_Tree-D98nX9qT.css.map → C_Tree-CsXgGfhn.css.map} +1 -1
- package/dist/{C_Tree-ulfm7b-P.css.map → C_Tree-P7eRpnOa.css.map} +1 -1
- package/dist/C_Tree.css +33 -33
- package/dist/C_Tree.js.map +1 -1
- package/dist/C_Tree2.js +1 -1
- package/dist/C_Tree2.js.map +1 -1
- package/dist/{C_Upload-BR9fg5r4.css.map → C_Upload-CHjiVVh7.css.map} +1 -1
- package/dist/{C_Upload-CPqf74Ea.css.map → C_Upload-DE3OLsZD.css.map} +1 -1
- package/dist/C_Upload.css +50 -50
- package/dist/C_Upload.js.map +1 -1
- package/dist/C_Upload2.js +2 -2
- package/dist/C_Upload2.js.map +1 -1
- package/dist/{C_VideoPlayer-4J96tKfK.css.map → C_VideoPlayer-CnaNOFtW.css.map} +1 -1
- package/dist/{C_VideoPlayer-D35seHkm.css.map → C_VideoPlayer-cnP88zNV.css.map} +1 -1
- package/dist/C_VideoPlayer.css +68 -68
- package/dist/C_VideoPlayer.js.map +1 -1
- package/dist/C_VideoPlayer2.js +3 -3
- package/dist/C_VideoPlayer2.js.map +1 -1
- package/dist/{C_VtableGantt-C2lxFmWg.css.map → C_VtableGantt-CZlJgvpC.css.map} +1 -1
- package/dist/{C_VtableGantt-Dwnkw_WL.css.map → C_VtableGantt-DKfQkql0.css.map} +1 -1
- package/dist/C_VtableGantt.css +15 -15
- package/dist/C_VtableGantt.js.map +1 -1
- package/dist/C_VtableGantt2.js +1 -1
- package/dist/C_VtableGantt2.js.map +1 -1
- package/dist/{C_WaterFall-C4HDqf-a.css.map → C_WaterFall-BJ_39ext.css.map} +1 -1
- package/dist/{C_WaterFall-HWB-gPON.css.map → C_WaterFall-cYc1vntE.css.map} +1 -1
- package/dist/C_WaterFall.css +16 -16
- package/dist/C_WaterFall.js.map +1 -1
- package/dist/C_WaterFall2.js +1 -1
- package/dist/C_WaterFall2.js.map +1 -1
- package/dist/{C_WorkFlow-2hJfvvTK.css.map → C_WorkFlow-BFzRGGhJ.css.map} +1 -1
- package/dist/{C_WorkFlow-DHoNjl8-.css.map → C_WorkFlow-DSyCOvRp.css.map} +1 -1
- package/dist/C_WorkFlow.css +193 -193
- package/dist/C_WorkFlow.js.map +1 -1
- package/dist/C_WorkFlow2.js +1 -1
- package/dist/C_WorkFlow2.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants2.d.ts +2 -2
- package/dist/constants3.d.ts +1 -1
- package/dist/constants4.d.ts +1 -1
- package/dist/constants5.d.ts +2 -2
- package/dist/data.d.ts +1 -1
- package/dist/index.vue.d.ts +2 -2
- package/dist/index11.vue.d.ts +2 -2
- package/dist/index12.vue.d.ts +1 -1
- package/dist/index13.vue.d.ts +2 -2
- package/dist/index14.vue.d.ts +3 -3
- package/dist/index15.vue.d.ts +6 -6
- package/dist/index17.vue.d.ts +1 -1
- package/dist/index18.vue.d.ts +2 -2
- package/dist/index2.vue.d.ts +6 -6
- package/dist/index20.vue.d.ts +1 -1
- package/dist/index21.vue.d.ts +2 -2
- package/dist/index22.vue.d.ts +2 -2
- package/dist/index24.vue.d.ts +1 -1
- package/dist/index26.vue.d.ts +3 -3
- package/dist/index27.vue.d.ts +1 -1
- package/dist/index28.vue.d.ts +2 -2
- package/dist/index3.vue.d.ts +2 -2
- package/dist/index4.vue.d.ts +2 -2
- package/dist/index6.vue.d.ts +3 -3
- package/dist/style.css +1991 -1991
- package/dist/useCalendarEvents.d.ts +1 -1
- package/dist/useCollapsePanel.d.ts +3 -3
- package/dist/useCropperCore.d.ts +4 -4
- package/dist/useDraggableLayout.d.ts +2 -2
- package/dist/useDynamicFormState.d.ts +13 -13
- package/dist/useEdgeInteraction.d.ts +1 -1
- package/dist/useInfiniteScroll.d.ts +3 -3
- package/dist/useModalEdit.d.ts +3 -3
- package/dist/useQRCode.d.ts +3 -3
- package/dist/useSignatureHistory.d.ts +1 -1
- package/dist/useSplitResize.d.ts +5 -5
- package/dist/useTimeSelection.d.ts +2 -2
- package/dist/useTreeOperations.d.ts +4 -4
- package/dist/useWorkflowValidation.d.ts +4 -4
- package/package.json +4 -7
- package/dist/C_ActionBar-DYG0Yf3A.css.map +0 -1
- package/dist/C_ActionBar-MAjRhqcI.css.map +0 -1
- package/dist/C_Cascade-Dq0S5Jkm.css.map +0 -1
- package/dist/C_Cascade-IUUHIh7r.css.map +0 -1
- package/dist/C_Code-BFi5xxnM.css.map +0 -1
- package/dist/C_Code-CZ7yfnri.css.map +0 -1
- package/dist/C_FullCalendar-BQA0OjGB.css.map +0 -1
- package/dist/C_FullCalendar-ChJUosAi.css.map +0 -1
- package/dist/C_Steps-Bk1krgiR.css.map +0 -1
- package/dist/C_Steps-Dn2CMpy1.css.map +0 -1
- package/dist/C_Time-BzyQVvTS.css.map +0 -1
- package/dist/C_Time-DmpKLQHc.css.map +0 -1
- package/dist/themes/glass-morphism.css +0 -1
package/dist/C_AntV.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_AntV.js","names":["Graph"],"sources":["../src/components/C_AntV/composables/useGraphBase.ts","../src/components/C_AntV/utils/exportUtils.ts","../src/components/C_AntV/composables/useGraphExport.ts","../src/components/C_AntV/layout/ER/data.ts","../src/components/C_AntV/layout/ER/components/ERTableEditor.vue","../src/components/C_AntV/layout/ER/index.vue","../src/components/C_AntV/composables/useEdgeInteraction.ts","../src/components/C_AntV/layout/BPMN/data.ts","../src/components/C_AntV/layout/BPMN/components/BPMNPropertyEditor.vue","../src/components/C_AntV/layout/BPMN/index.vue","../src/components/C_AntV/layout/UML/components/UMLClassEditor.vue","../src/components/C_AntV/layout/UML/data.ts","../src/components/C_AntV/layout/UML/index.vue","../src/components/C_AntV/index.vue"],"sourcesContent":["import { Graph } from \"@antv/x6\";\r\nimport { ref, watch, nextTick, onUnmounted } from \"vue\";\r\nimport type { ComputedRef, Ref } from \"vue\";\r\n\r\n/**\r\n * 获取主题相关的颜色配置\r\n */\r\nfunction getThemeColors(isDark: boolean) {\r\n return {\r\n background: isDark ? \"#18181c\" : \"#f5f5f5\",\r\n gridPrimary: isDark ? \"rgba(255, 255, 255, 0.08)\" : \"#eee\",\r\n gridSecondary: isDark ? \"rgba(255, 255, 255, 0.04)\" : \"#ddd\",\r\n };\r\n}\r\n\r\n/**\r\n * 默认的图表配置选项\r\n */\r\nfunction getDefaultOptions(isDark: boolean = false) {\r\n const colors = getThemeColors(isDark);\r\n\r\n return {\r\n background: { color: colors.background },\r\n grid: {\r\n visible: true,\r\n type: \"doubleMesh\",\r\n args: [\r\n { color: colors.gridPrimary, thickness: 1 },\r\n { color: colors.gridSecondary, thickness: 1, factor: 4 },\r\n ],\r\n },\r\n mousewheel: {\r\n enabled: true,\r\n zoomAtMousePosition: true,\r\n modifiers: \"ctrl\",\r\n minScale: 0.5,\r\n maxScale: 2,\r\n },\r\n selecting: {\r\n enabled: true,\r\n rubberband: true,\r\n movable: true,\r\n showNodeSelectionBox: true,\r\n },\r\n resizing: true,\r\n rotating: true,\r\n snapline: true,\r\n keyboard: true,\r\n clipboard: true,\r\n };\r\n}\r\n\r\n/**\r\n * 获取容器的尺寸\r\n */\r\nfunction getContainerSize(container: HTMLElement | undefined) {\r\n if (!container) return { width: 0, height: 0 };\r\n return {\r\n width: container.clientWidth || container.offsetWidth || 800,\r\n height: container.clientHeight || container.offsetHeight || 600,\r\n };\r\n}\r\n\r\n/**\r\n * 创建和管理 AntV X6 图表实例的组合式 API\r\n */\r\nexport function useGraphBase(\r\n containerRef: Ref<HTMLElement | undefined>,\r\n isDarkRef?: Ref<boolean> | ComputedRef<boolean>,\r\n) {\r\n const MAX_RETRY = 10;\r\n let retryCount = 0;\r\n\r\n const graph: Ref<any> = ref(null);\r\n const loading = ref(false);\r\n\r\n /**\r\n * 初始化图表实例\r\n */\r\n const initGraph = async (options: any = {}) => {\r\n await nextTick();\r\n loading.value = true;\r\n\r\n try {\r\n if (!containerRef.value) return;\r\n\r\n // 销毁旧实例\r\n if (graph.value) {\r\n graph.value.dispose();\r\n graph.value = null;\r\n }\r\n\r\n const { width, height } = getContainerSize(containerRef.value);\r\n\r\n // 容器尺寸为0,延迟重试(最多 10 次)\r\n if (width === 0 || height === 0) {\r\n retryCount++;\r\n if (retryCount < MAX_RETRY) {\r\n setTimeout(() => initGraph(options), 100);\r\n }\r\n return;\r\n }\r\n retryCount = 0;\r\n\r\n const isDark = isDarkRef?.value ?? false;\r\n const defaultOptions = getDefaultOptions(isDark);\r\n\r\n const finalOptions = {\r\n container: containerRef.value,\r\n width,\r\n height,\r\n ...defaultOptions,\r\n ...options,\r\n };\r\n\r\n graph.value = new Graph(finalOptions);\r\n } catch {\r\n // 初始化失败静默处理\r\n } finally {\r\n loading.value = false;\r\n }\r\n };\r\n\r\n /**\r\n * 更新主题\r\n */\r\n function updateTheme(isDark: boolean) {\r\n if (!graph.value) return;\r\n\r\n const colors = getThemeColors(isDark);\r\n\r\n // 更新背景色\r\n graph.value.drawBackground({ color: colors.background });\r\n\r\n // 更新网格颜色\r\n graph.value.drawGrid({\r\n type: \"doubleMesh\",\r\n args: [\r\n { color: colors.gridPrimary, thickness: 1 },\r\n { color: colors.gridSecondary, thickness: 1, factor: 4 },\r\n ],\r\n });\r\n }\r\n\r\n // 监听主题变化\r\n if (isDarkRef) {\r\n watch(isDarkRef, (isDark) => {\r\n updateTheme(isDark);\r\n });\r\n }\r\n\r\n /**\r\n * 销毁当前图表实例\r\n */\r\n function destroyGraph() {\r\n if (graph.value) {\r\n graph.value.dispose();\r\n graph.value = null;\r\n }\r\n }\r\n\r\n /**\r\n * 将图表内容居中显示\r\n */\r\n function centerContent() {\r\n graph.value?.centerContent();\r\n }\r\n\r\n /**\r\n * 自适应缩放图表以适应容器\r\n */\r\n function zoomToFit() {\r\n graph.value?.zoomToFit({ padding: 20, maxScale: 1 });\r\n }\r\n\r\n /**\r\n * 按指定因子缩放图表\r\n */\r\n function zoom(factor: number) {\r\n graph.value?.zoom(factor);\r\n }\r\n\r\n /**\r\n * 调整图表尺寸以适应容器变化\r\n */\r\n function resizeGraph() {\r\n if (graph.value && containerRef.value) {\r\n const { width, height } = getContainerSize(containerRef.value);\r\n graph.value.resize(width, height);\r\n }\r\n }\r\n\r\n // 组件卸载时自动销毁图表\r\n onUnmounted(destroyGraph);\r\n\r\n return {\r\n graph,\r\n loading,\r\n initGraph,\r\n destroyGraph,\r\n centerContent,\r\n zoomToFit,\r\n zoom,\r\n resizeGraph,\r\n updateTheme,\r\n };\r\n}\r\n","import type { Graph } from \"@antv/x6\";\r\nimport html2canvas from \"html2canvas\";\r\n\r\n/**\r\n * 下载 Blob 文件到本地\r\n * @param blob - Blob 对象\r\n * @param filename - 文件名\r\n */\r\nfunction downloadBlob(blob: Blob, filename: string): void {\r\n const url = URL.createObjectURL(blob);\r\n const link = document.createElement(\"a\");\r\n link.href = url;\r\n link.download = filename;\r\n link.style.display = \"none\";\r\n document.body.appendChild(link);\r\n link.click();\r\n document.body.removeChild(link);\r\n URL.revokeObjectURL(url);\r\n}\r\n\r\n/**\r\n * 导出数据为 JSON 文件\r\n * @param data - 要导出的数据\r\n * @param filename - 文件名,默认 'diagram.json'\r\n */\r\nexport function exportJSON(data: any, filename = \"diagram.json\"): void {\r\n const jsonString = JSON.stringify(data, null, 2);\r\n const blob = new Blob([jsonString], { type: \"application/json\" });\r\n downloadBlob(blob, filename);\r\n}\r\n\r\n/**\r\n * 导出图表为 PNG 图片(基于 html2canvas 截图方案)\r\n * @param graph - AntV X6 图表实例\r\n * @param filename - 文件名,默认 'diagram.png'\r\n * @param options - 导出选项\r\n */\r\nexport async function exportPNG(\r\n graph: Graph,\r\n filename = \"diagram.png\",\r\n options: { backgroundColor?: string; scale?: number } = {},\r\n): Promise<void> {\r\n const { backgroundColor = \"#ffffff\", scale = 2 } = options;\r\n const { container } = graph;\r\n\r\n const canvas = await html2canvas(container, {\r\n backgroundColor,\r\n scale,\r\n useCORS: true,\r\n logging: false,\r\n });\r\n\r\n const blob = await canvasToBlob(canvas, \"image/png\");\r\n downloadBlob(blob, filename);\r\n}\r\n\r\n/**\r\n * 导出图表为 SVG 矢量图(从容器内 SVG 元素序列化)\r\n * @param graph - AntV X6 图表实例\r\n * @param filename - 文件名,默认 'diagram.svg'\r\n */\r\nexport function exportSVG(graph: Graph, filename = \"diagram.svg\"): void {\r\n const svgElement = graph.container.querySelector(\"svg\");\r\n if (!svgElement) {\r\n throw new Error(\"SVG导出失败: 未找到图表 SVG 元素\");\r\n }\r\n\r\n // 克隆以避免修改原始 DOM\r\n const cloned = svgElement.cloneNode(true) as SVGSVGElement;\r\n\r\n // 确保有 xmlns 属性\r\n if (!cloned.getAttribute(\"xmlns\")) {\r\n cloned.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\r\n }\r\n if (!cloned.getAttribute(\"xmlns:xlink\")) {\r\n cloned.setAttribute(\"xmlns:xlink\", \"http://www.w3.org/1999/xlink\");\r\n }\r\n\r\n const serializer = new XMLSerializer();\r\n const svgString = serializer.serializeToString(cloned);\r\n const blob = new Blob([svgString], { type: \"image/svg+xml;charset=utf-8\" });\r\n downloadBlob(blob, filename);\r\n}\r\n\r\n/**\r\n * 将 Canvas 转换为 Blob\r\n */\r\nfunction canvasToBlob(\r\n canvas: HTMLCanvasElement,\r\n mimeType: string,\r\n quality = 1,\r\n): Promise<Blob> {\r\n return new Promise((resolve, reject) => {\r\n canvas.toBlob(\r\n (blob) => {\r\n if (blob) {\r\n resolve(blob);\r\n } else {\r\n reject(new Error(\"Canvas 转 Blob 失败\"));\r\n }\r\n },\r\n mimeType,\r\n quality,\r\n );\r\n });\r\n}\r\n\r\n/**\r\n * 复制内容到剪贴板\r\n * @param content - 要复制的内容\r\n * @returns 是否复制成功\r\n */\r\nexport async function copyToClipboard(content: string): Promise<boolean> {\r\n try {\r\n if (!navigator.clipboard) {\r\n return fallbackCopyToClipboard(content);\r\n }\r\n\r\n await navigator.clipboard.writeText(content);\r\n return true;\r\n } catch {\r\n return fallbackCopyToClipboard(content);\r\n }\r\n}\r\n\r\n/**\r\n * 备用的复制到剪贴板方法(适用于不支持 Clipboard API 的浏览器)\r\n */\r\nfunction fallbackCopyToClipboard(content: string): boolean {\r\n try {\r\n const textArea = document.createElement(\"textarea\");\r\n textArea.value = content;\r\n textArea.style.position = \"fixed\";\r\n textArea.style.left = \"-999999px\";\r\n textArea.style.top = \"-999999px\";\r\n\r\n document.body.appendChild(textArea);\r\n textArea.focus();\r\n textArea.select();\r\n\r\n const result = document.execCommand(\"copy\");\r\n document.body.removeChild(textArea);\r\n return result;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n","import type { Ref } from 'vue'\nimport type { Graph } from '@antv/x6'\nimport type { DropdownMixedOption } from 'naive-ui/es/dropdown/src/interface'\nimport { useMessage } from 'naive-ui'\nimport { exportJSON, exportPNG, exportSVG } from '../utils/exportUtils'\n\n/** 导出下拉菜单选项(三个布局共享) */\nexport const EXPORT_OPTIONS: DropdownMixedOption[] = [\n { label: '导出PNG', key: 'png' },\n { label: '导出SVG', key: 'svg' },\n { label: '导出JSON', key: 'json' },\n]\n\n/**\n * 图表导出 composable — 统一 PNG / SVG / JSON 导出逻辑\n * @param graph - X6 Graph 实例引用\n * @param filenamePrefix - 导出文件名前缀,默认 'diagram'\n */\nexport function useGraphExport(\n graph: Ref<Graph | null>,\n filenamePrefix = 'diagram'\n) {\n const message = useMessage()\n /**\n * 处理导出操作\n * @param key - 导出格式 'png' | 'svg' | 'json'\n * @param getData - 获取当前图表数据的函数(用于 JSON 导出)\n */\n const handleExport = async (key: string, getData?: () => any) => {\n if (!graph.value) return\n\n try {\n switch (key) {\n case 'png':\n await exportPNG(graph.value, `${filenamePrefix}.png`)\n break\n case 'svg':\n exportSVG(graph.value, `${filenamePrefix}.svg`)\n break\n case 'json':\n if (getData) {\n exportJSON(getData(), `${filenamePrefix}.json`)\n }\n break\n }\n } catch (error) {\n console.error(`[useGraphExport] 导出失败 (${key}):`, error)\n message.error(`导出${key.toUpperCase()}失败,请重试`)\n }\n }\n\n return { exportOptions: EXPORT_OPTIONS, handleExport }\n}\n","/* 原有的常量数据 */\r\nexport const fieldTypes = [\r\n { label: \"BIGINT\", value: \"BIGINT\" },\r\n { label: \"INT\", value: \"INT\" },\r\n { label: \"SMALLINT\", value: \"SMALLINT\" },\r\n { label: \"TINYINT\", value: \"TINYINT\" },\r\n { label: \"VARCHAR(50)\", value: \"VARCHAR(50)\" },\r\n { label: \"VARCHAR(100)\", value: \"VARCHAR(100)\" },\r\n { label: \"VARCHAR(255)\", value: \"VARCHAR(255)\" },\r\n { label: \"CHAR(10)\", value: \"CHAR(10)\" },\r\n { label: \"TEXT\", value: \"TEXT\" },\r\n { label: \"LONGTEXT\", value: \"LONGTEXT\" },\r\n { label: \"DATETIME\", value: \"DATETIME\" },\r\n { label: \"TIMESTAMP\", value: \"TIMESTAMP\" },\r\n { label: \"DATE\", value: \"DATE\" },\r\n { label: \"TIME\", value: \"TIME\" },\r\n { label: \"DECIMAL(10,2)\", value: \"DECIMAL(10,2)\" },\r\n { label: \"FLOAT\", value: \"FLOAT\" },\r\n { label: \"DOUBLE\", value: \"DOUBLE\" },\r\n { label: \"BOOLEAN\", value: \"BOOLEAN\" },\r\n { label: \"JSON\", value: \"JSON\" },\r\n];\r\n","<!--\n ERTableEditor — ER 表编辑器抽屉\n 负责:表名/注释编辑 + 字段 CRUD + 主键处理\n-->\n<template>\n <NDrawer\n :show=\"show\"\n width=\"600\"\n placement=\"right\"\n @update:show=\"$emit('update:show', $event)\"\n >\n <NDrawerContent\n :title=\"`编辑表: ${editingTable?.name || '新表'}`\"\n closable\n >\n <div\n class=\"table-editor\"\n v-if=\"editingTable\"\n >\n <NForm\n :model=\"editingTable\"\n label-placement=\"top\"\n >\n <NFormItem label=\"表名\">\n <NInput\n v-model:value=\"editingTable.name\"\n placeholder=\"请输入表名\"\n />\n </NFormItem>\n <NFormItem label=\"表注释\">\n <NInput\n v-model:value=\"editingTable.comment\"\n placeholder=\"表注释\"\n />\n </NFormItem>\n\n <NDivider>字段列表</NDivider>\n\n <div class=\"fields-container\">\n <NCard\n v-for=\"(field, index) in editingTable.fields\"\n :key=\"index\"\n size=\"small\"\n class=\"field-card\"\n >\n <template #header>\n <div class=\"field-header\">\n <span>#{{ index + 1 }} {{ field.name || '新字段' }}</span>\n <NButton\n @click=\"removeField(index)\"\n size=\"tiny\"\n type=\"error\"\n quaternary\n :disabled=\"editingTable.fields.length <= 1\"\n >\n 删除\n </NButton>\n </div>\n </template>\n\n <NGrid\n :cols=\"2\"\n :x-gap=\"12\"\n >\n <NGi>\n <NFormItem\n label=\"字段名\"\n size=\"small\"\n >\n <NInput\n v-model:value=\"field.name\"\n placeholder=\"字段名\"\n size=\"small\"\n />\n </NFormItem>\n </NGi>\n <NGi>\n <NFormItem\n label=\"类型\"\n size=\"small\"\n >\n <NSelect\n v-model:value=\"field.type\"\n :options=\"fieldTypes\"\n size=\"small\"\n filterable\n placeholder=\"选择类型\"\n />\n </NFormItem>\n </NGi>\n </NGrid>\n\n <NSpace style=\"margin-top: 12px\">\n <NCheckbox\n v-model:checked=\"field.isPrimaryKey\"\n @update:checked=\"handlePrimaryKey(field, $event)\"\n >\n 主键\n </NCheckbox>\n <NCheckbox v-model:checked=\"field.isRequired\">必填</NCheckbox>\n <NCheckbox v-model:checked=\"field.isForeignKey\">外键</NCheckbox>\n </NSpace>\n\n <NFormItem\n label=\"注释\"\n size=\"small\"\n style=\"margin-top: 12px\"\n >\n <NInput\n v-model:value=\"field.comment\"\n placeholder=\"字段注释\"\n size=\"small\"\n />\n </NFormItem>\n </NCard>\n\n <NButton\n @click=\"addField\"\n dashed\n block\n type=\"primary\"\n ghost\n style=\"margin-top: 16px\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:plus\"\n :size=\"16\"\n />\n </template>\n 添加字段\n </NButton>\n </div>\n </NForm>\n </div>\n\n <template #footer>\n <NSpace justify=\"end\">\n <NButton @click=\"$emit('update:show', false)\">取消</NButton>\n <NButton\n @click=\"$emit('save')\"\n type=\"primary\"\n >保存</NButton\n >\n </NSpace>\n </template>\n </NDrawerContent>\n </NDrawer>\n</template>\n\n<script setup lang=\"ts\">\n import {\n NDrawer,\n NDrawerContent,\n NForm,\n NFormItem,\n NInput,\n NSelect,\n NCard,\n NGrid,\n NGi,\n NSpace,\n NCheckbox,\n NButton,\n NDivider,\n } from 'naive-ui'\n import type { ERTable, ERField } from '../../../types'\n import { fieldTypes } from '../data'\n import C_Icon from '../../../../C_Icon/index.vue'\n\n defineProps<{\n show: boolean\n }>()\n\n const editingTable = defineModel<ERTable>('editingTable')\n\n const emit = defineEmits<{\n 'update:show': [value: boolean]\n save: []\n 'add-field': []\n 'remove-field': [index: number]\n 'handle-primary-key': [field: ERField, isPrimaryKey: boolean]\n }>()\n\n const handlePrimaryKey = (field: ERField, isPrimaryKey: boolean) =>\n emit('handle-primary-key', field, isPrimaryKey)\n\n const addField = () => emit('add-field')\n\n const removeField = (index: number) => emit('remove-field', index)\n</script>\n","<template>\n <div class=\"er-layout\">\n <!-- 工具栏 -->\n <div\n class=\"toolbar\"\n v-if=\"showToolbar\"\n >\n <NSpace>\n <NButton\n @click=\"addTable\"\n type=\"primary\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:table-plus\"\n :size=\"16\"\n />\n </template>\n 添加表\n </NButton>\n <NButton\n @click=\"centerContent\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:image-filter-center-focus\"\n :size=\"16\"\n />\n </template>\n 居中\n </NButton>\n <NButton\n @click=\"zoomToFit\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:fit-to-screen\"\n :size=\"16\"\n />\n </template>\n 适应\n </NButton>\n <NButton\n @click=\"toggleDeleteMode\"\n :type=\"deleteMode ? 'error' : 'default'\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:delete\"\n :size=\"16\"\n />\n </template>\n {{ deleteMode ? '退出删除' : '删除连线' }}\n </NButton>\n <NDropdown\n :options=\"exportOptions\"\n @select=\"(key: string) => handleExport(key, getCurrentData)\"\n >\n <NButton size=\"small\">\n <template #icon>\n <C_Icon\n name=\"mdi:export\"\n :size=\"16\"\n />\n </template>\n 导出\n </NButton>\n </NDropdown>\n </NSpace>\n\n <div\n v-if=\"deleteMode\"\n style=\"margin-top: 8px\"\n >\n <NAlert\n type=\"info\"\n size=\"small\"\n :show-icon=\"false\"\n >\n 删除模式:点击连接线即可删除\n </NAlert>\n </div>\n </div>\n\n <!-- 图表容器 -->\n <div\n ref=\"containerRef\"\n class=\"graph-container\"\n ></div>\n\n <!-- 表编辑器 -->\n <ERTableEditor\n :show=\"showEditor\"\n v-model:editing-table=\"editingTable\"\n @update:show=\"showEditor = $event\"\n @save=\"saveTable\"\n @add-field=\"addField\"\n @remove-field=\"removeField\"\n @handle-primary-key=\"handlePrimaryKey\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'\n import { NSpace, NButton, NDropdown, NAlert } from 'naive-ui'\n import { Node, Graph, Cell, Edge } from '@antv/x6'\n import { useGraphBase } from '../../composables/useGraphBase'\n import { useGraphExport } from '../../composables/useGraphExport'\n import type { ERTable, ERField, ERDiagramData, ERRelation } from '../../types'\n import ERTableEditor from './components/ERTableEditor.vue'\n import C_Icon from '../../../C_Icon/index.vue'\n\n interface Props {\n data?: ERDiagramData\n showToolbar?: boolean\n readonly?: boolean\n theme?: 'light' | 'dark'\n }\n\n const props = withDefaults(defineProps<Props>(), {\n showToolbar: true,\n readonly: false,\n })\n\n const emit = defineEmits<{\n (e: 'ready', graph: Graph): void\n (e: 'data-change', data: ERDiagramData): void\n }>()\n\n // ==================== Composables ====================\n const containerRef = ref<HTMLDivElement>()\n const isDark = computed(() => props.theme === 'dark')\n const { graph, initGraph, centerContent, zoomToFit } = useGraphBase(\n containerRef,\n isDark\n )\n const { exportOptions, handleExport } = useGraphExport(graph, 'er-diagram')\n\n // ==================== 编辑器状态 ====================\n const showEditor = ref(false)\n const editingTable = ref<ERTable>()\n const deleteMode = ref(false)\n\n // ==================== 工具函数 ====================\n const truncateText = (text: string, maxLength: number) =>\n text.length > maxLength ? text.substring(0, maxLength - 1) + '..' : text\n\n const createPortConfig = (table: ERTable) =>\n table.fields?.map(field => {\n const displayName = field.isPrimaryKey\n ? `🔑 ${field.name}`\n : field.isRequired\n ? `* ${field.name}`\n : field.name\n return {\n id: `${table.id}_${field.name}`,\n group: 'list',\n attrs: {\n portNameLabel: {\n text: truncateText(displayName, 12),\n title: displayName,\n },\n portTypeLabel: {\n text: truncateText(field.type, 10),\n title: field.type,\n },\n portBody: { fill: field.isPrimaryKey ? '#FFF7E6' : '#EFF4FF' },\n },\n }\n }) || []\n\n const createNodeConfig = (table: ERTable) => ({\n id: table.id,\n shape: 'er-rect',\n x: table.position.x,\n y: table.position.y,\n width: 200,\n height: 24 + (table.fields?.length || 0) * 24,\n data: table,\n attrs: {\n label: {\n text: truncateText(table.name, 20),\n refX: 0.5,\n refY: 10,\n textAnchor: 'middle',\n title: table.name,\n },\n },\n ports: createPortConfig(table),\n })\n\n // ==================== 节点注册 ====================\n const registerNodes = () => {\n if (!graph.value) return\n\n Graph.registerPortLayout(\n 'erPortPosition',\n portsPositionArgs =>\n portsPositionArgs.map((_, index) => ({\n position: { x: 0, y: (index + 1) * 24 },\n angle: 0,\n })),\n true\n )\n\n Graph.registerNode(\n 'er-rect',\n {\n inherit: 'rect',\n markup: [\n { tagName: 'rect', selector: 'body' },\n { tagName: 'text', selector: 'label' },\n ],\n attrs: {\n rect: { strokeWidth: 1, stroke: '#5F95FF', fill: '#5F95FF' },\n label: { fontWeight: 'bold', fill: '#ffffff', fontSize: 12 },\n },\n ports: {\n groups: {\n list: {\n markup: [\n { tagName: 'rect', selector: 'portBody' },\n { tagName: 'text', selector: 'portNameLabel' },\n { tagName: 'text', selector: 'portTypeLabel' },\n ],\n attrs: {\n portBody: {\n width: 200,\n height: 24,\n strokeWidth: 1,\n stroke: '#5F95FF',\n fill: '#EFF4FF',\n magnet: true,\n },\n portNameLabel: {\n ref: 'portBody',\n refX: 6,\n refY: 6,\n fontSize: 9,\n textAnchor: 'start',\n textOverflow: 'ellipsis',\n },\n portTypeLabel: {\n ref: 'portBody',\n refX: 120,\n refY: 6,\n fontSize: 9,\n textAnchor: 'start',\n fill: '#666',\n },\n },\n position: 'erPortPosition',\n },\n },\n },\n },\n true\n )\n }\n\n // ==================== 删除模式 ====================\n const toggleDeleteMode = () => {\n deleteMode.value = !deleteMode.value\n if (!deleteMode.value) resetEdgeStyles()\n }\n\n const resetEdgeStyles = () => {\n graph.value?.getEdges().forEach((edge: any) => {\n edge.attr('line/stroke', '#A2B1C3')\n edge.attr('line/strokeWidth', 2)\n })\n }\n\n // ==================== 表 CRUD ====================\n const createTableNode = (table: ERTable) => {\n if (!graph.value) return\n const node = graph.value.createNode(createNodeConfig(table))\n graph.value.resetCells([node, ...graph.value.getCells()])\n return node\n }\n\n const findPosition = () => {\n const nodes = graph.value?.getNodes() || []\n const spacing = 250\n for (let row = 0; row < 10; row++) {\n for (let col = 0; col < 3; col++) {\n const pos = { x: col * spacing + 50, y: row * spacing + 50 }\n const hasOverlap = nodes.some((node: any) => {\n const nodePos = node.getPosition()\n return (\n Math.abs(nodePos.x - pos.x) < spacing * 0.8 &&\n Math.abs(nodePos.y - pos.y) < spacing * 0.8\n )\n })\n if (!hasOverlap) return pos\n }\n }\n return { x: 50, y: 50 }\n }\n\n const addTable = () => {\n const newTable: ERTable = {\n id: `table_${Date.now()}`,\n name: '新表',\n comment: '',\n fields: [\n {\n name: 'id',\n type: 'BIGINT',\n isPrimaryKey: true,\n isRequired: true,\n isForeignKey: false,\n comment: '主键',\n },\n {\n name: 'name',\n type: 'VARCHAR(100)',\n isPrimaryKey: false,\n isRequired: true,\n isForeignKey: false,\n comment: '名称',\n },\n ],\n position: findPosition(),\n }\n createTableNode(newTable)\n editTable(newTable)\n emitDataChange()\n }\n\n const editTable = (table: ERTable) => {\n editingTable.value = {\n ...table,\n fields: table.fields?.map(field => ({ ...field })) || [],\n }\n showEditor.value = true\n }\n\n const saveTable = () => {\n if (!graph.value || !editingTable.value) return\n const node = graph.value.getCellById(editingTable.value.id) as Node\n if (node) {\n node.setData(editingTable.value)\n node.prop({\n size: {\n width: 200,\n height: 24 + editingTable.value.fields.length * 24,\n },\n attrs: {\n label: {\n text: truncateText(editingTable.value.name, 20),\n title: editingTable.value.name,\n },\n },\n ports: createPortConfig(editingTable.value),\n })\n }\n showEditor.value = false\n emitDataChange()\n }\n\n // ==================== 字段操作(由子组件事件触发) ====================\n const handlePrimaryKey = (field: ERField, isPrimaryKey: boolean) => {\n if (!isPrimaryKey) return\n field.isRequired = true\n editingTable.value?.fields.forEach(f => {\n if (f !== field) f.isPrimaryKey = false\n })\n }\n\n const addField = () => {\n editingTable.value?.fields.push({\n name: `field_${(editingTable.value?.fields.length || 0) + 1}`,\n type: 'VARCHAR(100)',\n isPrimaryKey: false,\n isRequired: false,\n isForeignKey: false,\n comment: '',\n })\n }\n\n const removeField = (index: number) => {\n if (editingTable.value && editingTable.value.fields.length > 1)\n editingTable.value.fields.splice(index, 1)\n }\n\n // ==================== 数据获取 ====================\n const getCurrentData = (): ERDiagramData => {\n if (!graph.value) return { tables: [], relations: [] }\n\n const tables = graph.value.getNodes().map((node: any) => ({\n ...node.getData(),\n position: node.getPosition(),\n }))\n\n const relations: ERRelation[] = []\n graph.value.getEdges().forEach((edge: any) => {\n const source = edge.getSourceNode()\n const target = edge.getTargetNode()\n const sourcePort = edge.getSourcePortId()\n const targetPort = edge.getTargetPortId()\n if (source && target && sourcePort && targetPort) {\n relations.push({\n id: edge.id,\n type: 'foreign-key',\n sourceTable: source.id,\n sourceField: sourcePort.split('_').slice(1).join('_'),\n targetTable: target.id,\n targetField: targetPort.split('_').slice(1).join('_'),\n name: `${source.getData()?.name || source.id} -> ${target.getData()?.name || target.id}`,\n })\n }\n })\n return { tables, relations }\n }\n\n const emitDataChange = () => emit('data-change', getCurrentData())\n\n // ==================== Graph 事件绑定 ====================\n watch(\n graph,\n newGraph => {\n if (!(newGraph instanceof Graph)) return\n\n registerNodes()\n newGraph.on('node:dblclick', ({ node }) => {\n if (!props.readonly) editTable(node.getData() as ERTable)\n })\n newGraph.on('edge:connected', emitDataChange)\n newGraph.on('edge:removed', emitDataChange)\n\n let selectedEdge: Edge | null = null\n\n newGraph.on('edge:click', ({ edge }) => {\n if (deleteMode.value) {\n edge.remove()\n emitDataChange()\n } else {\n resetEdgeStyles()\n edge.attr('line/stroke', '#ff4d4f')\n edge.attr('line/strokeWidth', 3)\n selectedEdge = edge\n }\n })\n newGraph.on('edge:dblclick', ({ edge }) => {\n edge.remove()\n emitDataChange()\n })\n newGraph.on('blank:click', () => {\n selectedEdge = null\n if (!deleteMode.value) resetEdgeStyles()\n })\n\n const handleKeyDown = (e: KeyboardEvent) => {\n // 忽略来自 input/textarea/contenteditable 元素的按键\n const tag = (e.target as HTMLElement)?.tagName\n if (\n tag === 'INPUT' ||\n tag === 'TEXTAREA' ||\n (e.target as HTMLElement)?.isContentEditable\n )\n return\n\n if ((e.key === 'Delete' || e.key === 'Backspace') && selectedEdge) {\n selectedEdge.remove()\n emitDataChange()\n selectedEdge = null\n }\n }\n document.addEventListener('keydown', handleKeyDown)\n onUnmounted(() => document.removeEventListener('keydown', handleKeyDown))\n\n emit('ready', newGraph)\n\n nextTick(() => {\n if (props.data?.tables) {\n const cells: Cell[] = props.data.tables.map(table =>\n newGraph.createNode(createNodeConfig(table))\n )\n\n if (props.data.relations?.length) {\n props.data.relations.forEach(relation => {\n cells.push(\n newGraph.createEdge({\n source: {\n cell: relation.sourceTable,\n port: `${relation.sourceTable}_${relation.sourceField}`,\n },\n target: {\n cell: relation.targetTable,\n port: `${relation.targetTable}_${relation.targetField}`,\n },\n attrs: { line: { stroke: '#A2B1C3', strokeWidth: 2 } },\n })\n )\n })\n }\n\n newGraph.resetCells(cells)\n setTimeout(\n () => newGraph.zoomToFit({ padding: 20, maxScale: 1 }),\n 300\n )\n }\n })\n },\n { immediate: true }\n )\n\n watch(\n () => props.data,\n newData => {\n if (graph.value && newData?.tables) {\n const cells: Cell[] = newData.tables.map(table =>\n graph.value!.createNode(createNodeConfig(table))\n )\n\n // 加载关系连线\n if (newData.relations?.length) {\n newData.relations.forEach(relation => {\n cells.push(\n graph.value!.createEdge({\n source: {\n cell: relation.sourceTable,\n port: `${relation.sourceTable}_${relation.sourceField}`,\n },\n target: {\n cell: relation.targetTable,\n port: `${relation.targetTable}_${relation.targetField}`,\n },\n attrs: { line: { stroke: '#A2B1C3', strokeWidth: 2 } },\n })\n )\n })\n }\n\n graph.value.resetCells(cells)\n }\n },\n { deep: true }\n )\n\n onMounted(() => initGraph())\n\n defineExpose({\n getGraph: () => graph.value ?? undefined,\n getData: getCurrentData,\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","import type { Ref } from 'vue'\r\nimport type { Graph, Node } from '@antv/x6'\r\n\r\nexport interface EdgeInteractionOptions {\r\n /** 连线默认颜色 */\r\n defaultColor?: string\r\n /** 连线高亮颜色 */\r\n highlightColor?: string\r\n /** 默认线宽 */\r\n strokeWidth?: number\r\n /** 高亮线宽 */\r\n highlightStrokeWidth?: number\r\n /** 端口位置名称列表(用于控制 mouseenter/leave 显隐) */\r\n portPositions?: string[]\r\n /** 数据变更回调 */\r\n onDataChange?: () => void\r\n}\r\n\r\nconst DEFAULT_OPTIONS: Required<EdgeInteractionOptions> = {\r\n defaultColor: '#A2B1C3',\r\n highlightColor: '#ff4d4f',\r\n strokeWidth: 2,\r\n highlightStrokeWidth: 3,\r\n portPositions: [],\r\n onDataChange: () => {},\r\n}\r\n\r\n/**\r\n * 图表交互 composable — 统一管理连线点击/高亮/删除 + 端口显隐\r\n * @param graph - X6 Graph 实例引用\r\n * @param options - 交互配置\r\n */\r\nexport function useEdgeInteraction(\r\n graph: Ref<Graph | null>,\r\n options: EdgeInteractionOptions = {}\r\n) {\r\n const config = { ...DEFAULT_OPTIONS, ...options }\r\n\r\n /** 重置所有连线颜色 */\r\n const resetEdgeStyles = () => {\r\n graph.value?.getEdges().forEach(edge => {\r\n edge.attr('line/stroke', config.defaultColor)\r\n edge.attr('line/strokeWidth', config.strokeWidth)\r\n })\r\n }\r\n\r\n /** 高亮指定连线 */\r\n const highlightEdge = (edge: any) => {\r\n resetEdgeStyles()\r\n edge.attr('line/stroke', config.highlightColor)\r\n edge.attr('line/strokeWidth', config.highlightStrokeWidth)\r\n }\r\n\r\n /** 切换端口可见性 */\r\n const togglePorts = (node: Node, opacity: number) => {\r\n config.portPositions.forEach(pos =>\r\n node.attr(`port-${pos}/style/opacity`, opacity)\r\n )\r\n }\r\n\r\n /**\r\n * 绑定标准交互事件到 graph 实例\r\n * - edge:click → 高亮\r\n * - edge:dblclick → 删除\r\n * - blank:click / node:click → 重置颜色\r\n * - node:mouseenter / mouseleave → 端口显隐(如配置了 portPositions)\r\n */\r\n const bindInteractions = () => {\r\n const g = graph.value\r\n if (!g) return\r\n\r\n // 连线点击高亮\r\n g.on('edge:click', ({ edge }) => highlightEdge(edge))\r\n\r\n // 连线双击删除\r\n g.on('edge:dblclick', ({ edge }) => {\r\n edge.remove()\r\n config.onDataChange()\r\n })\r\n\r\n // 点击空白 / 节点时重置颜色\r\n g.on('blank:click', resetEdgeStyles)\r\n g.on('node:click', resetEdgeStyles)\r\n\r\n // 连线创建时通知数据变更\r\n g.on('edge:connected', config.onDataChange)\r\n\r\n // 端口显隐(如果配置了 portPositions)\r\n if (config.portPositions.length > 0) {\r\n g.on('node:mouseenter', ({ node }) => togglePorts(node, 1))\r\n g.on('node:mouseleave', ({ node }) => togglePorts(node, 0))\r\n }\r\n }\r\n\r\n return { resetEdgeStyles, highlightEdge, togglePorts, bindInteractions }\r\n}\r\n","export const elementTypes = {\r\n \"start-event\": {\r\n name: \"开始\",\r\n title: \"开始事件\",\r\n iconClass: \"circle start-event\",\r\n },\r\n activity: { name: \"任务\", title: \"任务活动\", iconClass: \"rect activity\" },\r\n gateway: { name: \"网关\", title: \"排他网关\", iconClass: \"diamond gateway\" },\r\n \"end-event\": {\r\n name: \"结束\",\r\n title: \"结束事件\",\r\n iconClass: \"circle end-event\",\r\n },\r\n};\r\n\r\nexport const elementTypeNames = {\r\n event: \"事件\",\r\n activity: \"活动\",\r\n gateway: \"网关\",\r\n \"bpmn-edge\": \"连接线\",\r\n};\r\n\r\n/* 端口位置配置 */\r\nexport const portPositions = [\"top\", \"right\", \"bottom\", \"left\"];\r\n\r\n/* 端口属性配置函数 */\r\nexport const createPortAttrs = (\r\n positions: string[],\r\n nodeType: \"circle\" | \"rect\" | \"polygon\" = \"rect\",\r\n) =>\r\n positions.reduce((acc, pos) => {\r\n const isCircle = nodeType === \"circle\";\r\n const refConfig =\r\n pos === \"top\"\r\n ? isCircle\r\n ? { refCx: 0.5, refCy: 0 }\r\n : { refX: 0.5, refY: 0 }\r\n : pos === \"right\"\r\n ? isCircle\r\n ? { refCx: 1, refCy: 0.5 }\r\n : { refX: 1, refY: 0.5 }\r\n : pos === \"bottom\"\r\n ? isCircle\r\n ? { refCx: 0.5, refCy: 1 }\r\n : { refX: 0.5, refY: 1 }\r\n : isCircle\r\n ? { refCx: 0, refCy: 0.5 }\r\n : { refX: 0, refY: 0.5 };\r\n\r\n acc[`port-${pos}`] = {\r\n ref: \"body\",\r\n ...refConfig,\r\n r: 4,\r\n fill: \"#31d0c6\",\r\n stroke: \"#ffffff\",\r\n strokeWidth: 2,\r\n magnet: true,\r\n style: { cursor: \"crosshair\", opacity: 0, transition: \"opacity 0.2s\" },\r\n };\r\n return acc;\r\n }, {} as any);\r\n\r\n/* 节点配置 */\r\nexport const nodeConfigs = {\r\n event: {\r\n inherit: \"circle\",\r\n attrs: {\r\n body: {\r\n strokeWidth: 2,\r\n stroke: \"#5F95FF\",\r\n fill: \"#FFF\",\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n text: {\r\n fontSize: 12,\r\n fill: \"#262626\",\r\n textAnchor: \"middle\",\r\n textVerticalAnchor: \"middle\",\r\n pointerEvents: \"none\",\r\n },\r\n },\r\n },\r\n activity: {\r\n inherit: \"rect\",\r\n attrs: {\r\n body: {\r\n rx: 6,\r\n ry: 6,\r\n stroke: \"#5F95FF\",\r\n fill: \"#EFF4FF\",\r\n strokeWidth: 1,\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n text: {\r\n fontSize: 12,\r\n fill: \"#262626\",\r\n textAnchor: \"middle\",\r\n textVerticalAnchor: \"middle\",\r\n pointerEvents: \"none\",\r\n },\r\n },\r\n },\r\n gateway: {\r\n inherit: \"polygon\",\r\n attrs: {\r\n body: {\r\n refPoints: \"0,10 10,0 20,10 10,20\",\r\n strokeWidth: 2,\r\n stroke: \"#5F95FF\",\r\n fill: \"#EFF4FF\",\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n text: {\r\n fontSize: 20,\r\n fill: \"#5F95FF\",\r\n textAnchor: \"middle\",\r\n textVerticalAnchor: \"middle\",\r\n pointerEvents: \"none\",\r\n },\r\n },\r\n },\r\n};\r\n\r\n/* 边配置 */\r\nexport const edgeConfig = {\r\n inherit: \"edge\",\r\n attrs: {\r\n line: {\r\n stroke: \"#A2B1C3\",\r\n strokeWidth: 2,\r\n targetMarker: {\r\n name: \"block\",\r\n width: 8,\r\n height: 6,\r\n fill: \"#A2B1C3\",\r\n },\r\n cursor: \"pointer\",\r\n },\r\n },\r\n};\r\n\r\n/**\r\n * 获取图形配置(支持主题切换)\r\n * @param isDark 是否为暗色主题\r\n * @returns Graph配置对象\r\n */\r\nexport function getGraphConfig(isDark = false) {\r\n const themeColors = {\r\n background: isDark ? \"#18181c\" : \"#ffffff\",\r\n gridPrimary: isDark ? \"rgba(255, 255, 255, 0.08)\" : \"#eee\",\r\n gridSecondary: isDark ? \"rgba(255, 255, 255, 0.04)\" : \"#ddd\",\r\n };\r\n\r\n return {\r\n background: { color: themeColors.background },\r\n grid: {\r\n visible: true,\r\n type: \"doubleMesh\",\r\n args: [\r\n { color: themeColors.gridPrimary, thickness: 1 },\r\n { color: themeColors.gridSecondary, thickness: 1, factor: 4 },\r\n ],\r\n },\r\n mousewheel: {\r\n enabled: true,\r\n zoomAtMousePosition: true,\r\n modifiers: \"ctrl\",\r\n minScale: 0.5,\r\n maxScale: 3,\r\n },\r\n connecting: {\r\n router: \"manhattan\",\r\n connector: { name: \"rounded\", args: { radius: 8 } },\r\n allowBlank: false,\r\n allowLoop: false,\r\n allowNode: false,\r\n snap: true,\r\n allowEdge: false,\r\n },\r\n highlighting: {\r\n magnetAvailable: {\r\n name: \"stroke\",\r\n args: { attrs: { fill: \"#31d0c6\", stroke: \"#31d0c6\", opacity: 1 } },\r\n },\r\n magnetAdsorbed: {\r\n name: \"stroke\",\r\n args: { attrs: { fill: \"#5F95FF\", stroke: \"#5F95FF\", opacity: 1 } },\r\n },\r\n },\r\n selecting: {\r\n enabled: true,\r\n rubberband: true,\r\n showNodeSelectionBox: true,\r\n },\r\n resizing: true,\r\n rotating: false,\r\n snapline: true,\r\n keyboard: true,\r\n clipboard: true,\r\n };\r\n}\r\n\r\n/* 保持向后兼容 */\r\nexport const graphConfig = getGraphConfig();\r\n\r\n/* 添加元素配置 */\r\nexport const addElementConfigs = {\r\n \"start-event\": {\r\n shape: \"event\",\r\n width: 50,\r\n height: 50,\r\n label: \"开始事件\",\r\n data: { type: \"start\" },\r\n },\r\n \"end-event\": {\r\n shape: \"event\",\r\n width: 50,\r\n height: 50,\r\n label: \"结束事件\",\r\n data: { type: \"end\" },\r\n },\r\n activity: {\r\n shape: \"activity\",\r\n width: 120,\r\n height: 60,\r\n label: \"新活动\",\r\n data: { description: \"\", assignee: \"\" },\r\n },\r\n gateway: {\r\n shape: \"gateway\",\r\n width: 40,\r\n height: 40,\r\n label: \"+\",\r\n data: { type: \"exclusive\" },\r\n },\r\n};\r\n\r\n/* 示例数据 */\r\nexport const sampleData = [\r\n {\r\n id: \"start-1\",\r\n shape: \"event\",\r\n x: 100,\r\n y: 200,\r\n width: 50,\r\n height: 50,\r\n label: \"流程开始\",\r\n data: { type: \"start\" },\r\n },\r\n {\r\n id: \"activity-1\",\r\n shape: \"activity\",\r\n x: 200,\r\n y: 180,\r\n width: 120,\r\n height: 60,\r\n label: \"用户申请\",\r\n data: { description: \"用户提交申请表单\", assignee: \"申请人\" },\r\n },\r\n {\r\n id: \"activity-2\",\r\n shape: \"activity\",\r\n x: 380,\r\n y: 180,\r\n width: 120,\r\n height: 60,\r\n label: \"初审\",\r\n data: { description: \"部门进行初步审核\", assignee: \"部门主管\" },\r\n },\r\n {\r\n id: \"gateway-1\",\r\n shape: \"gateway\",\r\n x: 550,\r\n y: 200,\r\n width: 40,\r\n height: 40,\r\n label: \"+\",\r\n data: { type: \"exclusive\" },\r\n },\r\n {\r\n id: \"activity-3\",\r\n shape: \"activity\",\r\n x: 650,\r\n y: 120,\r\n width: 120,\r\n height: 60,\r\n label: \"终审\",\r\n data: { description: \"高级主管最终审核\", assignee: \"总监\" },\r\n },\r\n {\r\n id: \"activity-4\",\r\n shape: \"activity\",\r\n x: 650,\r\n y: 260,\r\n width: 120,\r\n height: 60,\r\n label: \"驳回处理\",\r\n data: { description: \"处理驳回流程\", assignee: \"专员\" },\r\n },\r\n {\r\n id: \"end-1\",\r\n shape: \"event\",\r\n x: 820,\r\n y: 140,\r\n width: 50,\r\n height: 50,\r\n label: \"审批通过\",\r\n data: { type: \"end\" },\r\n },\r\n {\r\n id: \"end-2\",\r\n shape: \"event\",\r\n x: 820,\r\n y: 280,\r\n width: 50,\r\n height: 50,\r\n label: \"审批驳回\",\r\n data: { type: \"end\" },\r\n },\r\n {\r\n id: \"edge-1\",\r\n shape: \"bpmn-edge\",\r\n source: \"start-1\",\r\n target: \"activity-1\",\r\n x: 0,\r\n y: 0,\r\n },\r\n {\r\n id: \"edge-2\",\r\n shape: \"bpmn-edge\",\r\n source: \"activity-1\",\r\n target: \"activity-2\",\r\n x: 0,\r\n y: 0,\r\n },\r\n {\r\n id: \"edge-3\",\r\n shape: \"bpmn-edge\",\r\n source: \"activity-2\",\r\n target: \"gateway-1\",\r\n x: 0,\r\n y: 0,\r\n },\r\n {\r\n id: \"edge-4\",\r\n shape: \"bpmn-edge\",\r\n source: \"gateway-1\",\r\n target: \"activity-3\",\r\n label: \"通过\",\r\n x: 0,\r\n y: 0,\r\n },\r\n {\r\n id: \"edge-5\",\r\n shape: \"bpmn-edge\",\r\n source: \"gateway-1\",\r\n target: \"activity-4\",\r\n label: \"驳回\",\r\n x: 0,\r\n y: 0,\r\n },\r\n {\r\n id: \"edge-6\",\r\n shape: \"bpmn-edge\",\r\n source: \"activity-3\",\r\n target: \"end-1\",\r\n x: 0,\r\n y: 0,\r\n },\r\n {\r\n id: \"edge-7\",\r\n shape: \"bpmn-edge\",\r\n source: \"activity-4\",\r\n target: \"end-2\",\r\n x: 0,\r\n y: 0,\r\n },\r\n];\r\n","<template>\r\n <NDrawer\r\n :show=\"show\"\r\n width=\"300\"\r\n title=\"属性设置\"\r\n @update:show=\"emit('update:show', $event)\"\r\n >\r\n <div v-if=\"editingElement\" class=\"property-panel\">\r\n <div class=\"property-item\">\r\n <div class=\"property-label\">名称</div>\r\n <NInput\r\n v-model:value=\"editingElement.label\"\r\n placeholder=\"请输入名称\"\r\n size=\"small\"\r\n />\r\n </div>\r\n <div class=\"property-item\">\r\n <div class=\"property-label\">类型</div>\r\n <NInput :value=\"typeName\" readonly size=\"small\" />\r\n </div>\r\n <div class=\"property-item\" v-if=\"editingElement.shape === 'activity'\">\r\n <div class=\"property-label\">描述</div>\r\n <NInput\r\n v-model:value=\"editingElement.description\"\r\n type=\"textarea\"\r\n :rows=\"3\"\r\n placeholder=\"请输入活动描述\"\r\n size=\"small\"\r\n />\r\n </div>\r\n <div class=\"property-item\" v-if=\"editingElement.shape === 'activity'\">\r\n <div class=\"property-label\">执行人</div>\r\n <NInput\r\n v-model:value=\"editingElement.assignee\"\r\n placeholder=\"请输入执行人\"\r\n size=\"small\"\r\n />\r\n </div>\r\n <div class=\"form-actions\">\r\n <NSpace>\r\n <NButton @click=\"emit('save')\" type=\"primary\" size=\"small\">\r\n 保存\r\n </NButton>\r\n <NButton @click=\"emit('update:show', false)\" size=\"small\">\r\n 取消\r\n </NButton>\r\n <NButton @click=\"emit('delete')\" type=\"error\" size=\"small\">\r\n 删除\r\n </NButton>\r\n </NSpace>\r\n </div>\r\n </div>\r\n </NDrawer>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from \"vue\";\r\nimport { NDrawer, NInput, NSpace, NButton } from \"naive-ui\";\r\nimport { elementTypeNames } from \"../data\";\r\n\r\ninterface BPMNElement {\r\n id: string;\r\n shape: string;\r\n label?: string;\r\n description?: string;\r\n assignee?: string;\r\n [key: string]: any;\r\n}\r\n\r\ndefineProps<{\r\n show: boolean;\r\n}>();\r\n\r\nconst editingElement = defineModel<BPMNElement>(\"editingElement\");\r\n\r\nconst emit = defineEmits<{\r\n \"update:show\": [value: boolean];\r\n save: [];\r\n delete: [];\r\n}>();\r\n\r\nconst typeName = computed(\r\n () =>\r\n elementTypeNames[\r\n editingElement.value?.shape as keyof typeof elementTypeNames\r\n ] ||\r\n editingElement.value?.shape ||\r\n \"\",\r\n);\r\n</script>\r\n","<template>\n <div class=\"bpmn-layout\">\n <div\n class=\"top-toolbar\"\n v-if=\"showToolbar\"\n >\n <div class=\"toolbar-section\">\n <div class=\"toolbar-group\">\n <NButton\n @click=\"clearAll\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:delete-outline\"\n :size=\"16\"\n />\n </template>\n 清空\n </NButton>\n </div>\n <div class=\"toolbar-group\">\n <NButton\n @click=\"centerContent\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:image-filter-center-focus\"\n :size=\"16\"\n />\n </template>\n 居中\n </NButton>\n <NButton\n @click=\"zoomToFit\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:fit-to-screen\"\n :size=\"16\"\n />\n </template>\n 适应\n </NButton>\n </div>\n <div class=\"toolbar-group\">\n <NDropdown\n :options=\"exportOptions\"\n @select=\"(key: string) => handleExport(key, getCurrentData)\"\n >\n <NButton size=\"small\">\n <template #icon>\n <C_Icon\n name=\"mdi:export\"\n :size=\"16\"\n />\n </template>\n 导出\n </NButton>\n </NDropdown>\n </div>\n </div>\n </div>\n\n <div class=\"main-content\">\n <div\n class=\"left-panel\"\n v-if=\"showToolbar\"\n >\n <div class=\"panel-title\">组件</div>\n <div class=\"element-grid\">\n <div\n v-for=\"(item, key) in elementTypes\"\n :key=\"key\"\n class=\"element-item\"\n @click=\"addElement(key)\"\n :title=\"item.title\"\n >\n <div :class=\"['element-icon', item.iconClass]\"></div>\n <span>{{ item.name }}</span>\n </div>\n </div>\n </div>\n\n <div class=\"graph-wrapper\">\n <div\n ref=\"containerRef\"\n class=\"graph-container\"\n ></div>\n </div>\n </div>\n\n <BPMNPropertyEditor\n :show=\"showEditor\"\n v-model:editing-element=\"editingElement\"\n @update:show=\"showEditor = $event\"\n @save=\"saveElement\"\n @delete=\"deleteElement\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, onMounted } from 'vue'\n import { NButton, NDropdown } from 'naive-ui'\n import { Graph } from '@antv/x6'\n import { useGraphBase } from '../../composables/useGraphBase'\n import { useGraphExport } from '../../composables/useGraphExport'\n import { useEdgeInteraction } from '../../composables/useEdgeInteraction'\n import BPMNPropertyEditor from './components/BPMNPropertyEditor.vue'\n import C_Icon from '../../../C_Icon/index.vue'\n import {\n elementTypes,\n portPositions,\n createPortAttrs,\n nodeConfigs,\n edgeConfig,\n getGraphConfig,\n addElementConfigs,\n sampleData,\n } from './data'\n\n interface BPMNElement {\n id: string\n shape: string\n x: number\n y: number\n width?: number\n height?: number\n label?: string\n source?: string\n target?: string\n description?: string\n assignee?: string\n data?: any\n [key: string]: any\n }\n\n interface Props {\n data?: BPMNElement[] | Record<string, BPMNElement[]>\n showToolbar?: boolean\n readonly?: boolean\n width?: number | string\n height?: number | string\n theme?: 'light' | 'dark'\n }\n\n const props = withDefaults(defineProps<Props>(), {\n showToolbar: true,\n readonly: false,\n width: '100%',\n height: '600px',\n })\n\n const emit = defineEmits<{\n ready: [graph: Graph]\n 'data-change': [data: BPMNElement[]]\n }>()\n\n // ==================== Composables ====================\n const containerRef = ref<HTMLDivElement>()\n const isDark = computed(() => props.theme === 'dark')\n const { graph, initGraph, centerContent, zoomToFit } = useGraphBase(\n containerRef,\n isDark\n )\n const { exportOptions, handleExport } = useGraphExport(graph, 'bpmn-diagram')\n const { bindInteractions } = useEdgeInteraction(graph, {\n portPositions,\n onDataChange: () => emitDataChange(),\n })\n\n // ==================== 编辑器状态 ====================\n const showEditor = ref(false)\n const editingElement = ref<BPMNElement>()\n\n // ==================== 工具函数 ====================\n const getLabel = (cell: any): string =>\n String(cell.attr('text/text') || cell.attr('label/text') || '')\n\n const normalizeData = (data: any): any[] => {\n if (!data) return []\n if (Array.isArray(data)) return data\n const result: any[] = []\n Object.values(data).forEach((arr: any) => {\n if (Array.isArray(arr)) result.push(...arr)\n })\n return result\n }\n\n // ==================== 节点注册 ====================\n const registerNodes = () => {\n const portMarkup = portPositions.map(pos => ({\n tagName: 'circle',\n selector: `port-${pos}`,\n }))\n\n const nodeTypes = ['event', 'activity', 'gateway'] as const\n const bodyTags = { event: 'circle', activity: 'rect', gateway: 'polygon' }\n\n nodeTypes.forEach(type => {\n Graph.registerNode(\n type,\n {\n ...nodeConfigs[type],\n markup: [\n { tagName: bodyTags[type], selector: 'body' },\n { tagName: 'text', selector: 'text' },\n ...portMarkup,\n ],\n attrs: {\n ...nodeConfigs[type].attrs,\n ...createPortAttrs(portPositions, bodyTags[type] as any),\n },\n },\n true\n )\n })\n\n Graph.registerEdge('bpmn-edge', edgeConfig, true)\n }\n\n // ==================== 数据操作 ====================\n const loadData = (data: any[]) => {\n if (!graph.value || !data.length) return\n const cells = data.map(item => {\n const { data: nodeData, ...cellProps } = item\n const cell =\n item.shape === 'bpmn-edge'\n ? graph.value!.createEdge(cellProps)\n : graph.value!.createNode(cellProps)\n if (nodeData) cell.setData(nodeData)\n return cell\n })\n graph.value.resetCells(cells)\n setTimeout(() => graph.value!.zoomToFit({ padding: 50, maxScale: 1 }), 200)\n }\n\n const addElement = (type: string) => {\n if (!graph.value) return\n const config = addElementConfigs[type as keyof typeof addElementConfigs]\n if (!config) return\n\n const centerX = (graph.value.options.width as number) / 2\n const centerY = (graph.value.options.height as number) / 2\n const { data: nodeData, ...nodeProps } = {\n id: `${type}-${Date.now()}`,\n x: centerX + Math.random() * 100 - 50,\n y: centerY + Math.random() * 100 - 50,\n ...config,\n }\n const node = graph.value.createNode(nodeProps)\n if (nodeData) node.setData(nodeData)\n graph.value.addCell(node)\n emitDataChange()\n }\n\n const clearAll = () => {\n graph.value?.clearCells()\n emitDataChange()\n }\n\n // ==================== 元素编辑 ====================\n const editElement = (cell: any) => {\n const cellData = cell.getData() || {}\n editingElement.value = {\n id: cell.id,\n shape: cell.shape,\n label: getLabel(cell),\n description: cellData.description || '',\n assignee: cellData.assignee || '',\n x: 0,\n y: 0,\n }\n showEditor.value = true\n }\n\n const saveElement = () => {\n if (!graph.value || !editingElement.value) return\n const cell = graph.value.getCellById(editingElement.value.id)\n if (cell) {\n cell.setData({\n description: editingElement.value.description,\n assignee: editingElement.value.assignee,\n })\n cell.attr('text/text', editingElement.value.label || '')\n cell.attr('label/text', editingElement.value.label || '')\n }\n showEditor.value = false\n emitDataChange()\n }\n\n const deleteElement = () => {\n if (!graph.value || !editingElement.value) return\n graph.value.getCellById(editingElement.value.id)?.remove()\n showEditor.value = false\n emitDataChange()\n }\n\n // ==================== 数据获取 ====================\n const getCurrentData = (): BPMNElement[] => {\n if (!graph.value) return []\n return [\n ...graph.value.getNodes().map((node: any) => ({\n id: node.id,\n shape: node.shape,\n x: node.getPosition().x,\n y: node.getPosition().y,\n width: node.getSize().width,\n height: node.getSize().height,\n label: getLabel(node),\n data: node.getData() || {},\n })),\n ...graph.value.getEdges().map((edge: any) => ({\n id: edge.id,\n shape: 'bpmn-edge',\n source: edge.getSourceCellId() || '',\n target: edge.getTargetCellId() || '',\n label: getLabel(edge),\n x: 0,\n y: 0,\n })),\n ] as BPMNElement[]\n }\n\n const emitDataChange = () => emit('data-change', getCurrentData())\n\n // ==================== Graph 事件绑定 ====================\n watch(\n graph,\n newGraph => {\n if (!(newGraph instanceof Graph)) return\n\n if (!props.readonly) {\n bindInteractions()\n newGraph.on('node:dblclick', ({ node }) => editElement(node))\n newGraph.on('node:moved', emitDataChange)\n }\n\n emit('ready', newGraph)\n loadData(sampleData)\n },\n { immediate: true }\n )\n\n watch(\n () => props.data,\n newData => {\n if (!newData || !graph.value) return\n const normalized = normalizeData(newData)\n if (normalized.length > 0) loadData(normalized)\n },\n { deep: true }\n )\n\n onMounted(async () => {\n registerNodes()\n const bpmnConfig = getGraphConfig()\n await initGraph({\n ...bpmnConfig,\n connecting: {\n ...bpmnConfig.connecting,\n createEdge: () => graph.value!.createEdge({ shape: 'bpmn-edge' }),\n validateConnection: ({\n sourceView,\n targetView,\n sourceMagnet,\n targetMagnet,\n }: any) =>\n sourceView !== targetView &&\n !!sourceMagnet &&\n !!targetMagnet &&\n sourceMagnet.getAttribute('magnet') === 'true' &&\n targetMagnet.getAttribute('magnet') === 'true',\n },\n })\n })\n\n defineExpose({\n getGraph: () => graph.value,\n getData: getCurrentData,\n loadData,\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","<template>\n <NDrawer\n :show=\"show\"\n width=\"450\"\n title=\"编辑类\"\n @update:show=\"emit('update:show', $event)\"\n >\n <div\n v-if=\"editingClass\"\n class=\"class-editor\"\n >\n <NForm label-placement=\"top\">\n <NFormItem label=\"类名\">\n <NInput\n v-model:value=\"editingClass.name\"\n placeholder=\"请输入类名\"\n />\n </NFormItem>\n\n <NDivider style=\"margin: 20px 0\">属性</NDivider>\n <div class=\"section\">\n <div\n v-for=\"(attr, index) in editingClass.attributes\"\n :key=\"index\"\n class=\"item\"\n >\n <NCard\n size=\"small\"\n style=\"margin-bottom: 12px\"\n >\n <template #header>\n <div class=\"section-header\">\n <span style=\"font-size: 13px\"\n >#{{ index + 1 }} {{ attr.name || '新属性' }}</span\n >\n <NButton\n @click=\"editingClass!.attributes.splice(index, 1)\"\n size=\"tiny\"\n type=\"error\"\n quaternary\n style=\"margin-left: auto\"\n >\n 删除\n </NButton>\n </div>\n </template>\n <NSpace\n vertical\n size=\"small\"\n >\n <NSpace>\n <NFormItem\n label=\"属性名\"\n style=\"margin: 0; flex: 1\"\n >\n <NInput\n v-model:value=\"attr.name\"\n placeholder=\"属性名\"\n size=\"small\"\n />\n </NFormItem>\n <NFormItem\n label=\"类型\"\n style=\"margin: 0; flex: 1\"\n >\n <NInput\n v-model:value=\"attr.type\"\n placeholder=\"类型\"\n size=\"small\"\n />\n </NFormItem>\n </NSpace>\n <NFormItem\n label=\"可见性\"\n style=\"margin: 0\"\n >\n <NRadioGroup\n v-model:value=\"attr.visibility\"\n size=\"small\"\n >\n <NRadio value=\"public\">+ public</NRadio>\n <NRadio value=\"private\">- private</NRadio>\n <NRadio value=\"protected\"># protected</NRadio>\n </NRadioGroup>\n </NFormItem>\n </NSpace>\n </NCard>\n </div>\n <NButton\n @click=\"\n editingClass!.attributes.push({\n name: 'newAttribute',\n type: 'string',\n visibility: 'private',\n })\n \"\n dashed\n block\n type=\"primary\"\n ghost\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:plus\"\n :size=\"16\"\n />\n </template>\n 添加属性\n </NButton>\n </div>\n\n <NDivider style=\"margin: 20px 0\">方法</NDivider>\n <div class=\"section\">\n <div\n v-for=\"(method, index) in editingClass.methods\"\n :key=\"index\"\n class=\"item\"\n >\n <NCard\n size=\"small\"\n style=\"margin-bottom: 12px\"\n >\n <template #header>\n <div class=\"section-header\">\n <span style=\"font-size: 13px\"\n >#{{ index + 1 }} {{ method.name || '新方法' }}</span\n >\n <NButton\n @click=\"editingClass!.methods.splice(index, 1)\"\n size=\"tiny\"\n type=\"error\"\n quaternary\n style=\"margin-left: auto\"\n >\n 删除\n </NButton>\n </div>\n </template>\n <NSpace\n vertical\n size=\"small\"\n >\n <NSpace>\n <NFormItem\n label=\"方法名\"\n style=\"margin: 0; flex: 1\"\n >\n <NInput\n v-model:value=\"method.name\"\n placeholder=\"方法名\"\n size=\"small\"\n />\n </NFormItem>\n <NFormItem\n label=\"返回类型\"\n style=\"margin: 0; flex: 1\"\n >\n <NInput\n v-model:value=\"method.returnType\"\n placeholder=\"返回类型\"\n size=\"small\"\n />\n </NFormItem>\n </NSpace>\n <NFormItem\n label=\"可见性\"\n style=\"margin: 0\"\n >\n <NRadioGroup\n v-model:value=\"method.visibility\"\n size=\"small\"\n >\n <NRadio value=\"public\">+ public</NRadio>\n <NRadio value=\"private\">- private</NRadio>\n <NRadio value=\"protected\"># protected</NRadio>\n </NRadioGroup>\n </NFormItem>\n </NSpace>\n </NCard>\n </div>\n <NButton\n @click=\"\n editingClass!.methods.push({\n name: 'newMethod',\n returnType: 'void',\n visibility: 'public',\n })\n \"\n dashed\n block\n type=\"primary\"\n ghost\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:plus\"\n :size=\"16\"\n />\n </template>\n 添加方法\n </NButton>\n </div>\n\n <NDivider style=\"margin: 20px 0\"></NDivider>\n <NSpace justify=\"space-between\">\n <NButton\n @click=\"emit('delete')\"\n type=\"error\"\n ghost\n >\n <template #icon>\n <C_Icon\n name=\"mdi:delete\"\n :size=\"16\"\n />\n </template>\n 删除类\n </NButton>\n <NSpace>\n <NButton @click=\"emit('update:show', false)\">取消</NButton>\n <NButton\n @click=\"emit('save')\"\n type=\"primary\"\n >\n 保存\n </NButton>\n </NSpace>\n </NSpace>\n </NForm>\n </div>\n </NDrawer>\n</template>\n\n<script setup lang=\"ts\">\n import {\n NDrawer,\n NForm,\n NFormItem,\n NInput,\n NCard,\n NSpace,\n NButton,\n NDivider,\n NRadioGroup,\n NRadio,\n } from 'naive-ui'\n import type { UMLClass } from '../../../types'\n import C_Icon from '../../../../C_Icon/index.vue'\n\n defineProps<{\n show: boolean\n }>()\n\n const editingClass = defineModel<UMLClass>('editingClass')\n\n const emit = defineEmits<{\n 'update:show': [value: boolean]\n save: []\n delete: []\n }>()\n</script>\n\n<style lang=\"scss\" scoped>\n .class-editor {\n padding: 20px;\n height: calc(100vh - 60px);\n overflow-y: auto;\n }\n\n .section {\n max-height: 300px;\n overflow-y: auto;\n padding-right: 4px;\n\n &::-webkit-scrollbar {\n width: 6px;\n }\n\n &::-webkit-scrollbar-thumb {\n background: #d4d4d4;\n border-radius: 3px;\n }\n }\n\n .section-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .item {\n margin-bottom: 8px;\n }\n\n .section .n-card {\n border: 1px solid #e8e8e8;\n }\n\n .section .n-card-header {\n padding: 8px 12px;\n background: #fafafa;\n border-bottom: 1px solid #e8e8e8;\n }\n\n .section .n-card__content {\n padding: 12px;\n }\n\n .section .n-form-item {\n margin-bottom: 0;\n }\n\n .section .n-form-item-label {\n font-size: 12px;\n margin-bottom: 4px;\n color: #666;\n }\n</style>\n","import type { UMLAttribute, UMLMethod } from \"../../types\";\r\n\r\nexport const visibilityMap = {\r\n public: \"+\",\r\n private: \"-\",\r\n protected: \"#\",\r\n};\r\n\r\n/* 连线类型配置 */\r\nexport const edgeTypes = {\r\n extends: {\r\n strokeDasharray: 0,\r\n targetMarker: {\r\n name: \"block\",\r\n width: 10,\r\n height: 8,\r\n fill: \"white\",\r\n stroke: \"#722ed1\",\r\n strokeWidth: 2,\r\n },\r\n },\r\n implement: {\r\n strokeDasharray: \"8,4\",\r\n targetMarker: {\r\n name: \"block\",\r\n width: 10,\r\n height: 8,\r\n fill: \"white\",\r\n stroke: \"#722ed1\",\r\n strokeWidth: 2,\r\n },\r\n },\r\n composition: {\r\n strokeDasharray: 0,\r\n sourceMarker: {\r\n name: \"diamond\",\r\n width: 12,\r\n height: 8,\r\n fill: \"#722ed1\",\r\n stroke: \"#722ed1\",\r\n },\r\n },\r\n aggregation: {\r\n strokeDasharray: 0,\r\n sourceMarker: {\r\n name: \"diamond\",\r\n width: 12,\r\n height: 8,\r\n fill: \"white\",\r\n stroke: \"#722ed1\",\r\n strokeWidth: 2,\r\n },\r\n },\r\n association: {\r\n strokeDasharray: 0,\r\n targetMarker: { name: \"classic\", size: 8, fill: \"#722ed1\" },\r\n },\r\n};\r\n\r\n/* 端口配置 */\r\nexport const portConfig = [\"top\", \"right\", \"bottom\", \"left\"].reduce(\r\n (acc, pos) => {\r\n const refConfig =\r\n pos === \"top\"\r\n ? { refX: 0.5, refY: 0 }\r\n : pos === \"right\"\r\n ? { refX: 1, refY: 0.5 }\r\n : pos === \"bottom\"\r\n ? { refX: 0.5, refY: 1 }\r\n : { refX: 0, refY: 0.5 };\r\n acc[`port-${pos}`] = {\r\n ref: \"body\",\r\n ...refConfig,\r\n r: 4,\r\n fill: \"#31d0c6\",\r\n stroke: \"#ffffff\",\r\n strokeWidth: 2,\r\n magnet: true,\r\n style: {\r\n cursor: \"crosshair\",\r\n opacity: 0,\r\n transition: \"opacity 0.2s\",\r\n },\r\n };\r\n return acc;\r\n },\r\n {} as any,\r\n);\r\n\r\n/* UML类节点配置 */\r\nexport const classNodeConfig = {\r\n inherit: \"rect\",\r\n markup: [\r\n { tagName: \"rect\", selector: \"body\" },\r\n { tagName: \"rect\", selector: \"name-rect\" },\r\n { tagName: \"rect\", selector: \"attrs-rect\" },\r\n { tagName: \"rect\", selector: \"methods-rect\" },\r\n { tagName: \"text\", selector: \"name-text\" },\r\n { tagName: \"text\", selector: \"attrs-text\" },\r\n { tagName: \"text\", selector: \"methods-text\" },\r\n { tagName: \"circle\", selector: \"port-top\" },\r\n { tagName: \"circle\", selector: \"port-right\" },\r\n { tagName: \"circle\", selector: \"port-bottom\" },\r\n { tagName: \"circle\", selector: \"port-left\" },\r\n ],\r\n attrs: {\r\n rect: { width: 160 },\r\n body: {\r\n stroke: \"#5f95ff\",\r\n strokeWidth: 1,\r\n fill: \"#fff\",\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n \"name-rect\": {\r\n fill: \"#5f95ff\",\r\n stroke: \"#fff\",\r\n strokeWidth: 0.5,\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n \"attrs-rect\": {\r\n fill: \"#eff4ff\",\r\n stroke: \"#fff\",\r\n strokeWidth: 0.5,\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n \"methods-rect\": {\r\n fill: \"#eff4ff\",\r\n stroke: \"#fff\",\r\n strokeWidth: 0.5,\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n \"name-text\": {\r\n ref: \"name-rect\",\r\n refY: 0.5,\r\n refX: 0.5,\r\n textAnchor: \"middle\",\r\n fontWeight: \"bold\",\r\n fill: \"#fff\",\r\n fontSize: 12,\r\n pointerEvents: \"none\",\r\n },\r\n \"attrs-text\": {\r\n ref: \"attrs-rect\",\r\n refY: 0.5,\r\n refX: 5,\r\n textAnchor: \"left\",\r\n fill: \"black\",\r\n fontSize: 10,\r\n pointerEvents: \"none\",\r\n },\r\n \"methods-text\": {\r\n ref: \"methods-rect\",\r\n refY: 0.5,\r\n refX: 5,\r\n textAnchor: \"left\",\r\n fill: \"black\",\r\n fontSize: 10,\r\n pointerEvents: \"none\",\r\n },\r\n ...portConfig,\r\n },\r\n};\r\n\r\n/* 图形配置 */\r\nexport const graphConfig = {\r\n grid: true,\r\n panning: true,\r\n mousewheel: {\r\n enabled: true,\r\n zoomAtMousePosition: true,\r\n modifiers: \"ctrl\",\r\n minScale: 0.5,\r\n maxScale: 3,\r\n },\r\n};\r\n\r\n/* 连接配置 */\r\nexport const connectingConfig = {\r\n router: \"manhattan\",\r\n connector: { name: \"rounded\", args: { radius: 8 } },\r\n allowBlank: false,\r\n allowLoop: false,\r\n allowNode: false,\r\n snap: true,\r\n allowEdge: false,\r\n};\r\n\r\n/* 高亮配置 */\r\nexport const highlightingConfig = {\r\n magnetAvailable: {\r\n name: \"stroke\",\r\n args: { attrs: { fill: \"#31d0c6\", stroke: \"#31d0c6\", opacity: 1 } },\r\n },\r\n magnetAdsorbed: {\r\n name: \"stroke\",\r\n args: { attrs: { fill: \"#5F95FF\", stroke: \"#5F95FF\", opacity: 1 } },\r\n },\r\n};\r\n\r\n/* 默认边配置 */\r\nexport const defaultEdgeConfig = {\r\n shape: \"extends\",\r\n attrs: {\r\n line: {\r\n stroke: \"#722ed1\",\r\n strokeWidth: 2,\r\n targetMarker: {\r\n name: \"block\",\r\n width: 8,\r\n height: 6,\r\n fill: \"#722ed1\",\r\n },\r\n },\r\n },\r\n};\r\n\r\n/* 示例类数据 */\r\nexport const sampleClasses = [\r\n {\r\n id: \"animal\",\r\n name: \"<<Abstract>>\\n动物\",\r\n x: 342,\r\n y: 98,\r\n attributes: [{ name: \"名字\", type: \"string\", visibility: \"public\" }],\r\n methods: [\r\n { name: \"新陈代谢\", returnType: \"void\", visibility: \"public\" },\r\n { name: \"繁殖\", returnType: \"void\", visibility: \"public\" },\r\n ],\r\n },\r\n {\r\n id: \"bird\",\r\n name: \"鸟\",\r\n x: 575,\r\n y: 280,\r\n attributes: [\r\n { name: \"羽毛\", type: \"string\", visibility: \"public\" },\r\n { name: \"下蛋\", type: \"boolean\", visibility: \"public\" },\r\n ],\r\n methods: [],\r\n },\r\n {\r\n id: \"mammal\",\r\n name: \"哺乳动物\",\r\n x: 844,\r\n y: 319,\r\n attributes: [{ name: \"翅膀\", type: \"boolean\", visibility: \"public\" }],\r\n methods: [],\r\n },\r\n {\r\n id: \"dog\",\r\n name: \"狗\",\r\n x: 656,\r\n y: 456,\r\n attributes: [{ name: \"下蛋\", type: \"boolean\", visibility: \"public\" }],\r\n methods: [],\r\n },\r\n {\r\n id: \"enterprise\",\r\n name: \"企鹅\",\r\n x: 984,\r\n y: 456,\r\n attributes: [{ name: \"下蛋\", type: \"boolean\", visibility: \"public\" }],\r\n methods: [],\r\n },\r\n {\r\n id: \"sparrow\",\r\n name: \"麻雀\",\r\n x: 531,\r\n y: 608,\r\n attributes: [{ name: \"学飞\", type: \"boolean\", visibility: \"public\" }],\r\n methods: [],\r\n },\r\n {\r\n id: \"interface-flying\",\r\n name: \"<<interface>>\\n飞翔\",\r\n x: 762,\r\n y: 608,\r\n attributes: [{ name: \"下蛋\", type: \"boolean\", visibility: \"public\" }],\r\n methods: [],\r\n },\r\n { id: \"qemu\", name: \"气球\", x: 981, y: 608, attributes: [], methods: [] },\r\n];\r\n\r\n/* 示例连接关系 */\r\nexport const sampleConnections = [\r\n { id: \"edge-1\", shape: \"extends\", source: \"bird\", target: \"animal\" },\r\n { id: \"edge-2\", shape: \"extends\", source: \"mammal\", target: \"animal\" },\r\n { id: \"edge-3\", shape: \"extends\", source: \"dog\", target: \"mammal\" },\r\n {\r\n id: \"edge-4\",\r\n shape: \"extends\",\r\n source: \"enterprise\",\r\n target: \"mammal\",\r\n },\r\n { id: \"edge-5\", shape: \"extends\", source: \"sparrow\", target: \"bird\" },\r\n {\r\n id: \"edge-6\",\r\n shape: \"implement\",\r\n source: \"sparrow\",\r\n target: \"interface-flying\",\r\n },\r\n {\r\n id: \"edge-7\",\r\n shape: \"implement\",\r\n source: \"enterprise\",\r\n target: \"interface-flying\",\r\n },\r\n {\r\n id: \"edge-8\",\r\n shape: \"association\",\r\n source: \"bird\",\r\n target: \"mammal\",\r\n label: \"1:2\",\r\n },\r\n];\r\n\r\n/* 工具函数 */\r\nexport const getVisibilitySymbol = (visibility: string) =>\r\n visibilityMap[visibility as keyof typeof visibilityMap] || \"+\";\r\n\r\n/* 新类模板 */\r\nexport const newClassTemplate = {\r\n name: \"新类\",\r\n attributes: [\r\n { name: \"attribute\", type: \"string\", visibility: \"private\" },\r\n ] as UMLAttribute[],\r\n methods: [\r\n { name: \"method\", returnType: \"void\", visibility: \"public\" },\r\n ] as UMLMethod[],\r\n position: { x: 100, y: 100 },\r\n};\r\n","<template>\n <div class=\"uml-layout\">\n <div class=\"toolbar\" v-if=\"showToolbar\">\n <NSpace>\n <NButton @click=\"addClass\" type=\"primary\" size=\"small\">\n <template #icon>\n <C_Icon name=\"mdi:plus-box\" :size=\"16\" />\n </template>\n 添加类\n </NButton>\n <NButton @click=\"centerContent\" size=\"small\">\n <template #icon>\n <C_Icon name=\"mdi:image-filter-center-focus\" :size=\"16\" />\n </template>\n 居中\n </NButton>\n <NButton @click=\"zoomToFit\" size=\"small\">\n <template #icon>\n <C_Icon name=\"mdi:fit-to-screen\" :size=\"16\" />\n </template>\n 适应\n </NButton>\n <NDropdown\n :options=\"exportOptions\"\n @select=\"(key: string) => handleExport(key, getCurrentData)\"\n >\n <NButton size=\"small\">\n <template #icon>\n <C_Icon name=\"mdi:export\" :size=\"16\" />\n </template>\n 导出\n </NButton>\n </NDropdown>\n </NSpace>\n </div>\n\n <div\n ref=\"containerRef\"\n class=\"graph-container\"\n :style=\"{ width: props.width, height: props.height }\"\n ></div>\n\n <UMLClassEditor\n :show=\"showEditor\"\n v-model:editing-class=\"editingClass\"\n @update:show=\"showEditor = $event\"\n @save=\"saveClass\"\n @delete=\"deleteClass\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted } from \"vue\";\nimport { NSpace, NButton, NDropdown } from \"naive-ui\";\nimport { Graph, ObjectExt, type Node, type Cell } from \"@antv/x6\";\nimport { useGraphBase } from \"../../composables/useGraphBase\";\nimport { useGraphExport } from \"../../composables/useGraphExport\";\nimport { useEdgeInteraction } from \"../../composables/useEdgeInteraction\";\nimport type { UMLClass, UMLDiagramData } from \"../../types\";\nimport UMLClassEditor from \"./components/UMLClassEditor.vue\";\nimport C_Icon from \"../../../C_Icon/index.vue\";\nimport {\n edgeTypes,\n classNodeConfig,\n connectingConfig,\n highlightingConfig,\n defaultEdgeConfig,\n sampleClasses,\n sampleConnections,\n getVisibilitySymbol,\n newClassTemplate,\n} from \"./data\";\n\ninterface Props {\n data?: UMLDiagramData;\n showToolbar?: boolean;\n readonly?: boolean;\n width?: number | string;\n height?: number | string;\n theme?: \"light\" | \"dark\";\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n showToolbar: true,\n readonly: false,\n width: \"100%\",\n height: \"600px\",\n});\n\nconst emit = defineEmits<{\n ready: [graph: any];\n \"data-change\": [data: UMLDiagramData];\n}>();\n\n// ==================== Composables ====================\nconst containerRef = ref<HTMLDivElement>();\nconst isDark = computed(() => props.theme === \"dark\");\nconst { graph, initGraph, centerContent, zoomToFit } = useGraphBase(\n containerRef,\n isDark,\n);\nconst { exportOptions, handleExport } = useGraphExport(graph, \"uml-diagram\");\nconst { bindInteractions } = useEdgeInteraction(graph, {\n defaultColor: \"#722ed1\",\n portPositions: [\"top\", \"right\", \"bottom\", \"left\"],\n onDataChange: () => emitDataChange(),\n});\n\n// ==================== 编辑器状态 ====================\nconst showEditor = ref(false);\nconst editingClass = ref<UMLClass>();\n\n// ==================== 节点注册 ====================\nconst registerNodes = () => {\n Graph.registerNode(\n \"class\",\n {\n ...classNodeConfig,\n /** @description 节点属性钩子,用于计算 UML 类图节点布局 */\n propHooks(meta: any) {\n const { name, attributes, methods, ...others } = meta;\n if (!(name && attributes && methods)) return meta;\n\n let offsetY = 0;\n [\n { type: \"name\", text: name },\n { type: \"attrs\", text: attributes },\n { type: \"methods\", text: methods },\n ].forEach((rect) => {\n const height = Array.isArray(rect.text)\n ? rect.text.length * 12 + 16\n : 32;\n ObjectExt.setByPath(\n others,\n `attrs/${rect.type}-text/text`,\n Array.isArray(rect.text) ? rect.text.join(\"\\n\") : rect.text,\n );\n ObjectExt.setByPath(others, `attrs/${rect.type}-rect/height`, height);\n ObjectExt.setByPath(\n others,\n `attrs/${rect.type}-rect/transform`,\n `translate(0,${offsetY})`,\n );\n offsetY += height;\n });\n others.size = { width: 160, height: offsetY };\n return others;\n },\n },\n true,\n );\n\n Object.entries(edgeTypes).forEach(([type, config]) => {\n Graph.registerEdge(\n type,\n {\n inherit: \"edge\",\n attrs: { line: { strokeWidth: 2, stroke: \"#722ed1\", ...config } },\n },\n true,\n );\n });\n};\n\n// ==================== 数据加载 ====================\nconst loadData = (data: any[]) => {\n if (!graph.value || !data.length) return;\n const edgeShapes = [\n \"extends\",\n \"composition\",\n \"implement\",\n \"aggregation\",\n \"association\",\n ];\n const cells: Cell[] = [];\n\n data.forEach((item) => {\n if (edgeShapes.includes(item.shape)) {\n cells.push(graph.value!.createEdge(item));\n } else {\n const { data: nodeData, ...displayProps } = item;\n const node = graph.value!.createNode(displayProps);\n if (nodeData) node.setData(nodeData);\n cells.push(node);\n }\n });\n\n graph.value.resetCells(cells);\n setTimeout(() => graph.value!.zoomToFit({ padding: 10, maxScale: 1 }), 200);\n};\n\nconst formatClassDisplay = (cls: {\n name: string;\n attributes: any[];\n methods: any[];\n}) => ({\n name: cls.name,\n attributes: cls.attributes.map(\n (attr) =>\n `${getVisibilitySymbol(attr.visibility)} ${attr.name}: ${attr.type}`,\n ),\n methods: cls.methods.map(\n (method) =>\n `${getVisibilitySymbol(method.visibility)} ${method.name}(): ${method.returnType}`,\n ),\n});\n\n// ==================== 类 CRUD ====================\nconst addClass = () => {\n if (!graph.value) return;\n const newClass: UMLClass = {\n id: `class_${Date.now()}`,\n ...newClassTemplate,\n };\n const nodeData = {\n id: newClass.id,\n shape: \"class\",\n x: newClass.position.x,\n y: newClass.position.y,\n ...formatClassDisplay(newClass),\n data: newClass,\n };\n graph.value.addCell(graph.value.createNode(nodeData));\n emitDataChange();\n};\n\nconst editClass = (umlClass: UMLClass) => {\n editingClass.value = {\n ...umlClass,\n attributes: [...(umlClass.attributes || [])],\n methods: [...(umlClass.methods || [])],\n };\n showEditor.value = true;\n};\n\nconst saveClass = () => {\n if (!graph.value || !editingClass.value) return;\n const node = graph.value.getCellById(editingClass.value.id) as Node;\n if (node) {\n node.setData(editingClass.value);\n node.prop(formatClassDisplay(editingClass.value));\n }\n showEditor.value = false;\n emitDataChange();\n};\n\nconst deleteClass = () => {\n if (!graph.value || !editingClass.value) return;\n graph.value.getCellById(editingClass.value.id)?.remove();\n showEditor.value = false;\n emitDataChange();\n};\n\n// ==================== 数据获取 ====================\nconst getCurrentData = (): UMLDiagramData => ({\n classes:\n graph.value?.getNodes().map((node: Node) => ({\n ...node.getData(),\n position: node.getPosition(),\n })) || [],\n relations:\n graph.value?.getEdges().map((edge: any) => ({\n id: edge.id,\n type: edge.shape as string,\n source: edge.getSourceCellId() || \"\",\n target: edge.getTargetCellId() || \"\",\n })) || [],\n});\n\nconst emitDataChange = () => emit(\"data-change\", getCurrentData());\n\n// ==================== Graph 事件绑定 ====================\nwatch(\n graph,\n (newGraph) => {\n if (!(newGraph instanceof Graph)) return;\n\n registerNodes();\n bindInteractions();\n\n newGraph.on(\"node:dblclick\", ({ node }: { node: Node }) => {\n if (!props.readonly && node.getData()) editClass(node.getData());\n });\n\n emit(\"ready\", newGraph);\n\n const defaultCells = [\n ...sampleClasses.map((cls) => ({\n id: cls.id,\n shape: \"class\",\n x: cls.x,\n y: cls.y,\n ...formatClassDisplay(cls),\n data: {\n id: cls.id,\n name: cls.name,\n attributes: cls.attributes,\n methods: cls.methods,\n position: { x: cls.x, y: cls.y },\n },\n })),\n ...sampleConnections,\n ];\n loadData(defaultCells);\n },\n { immediate: true },\n);\n\nwatch(\n () => props.data,\n (newData) => {\n if (graph.value && newData?.classes) {\n const edgeShapes = [\n \"extends\",\n \"composition\",\n \"implement\",\n \"aggregation\",\n \"association\",\n ];\n const cells: any[] = [\n ...newData.classes.map((cls) => ({\n id: cls.id,\n shape: \"class\",\n x: cls.position?.x ?? 50,\n y: cls.position?.y ?? 50,\n ...formatClassDisplay(cls),\n data: cls,\n })),\n ...(newData.relations || [])\n .filter((r) => edgeShapes.includes(r.type))\n .map((r) => ({\n shape: r.type,\n source: r.source,\n target: r.target,\n })),\n ];\n loadData(cells);\n }\n },\n { deep: true },\n);\n\nonMounted(() => {\n initGraph({\n interacting: true,\n connecting: {\n ...connectingConfig,\n createEdge: () => graph.value!.createEdge(defaultEdgeConfig),\n validateConnection: ({\n sourceView,\n targetView,\n sourceMagnet,\n targetMagnet,\n }: any) =>\n sourceView !== targetView &&\n !!sourceMagnet &&\n !!targetMagnet &&\n sourceMagnet.getAttribute(\"magnet\") === \"true\" &&\n targetMagnet.getAttribute(\"magnet\") === \"true\",\n },\n highlighting: highlightingConfig,\n });\n});\n\ndefineExpose({\n getGraph: () => graph.value,\n getData: getCurrentData,\n addClass,\n centerContent,\n zoomToFit,\n});\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-08-01\r\n * @Description: AntV X6 图形编辑器组件(ER/BPMN/UML)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-antv-container\">\r\n <component\r\n :is=\"currentComponent\"\r\n v-bind=\"componentProps\"\r\n @ready=\"handleReady\"\r\n @data-change=\"handleDataChange\"\r\n ref=\"layoutRef\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed } from \"vue\";\r\nimport ERLayout from \"./layout/ER/index.vue\";\r\nimport BPMNLayout from \"./layout/BPMN/index.vue\";\r\nimport UMLLayout from \"./layout/UML/index.vue\";\r\nimport type { DiagramConfig, DiagramData } from \"./types\";\r\n\r\ndefineOptions({ name: \"C_AntV\" });\r\n\r\ninterface Props extends DiagramConfig {\r\n type: \"er\" | \"bpmn\" | \"uml\";\r\n data?: DiagramData;\r\n width?: string | number;\r\n height?: string | number;\r\n readonly?: boolean;\r\n showToolbar?: boolean;\r\n theme?: \"light\" | \"dark\";\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n width: \"100%\",\r\n height: \"600px\",\r\n readonly: false,\r\n showToolbar: true,\r\n theme: \"light\",\r\n});\r\n\r\nconst emit = defineEmits<{\r\n (e: \"ready\", graph: any): void;\r\n (e: \"data-change\", data: DiagramData): void;\r\n}>();\r\n\r\nconst layoutRef = ref();\r\n\r\nconst components = {\r\n er: ERLayout,\r\n bpmn: BPMNLayout,\r\n uml: UMLLayout,\r\n} as const;\r\n\r\nconst currentComponent = computed(() => components[props.type]);\r\n\r\nconst componentProps = computed(() => {\r\n const baseProps = {\r\n width: props.width,\r\n height: props.height,\r\n readonly: props.readonly,\r\n showToolbar: props.showToolbar,\r\n theme: props.theme,\r\n };\r\n\r\n // 处理 BPMN 数据格式转换\r\n let adaptedData: any = props.data;\r\n\r\n if (props.type === \"bpmn\" && props.data) {\r\n // 检查是否为 BPMNDiagramData 格式\r\n const bpmnData = props.data as any;\r\n if (\r\n bpmnData &&\r\n typeof bpmnData === \"object\" &&\r\n \"nodes\" in bpmnData &&\r\n \"edges\" in bpmnData\r\n ) {\r\n // 转换为 BPMNLayout 期望的 BPMNElement[] 格式\r\n adaptedData = [\r\n ...(bpmnData.nodes || []).map((node: any) => ({\r\n ...node,\r\n shape: node.type || node.shape || \"rect\",\r\n x: node.x ?? 0,\r\n y: node.y ?? 0,\r\n })),\r\n ...(bpmnData.edges || []).map((edge: any) => ({\r\n ...edge,\r\n shape: \"edge\",\r\n x: 0,\r\n y: 0,\r\n })),\r\n ];\r\n }\r\n }\r\n\r\n return {\r\n ...baseProps,\r\n data: adaptedData,\r\n } as any;\r\n});\r\n\r\nconst handleReady = (graph: any) => {\r\n emit(\"ready\", graph);\r\n};\r\n\r\nconst handleDataChange = (data: any) => {\r\n let convertedData: DiagramData;\r\n\r\n if (props.type === \"bpmn\" && Array.isArray(data)) {\r\n // 将 BPMNElement[] 转换回 BPMNDiagramData 格式,包含必需的 flows 属性\r\n const nodes = data\r\n .filter((item: any) => item.shape !== \"edge\")\r\n .map((item: any) => {\r\n const { shape, x, y, ...node } = item;\r\n return {\r\n ...node,\r\n type: shape === \"rect\" ? \"task\" : shape,\r\n x: x || 0,\r\n y: y || 0,\r\n };\r\n });\r\n\r\n const edges = data\r\n .filter((item: any) => item.shape === \"edge\")\r\n .map((item: any) => {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const { shape, x, y, ...edge } = item;\r\n return edge;\r\n });\r\n\r\n // 创建完整的 BPMNDiagramData 对象,包含必需的 flows 属性\r\n convertedData = {\r\n nodes,\r\n edges,\r\n flows: [], // 添加必需的 flows 属性,根据实际需求填充\r\n } as unknown as DiagramData; // 使用双重断言确保类型转换\r\n } else {\r\n convertedData = data as DiagramData;\r\n }\r\n\r\n emit(\"data-change\", convertedData);\r\n};\r\n\r\ndefineExpose({\r\n getGraph: () => layoutRef.value?.getGraph?.(),\r\n getData: () => {\r\n const rawData = layoutRef.value?.getData?.();\r\n\r\n // 根据组件类型转换回标准格式\r\n if (props.type === \"bpmn\" && Array.isArray(rawData)) {\r\n const nodes = rawData.filter((item: any) => item.shape !== \"edge\");\r\n const edges = rawData.filter((item: any) => item.shape === \"edge\");\r\n\r\n return {\r\n nodes,\r\n edges,\r\n flows: [], // 确保包含 flows 属性\r\n } as unknown as DiagramData;\r\n }\r\n\r\n return rawData;\r\n },\r\n});\r\n</script>\r\n\r\n<style scoped>\r\n.c-antv-container {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n</style>\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"C_AntV.js","names":["Graph","show","$emit","showToolbar","show","showToolbar","show","showToolbar"],"sources":["../src/components/C_AntV/composables/useGraphBase.ts","../src/components/C_AntV/utils/exportUtils.ts","../src/components/C_AntV/composables/useGraphExport.ts","../src/components/C_AntV/layout/ER/data.ts","../src/components/C_AntV/layout/ER/components/ERTableEditor.vue","../src/components/C_AntV/layout/ER/components/ERTableEditor.vue","../src/components/C_AntV/layout/ER/index.vue","../src/components/C_AntV/layout/ER/index.vue","../src/components/C_AntV/composables/useEdgeInteraction.ts","../src/components/C_AntV/layout/BPMN/data.ts","../src/components/C_AntV/layout/BPMN/components/BPMNPropertyEditor.vue","../src/components/C_AntV/layout/BPMN/components/BPMNPropertyEditor.vue","../src/components/C_AntV/layout/BPMN/index.vue","../src/components/C_AntV/layout/BPMN/index.vue","../src/components/C_AntV/layout/UML/components/UMLClassEditor.vue","../src/components/C_AntV/layout/UML/components/UMLClassEditor.vue","../src/components/C_AntV/layout/UML/data.ts","../src/components/C_AntV/layout/UML/index.vue","../src/components/C_AntV/layout/UML/index.vue","../src/components/C_AntV/index.vue","../src/components/C_AntV/index.vue"],"sourcesContent":["import { Graph } from \"@antv/x6\";\r\nimport { ref, watch, nextTick, onUnmounted } from \"vue\";\r\nimport type { ComputedRef, Ref } from \"vue\";\r\n\r\n/**\r\n * 获取主题相关的颜色配置\r\n */\r\nfunction getThemeColors(isDark: boolean) {\r\n return {\r\n background: isDark ? \"#18181c\" : \"#f5f5f5\",\r\n gridPrimary: isDark ? \"rgba(255, 255, 255, 0.08)\" : \"#eee\",\r\n gridSecondary: isDark ? \"rgba(255, 255, 255, 0.04)\" : \"#ddd\",\r\n };\r\n}\r\n\r\n/**\r\n * 默认的图表配置选项\r\n */\r\nfunction getDefaultOptions(isDark: boolean = false) {\r\n const colors = getThemeColors(isDark);\r\n\r\n return {\r\n background: { color: colors.background },\r\n grid: {\r\n visible: true,\r\n type: \"doubleMesh\",\r\n args: [\r\n { color: colors.gridPrimary, thickness: 1 },\r\n { color: colors.gridSecondary, thickness: 1, factor: 4 },\r\n ],\r\n },\r\n mousewheel: {\r\n enabled: true,\r\n zoomAtMousePosition: true,\r\n modifiers: \"ctrl\",\r\n minScale: 0.5,\r\n maxScale: 2,\r\n },\r\n selecting: {\r\n enabled: true,\r\n rubberband: true,\r\n movable: true,\r\n showNodeSelectionBox: true,\r\n },\r\n resizing: true,\r\n rotating: true,\r\n snapline: true,\r\n keyboard: true,\r\n clipboard: true,\r\n };\r\n}\r\n\r\n/**\r\n * 获取容器的尺寸\r\n */\r\nfunction getContainerSize(container: HTMLElement | undefined) {\r\n if (!container) return { width: 0, height: 0 };\r\n return {\r\n width: container.clientWidth || container.offsetWidth || 800,\r\n height: container.clientHeight || container.offsetHeight || 600,\r\n };\r\n}\r\n\r\n/**\r\n * 创建和管理 AntV X6 图表实例的组合式 API\r\n */\r\nexport function useGraphBase(\r\n containerRef: Ref<HTMLElement | undefined>,\r\n isDarkRef?: Ref<boolean> | ComputedRef<boolean>,\r\n) {\r\n const MAX_RETRY = 10;\r\n let retryCount = 0;\r\n\r\n const graph: Ref<any> = ref(null);\r\n const loading = ref(false);\r\n\r\n /**\r\n * 初始化图表实例\r\n */\r\n const initGraph = async (options: any = {}) => {\r\n await nextTick();\r\n loading.value = true;\r\n\r\n try {\r\n if (!containerRef.value) return;\r\n\r\n // 销毁旧实例\r\n if (graph.value) {\r\n graph.value.dispose();\r\n graph.value = null;\r\n }\r\n\r\n const { width, height } = getContainerSize(containerRef.value);\r\n\r\n // 容器尺寸为0,延迟重试(最多 10 次)\r\n if (width === 0 || height === 0) {\r\n retryCount++;\r\n if (retryCount < MAX_RETRY) {\r\n setTimeout(() => initGraph(options), 100);\r\n }\r\n return;\r\n }\r\n retryCount = 0;\r\n\r\n const isDark = isDarkRef?.value ?? false;\r\n const defaultOptions = getDefaultOptions(isDark);\r\n\r\n const finalOptions = {\r\n container: containerRef.value,\r\n width,\r\n height,\r\n ...defaultOptions,\r\n ...options,\r\n };\r\n\r\n graph.value = new Graph(finalOptions);\r\n } catch {\r\n // 初始化失败静默处理\r\n } finally {\r\n loading.value = false;\r\n }\r\n };\r\n\r\n /**\r\n * 更新主题\r\n */\r\n function updateTheme(isDark: boolean) {\r\n if (!graph.value) return;\r\n\r\n const colors = getThemeColors(isDark);\r\n\r\n // 更新背景色\r\n graph.value.drawBackground({ color: colors.background });\r\n\r\n // 更新网格颜色\r\n graph.value.drawGrid({\r\n type: \"doubleMesh\",\r\n args: [\r\n { color: colors.gridPrimary, thickness: 1 },\r\n { color: colors.gridSecondary, thickness: 1, factor: 4 },\r\n ],\r\n });\r\n }\r\n\r\n // 监听主题变化\r\n if (isDarkRef) {\r\n watch(isDarkRef, (isDark) => {\r\n updateTheme(isDark);\r\n });\r\n }\r\n\r\n /**\r\n * 销毁当前图表实例\r\n */\r\n function destroyGraph() {\r\n if (graph.value) {\r\n graph.value.dispose();\r\n graph.value = null;\r\n }\r\n }\r\n\r\n /**\r\n * 将图表内容居中显示\r\n */\r\n function centerContent() {\r\n graph.value?.centerContent();\r\n }\r\n\r\n /**\r\n * 自适应缩放图表以适应容器\r\n */\r\n function zoomToFit() {\r\n graph.value?.zoomToFit({ padding: 20, maxScale: 1 });\r\n }\r\n\r\n /**\r\n * 按指定因子缩放图表\r\n */\r\n function zoom(factor: number) {\r\n graph.value?.zoom(factor);\r\n }\r\n\r\n /**\r\n * 调整图表尺寸以适应容器变化\r\n */\r\n function resizeGraph() {\r\n if (graph.value && containerRef.value) {\r\n const { width, height } = getContainerSize(containerRef.value);\r\n graph.value.resize(width, height);\r\n }\r\n }\r\n\r\n // 组件卸载时自动销毁图表\r\n onUnmounted(destroyGraph);\r\n\r\n return {\r\n graph,\r\n loading,\r\n initGraph,\r\n destroyGraph,\r\n centerContent,\r\n zoomToFit,\r\n zoom,\r\n resizeGraph,\r\n updateTheme,\r\n };\r\n}\r\n","import type { Graph } from \"@antv/x6\";\r\nimport html2canvas from \"html2canvas\";\r\n\r\n/**\r\n * 下载 Blob 文件到本地\r\n * @param blob - Blob 对象\r\n * @param filename - 文件名\r\n */\r\nfunction downloadBlob(blob: Blob, filename: string): void {\r\n const url = URL.createObjectURL(blob);\r\n const link = document.createElement(\"a\");\r\n link.href = url;\r\n link.download = filename;\r\n link.style.display = \"none\";\r\n document.body.appendChild(link);\r\n link.click();\r\n document.body.removeChild(link);\r\n URL.revokeObjectURL(url);\r\n}\r\n\r\n/**\r\n * 导出数据为 JSON 文件\r\n * @param data - 要导出的数据\r\n * @param filename - 文件名,默认 'diagram.json'\r\n */\r\nexport function exportJSON(data: any, filename = \"diagram.json\"): void {\r\n const jsonString = JSON.stringify(data, null, 2);\r\n const blob = new Blob([jsonString], { type: \"application/json\" });\r\n downloadBlob(blob, filename);\r\n}\r\n\r\n/**\r\n * 导出图表为 PNG 图片(基于 html2canvas 截图方案)\r\n * @param graph - AntV X6 图表实例\r\n * @param filename - 文件名,默认 'diagram.png'\r\n * @param options - 导出选项\r\n */\r\nexport async function exportPNG(\r\n graph: Graph,\r\n filename = \"diagram.png\",\r\n options: { backgroundColor?: string; scale?: number } = {},\r\n): Promise<void> {\r\n const { backgroundColor = \"#ffffff\", scale = 2 } = options;\r\n const { container } = graph;\r\n\r\n const canvas = await html2canvas(container, {\r\n backgroundColor,\r\n scale,\r\n useCORS: true,\r\n logging: false,\r\n });\r\n\r\n const blob = await canvasToBlob(canvas, \"image/png\");\r\n downloadBlob(blob, filename);\r\n}\r\n\r\n/**\r\n * 导出图表为 SVG 矢量图(从容器内 SVG 元素序列化)\r\n * @param graph - AntV X6 图表实例\r\n * @param filename - 文件名,默认 'diagram.svg'\r\n */\r\nexport function exportSVG(graph: Graph, filename = \"diagram.svg\"): void {\r\n const svgElement = graph.container.querySelector(\"svg\");\r\n if (!svgElement) {\r\n throw new Error(\"SVG导出失败: 未找到图表 SVG 元素\");\r\n }\r\n\r\n // 克隆以避免修改原始 DOM\r\n const cloned = svgElement.cloneNode(true) as SVGSVGElement;\r\n\r\n // 确保有 xmlns 属性\r\n if (!cloned.getAttribute(\"xmlns\")) {\r\n cloned.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\r\n }\r\n if (!cloned.getAttribute(\"xmlns:xlink\")) {\r\n cloned.setAttribute(\"xmlns:xlink\", \"http://www.w3.org/1999/xlink\");\r\n }\r\n\r\n const serializer = new XMLSerializer();\r\n const svgString = serializer.serializeToString(cloned);\r\n const blob = new Blob([svgString], { type: \"image/svg+xml;charset=utf-8\" });\r\n downloadBlob(blob, filename);\r\n}\r\n\r\n/**\r\n * 将 Canvas 转换为 Blob\r\n */\r\nfunction canvasToBlob(\r\n canvas: HTMLCanvasElement,\r\n mimeType: string,\r\n quality = 1,\r\n): Promise<Blob> {\r\n return new Promise((resolve, reject) => {\r\n canvas.toBlob(\r\n (blob) => {\r\n if (blob) {\r\n resolve(blob);\r\n } else {\r\n reject(new Error(\"Canvas 转 Blob 失败\"));\r\n }\r\n },\r\n mimeType,\r\n quality,\r\n );\r\n });\r\n}\r\n\r\n/**\r\n * 复制内容到剪贴板\r\n * @param content - 要复制的内容\r\n * @returns 是否复制成功\r\n */\r\nexport async function copyToClipboard(content: string): Promise<boolean> {\r\n try {\r\n if (!navigator.clipboard) {\r\n return fallbackCopyToClipboard(content);\r\n }\r\n\r\n await navigator.clipboard.writeText(content);\r\n return true;\r\n } catch {\r\n return fallbackCopyToClipboard(content);\r\n }\r\n}\r\n\r\n/**\r\n * 备用的复制到剪贴板方法(适用于不支持 Clipboard API 的浏览器)\r\n */\r\nfunction fallbackCopyToClipboard(content: string): boolean {\r\n try {\r\n const textArea = document.createElement(\"textarea\");\r\n textArea.value = content;\r\n textArea.style.position = \"fixed\";\r\n textArea.style.left = \"-999999px\";\r\n textArea.style.top = \"-999999px\";\r\n\r\n document.body.appendChild(textArea);\r\n textArea.focus();\r\n textArea.select();\r\n\r\n const result = document.execCommand(\"copy\");\r\n document.body.removeChild(textArea);\r\n return result;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n","import type { Ref } from 'vue'\nimport type { Graph } from '@antv/x6'\nimport type { DropdownMixedOption } from 'naive-ui/es/dropdown/src/interface'\nimport { useMessage } from 'naive-ui'\nimport { exportJSON, exportPNG, exportSVG } from '../utils/exportUtils'\n\n/** 导出下拉菜单选项(三个布局共享) */\nexport const EXPORT_OPTIONS: DropdownMixedOption[] = [\n { label: '导出PNG', key: 'png' },\n { label: '导出SVG', key: 'svg' },\n { label: '导出JSON', key: 'json' },\n]\n\n/**\n * 图表导出 composable — 统一 PNG / SVG / JSON 导出逻辑\n * @param graph - X6 Graph 实例引用\n * @param filenamePrefix - 导出文件名前缀,默认 'diagram'\n */\nexport function useGraphExport(\n graph: Ref<Graph | null>,\n filenamePrefix = 'diagram'\n) {\n const message = useMessage()\n /**\n * 处理导出操作\n * @param key - 导出格式 'png' | 'svg' | 'json'\n * @param getData - 获取当前图表数据的函数(用于 JSON 导出)\n */\n const handleExport = async (key: string, getData?: () => any) => {\n if (!graph.value) return\n\n try {\n switch (key) {\n case 'png':\n await exportPNG(graph.value, `${filenamePrefix}.png`)\n break\n case 'svg':\n exportSVG(graph.value, `${filenamePrefix}.svg`)\n break\n case 'json':\n if (getData) {\n exportJSON(getData(), `${filenamePrefix}.json`)\n }\n break\n }\n } catch (error) {\n console.error(`[useGraphExport] 导出失败 (${key}):`, error)\n message.error(`导出${key.toUpperCase()}失败,请重试`)\n }\n }\n\n return { exportOptions: EXPORT_OPTIONS, handleExport }\n}\n","/* 原有的常量数据 */\r\nexport const fieldTypes = [\r\n { label: \"BIGINT\", value: \"BIGINT\" },\r\n { label: \"INT\", value: \"INT\" },\r\n { label: \"SMALLINT\", value: \"SMALLINT\" },\r\n { label: \"TINYINT\", value: \"TINYINT\" },\r\n { label: \"VARCHAR(50)\", value: \"VARCHAR(50)\" },\r\n { label: \"VARCHAR(100)\", value: \"VARCHAR(100)\" },\r\n { label: \"VARCHAR(255)\", value: \"VARCHAR(255)\" },\r\n { label: \"CHAR(10)\", value: \"CHAR(10)\" },\r\n { label: \"TEXT\", value: \"TEXT\" },\r\n { label: \"LONGTEXT\", value: \"LONGTEXT\" },\r\n { label: \"DATETIME\", value: \"DATETIME\" },\r\n { label: \"TIMESTAMP\", value: \"TIMESTAMP\" },\r\n { label: \"DATE\", value: \"DATE\" },\r\n { label: \"TIME\", value: \"TIME\" },\r\n { label: \"DECIMAL(10,2)\", value: \"DECIMAL(10,2)\" },\r\n { label: \"FLOAT\", value: \"FLOAT\" },\r\n { label: \"DOUBLE\", value: \"DOUBLE\" },\r\n { label: \"BOOLEAN\", value: \"BOOLEAN\" },\r\n { label: \"JSON\", value: \"JSON\" },\r\n];\r\n","<!--\n ERTableEditor — ER 表编辑器抽屉\n 负责:表名/注释编辑 + 字段 CRUD + 主键处理\n-->\n<template>\n <NDrawer\n :show=\"show\"\n width=\"600\"\n placement=\"right\"\n @update:show=\"$emit('update:show', $event)\"\n >\n <NDrawerContent\n :title=\"`编辑表: ${editingTable?.name || '新表'}`\"\n closable\n >\n <div\n class=\"table-editor\"\n v-if=\"editingTable\"\n >\n <NForm\n :model=\"editingTable\"\n label-placement=\"top\"\n >\n <NFormItem label=\"表名\">\n <NInput\n v-model:value=\"editingTable.name\"\n placeholder=\"请输入表名\"\n />\n </NFormItem>\n <NFormItem label=\"表注释\">\n <NInput\n v-model:value=\"editingTable.comment\"\n placeholder=\"表注释\"\n />\n </NFormItem>\n\n <NDivider>字段列表</NDivider>\n\n <div class=\"fields-container\">\n <NCard\n v-for=\"(field, index) in editingTable.fields\"\n :key=\"index\"\n size=\"small\"\n class=\"field-card\"\n >\n <template #header>\n <div class=\"field-header\">\n <span>#{{ index + 1 }} {{ field.name || '新字段' }}</span>\n <NButton\n @click=\"removeField(index)\"\n size=\"tiny\"\n type=\"error\"\n quaternary\n :disabled=\"editingTable.fields.length <= 1\"\n >\n 删除\n </NButton>\n </div>\n </template>\n\n <NGrid\n :cols=\"2\"\n :x-gap=\"12\"\n >\n <NGi>\n <NFormItem\n label=\"字段名\"\n size=\"small\"\n >\n <NInput\n v-model:value=\"field.name\"\n placeholder=\"字段名\"\n size=\"small\"\n />\n </NFormItem>\n </NGi>\n <NGi>\n <NFormItem\n label=\"类型\"\n size=\"small\"\n >\n <NSelect\n v-model:value=\"field.type\"\n :options=\"fieldTypes\"\n size=\"small\"\n filterable\n placeholder=\"选择类型\"\n />\n </NFormItem>\n </NGi>\n </NGrid>\n\n <NSpace style=\"margin-top: 12px\">\n <NCheckbox\n v-model:checked=\"field.isPrimaryKey\"\n @update:checked=\"handlePrimaryKey(field, $event)\"\n >\n 主键\n </NCheckbox>\n <NCheckbox v-model:checked=\"field.isRequired\">必填</NCheckbox>\n <NCheckbox v-model:checked=\"field.isForeignKey\">外键</NCheckbox>\n </NSpace>\n\n <NFormItem\n label=\"注释\"\n size=\"small\"\n style=\"margin-top: 12px\"\n >\n <NInput\n v-model:value=\"field.comment\"\n placeholder=\"字段注释\"\n size=\"small\"\n />\n </NFormItem>\n </NCard>\n\n <NButton\n @click=\"addField\"\n dashed\n block\n type=\"primary\"\n ghost\n style=\"margin-top: 16px\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:plus\"\n :size=\"16\"\n />\n </template>\n 添加字段\n </NButton>\n </div>\n </NForm>\n </div>\n\n <template #footer>\n <NSpace justify=\"end\">\n <NButton @click=\"$emit('update:show', false)\">取消</NButton>\n <NButton\n @click=\"$emit('save')\"\n type=\"primary\"\n >保存</NButton\n >\n </NSpace>\n </template>\n </NDrawerContent>\n </NDrawer>\n</template>\n\n<script setup lang=\"ts\">\n import {\n NDrawer,\n NDrawerContent,\n NForm,\n NFormItem,\n NInput,\n NSelect,\n NCard,\n NGrid,\n NGi,\n NSpace,\n NCheckbox,\n NButton,\n NDivider,\n } from 'naive-ui'\n import type { ERTable, ERField } from '../../../types'\n import { fieldTypes } from '../data'\n import C_Icon from '../../../../C_Icon/index.vue'\n\n defineProps<{\n show: boolean\n }>()\n\n const editingTable = defineModel<ERTable>('editingTable')\n\n const emit = defineEmits<{\n 'update:show': [value: boolean]\n save: []\n 'add-field': []\n 'remove-field': [index: number]\n 'handle-primary-key': [field: ERField, isPrimaryKey: boolean]\n }>()\n\n const handlePrimaryKey = (field: ERField, isPrimaryKey: boolean) =>\n emit('handle-primary-key', field, isPrimaryKey)\n\n const addField = () => emit('add-field')\n\n const removeField = (index: number) => emit('remove-field', index)\n</script>\n","<!--\n ERTableEditor — ER 表编辑器抽屉\n 负责:表名/注释编辑 + 字段 CRUD + 主键处理\n-->\n<template>\n <NDrawer\n :show=\"show\"\n width=\"600\"\n placement=\"right\"\n @update:show=\"$emit('update:show', $event)\"\n >\n <NDrawerContent\n :title=\"`编辑表: ${editingTable?.name || '新表'}`\"\n closable\n >\n <div\n class=\"table-editor\"\n v-if=\"editingTable\"\n >\n <NForm\n :model=\"editingTable\"\n label-placement=\"top\"\n >\n <NFormItem label=\"表名\">\n <NInput\n v-model:value=\"editingTable.name\"\n placeholder=\"请输入表名\"\n />\n </NFormItem>\n <NFormItem label=\"表注释\">\n <NInput\n v-model:value=\"editingTable.comment\"\n placeholder=\"表注释\"\n />\n </NFormItem>\n\n <NDivider>字段列表</NDivider>\n\n <div class=\"fields-container\">\n <NCard\n v-for=\"(field, index) in editingTable.fields\"\n :key=\"index\"\n size=\"small\"\n class=\"field-card\"\n >\n <template #header>\n <div class=\"field-header\">\n <span>#{{ index + 1 }} {{ field.name || '新字段' }}</span>\n <NButton\n @click=\"removeField(index)\"\n size=\"tiny\"\n type=\"error\"\n quaternary\n :disabled=\"editingTable.fields.length <= 1\"\n >\n 删除\n </NButton>\n </div>\n </template>\n\n <NGrid\n :cols=\"2\"\n :x-gap=\"12\"\n >\n <NGi>\n <NFormItem\n label=\"字段名\"\n size=\"small\"\n >\n <NInput\n v-model:value=\"field.name\"\n placeholder=\"字段名\"\n size=\"small\"\n />\n </NFormItem>\n </NGi>\n <NGi>\n <NFormItem\n label=\"类型\"\n size=\"small\"\n >\n <NSelect\n v-model:value=\"field.type\"\n :options=\"fieldTypes\"\n size=\"small\"\n filterable\n placeholder=\"选择类型\"\n />\n </NFormItem>\n </NGi>\n </NGrid>\n\n <NSpace style=\"margin-top: 12px\">\n <NCheckbox\n v-model:checked=\"field.isPrimaryKey\"\n @update:checked=\"handlePrimaryKey(field, $event)\"\n >\n 主键\n </NCheckbox>\n <NCheckbox v-model:checked=\"field.isRequired\">必填</NCheckbox>\n <NCheckbox v-model:checked=\"field.isForeignKey\">外键</NCheckbox>\n </NSpace>\n\n <NFormItem\n label=\"注释\"\n size=\"small\"\n style=\"margin-top: 12px\"\n >\n <NInput\n v-model:value=\"field.comment\"\n placeholder=\"字段注释\"\n size=\"small\"\n />\n </NFormItem>\n </NCard>\n\n <NButton\n @click=\"addField\"\n dashed\n block\n type=\"primary\"\n ghost\n style=\"margin-top: 16px\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:plus\"\n :size=\"16\"\n />\n </template>\n 添加字段\n </NButton>\n </div>\n </NForm>\n </div>\n\n <template #footer>\n <NSpace justify=\"end\">\n <NButton @click=\"$emit('update:show', false)\">取消</NButton>\n <NButton\n @click=\"$emit('save')\"\n type=\"primary\"\n >保存</NButton\n >\n </NSpace>\n </template>\n </NDrawerContent>\n </NDrawer>\n</template>\n\n<script setup lang=\"ts\">\n import {\n NDrawer,\n NDrawerContent,\n NForm,\n NFormItem,\n NInput,\n NSelect,\n NCard,\n NGrid,\n NGi,\n NSpace,\n NCheckbox,\n NButton,\n NDivider,\n } from 'naive-ui'\n import type { ERTable, ERField } from '../../../types'\n import { fieldTypes } from '../data'\n import C_Icon from '../../../../C_Icon/index.vue'\n\n defineProps<{\n show: boolean\n }>()\n\n const editingTable = defineModel<ERTable>('editingTable')\n\n const emit = defineEmits<{\n 'update:show': [value: boolean]\n save: []\n 'add-field': []\n 'remove-field': [index: number]\n 'handle-primary-key': [field: ERField, isPrimaryKey: boolean]\n }>()\n\n const handlePrimaryKey = (field: ERField, isPrimaryKey: boolean) =>\n emit('handle-primary-key', field, isPrimaryKey)\n\n const addField = () => emit('add-field')\n\n const removeField = (index: number) => emit('remove-field', index)\n</script>\n","<template>\n <div class=\"er-layout\">\n <!-- 工具栏 -->\n <div\n class=\"toolbar\"\n v-if=\"showToolbar\"\n >\n <NSpace>\n <NButton\n @click=\"addTable\"\n type=\"primary\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:table-plus\"\n :size=\"16\"\n />\n </template>\n 添加表\n </NButton>\n <NButton\n @click=\"centerContent\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:image-filter-center-focus\"\n :size=\"16\"\n />\n </template>\n 居中\n </NButton>\n <NButton\n @click=\"zoomToFit\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:fit-to-screen\"\n :size=\"16\"\n />\n </template>\n 适应\n </NButton>\n <NButton\n @click=\"toggleDeleteMode\"\n :type=\"deleteMode ? 'error' : 'default'\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:delete\"\n :size=\"16\"\n />\n </template>\n {{ deleteMode ? '退出删除' : '删除连线' }}\n </NButton>\n <NDropdown\n :options=\"exportOptions\"\n @select=\"(key: string) => handleExport(key, getCurrentData)\"\n >\n <NButton size=\"small\">\n <template #icon>\n <C_Icon\n name=\"mdi:export\"\n :size=\"16\"\n />\n </template>\n 导出\n </NButton>\n </NDropdown>\n </NSpace>\n\n <div\n v-if=\"deleteMode\"\n style=\"margin-top: 8px\"\n >\n <NAlert\n type=\"info\"\n size=\"small\"\n :show-icon=\"false\"\n >\n 删除模式:点击连接线即可删除\n </NAlert>\n </div>\n </div>\n\n <!-- 图表容器 -->\n <div\n ref=\"containerRef\"\n class=\"graph-container\"\n ></div>\n\n <!-- 表编辑器 -->\n <ERTableEditor\n :show=\"showEditor\"\n v-model:editing-table=\"editingTable\"\n @update:show=\"showEditor = $event\"\n @save=\"saveTable\"\n @add-field=\"addField\"\n @remove-field=\"removeField\"\n @handle-primary-key=\"handlePrimaryKey\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'\n import { NSpace, NButton, NDropdown, NAlert } from 'naive-ui'\n import { Node, Graph, Cell, Edge } from '@antv/x6'\n import { useGraphBase } from '../../composables/useGraphBase'\n import { useGraphExport } from '../../composables/useGraphExport'\n import type { ERTable, ERField, ERDiagramData, ERRelation } from '../../types'\n import ERTableEditor from './components/ERTableEditor.vue'\n import C_Icon from '../../../C_Icon/index.vue'\n\n interface Props {\n data?: ERDiagramData\n showToolbar?: boolean\n readonly?: boolean\n theme?: 'light' | 'dark'\n }\n\n const props = withDefaults(defineProps<Props>(), {\n showToolbar: true,\n readonly: false,\n })\n\n const emit = defineEmits<{\n (e: 'ready', graph: Graph): void\n (e: 'data-change', data: ERDiagramData): void\n }>()\n\n // ==================== Composables ====================\n const containerRef = ref<HTMLDivElement>()\n const isDark = computed(() => props.theme === 'dark')\n const { graph, initGraph, centerContent, zoomToFit } = useGraphBase(\n containerRef,\n isDark\n )\n const { exportOptions, handleExport } = useGraphExport(graph, 'er-diagram')\n\n // ==================== 编辑器状态 ====================\n const showEditor = ref(false)\n const editingTable = ref<ERTable>()\n const deleteMode = ref(false)\n\n // ==================== 工具函数 ====================\n const truncateText = (text: string, maxLength: number) =>\n text.length > maxLength ? text.substring(0, maxLength - 1) + '..' : text\n\n const createPortConfig = (table: ERTable) =>\n table.fields?.map(field => {\n const displayName = field.isPrimaryKey\n ? `🔑 ${field.name}`\n : field.isRequired\n ? `* ${field.name}`\n : field.name\n return {\n id: `${table.id}_${field.name}`,\n group: 'list',\n attrs: {\n portNameLabel: {\n text: truncateText(displayName, 12),\n title: displayName,\n },\n portTypeLabel: {\n text: truncateText(field.type, 10),\n title: field.type,\n },\n portBody: { fill: field.isPrimaryKey ? '#FFF7E6' : '#EFF4FF' },\n },\n }\n }) || []\n\n const createNodeConfig = (table: ERTable) => ({\n id: table.id,\n shape: 'er-rect',\n x: table.position.x,\n y: table.position.y,\n width: 200,\n height: 24 + (table.fields?.length || 0) * 24,\n data: table,\n attrs: {\n label: {\n text: truncateText(table.name, 20),\n refX: 0.5,\n refY: 10,\n textAnchor: 'middle',\n title: table.name,\n },\n },\n ports: createPortConfig(table),\n })\n\n // ==================== 节点注册 ====================\n const registerNodes = () => {\n if (!graph.value) return\n\n Graph.registerPortLayout(\n 'erPortPosition',\n portsPositionArgs =>\n portsPositionArgs.map((_, index) => ({\n position: { x: 0, y: (index + 1) * 24 },\n angle: 0,\n })),\n true\n )\n\n Graph.registerNode(\n 'er-rect',\n {\n inherit: 'rect',\n markup: [\n { tagName: 'rect', selector: 'body' },\n { tagName: 'text', selector: 'label' },\n ],\n attrs: {\n rect: { strokeWidth: 1, stroke: '#5F95FF', fill: '#5F95FF' },\n label: { fontWeight: 'bold', fill: '#ffffff', fontSize: 12 },\n },\n ports: {\n groups: {\n list: {\n markup: [\n { tagName: 'rect', selector: 'portBody' },\n { tagName: 'text', selector: 'portNameLabel' },\n { tagName: 'text', selector: 'portTypeLabel' },\n ],\n attrs: {\n portBody: {\n width: 200,\n height: 24,\n strokeWidth: 1,\n stroke: '#5F95FF',\n fill: '#EFF4FF',\n magnet: true,\n },\n portNameLabel: {\n ref: 'portBody',\n refX: 6,\n refY: 6,\n fontSize: 9,\n textAnchor: 'start',\n textOverflow: 'ellipsis',\n },\n portTypeLabel: {\n ref: 'portBody',\n refX: 120,\n refY: 6,\n fontSize: 9,\n textAnchor: 'start',\n fill: '#666',\n },\n },\n position: 'erPortPosition',\n },\n },\n },\n },\n true\n )\n }\n\n // ==================== 删除模式 ====================\n const toggleDeleteMode = () => {\n deleteMode.value = !deleteMode.value\n if (!deleteMode.value) resetEdgeStyles()\n }\n\n const resetEdgeStyles = () => {\n graph.value?.getEdges().forEach((edge: any) => {\n edge.attr('line/stroke', '#A2B1C3')\n edge.attr('line/strokeWidth', 2)\n })\n }\n\n // ==================== 表 CRUD ====================\n const createTableNode = (table: ERTable) => {\n if (!graph.value) return\n const node = graph.value.createNode(createNodeConfig(table))\n graph.value.resetCells([node, ...graph.value.getCells()])\n return node\n }\n\n const findPosition = () => {\n const nodes = graph.value?.getNodes() || []\n const spacing = 250\n for (let row = 0; row < 10; row++) {\n for (let col = 0; col < 3; col++) {\n const pos = { x: col * spacing + 50, y: row * spacing + 50 }\n const hasOverlap = nodes.some((node: any) => {\n const nodePos = node.getPosition()\n return (\n Math.abs(nodePos.x - pos.x) < spacing * 0.8 &&\n Math.abs(nodePos.y - pos.y) < spacing * 0.8\n )\n })\n if (!hasOverlap) return pos\n }\n }\n return { x: 50, y: 50 }\n }\n\n const addTable = () => {\n const newTable: ERTable = {\n id: `table_${Date.now()}`,\n name: '新表',\n comment: '',\n fields: [\n {\n name: 'id',\n type: 'BIGINT',\n isPrimaryKey: true,\n isRequired: true,\n isForeignKey: false,\n comment: '主键',\n },\n {\n name: 'name',\n type: 'VARCHAR(100)',\n isPrimaryKey: false,\n isRequired: true,\n isForeignKey: false,\n comment: '名称',\n },\n ],\n position: findPosition(),\n }\n createTableNode(newTable)\n editTable(newTable)\n emitDataChange()\n }\n\n const editTable = (table: ERTable) => {\n editingTable.value = {\n ...table,\n fields: table.fields?.map(field => ({ ...field })) || [],\n }\n showEditor.value = true\n }\n\n const saveTable = () => {\n if (!graph.value || !editingTable.value) return\n const node = graph.value.getCellById(editingTable.value.id) as Node\n if (node) {\n node.setData(editingTable.value)\n node.prop({\n size: {\n width: 200,\n height: 24 + editingTable.value.fields.length * 24,\n },\n attrs: {\n label: {\n text: truncateText(editingTable.value.name, 20),\n title: editingTable.value.name,\n },\n },\n ports: createPortConfig(editingTable.value),\n })\n }\n showEditor.value = false\n emitDataChange()\n }\n\n // ==================== 字段操作(由子组件事件触发) ====================\n const handlePrimaryKey = (field: ERField, isPrimaryKey: boolean) => {\n if (!isPrimaryKey) return\n field.isRequired = true\n editingTable.value?.fields.forEach(f => {\n if (f !== field) f.isPrimaryKey = false\n })\n }\n\n const addField = () => {\n editingTable.value?.fields.push({\n name: `field_${(editingTable.value?.fields.length || 0) + 1}`,\n type: 'VARCHAR(100)',\n isPrimaryKey: false,\n isRequired: false,\n isForeignKey: false,\n comment: '',\n })\n }\n\n const removeField = (index: number) => {\n if (editingTable.value && editingTable.value.fields.length > 1)\n editingTable.value.fields.splice(index, 1)\n }\n\n // ==================== 数据获取 ====================\n const getCurrentData = (): ERDiagramData => {\n if (!graph.value) return { tables: [], relations: [] }\n\n const tables = graph.value.getNodes().map((node: any) => ({\n ...node.getData(),\n position: node.getPosition(),\n }))\n\n const relations: ERRelation[] = []\n graph.value.getEdges().forEach((edge: any) => {\n const source = edge.getSourceNode()\n const target = edge.getTargetNode()\n const sourcePort = edge.getSourcePortId()\n const targetPort = edge.getTargetPortId()\n if (source && target && sourcePort && targetPort) {\n relations.push({\n id: edge.id,\n type: 'foreign-key',\n sourceTable: source.id,\n sourceField: sourcePort.split('_').slice(1).join('_'),\n targetTable: target.id,\n targetField: targetPort.split('_').slice(1).join('_'),\n name: `${source.getData()?.name || source.id} -> ${target.getData()?.name || target.id}`,\n })\n }\n })\n return { tables, relations }\n }\n\n const emitDataChange = () => emit('data-change', getCurrentData())\n\n // ==================== Graph 事件绑定 ====================\n watch(\n graph,\n newGraph => {\n if (!(newGraph instanceof Graph)) return\n\n registerNodes()\n newGraph.on('node:dblclick', ({ node }) => {\n if (!props.readonly) editTable(node.getData() as ERTable)\n })\n newGraph.on('edge:connected', emitDataChange)\n newGraph.on('edge:removed', emitDataChange)\n\n let selectedEdge: Edge | null = null\n\n newGraph.on('edge:click', ({ edge }) => {\n if (deleteMode.value) {\n edge.remove()\n emitDataChange()\n } else {\n resetEdgeStyles()\n edge.attr('line/stroke', '#ff4d4f')\n edge.attr('line/strokeWidth', 3)\n selectedEdge = edge\n }\n })\n newGraph.on('edge:dblclick', ({ edge }) => {\n edge.remove()\n emitDataChange()\n })\n newGraph.on('blank:click', () => {\n selectedEdge = null\n if (!deleteMode.value) resetEdgeStyles()\n })\n\n const handleKeyDown = (e: KeyboardEvent) => {\n // 忽略来自 input/textarea/contenteditable 元素的按键\n const tag = (e.target as HTMLElement)?.tagName\n if (\n tag === 'INPUT' ||\n tag === 'TEXTAREA' ||\n (e.target as HTMLElement)?.isContentEditable\n )\n return\n\n if ((e.key === 'Delete' || e.key === 'Backspace') && selectedEdge) {\n selectedEdge.remove()\n emitDataChange()\n selectedEdge = null\n }\n }\n document.addEventListener('keydown', handleKeyDown)\n onUnmounted(() => document.removeEventListener('keydown', handleKeyDown))\n\n emit('ready', newGraph)\n\n nextTick(() => {\n if (props.data?.tables) {\n const cells: Cell[] = props.data.tables.map(table =>\n newGraph.createNode(createNodeConfig(table))\n )\n\n if (props.data.relations?.length) {\n props.data.relations.forEach(relation => {\n cells.push(\n newGraph.createEdge({\n source: {\n cell: relation.sourceTable,\n port: `${relation.sourceTable}_${relation.sourceField}`,\n },\n target: {\n cell: relation.targetTable,\n port: `${relation.targetTable}_${relation.targetField}`,\n },\n attrs: { line: { stroke: '#A2B1C3', strokeWidth: 2 } },\n })\n )\n })\n }\n\n newGraph.resetCells(cells)\n setTimeout(\n () => newGraph.zoomToFit({ padding: 20, maxScale: 1 }),\n 300\n )\n }\n })\n },\n { immediate: true }\n )\n\n watch(\n () => props.data,\n newData => {\n if (graph.value && newData?.tables) {\n const cells: Cell[] = newData.tables.map(table =>\n graph.value!.createNode(createNodeConfig(table))\n )\n\n // 加载关系连线\n if (newData.relations?.length) {\n newData.relations.forEach(relation => {\n cells.push(\n graph.value!.createEdge({\n source: {\n cell: relation.sourceTable,\n port: `${relation.sourceTable}_${relation.sourceField}`,\n },\n target: {\n cell: relation.targetTable,\n port: `${relation.targetTable}_${relation.targetField}`,\n },\n attrs: { line: { stroke: '#A2B1C3', strokeWidth: 2 } },\n })\n )\n })\n }\n\n graph.value.resetCells(cells)\n }\n },\n { deep: true }\n )\n\n onMounted(() => initGraph())\n\n defineExpose({\n getGraph: () => graph.value ?? undefined,\n getData: getCurrentData,\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","<template>\n <div class=\"er-layout\">\n <!-- 工具栏 -->\n <div\n class=\"toolbar\"\n v-if=\"showToolbar\"\n >\n <NSpace>\n <NButton\n @click=\"addTable\"\n type=\"primary\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:table-plus\"\n :size=\"16\"\n />\n </template>\n 添加表\n </NButton>\n <NButton\n @click=\"centerContent\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:image-filter-center-focus\"\n :size=\"16\"\n />\n </template>\n 居中\n </NButton>\n <NButton\n @click=\"zoomToFit\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:fit-to-screen\"\n :size=\"16\"\n />\n </template>\n 适应\n </NButton>\n <NButton\n @click=\"toggleDeleteMode\"\n :type=\"deleteMode ? 'error' : 'default'\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:delete\"\n :size=\"16\"\n />\n </template>\n {{ deleteMode ? '退出删除' : '删除连线' }}\n </NButton>\n <NDropdown\n :options=\"exportOptions\"\n @select=\"(key: string) => handleExport(key, getCurrentData)\"\n >\n <NButton size=\"small\">\n <template #icon>\n <C_Icon\n name=\"mdi:export\"\n :size=\"16\"\n />\n </template>\n 导出\n </NButton>\n </NDropdown>\n </NSpace>\n\n <div\n v-if=\"deleteMode\"\n style=\"margin-top: 8px\"\n >\n <NAlert\n type=\"info\"\n size=\"small\"\n :show-icon=\"false\"\n >\n 删除模式:点击连接线即可删除\n </NAlert>\n </div>\n </div>\n\n <!-- 图表容器 -->\n <div\n ref=\"containerRef\"\n class=\"graph-container\"\n ></div>\n\n <!-- 表编辑器 -->\n <ERTableEditor\n :show=\"showEditor\"\n v-model:editing-table=\"editingTable\"\n @update:show=\"showEditor = $event\"\n @save=\"saveTable\"\n @add-field=\"addField\"\n @remove-field=\"removeField\"\n @handle-primary-key=\"handlePrimaryKey\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'\n import { NSpace, NButton, NDropdown, NAlert } from 'naive-ui'\n import { Node, Graph, Cell, Edge } from '@antv/x6'\n import { useGraphBase } from '../../composables/useGraphBase'\n import { useGraphExport } from '../../composables/useGraphExport'\n import type { ERTable, ERField, ERDiagramData, ERRelation } from '../../types'\n import ERTableEditor from './components/ERTableEditor.vue'\n import C_Icon from '../../../C_Icon/index.vue'\n\n interface Props {\n data?: ERDiagramData\n showToolbar?: boolean\n readonly?: boolean\n theme?: 'light' | 'dark'\n }\n\n const props = withDefaults(defineProps<Props>(), {\n showToolbar: true,\n readonly: false,\n })\n\n const emit = defineEmits<{\n (e: 'ready', graph: Graph): void\n (e: 'data-change', data: ERDiagramData): void\n }>()\n\n // ==================== Composables ====================\n const containerRef = ref<HTMLDivElement>()\n const isDark = computed(() => props.theme === 'dark')\n const { graph, initGraph, centerContent, zoomToFit } = useGraphBase(\n containerRef,\n isDark\n )\n const { exportOptions, handleExport } = useGraphExport(graph, 'er-diagram')\n\n // ==================== 编辑器状态 ====================\n const showEditor = ref(false)\n const editingTable = ref<ERTable>()\n const deleteMode = ref(false)\n\n // ==================== 工具函数 ====================\n const truncateText = (text: string, maxLength: number) =>\n text.length > maxLength ? text.substring(0, maxLength - 1) + '..' : text\n\n const createPortConfig = (table: ERTable) =>\n table.fields?.map(field => {\n const displayName = field.isPrimaryKey\n ? `🔑 ${field.name}`\n : field.isRequired\n ? `* ${field.name}`\n : field.name\n return {\n id: `${table.id}_${field.name}`,\n group: 'list',\n attrs: {\n portNameLabel: {\n text: truncateText(displayName, 12),\n title: displayName,\n },\n portTypeLabel: {\n text: truncateText(field.type, 10),\n title: field.type,\n },\n portBody: { fill: field.isPrimaryKey ? '#FFF7E6' : '#EFF4FF' },\n },\n }\n }) || []\n\n const createNodeConfig = (table: ERTable) => ({\n id: table.id,\n shape: 'er-rect',\n x: table.position.x,\n y: table.position.y,\n width: 200,\n height: 24 + (table.fields?.length || 0) * 24,\n data: table,\n attrs: {\n label: {\n text: truncateText(table.name, 20),\n refX: 0.5,\n refY: 10,\n textAnchor: 'middle',\n title: table.name,\n },\n },\n ports: createPortConfig(table),\n })\n\n // ==================== 节点注册 ====================\n const registerNodes = () => {\n if (!graph.value) return\n\n Graph.registerPortLayout(\n 'erPortPosition',\n portsPositionArgs =>\n portsPositionArgs.map((_, index) => ({\n position: { x: 0, y: (index + 1) * 24 },\n angle: 0,\n })),\n true\n )\n\n Graph.registerNode(\n 'er-rect',\n {\n inherit: 'rect',\n markup: [\n { tagName: 'rect', selector: 'body' },\n { tagName: 'text', selector: 'label' },\n ],\n attrs: {\n rect: { strokeWidth: 1, stroke: '#5F95FF', fill: '#5F95FF' },\n label: { fontWeight: 'bold', fill: '#ffffff', fontSize: 12 },\n },\n ports: {\n groups: {\n list: {\n markup: [\n { tagName: 'rect', selector: 'portBody' },\n { tagName: 'text', selector: 'portNameLabel' },\n { tagName: 'text', selector: 'portTypeLabel' },\n ],\n attrs: {\n portBody: {\n width: 200,\n height: 24,\n strokeWidth: 1,\n stroke: '#5F95FF',\n fill: '#EFF4FF',\n magnet: true,\n },\n portNameLabel: {\n ref: 'portBody',\n refX: 6,\n refY: 6,\n fontSize: 9,\n textAnchor: 'start',\n textOverflow: 'ellipsis',\n },\n portTypeLabel: {\n ref: 'portBody',\n refX: 120,\n refY: 6,\n fontSize: 9,\n textAnchor: 'start',\n fill: '#666',\n },\n },\n position: 'erPortPosition',\n },\n },\n },\n },\n true\n )\n }\n\n // ==================== 删除模式 ====================\n const toggleDeleteMode = () => {\n deleteMode.value = !deleteMode.value\n if (!deleteMode.value) resetEdgeStyles()\n }\n\n const resetEdgeStyles = () => {\n graph.value?.getEdges().forEach((edge: any) => {\n edge.attr('line/stroke', '#A2B1C3')\n edge.attr('line/strokeWidth', 2)\n })\n }\n\n // ==================== 表 CRUD ====================\n const createTableNode = (table: ERTable) => {\n if (!graph.value) return\n const node = graph.value.createNode(createNodeConfig(table))\n graph.value.resetCells([node, ...graph.value.getCells()])\n return node\n }\n\n const findPosition = () => {\n const nodes = graph.value?.getNodes() || []\n const spacing = 250\n for (let row = 0; row < 10; row++) {\n for (let col = 0; col < 3; col++) {\n const pos = { x: col * spacing + 50, y: row * spacing + 50 }\n const hasOverlap = nodes.some((node: any) => {\n const nodePos = node.getPosition()\n return (\n Math.abs(nodePos.x - pos.x) < spacing * 0.8 &&\n Math.abs(nodePos.y - pos.y) < spacing * 0.8\n )\n })\n if (!hasOverlap) return pos\n }\n }\n return { x: 50, y: 50 }\n }\n\n const addTable = () => {\n const newTable: ERTable = {\n id: `table_${Date.now()}`,\n name: '新表',\n comment: '',\n fields: [\n {\n name: 'id',\n type: 'BIGINT',\n isPrimaryKey: true,\n isRequired: true,\n isForeignKey: false,\n comment: '主键',\n },\n {\n name: 'name',\n type: 'VARCHAR(100)',\n isPrimaryKey: false,\n isRequired: true,\n isForeignKey: false,\n comment: '名称',\n },\n ],\n position: findPosition(),\n }\n createTableNode(newTable)\n editTable(newTable)\n emitDataChange()\n }\n\n const editTable = (table: ERTable) => {\n editingTable.value = {\n ...table,\n fields: table.fields?.map(field => ({ ...field })) || [],\n }\n showEditor.value = true\n }\n\n const saveTable = () => {\n if (!graph.value || !editingTable.value) return\n const node = graph.value.getCellById(editingTable.value.id) as Node\n if (node) {\n node.setData(editingTable.value)\n node.prop({\n size: {\n width: 200,\n height: 24 + editingTable.value.fields.length * 24,\n },\n attrs: {\n label: {\n text: truncateText(editingTable.value.name, 20),\n title: editingTable.value.name,\n },\n },\n ports: createPortConfig(editingTable.value),\n })\n }\n showEditor.value = false\n emitDataChange()\n }\n\n // ==================== 字段操作(由子组件事件触发) ====================\n const handlePrimaryKey = (field: ERField, isPrimaryKey: boolean) => {\n if (!isPrimaryKey) return\n field.isRequired = true\n editingTable.value?.fields.forEach(f => {\n if (f !== field) f.isPrimaryKey = false\n })\n }\n\n const addField = () => {\n editingTable.value?.fields.push({\n name: `field_${(editingTable.value?.fields.length || 0) + 1}`,\n type: 'VARCHAR(100)',\n isPrimaryKey: false,\n isRequired: false,\n isForeignKey: false,\n comment: '',\n })\n }\n\n const removeField = (index: number) => {\n if (editingTable.value && editingTable.value.fields.length > 1)\n editingTable.value.fields.splice(index, 1)\n }\n\n // ==================== 数据获取 ====================\n const getCurrentData = (): ERDiagramData => {\n if (!graph.value) return { tables: [], relations: [] }\n\n const tables = graph.value.getNodes().map((node: any) => ({\n ...node.getData(),\n position: node.getPosition(),\n }))\n\n const relations: ERRelation[] = []\n graph.value.getEdges().forEach((edge: any) => {\n const source = edge.getSourceNode()\n const target = edge.getTargetNode()\n const sourcePort = edge.getSourcePortId()\n const targetPort = edge.getTargetPortId()\n if (source && target && sourcePort && targetPort) {\n relations.push({\n id: edge.id,\n type: 'foreign-key',\n sourceTable: source.id,\n sourceField: sourcePort.split('_').slice(1).join('_'),\n targetTable: target.id,\n targetField: targetPort.split('_').slice(1).join('_'),\n name: `${source.getData()?.name || source.id} -> ${target.getData()?.name || target.id}`,\n })\n }\n })\n return { tables, relations }\n }\n\n const emitDataChange = () => emit('data-change', getCurrentData())\n\n // ==================== Graph 事件绑定 ====================\n watch(\n graph,\n newGraph => {\n if (!(newGraph instanceof Graph)) return\n\n registerNodes()\n newGraph.on('node:dblclick', ({ node }) => {\n if (!props.readonly) editTable(node.getData() as ERTable)\n })\n newGraph.on('edge:connected', emitDataChange)\n newGraph.on('edge:removed', emitDataChange)\n\n let selectedEdge: Edge | null = null\n\n newGraph.on('edge:click', ({ edge }) => {\n if (deleteMode.value) {\n edge.remove()\n emitDataChange()\n } else {\n resetEdgeStyles()\n edge.attr('line/stroke', '#ff4d4f')\n edge.attr('line/strokeWidth', 3)\n selectedEdge = edge\n }\n })\n newGraph.on('edge:dblclick', ({ edge }) => {\n edge.remove()\n emitDataChange()\n })\n newGraph.on('blank:click', () => {\n selectedEdge = null\n if (!deleteMode.value) resetEdgeStyles()\n })\n\n const handleKeyDown = (e: KeyboardEvent) => {\n // 忽略来自 input/textarea/contenteditable 元素的按键\n const tag = (e.target as HTMLElement)?.tagName\n if (\n tag === 'INPUT' ||\n tag === 'TEXTAREA' ||\n (e.target as HTMLElement)?.isContentEditable\n )\n return\n\n if ((e.key === 'Delete' || e.key === 'Backspace') && selectedEdge) {\n selectedEdge.remove()\n emitDataChange()\n selectedEdge = null\n }\n }\n document.addEventListener('keydown', handleKeyDown)\n onUnmounted(() => document.removeEventListener('keydown', handleKeyDown))\n\n emit('ready', newGraph)\n\n nextTick(() => {\n if (props.data?.tables) {\n const cells: Cell[] = props.data.tables.map(table =>\n newGraph.createNode(createNodeConfig(table))\n )\n\n if (props.data.relations?.length) {\n props.data.relations.forEach(relation => {\n cells.push(\n newGraph.createEdge({\n source: {\n cell: relation.sourceTable,\n port: `${relation.sourceTable}_${relation.sourceField}`,\n },\n target: {\n cell: relation.targetTable,\n port: `${relation.targetTable}_${relation.targetField}`,\n },\n attrs: { line: { stroke: '#A2B1C3', strokeWidth: 2 } },\n })\n )\n })\n }\n\n newGraph.resetCells(cells)\n setTimeout(\n () => newGraph.zoomToFit({ padding: 20, maxScale: 1 }),\n 300\n )\n }\n })\n },\n { immediate: true }\n )\n\n watch(\n () => props.data,\n newData => {\n if (graph.value && newData?.tables) {\n const cells: Cell[] = newData.tables.map(table =>\n graph.value!.createNode(createNodeConfig(table))\n )\n\n // 加载关系连线\n if (newData.relations?.length) {\n newData.relations.forEach(relation => {\n cells.push(\n graph.value!.createEdge({\n source: {\n cell: relation.sourceTable,\n port: `${relation.sourceTable}_${relation.sourceField}`,\n },\n target: {\n cell: relation.targetTable,\n port: `${relation.targetTable}_${relation.targetField}`,\n },\n attrs: { line: { stroke: '#A2B1C3', strokeWidth: 2 } },\n })\n )\n })\n }\n\n graph.value.resetCells(cells)\n }\n },\n { deep: true }\n )\n\n onMounted(() => initGraph())\n\n defineExpose({\n getGraph: () => graph.value ?? undefined,\n getData: getCurrentData,\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","import type { Ref } from 'vue'\r\nimport type { Graph, Node } from '@antv/x6'\r\n\r\nexport interface EdgeInteractionOptions {\r\n /** 连线默认颜色 */\r\n defaultColor?: string\r\n /** 连线高亮颜色 */\r\n highlightColor?: string\r\n /** 默认线宽 */\r\n strokeWidth?: number\r\n /** 高亮线宽 */\r\n highlightStrokeWidth?: number\r\n /** 端口位置名称列表(用于控制 mouseenter/leave 显隐) */\r\n portPositions?: string[]\r\n /** 数据变更回调 */\r\n onDataChange?: () => void\r\n}\r\n\r\nconst DEFAULT_OPTIONS: Required<EdgeInteractionOptions> = {\r\n defaultColor: '#A2B1C3',\r\n highlightColor: '#ff4d4f',\r\n strokeWidth: 2,\r\n highlightStrokeWidth: 3,\r\n portPositions: [],\r\n onDataChange: () => {},\r\n}\r\n\r\n/**\r\n * 图表交互 composable — 统一管理连线点击/高亮/删除 + 端口显隐\r\n * @param graph - X6 Graph 实例引用\r\n * @param options - 交互配置\r\n */\r\nexport function useEdgeInteraction(\r\n graph: Ref<Graph | null>,\r\n options: EdgeInteractionOptions = {}\r\n) {\r\n const config = { ...DEFAULT_OPTIONS, ...options }\r\n\r\n /** 重置所有连线颜色 */\r\n const resetEdgeStyles = () => {\r\n graph.value?.getEdges().forEach(edge => {\r\n edge.attr('line/stroke', config.defaultColor)\r\n edge.attr('line/strokeWidth', config.strokeWidth)\r\n })\r\n }\r\n\r\n /** 高亮指定连线 */\r\n const highlightEdge = (edge: any) => {\r\n resetEdgeStyles()\r\n edge.attr('line/stroke', config.highlightColor)\r\n edge.attr('line/strokeWidth', config.highlightStrokeWidth)\r\n }\r\n\r\n /** 切换端口可见性 */\r\n const togglePorts = (node: Node, opacity: number) => {\r\n config.portPositions.forEach(pos =>\r\n node.attr(`port-${pos}/style/opacity`, opacity)\r\n )\r\n }\r\n\r\n /**\r\n * 绑定标准交互事件到 graph 实例\r\n * - edge:click → 高亮\r\n * - edge:dblclick → 删除\r\n * - blank:click / node:click → 重置颜色\r\n * - node:mouseenter / mouseleave → 端口显隐(如配置了 portPositions)\r\n */\r\n const bindInteractions = () => {\r\n const g = graph.value\r\n if (!g) return\r\n\r\n // 连线点击高亮\r\n g.on('edge:click', ({ edge }) => highlightEdge(edge))\r\n\r\n // 连线双击删除\r\n g.on('edge:dblclick', ({ edge }) => {\r\n edge.remove()\r\n config.onDataChange()\r\n })\r\n\r\n // 点击空白 / 节点时重置颜色\r\n g.on('blank:click', resetEdgeStyles)\r\n g.on('node:click', resetEdgeStyles)\r\n\r\n // 连线创建时通知数据变更\r\n g.on('edge:connected', config.onDataChange)\r\n\r\n // 端口显隐(如果配置了 portPositions)\r\n if (config.portPositions.length > 0) {\r\n g.on('node:mouseenter', ({ node }) => togglePorts(node, 1))\r\n g.on('node:mouseleave', ({ node }) => togglePorts(node, 0))\r\n }\r\n }\r\n\r\n return { resetEdgeStyles, highlightEdge, togglePorts, bindInteractions }\r\n}\r\n","export const elementTypes = {\r\n \"start-event\": {\r\n name: \"开始\",\r\n title: \"开始事件\",\r\n iconClass: \"circle start-event\",\r\n },\r\n activity: { name: \"任务\", title: \"任务活动\", iconClass: \"rect activity\" },\r\n gateway: { name: \"网关\", title: \"排他网关\", iconClass: \"diamond gateway\" },\r\n \"end-event\": {\r\n name: \"结束\",\r\n title: \"结束事件\",\r\n iconClass: \"circle end-event\",\r\n },\r\n};\r\n\r\nexport const elementTypeNames = {\r\n event: \"事件\",\r\n activity: \"活动\",\r\n gateway: \"网关\",\r\n \"bpmn-edge\": \"连接线\",\r\n};\r\n\r\n/* 端口位置配置 */\r\nexport const portPositions = [\"top\", \"right\", \"bottom\", \"left\"];\r\n\r\n/* 端口属性配置函数 */\r\nexport const createPortAttrs = (\r\n positions: string[],\r\n nodeType: \"circle\" | \"rect\" | \"polygon\" = \"rect\",\r\n) =>\r\n positions.reduce((acc, pos) => {\r\n const isCircle = nodeType === \"circle\";\r\n const refConfig =\r\n pos === \"top\"\r\n ? isCircle\r\n ? { refCx: 0.5, refCy: 0 }\r\n : { refX: 0.5, refY: 0 }\r\n : pos === \"right\"\r\n ? isCircle\r\n ? { refCx: 1, refCy: 0.5 }\r\n : { refX: 1, refY: 0.5 }\r\n : pos === \"bottom\"\r\n ? isCircle\r\n ? { refCx: 0.5, refCy: 1 }\r\n : { refX: 0.5, refY: 1 }\r\n : isCircle\r\n ? { refCx: 0, refCy: 0.5 }\r\n : { refX: 0, refY: 0.5 };\r\n\r\n acc[`port-${pos}`] = {\r\n ref: \"body\",\r\n ...refConfig,\r\n r: 4,\r\n fill: \"#31d0c6\",\r\n stroke: \"#ffffff\",\r\n strokeWidth: 2,\r\n magnet: true,\r\n style: { cursor: \"crosshair\", opacity: 0, transition: \"opacity 0.2s\" },\r\n };\r\n return acc;\r\n }, {} as any);\r\n\r\n/* 节点配置 */\r\nexport const nodeConfigs = {\r\n event: {\r\n inherit: \"circle\",\r\n attrs: {\r\n body: {\r\n strokeWidth: 2,\r\n stroke: \"#5F95FF\",\r\n fill: \"#FFF\",\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n text: {\r\n fontSize: 12,\r\n fill: \"#262626\",\r\n textAnchor: \"middle\",\r\n textVerticalAnchor: \"middle\",\r\n pointerEvents: \"none\",\r\n },\r\n },\r\n },\r\n activity: {\r\n inherit: \"rect\",\r\n attrs: {\r\n body: {\r\n rx: 6,\r\n ry: 6,\r\n stroke: \"#5F95FF\",\r\n fill: \"#EFF4FF\",\r\n strokeWidth: 1,\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n text: {\r\n fontSize: 12,\r\n fill: \"#262626\",\r\n textAnchor: \"middle\",\r\n textVerticalAnchor: \"middle\",\r\n pointerEvents: \"none\",\r\n },\r\n },\r\n },\r\n gateway: {\r\n inherit: \"polygon\",\r\n attrs: {\r\n body: {\r\n refPoints: \"0,10 10,0 20,10 10,20\",\r\n strokeWidth: 2,\r\n stroke: \"#5F95FF\",\r\n fill: \"#EFF4FF\",\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n text: {\r\n fontSize: 20,\r\n fill: \"#5F95FF\",\r\n textAnchor: \"middle\",\r\n textVerticalAnchor: \"middle\",\r\n pointerEvents: \"none\",\r\n },\r\n },\r\n },\r\n};\r\n\r\n/* 边配置 */\r\nexport const edgeConfig = {\r\n inherit: \"edge\",\r\n attrs: {\r\n line: {\r\n stroke: \"#A2B1C3\",\r\n strokeWidth: 2,\r\n targetMarker: {\r\n name: \"block\",\r\n width: 8,\r\n height: 6,\r\n fill: \"#A2B1C3\",\r\n },\r\n cursor: \"pointer\",\r\n },\r\n },\r\n};\r\n\r\n/**\r\n * 获取图形配置(支持主题切换)\r\n * @param isDark 是否为暗色主题\r\n * @returns Graph配置对象\r\n */\r\nexport function getGraphConfig(isDark = false) {\r\n const themeColors = {\r\n background: isDark ? \"#18181c\" : \"#ffffff\",\r\n gridPrimary: isDark ? \"rgba(255, 255, 255, 0.08)\" : \"#eee\",\r\n gridSecondary: isDark ? \"rgba(255, 255, 255, 0.04)\" : \"#ddd\",\r\n };\r\n\r\n return {\r\n background: { color: themeColors.background },\r\n grid: {\r\n visible: true,\r\n type: \"doubleMesh\",\r\n args: [\r\n { color: themeColors.gridPrimary, thickness: 1 },\r\n { color: themeColors.gridSecondary, thickness: 1, factor: 4 },\r\n ],\r\n },\r\n mousewheel: {\r\n enabled: true,\r\n zoomAtMousePosition: true,\r\n modifiers: \"ctrl\",\r\n minScale: 0.5,\r\n maxScale: 3,\r\n },\r\n connecting: {\r\n router: \"manhattan\",\r\n connector: { name: \"rounded\", args: { radius: 8 } },\r\n allowBlank: false,\r\n allowLoop: false,\r\n allowNode: false,\r\n snap: true,\r\n allowEdge: false,\r\n },\r\n highlighting: {\r\n magnetAvailable: {\r\n name: \"stroke\",\r\n args: { attrs: { fill: \"#31d0c6\", stroke: \"#31d0c6\", opacity: 1 } },\r\n },\r\n magnetAdsorbed: {\r\n name: \"stroke\",\r\n args: { attrs: { fill: \"#5F95FF\", stroke: \"#5F95FF\", opacity: 1 } },\r\n },\r\n },\r\n selecting: {\r\n enabled: true,\r\n rubberband: true,\r\n showNodeSelectionBox: true,\r\n },\r\n resizing: true,\r\n rotating: false,\r\n snapline: true,\r\n keyboard: true,\r\n clipboard: true,\r\n };\r\n}\r\n\r\n/* 保持向后兼容 */\r\nexport const graphConfig = getGraphConfig();\r\n\r\n/* 添加元素配置 */\r\nexport const addElementConfigs = {\r\n \"start-event\": {\r\n shape: \"event\",\r\n width: 50,\r\n height: 50,\r\n label: \"开始事件\",\r\n data: { type: \"start\" },\r\n },\r\n \"end-event\": {\r\n shape: \"event\",\r\n width: 50,\r\n height: 50,\r\n label: \"结束事件\",\r\n data: { type: \"end\" },\r\n },\r\n activity: {\r\n shape: \"activity\",\r\n width: 120,\r\n height: 60,\r\n label: \"新活动\",\r\n data: { description: \"\", assignee: \"\" },\r\n },\r\n gateway: {\r\n shape: \"gateway\",\r\n width: 40,\r\n height: 40,\r\n label: \"+\",\r\n data: { type: \"exclusive\" },\r\n },\r\n};\r\n\r\n/* 示例数据 */\r\nexport const sampleData = [\r\n {\r\n id: \"start-1\",\r\n shape: \"event\",\r\n x: 100,\r\n y: 200,\r\n width: 50,\r\n height: 50,\r\n label: \"流程开始\",\r\n data: { type: \"start\" },\r\n },\r\n {\r\n id: \"activity-1\",\r\n shape: \"activity\",\r\n x: 200,\r\n y: 180,\r\n width: 120,\r\n height: 60,\r\n label: \"用户申请\",\r\n data: { description: \"用户提交申请表单\", assignee: \"申请人\" },\r\n },\r\n {\r\n id: \"activity-2\",\r\n shape: \"activity\",\r\n x: 380,\r\n y: 180,\r\n width: 120,\r\n height: 60,\r\n label: \"初审\",\r\n data: { description: \"部门进行初步审核\", assignee: \"部门主管\" },\r\n },\r\n {\r\n id: \"gateway-1\",\r\n shape: \"gateway\",\r\n x: 550,\r\n y: 200,\r\n width: 40,\r\n height: 40,\r\n label: \"+\",\r\n data: { type: \"exclusive\" },\r\n },\r\n {\r\n id: \"activity-3\",\r\n shape: \"activity\",\r\n x: 650,\r\n y: 120,\r\n width: 120,\r\n height: 60,\r\n label: \"终审\",\r\n data: { description: \"高级主管最终审核\", assignee: \"总监\" },\r\n },\r\n {\r\n id: \"activity-4\",\r\n shape: \"activity\",\r\n x: 650,\r\n y: 260,\r\n width: 120,\r\n height: 60,\r\n label: \"驳回处理\",\r\n data: { description: \"处理驳回流程\", assignee: \"专员\" },\r\n },\r\n {\r\n id: \"end-1\",\r\n shape: \"event\",\r\n x: 820,\r\n y: 140,\r\n width: 50,\r\n height: 50,\r\n label: \"审批通过\",\r\n data: { type: \"end\" },\r\n },\r\n {\r\n id: \"end-2\",\r\n shape: \"event\",\r\n x: 820,\r\n y: 280,\r\n width: 50,\r\n height: 50,\r\n label: \"审批驳回\",\r\n data: { type: \"end\" },\r\n },\r\n {\r\n id: \"edge-1\",\r\n shape: \"bpmn-edge\",\r\n source: \"start-1\",\r\n target: \"activity-1\",\r\n x: 0,\r\n y: 0,\r\n },\r\n {\r\n id: \"edge-2\",\r\n shape: \"bpmn-edge\",\r\n source: \"activity-1\",\r\n target: \"activity-2\",\r\n x: 0,\r\n y: 0,\r\n },\r\n {\r\n id: \"edge-3\",\r\n shape: \"bpmn-edge\",\r\n source: \"activity-2\",\r\n target: \"gateway-1\",\r\n x: 0,\r\n y: 0,\r\n },\r\n {\r\n id: \"edge-4\",\r\n shape: \"bpmn-edge\",\r\n source: \"gateway-1\",\r\n target: \"activity-3\",\r\n label: \"通过\",\r\n x: 0,\r\n y: 0,\r\n },\r\n {\r\n id: \"edge-5\",\r\n shape: \"bpmn-edge\",\r\n source: \"gateway-1\",\r\n target: \"activity-4\",\r\n label: \"驳回\",\r\n x: 0,\r\n y: 0,\r\n },\r\n {\r\n id: \"edge-6\",\r\n shape: \"bpmn-edge\",\r\n source: \"activity-3\",\r\n target: \"end-1\",\r\n x: 0,\r\n y: 0,\r\n },\r\n {\r\n id: \"edge-7\",\r\n shape: \"bpmn-edge\",\r\n source: \"activity-4\",\r\n target: \"end-2\",\r\n x: 0,\r\n y: 0,\r\n },\r\n];\r\n","<template>\r\n <NDrawer\r\n :show=\"show\"\r\n width=\"300\"\r\n title=\"属性设置\"\r\n @update:show=\"emit('update:show', $event)\"\r\n >\r\n <div v-if=\"editingElement\" class=\"property-panel\">\r\n <div class=\"property-item\">\r\n <div class=\"property-label\">名称</div>\r\n <NInput\r\n v-model:value=\"editingElement.label\"\r\n placeholder=\"请输入名称\"\r\n size=\"small\"\r\n />\r\n </div>\r\n <div class=\"property-item\">\r\n <div class=\"property-label\">类型</div>\r\n <NInput :value=\"typeName\" readonly size=\"small\" />\r\n </div>\r\n <div class=\"property-item\" v-if=\"editingElement.shape === 'activity'\">\r\n <div class=\"property-label\">描述</div>\r\n <NInput\r\n v-model:value=\"editingElement.description\"\r\n type=\"textarea\"\r\n :rows=\"3\"\r\n placeholder=\"请输入活动描述\"\r\n size=\"small\"\r\n />\r\n </div>\r\n <div class=\"property-item\" v-if=\"editingElement.shape === 'activity'\">\r\n <div class=\"property-label\">执行人</div>\r\n <NInput\r\n v-model:value=\"editingElement.assignee\"\r\n placeholder=\"请输入执行人\"\r\n size=\"small\"\r\n />\r\n </div>\r\n <div class=\"form-actions\">\r\n <NSpace>\r\n <NButton @click=\"emit('save')\" type=\"primary\" size=\"small\">\r\n 保存\r\n </NButton>\r\n <NButton @click=\"emit('update:show', false)\" size=\"small\">\r\n 取消\r\n </NButton>\r\n <NButton @click=\"emit('delete')\" type=\"error\" size=\"small\">\r\n 删除\r\n </NButton>\r\n </NSpace>\r\n </div>\r\n </div>\r\n </NDrawer>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from \"vue\";\r\nimport { NDrawer, NInput, NSpace, NButton } from \"naive-ui\";\r\nimport { elementTypeNames } from \"../data\";\r\n\r\ninterface BPMNElement {\r\n id: string;\r\n shape: string;\r\n label?: string;\r\n description?: string;\r\n assignee?: string;\r\n [key: string]: any;\r\n}\r\n\r\ndefineProps<{\r\n show: boolean;\r\n}>();\r\n\r\nconst editingElement = defineModel<BPMNElement>(\"editingElement\");\r\n\r\nconst emit = defineEmits<{\r\n \"update:show\": [value: boolean];\r\n save: [];\r\n delete: [];\r\n}>();\r\n\r\nconst typeName = computed(\r\n () =>\r\n elementTypeNames[\r\n editingElement.value?.shape as keyof typeof elementTypeNames\r\n ] ||\r\n editingElement.value?.shape ||\r\n \"\",\r\n);\r\n</script>\r\n","<template>\r\n <NDrawer\r\n :show=\"show\"\r\n width=\"300\"\r\n title=\"属性设置\"\r\n @update:show=\"emit('update:show', $event)\"\r\n >\r\n <div v-if=\"editingElement\" class=\"property-panel\">\r\n <div class=\"property-item\">\r\n <div class=\"property-label\">名称</div>\r\n <NInput\r\n v-model:value=\"editingElement.label\"\r\n placeholder=\"请输入名称\"\r\n size=\"small\"\r\n />\r\n </div>\r\n <div class=\"property-item\">\r\n <div class=\"property-label\">类型</div>\r\n <NInput :value=\"typeName\" readonly size=\"small\" />\r\n </div>\r\n <div class=\"property-item\" v-if=\"editingElement.shape === 'activity'\">\r\n <div class=\"property-label\">描述</div>\r\n <NInput\r\n v-model:value=\"editingElement.description\"\r\n type=\"textarea\"\r\n :rows=\"3\"\r\n placeholder=\"请输入活动描述\"\r\n size=\"small\"\r\n />\r\n </div>\r\n <div class=\"property-item\" v-if=\"editingElement.shape === 'activity'\">\r\n <div class=\"property-label\">执行人</div>\r\n <NInput\r\n v-model:value=\"editingElement.assignee\"\r\n placeholder=\"请输入执行人\"\r\n size=\"small\"\r\n />\r\n </div>\r\n <div class=\"form-actions\">\r\n <NSpace>\r\n <NButton @click=\"emit('save')\" type=\"primary\" size=\"small\">\r\n 保存\r\n </NButton>\r\n <NButton @click=\"emit('update:show', false)\" size=\"small\">\r\n 取消\r\n </NButton>\r\n <NButton @click=\"emit('delete')\" type=\"error\" size=\"small\">\r\n 删除\r\n </NButton>\r\n </NSpace>\r\n </div>\r\n </div>\r\n </NDrawer>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from \"vue\";\r\nimport { NDrawer, NInput, NSpace, NButton } from \"naive-ui\";\r\nimport { elementTypeNames } from \"../data\";\r\n\r\ninterface BPMNElement {\r\n id: string;\r\n shape: string;\r\n label?: string;\r\n description?: string;\r\n assignee?: string;\r\n [key: string]: any;\r\n}\r\n\r\ndefineProps<{\r\n show: boolean;\r\n}>();\r\n\r\nconst editingElement = defineModel<BPMNElement>(\"editingElement\");\r\n\r\nconst emit = defineEmits<{\r\n \"update:show\": [value: boolean];\r\n save: [];\r\n delete: [];\r\n}>();\r\n\r\nconst typeName = computed(\r\n () =>\r\n elementTypeNames[\r\n editingElement.value?.shape as keyof typeof elementTypeNames\r\n ] ||\r\n editingElement.value?.shape ||\r\n \"\",\r\n);\r\n</script>\r\n","<template>\n <div class=\"bpmn-layout\">\n <div\n class=\"top-toolbar\"\n v-if=\"showToolbar\"\n >\n <div class=\"toolbar-section\">\n <div class=\"toolbar-group\">\n <NButton\n @click=\"clearAll\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:delete-outline\"\n :size=\"16\"\n />\n </template>\n 清空\n </NButton>\n </div>\n <div class=\"toolbar-group\">\n <NButton\n @click=\"centerContent\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:image-filter-center-focus\"\n :size=\"16\"\n />\n </template>\n 居中\n </NButton>\n <NButton\n @click=\"zoomToFit\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:fit-to-screen\"\n :size=\"16\"\n />\n </template>\n 适应\n </NButton>\n </div>\n <div class=\"toolbar-group\">\n <NDropdown\n :options=\"exportOptions\"\n @select=\"(key: string) => handleExport(key, getCurrentData)\"\n >\n <NButton size=\"small\">\n <template #icon>\n <C_Icon\n name=\"mdi:export\"\n :size=\"16\"\n />\n </template>\n 导出\n </NButton>\n </NDropdown>\n </div>\n </div>\n </div>\n\n <div class=\"main-content\">\n <div\n class=\"left-panel\"\n v-if=\"showToolbar\"\n >\n <div class=\"panel-title\">组件</div>\n <div class=\"element-grid\">\n <div\n v-for=\"(item, key) in elementTypes\"\n :key=\"key\"\n class=\"element-item\"\n @click=\"addElement(key)\"\n :title=\"item.title\"\n >\n <div :class=\"['element-icon', item.iconClass]\"></div>\n <span>{{ item.name }}</span>\n </div>\n </div>\n </div>\n\n <div class=\"graph-wrapper\">\n <div\n ref=\"containerRef\"\n class=\"graph-container\"\n ></div>\n </div>\n </div>\n\n <BPMNPropertyEditor\n :show=\"showEditor\"\n v-model:editing-element=\"editingElement\"\n @update:show=\"showEditor = $event\"\n @save=\"saveElement\"\n @delete=\"deleteElement\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, onMounted } from 'vue'\n import { NButton, NDropdown } from 'naive-ui'\n import { Graph } from '@antv/x6'\n import { useGraphBase } from '../../composables/useGraphBase'\n import { useGraphExport } from '../../composables/useGraphExport'\n import { useEdgeInteraction } from '../../composables/useEdgeInteraction'\n import BPMNPropertyEditor from './components/BPMNPropertyEditor.vue'\n import C_Icon from '../../../C_Icon/index.vue'\n import {\n elementTypes,\n portPositions,\n createPortAttrs,\n nodeConfigs,\n edgeConfig,\n getGraphConfig,\n addElementConfigs,\n sampleData,\n } from './data'\n\n interface BPMNElement {\n id: string\n shape: string\n x: number\n y: number\n width?: number\n height?: number\n label?: string\n source?: string\n target?: string\n description?: string\n assignee?: string\n data?: any\n [key: string]: any\n }\n\n interface Props {\n data?: BPMNElement[] | Record<string, BPMNElement[]>\n showToolbar?: boolean\n readonly?: boolean\n width?: number | string\n height?: number | string\n theme?: 'light' | 'dark'\n }\n\n const props = withDefaults(defineProps<Props>(), {\n showToolbar: true,\n readonly: false,\n width: '100%',\n height: '600px',\n })\n\n const emit = defineEmits<{\n ready: [graph: Graph]\n 'data-change': [data: BPMNElement[]]\n }>()\n\n // ==================== Composables ====================\n const containerRef = ref<HTMLDivElement>()\n const isDark = computed(() => props.theme === 'dark')\n const { graph, initGraph, centerContent, zoomToFit } = useGraphBase(\n containerRef,\n isDark\n )\n const { exportOptions, handleExport } = useGraphExport(graph, 'bpmn-diagram')\n const { bindInteractions } = useEdgeInteraction(graph, {\n portPositions,\n onDataChange: () => emitDataChange(),\n })\n\n // ==================== 编辑器状态 ====================\n const showEditor = ref(false)\n const editingElement = ref<BPMNElement>()\n\n // ==================== 工具函数 ====================\n const getLabel = (cell: any): string =>\n String(cell.attr('text/text') || cell.attr('label/text') || '')\n\n const normalizeData = (data: any): any[] => {\n if (!data) return []\n if (Array.isArray(data)) return data\n const result: any[] = []\n Object.values(data).forEach((arr: any) => {\n if (Array.isArray(arr)) result.push(...arr)\n })\n return result\n }\n\n // ==================== 节点注册 ====================\n const registerNodes = () => {\n const portMarkup = portPositions.map(pos => ({\n tagName: 'circle',\n selector: `port-${pos}`,\n }))\n\n const nodeTypes = ['event', 'activity', 'gateway'] as const\n const bodyTags = { event: 'circle', activity: 'rect', gateway: 'polygon' }\n\n nodeTypes.forEach(type => {\n Graph.registerNode(\n type,\n {\n ...nodeConfigs[type],\n markup: [\n { tagName: bodyTags[type], selector: 'body' },\n { tagName: 'text', selector: 'text' },\n ...portMarkup,\n ],\n attrs: {\n ...nodeConfigs[type].attrs,\n ...createPortAttrs(portPositions, bodyTags[type] as any),\n },\n },\n true\n )\n })\n\n Graph.registerEdge('bpmn-edge', edgeConfig, true)\n }\n\n // ==================== 数据操作 ====================\n const loadData = (data: any[]) => {\n if (!graph.value || !data.length) return\n const cells = data.map(item => {\n const { data: nodeData, ...cellProps } = item\n const cell =\n item.shape === 'bpmn-edge'\n ? graph.value!.createEdge(cellProps)\n : graph.value!.createNode(cellProps)\n if (nodeData) cell.setData(nodeData)\n return cell\n })\n graph.value.resetCells(cells)\n setTimeout(() => graph.value!.zoomToFit({ padding: 50, maxScale: 1 }), 200)\n }\n\n const addElement = (type: string) => {\n if (!graph.value) return\n const config = addElementConfigs[type as keyof typeof addElementConfigs]\n if (!config) return\n\n const centerX = (graph.value.options.width as number) / 2\n const centerY = (graph.value.options.height as number) / 2\n const { data: nodeData, ...nodeProps } = {\n id: `${type}-${Date.now()}`,\n x: centerX + Math.random() * 100 - 50,\n y: centerY + Math.random() * 100 - 50,\n ...config,\n }\n const node = graph.value.createNode(nodeProps)\n if (nodeData) node.setData(nodeData)\n graph.value.addCell(node)\n emitDataChange()\n }\n\n const clearAll = () => {\n graph.value?.clearCells()\n emitDataChange()\n }\n\n // ==================== 元素编辑 ====================\n const editElement = (cell: any) => {\n const cellData = cell.getData() || {}\n editingElement.value = {\n id: cell.id,\n shape: cell.shape,\n label: getLabel(cell),\n description: cellData.description || '',\n assignee: cellData.assignee || '',\n x: 0,\n y: 0,\n }\n showEditor.value = true\n }\n\n const saveElement = () => {\n if (!graph.value || !editingElement.value) return\n const cell = graph.value.getCellById(editingElement.value.id)\n if (cell) {\n cell.setData({\n description: editingElement.value.description,\n assignee: editingElement.value.assignee,\n })\n cell.attr('text/text', editingElement.value.label || '')\n cell.attr('label/text', editingElement.value.label || '')\n }\n showEditor.value = false\n emitDataChange()\n }\n\n const deleteElement = () => {\n if (!graph.value || !editingElement.value) return\n graph.value.getCellById(editingElement.value.id)?.remove()\n showEditor.value = false\n emitDataChange()\n }\n\n // ==================== 数据获取 ====================\n const getCurrentData = (): BPMNElement[] => {\n if (!graph.value) return []\n return [\n ...graph.value.getNodes().map((node: any) => ({\n id: node.id,\n shape: node.shape,\n x: node.getPosition().x,\n y: node.getPosition().y,\n width: node.getSize().width,\n height: node.getSize().height,\n label: getLabel(node),\n data: node.getData() || {},\n })),\n ...graph.value.getEdges().map((edge: any) => ({\n id: edge.id,\n shape: 'bpmn-edge',\n source: edge.getSourceCellId() || '',\n target: edge.getTargetCellId() || '',\n label: getLabel(edge),\n x: 0,\n y: 0,\n })),\n ] as BPMNElement[]\n }\n\n const emitDataChange = () => emit('data-change', getCurrentData())\n\n // ==================== Graph 事件绑定 ====================\n watch(\n graph,\n newGraph => {\n if (!(newGraph instanceof Graph)) return\n\n if (!props.readonly) {\n bindInteractions()\n newGraph.on('node:dblclick', ({ node }) => editElement(node))\n newGraph.on('node:moved', emitDataChange)\n }\n\n emit('ready', newGraph)\n loadData(sampleData)\n },\n { immediate: true }\n )\n\n watch(\n () => props.data,\n newData => {\n if (!newData || !graph.value) return\n const normalized = normalizeData(newData)\n if (normalized.length > 0) loadData(normalized)\n },\n { deep: true }\n )\n\n onMounted(async () => {\n registerNodes()\n const bpmnConfig = getGraphConfig()\n await initGraph({\n ...bpmnConfig,\n connecting: {\n ...bpmnConfig.connecting,\n createEdge: () => graph.value!.createEdge({ shape: 'bpmn-edge' }),\n validateConnection: ({\n sourceView,\n targetView,\n sourceMagnet,\n targetMagnet,\n }: any) =>\n sourceView !== targetView &&\n !!sourceMagnet &&\n !!targetMagnet &&\n sourceMagnet.getAttribute('magnet') === 'true' &&\n targetMagnet.getAttribute('magnet') === 'true',\n },\n })\n })\n\n defineExpose({\n getGraph: () => graph.value,\n getData: getCurrentData,\n loadData,\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","<template>\n <div class=\"bpmn-layout\">\n <div\n class=\"top-toolbar\"\n v-if=\"showToolbar\"\n >\n <div class=\"toolbar-section\">\n <div class=\"toolbar-group\">\n <NButton\n @click=\"clearAll\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:delete-outline\"\n :size=\"16\"\n />\n </template>\n 清空\n </NButton>\n </div>\n <div class=\"toolbar-group\">\n <NButton\n @click=\"centerContent\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:image-filter-center-focus\"\n :size=\"16\"\n />\n </template>\n 居中\n </NButton>\n <NButton\n @click=\"zoomToFit\"\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:fit-to-screen\"\n :size=\"16\"\n />\n </template>\n 适应\n </NButton>\n </div>\n <div class=\"toolbar-group\">\n <NDropdown\n :options=\"exportOptions\"\n @select=\"(key: string) => handleExport(key, getCurrentData)\"\n >\n <NButton size=\"small\">\n <template #icon>\n <C_Icon\n name=\"mdi:export\"\n :size=\"16\"\n />\n </template>\n 导出\n </NButton>\n </NDropdown>\n </div>\n </div>\n </div>\n\n <div class=\"main-content\">\n <div\n class=\"left-panel\"\n v-if=\"showToolbar\"\n >\n <div class=\"panel-title\">组件</div>\n <div class=\"element-grid\">\n <div\n v-for=\"(item, key) in elementTypes\"\n :key=\"key\"\n class=\"element-item\"\n @click=\"addElement(key)\"\n :title=\"item.title\"\n >\n <div :class=\"['element-icon', item.iconClass]\"></div>\n <span>{{ item.name }}</span>\n </div>\n </div>\n </div>\n\n <div class=\"graph-wrapper\">\n <div\n ref=\"containerRef\"\n class=\"graph-container\"\n ></div>\n </div>\n </div>\n\n <BPMNPropertyEditor\n :show=\"showEditor\"\n v-model:editing-element=\"editingElement\"\n @update:show=\"showEditor = $event\"\n @save=\"saveElement\"\n @delete=\"deleteElement\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, onMounted } from 'vue'\n import { NButton, NDropdown } from 'naive-ui'\n import { Graph } from '@antv/x6'\n import { useGraphBase } from '../../composables/useGraphBase'\n import { useGraphExport } from '../../composables/useGraphExport'\n import { useEdgeInteraction } from '../../composables/useEdgeInteraction'\n import BPMNPropertyEditor from './components/BPMNPropertyEditor.vue'\n import C_Icon from '../../../C_Icon/index.vue'\n import {\n elementTypes,\n portPositions,\n createPortAttrs,\n nodeConfigs,\n edgeConfig,\n getGraphConfig,\n addElementConfigs,\n sampleData,\n } from './data'\n\n interface BPMNElement {\n id: string\n shape: string\n x: number\n y: number\n width?: number\n height?: number\n label?: string\n source?: string\n target?: string\n description?: string\n assignee?: string\n data?: any\n [key: string]: any\n }\n\n interface Props {\n data?: BPMNElement[] | Record<string, BPMNElement[]>\n showToolbar?: boolean\n readonly?: boolean\n width?: number | string\n height?: number | string\n theme?: 'light' | 'dark'\n }\n\n const props = withDefaults(defineProps<Props>(), {\n showToolbar: true,\n readonly: false,\n width: '100%',\n height: '600px',\n })\n\n const emit = defineEmits<{\n ready: [graph: Graph]\n 'data-change': [data: BPMNElement[]]\n }>()\n\n // ==================== Composables ====================\n const containerRef = ref<HTMLDivElement>()\n const isDark = computed(() => props.theme === 'dark')\n const { graph, initGraph, centerContent, zoomToFit } = useGraphBase(\n containerRef,\n isDark\n )\n const { exportOptions, handleExport } = useGraphExport(graph, 'bpmn-diagram')\n const { bindInteractions } = useEdgeInteraction(graph, {\n portPositions,\n onDataChange: () => emitDataChange(),\n })\n\n // ==================== 编辑器状态 ====================\n const showEditor = ref(false)\n const editingElement = ref<BPMNElement>()\n\n // ==================== 工具函数 ====================\n const getLabel = (cell: any): string =>\n String(cell.attr('text/text') || cell.attr('label/text') || '')\n\n const normalizeData = (data: any): any[] => {\n if (!data) return []\n if (Array.isArray(data)) return data\n const result: any[] = []\n Object.values(data).forEach((arr: any) => {\n if (Array.isArray(arr)) result.push(...arr)\n })\n return result\n }\n\n // ==================== 节点注册 ====================\n const registerNodes = () => {\n const portMarkup = portPositions.map(pos => ({\n tagName: 'circle',\n selector: `port-${pos}`,\n }))\n\n const nodeTypes = ['event', 'activity', 'gateway'] as const\n const bodyTags = { event: 'circle', activity: 'rect', gateway: 'polygon' }\n\n nodeTypes.forEach(type => {\n Graph.registerNode(\n type,\n {\n ...nodeConfigs[type],\n markup: [\n { tagName: bodyTags[type], selector: 'body' },\n { tagName: 'text', selector: 'text' },\n ...portMarkup,\n ],\n attrs: {\n ...nodeConfigs[type].attrs,\n ...createPortAttrs(portPositions, bodyTags[type] as any),\n },\n },\n true\n )\n })\n\n Graph.registerEdge('bpmn-edge', edgeConfig, true)\n }\n\n // ==================== 数据操作 ====================\n const loadData = (data: any[]) => {\n if (!graph.value || !data.length) return\n const cells = data.map(item => {\n const { data: nodeData, ...cellProps } = item\n const cell =\n item.shape === 'bpmn-edge'\n ? graph.value!.createEdge(cellProps)\n : graph.value!.createNode(cellProps)\n if (nodeData) cell.setData(nodeData)\n return cell\n })\n graph.value.resetCells(cells)\n setTimeout(() => graph.value!.zoomToFit({ padding: 50, maxScale: 1 }), 200)\n }\n\n const addElement = (type: string) => {\n if (!graph.value) return\n const config = addElementConfigs[type as keyof typeof addElementConfigs]\n if (!config) return\n\n const centerX = (graph.value.options.width as number) / 2\n const centerY = (graph.value.options.height as number) / 2\n const { data: nodeData, ...nodeProps } = {\n id: `${type}-${Date.now()}`,\n x: centerX + Math.random() * 100 - 50,\n y: centerY + Math.random() * 100 - 50,\n ...config,\n }\n const node = graph.value.createNode(nodeProps)\n if (nodeData) node.setData(nodeData)\n graph.value.addCell(node)\n emitDataChange()\n }\n\n const clearAll = () => {\n graph.value?.clearCells()\n emitDataChange()\n }\n\n // ==================== 元素编辑 ====================\n const editElement = (cell: any) => {\n const cellData = cell.getData() || {}\n editingElement.value = {\n id: cell.id,\n shape: cell.shape,\n label: getLabel(cell),\n description: cellData.description || '',\n assignee: cellData.assignee || '',\n x: 0,\n y: 0,\n }\n showEditor.value = true\n }\n\n const saveElement = () => {\n if (!graph.value || !editingElement.value) return\n const cell = graph.value.getCellById(editingElement.value.id)\n if (cell) {\n cell.setData({\n description: editingElement.value.description,\n assignee: editingElement.value.assignee,\n })\n cell.attr('text/text', editingElement.value.label || '')\n cell.attr('label/text', editingElement.value.label || '')\n }\n showEditor.value = false\n emitDataChange()\n }\n\n const deleteElement = () => {\n if (!graph.value || !editingElement.value) return\n graph.value.getCellById(editingElement.value.id)?.remove()\n showEditor.value = false\n emitDataChange()\n }\n\n // ==================== 数据获取 ====================\n const getCurrentData = (): BPMNElement[] => {\n if (!graph.value) return []\n return [\n ...graph.value.getNodes().map((node: any) => ({\n id: node.id,\n shape: node.shape,\n x: node.getPosition().x,\n y: node.getPosition().y,\n width: node.getSize().width,\n height: node.getSize().height,\n label: getLabel(node),\n data: node.getData() || {},\n })),\n ...graph.value.getEdges().map((edge: any) => ({\n id: edge.id,\n shape: 'bpmn-edge',\n source: edge.getSourceCellId() || '',\n target: edge.getTargetCellId() || '',\n label: getLabel(edge),\n x: 0,\n y: 0,\n })),\n ] as BPMNElement[]\n }\n\n const emitDataChange = () => emit('data-change', getCurrentData())\n\n // ==================== Graph 事件绑定 ====================\n watch(\n graph,\n newGraph => {\n if (!(newGraph instanceof Graph)) return\n\n if (!props.readonly) {\n bindInteractions()\n newGraph.on('node:dblclick', ({ node }) => editElement(node))\n newGraph.on('node:moved', emitDataChange)\n }\n\n emit('ready', newGraph)\n loadData(sampleData)\n },\n { immediate: true }\n )\n\n watch(\n () => props.data,\n newData => {\n if (!newData || !graph.value) return\n const normalized = normalizeData(newData)\n if (normalized.length > 0) loadData(normalized)\n },\n { deep: true }\n )\n\n onMounted(async () => {\n registerNodes()\n const bpmnConfig = getGraphConfig()\n await initGraph({\n ...bpmnConfig,\n connecting: {\n ...bpmnConfig.connecting,\n createEdge: () => graph.value!.createEdge({ shape: 'bpmn-edge' }),\n validateConnection: ({\n sourceView,\n targetView,\n sourceMagnet,\n targetMagnet,\n }: any) =>\n sourceView !== targetView &&\n !!sourceMagnet &&\n !!targetMagnet &&\n sourceMagnet.getAttribute('magnet') === 'true' &&\n targetMagnet.getAttribute('magnet') === 'true',\n },\n })\n })\n\n defineExpose({\n getGraph: () => graph.value,\n getData: getCurrentData,\n loadData,\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @use './index.scss';\n</style>\n","<template>\n <NDrawer\n :show=\"show\"\n width=\"450\"\n title=\"编辑类\"\n @update:show=\"emit('update:show', $event)\"\n >\n <div\n v-if=\"editingClass\"\n class=\"class-editor\"\n >\n <NForm label-placement=\"top\">\n <NFormItem label=\"类名\">\n <NInput\n v-model:value=\"editingClass.name\"\n placeholder=\"请输入类名\"\n />\n </NFormItem>\n\n <NDivider style=\"margin: 20px 0\">属性</NDivider>\n <div class=\"section\">\n <div\n v-for=\"(attr, index) in editingClass.attributes\"\n :key=\"index\"\n class=\"item\"\n >\n <NCard\n size=\"small\"\n style=\"margin-bottom: 12px\"\n >\n <template #header>\n <div class=\"section-header\">\n <span style=\"font-size: 13px\"\n >#{{ index + 1 }} {{ attr.name || '新属性' }}</span\n >\n <NButton\n @click=\"editingClass!.attributes.splice(index, 1)\"\n size=\"tiny\"\n type=\"error\"\n quaternary\n style=\"margin-left: auto\"\n >\n 删除\n </NButton>\n </div>\n </template>\n <NSpace\n vertical\n size=\"small\"\n >\n <NSpace>\n <NFormItem\n label=\"属性名\"\n style=\"margin: 0; flex: 1\"\n >\n <NInput\n v-model:value=\"attr.name\"\n placeholder=\"属性名\"\n size=\"small\"\n />\n </NFormItem>\n <NFormItem\n label=\"类型\"\n style=\"margin: 0; flex: 1\"\n >\n <NInput\n v-model:value=\"attr.type\"\n placeholder=\"类型\"\n size=\"small\"\n />\n </NFormItem>\n </NSpace>\n <NFormItem\n label=\"可见性\"\n style=\"margin: 0\"\n >\n <NRadioGroup\n v-model:value=\"attr.visibility\"\n size=\"small\"\n >\n <NRadio value=\"public\">+ public</NRadio>\n <NRadio value=\"private\">- private</NRadio>\n <NRadio value=\"protected\"># protected</NRadio>\n </NRadioGroup>\n </NFormItem>\n </NSpace>\n </NCard>\n </div>\n <NButton\n @click=\"\n editingClass!.attributes.push({\n name: 'newAttribute',\n type: 'string',\n visibility: 'private',\n })\n \"\n dashed\n block\n type=\"primary\"\n ghost\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:plus\"\n :size=\"16\"\n />\n </template>\n 添加属性\n </NButton>\n </div>\n\n <NDivider style=\"margin: 20px 0\">方法</NDivider>\n <div class=\"section\">\n <div\n v-for=\"(method, index) in editingClass.methods\"\n :key=\"index\"\n class=\"item\"\n >\n <NCard\n size=\"small\"\n style=\"margin-bottom: 12px\"\n >\n <template #header>\n <div class=\"section-header\">\n <span style=\"font-size: 13px\"\n >#{{ index + 1 }} {{ method.name || '新方法' }}</span\n >\n <NButton\n @click=\"editingClass!.methods.splice(index, 1)\"\n size=\"tiny\"\n type=\"error\"\n quaternary\n style=\"margin-left: auto\"\n >\n 删除\n </NButton>\n </div>\n </template>\n <NSpace\n vertical\n size=\"small\"\n >\n <NSpace>\n <NFormItem\n label=\"方法名\"\n style=\"margin: 0; flex: 1\"\n >\n <NInput\n v-model:value=\"method.name\"\n placeholder=\"方法名\"\n size=\"small\"\n />\n </NFormItem>\n <NFormItem\n label=\"返回类型\"\n style=\"margin: 0; flex: 1\"\n >\n <NInput\n v-model:value=\"method.returnType\"\n placeholder=\"返回类型\"\n size=\"small\"\n />\n </NFormItem>\n </NSpace>\n <NFormItem\n label=\"可见性\"\n style=\"margin: 0\"\n >\n <NRadioGroup\n v-model:value=\"method.visibility\"\n size=\"small\"\n >\n <NRadio value=\"public\">+ public</NRadio>\n <NRadio value=\"private\">- private</NRadio>\n <NRadio value=\"protected\"># protected</NRadio>\n </NRadioGroup>\n </NFormItem>\n </NSpace>\n </NCard>\n </div>\n <NButton\n @click=\"\n editingClass!.methods.push({\n name: 'newMethod',\n returnType: 'void',\n visibility: 'public',\n })\n \"\n dashed\n block\n type=\"primary\"\n ghost\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:plus\"\n :size=\"16\"\n />\n </template>\n 添加方法\n </NButton>\n </div>\n\n <NDivider style=\"margin: 20px 0\"></NDivider>\n <NSpace justify=\"space-between\">\n <NButton\n @click=\"emit('delete')\"\n type=\"error\"\n ghost\n >\n <template #icon>\n <C_Icon\n name=\"mdi:delete\"\n :size=\"16\"\n />\n </template>\n 删除类\n </NButton>\n <NSpace>\n <NButton @click=\"emit('update:show', false)\">取消</NButton>\n <NButton\n @click=\"emit('save')\"\n type=\"primary\"\n >\n 保存\n </NButton>\n </NSpace>\n </NSpace>\n </NForm>\n </div>\n </NDrawer>\n</template>\n\n<script setup lang=\"ts\">\n import {\n NDrawer,\n NForm,\n NFormItem,\n NInput,\n NCard,\n NSpace,\n NButton,\n NDivider,\n NRadioGroup,\n NRadio,\n } from 'naive-ui'\n import type { UMLClass } from '../../../types'\n import C_Icon from '../../../../C_Icon/index.vue'\n\n defineProps<{\n show: boolean\n }>()\n\n const editingClass = defineModel<UMLClass>('editingClass')\n\n const emit = defineEmits<{\n 'update:show': [value: boolean]\n save: []\n delete: []\n }>()\n</script>\n\n<style lang=\"scss\" scoped>\n .class-editor {\n padding: 20px;\n height: calc(100vh - 60px);\n overflow-y: auto;\n }\n\n .section {\n max-height: 300px;\n overflow-y: auto;\n padding-right: 4px;\n\n &::-webkit-scrollbar {\n width: 6px;\n }\n\n &::-webkit-scrollbar-thumb {\n background: #d4d4d4;\n border-radius: 3px;\n }\n }\n\n .section-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .item {\n margin-bottom: 8px;\n }\n\n .section .n-card {\n border: 1px solid #e8e8e8;\n }\n\n .section .n-card-header {\n padding: 8px 12px;\n background: #fafafa;\n border-bottom: 1px solid #e8e8e8;\n }\n\n .section .n-card__content {\n padding: 12px;\n }\n\n .section .n-form-item {\n margin-bottom: 0;\n }\n\n .section .n-form-item-label {\n font-size: 12px;\n margin-bottom: 4px;\n color: #666;\n }\n</style>\n","<template>\n <NDrawer\n :show=\"show\"\n width=\"450\"\n title=\"编辑类\"\n @update:show=\"emit('update:show', $event)\"\n >\n <div\n v-if=\"editingClass\"\n class=\"class-editor\"\n >\n <NForm label-placement=\"top\">\n <NFormItem label=\"类名\">\n <NInput\n v-model:value=\"editingClass.name\"\n placeholder=\"请输入类名\"\n />\n </NFormItem>\n\n <NDivider style=\"margin: 20px 0\">属性</NDivider>\n <div class=\"section\">\n <div\n v-for=\"(attr, index) in editingClass.attributes\"\n :key=\"index\"\n class=\"item\"\n >\n <NCard\n size=\"small\"\n style=\"margin-bottom: 12px\"\n >\n <template #header>\n <div class=\"section-header\">\n <span style=\"font-size: 13px\"\n >#{{ index + 1 }} {{ attr.name || '新属性' }}</span\n >\n <NButton\n @click=\"editingClass!.attributes.splice(index, 1)\"\n size=\"tiny\"\n type=\"error\"\n quaternary\n style=\"margin-left: auto\"\n >\n 删除\n </NButton>\n </div>\n </template>\n <NSpace\n vertical\n size=\"small\"\n >\n <NSpace>\n <NFormItem\n label=\"属性名\"\n style=\"margin: 0; flex: 1\"\n >\n <NInput\n v-model:value=\"attr.name\"\n placeholder=\"属性名\"\n size=\"small\"\n />\n </NFormItem>\n <NFormItem\n label=\"类型\"\n style=\"margin: 0; flex: 1\"\n >\n <NInput\n v-model:value=\"attr.type\"\n placeholder=\"类型\"\n size=\"small\"\n />\n </NFormItem>\n </NSpace>\n <NFormItem\n label=\"可见性\"\n style=\"margin: 0\"\n >\n <NRadioGroup\n v-model:value=\"attr.visibility\"\n size=\"small\"\n >\n <NRadio value=\"public\">+ public</NRadio>\n <NRadio value=\"private\">- private</NRadio>\n <NRadio value=\"protected\"># protected</NRadio>\n </NRadioGroup>\n </NFormItem>\n </NSpace>\n </NCard>\n </div>\n <NButton\n @click=\"\n editingClass!.attributes.push({\n name: 'newAttribute',\n type: 'string',\n visibility: 'private',\n })\n \"\n dashed\n block\n type=\"primary\"\n ghost\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:plus\"\n :size=\"16\"\n />\n </template>\n 添加属性\n </NButton>\n </div>\n\n <NDivider style=\"margin: 20px 0\">方法</NDivider>\n <div class=\"section\">\n <div\n v-for=\"(method, index) in editingClass.methods\"\n :key=\"index\"\n class=\"item\"\n >\n <NCard\n size=\"small\"\n style=\"margin-bottom: 12px\"\n >\n <template #header>\n <div class=\"section-header\">\n <span style=\"font-size: 13px\"\n >#{{ index + 1 }} {{ method.name || '新方法' }}</span\n >\n <NButton\n @click=\"editingClass!.methods.splice(index, 1)\"\n size=\"tiny\"\n type=\"error\"\n quaternary\n style=\"margin-left: auto\"\n >\n 删除\n </NButton>\n </div>\n </template>\n <NSpace\n vertical\n size=\"small\"\n >\n <NSpace>\n <NFormItem\n label=\"方法名\"\n style=\"margin: 0; flex: 1\"\n >\n <NInput\n v-model:value=\"method.name\"\n placeholder=\"方法名\"\n size=\"small\"\n />\n </NFormItem>\n <NFormItem\n label=\"返回类型\"\n style=\"margin: 0; flex: 1\"\n >\n <NInput\n v-model:value=\"method.returnType\"\n placeholder=\"返回类型\"\n size=\"small\"\n />\n </NFormItem>\n </NSpace>\n <NFormItem\n label=\"可见性\"\n style=\"margin: 0\"\n >\n <NRadioGroup\n v-model:value=\"method.visibility\"\n size=\"small\"\n >\n <NRadio value=\"public\">+ public</NRadio>\n <NRadio value=\"private\">- private</NRadio>\n <NRadio value=\"protected\"># protected</NRadio>\n </NRadioGroup>\n </NFormItem>\n </NSpace>\n </NCard>\n </div>\n <NButton\n @click=\"\n editingClass!.methods.push({\n name: 'newMethod',\n returnType: 'void',\n visibility: 'public',\n })\n \"\n dashed\n block\n type=\"primary\"\n ghost\n size=\"small\"\n >\n <template #icon>\n <C_Icon\n name=\"mdi:plus\"\n :size=\"16\"\n />\n </template>\n 添加方法\n </NButton>\n </div>\n\n <NDivider style=\"margin: 20px 0\"></NDivider>\n <NSpace justify=\"space-between\">\n <NButton\n @click=\"emit('delete')\"\n type=\"error\"\n ghost\n >\n <template #icon>\n <C_Icon\n name=\"mdi:delete\"\n :size=\"16\"\n />\n </template>\n 删除类\n </NButton>\n <NSpace>\n <NButton @click=\"emit('update:show', false)\">取消</NButton>\n <NButton\n @click=\"emit('save')\"\n type=\"primary\"\n >\n 保存\n </NButton>\n </NSpace>\n </NSpace>\n </NForm>\n </div>\n </NDrawer>\n</template>\n\n<script setup lang=\"ts\">\n import {\n NDrawer,\n NForm,\n NFormItem,\n NInput,\n NCard,\n NSpace,\n NButton,\n NDivider,\n NRadioGroup,\n NRadio,\n } from 'naive-ui'\n import type { UMLClass } from '../../../types'\n import C_Icon from '../../../../C_Icon/index.vue'\n\n defineProps<{\n show: boolean\n }>()\n\n const editingClass = defineModel<UMLClass>('editingClass')\n\n const emit = defineEmits<{\n 'update:show': [value: boolean]\n save: []\n delete: []\n }>()\n</script>\n\n<style lang=\"scss\" scoped>\n .class-editor {\n padding: 20px;\n height: calc(100vh - 60px);\n overflow-y: auto;\n }\n\n .section {\n max-height: 300px;\n overflow-y: auto;\n padding-right: 4px;\n\n &::-webkit-scrollbar {\n width: 6px;\n }\n\n &::-webkit-scrollbar-thumb {\n background: #d4d4d4;\n border-radius: 3px;\n }\n }\n\n .section-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .item {\n margin-bottom: 8px;\n }\n\n .section .n-card {\n border: 1px solid #e8e8e8;\n }\n\n .section .n-card-header {\n padding: 8px 12px;\n background: #fafafa;\n border-bottom: 1px solid #e8e8e8;\n }\n\n .section .n-card__content {\n padding: 12px;\n }\n\n .section .n-form-item {\n margin-bottom: 0;\n }\n\n .section .n-form-item-label {\n font-size: 12px;\n margin-bottom: 4px;\n color: #666;\n }\n</style>\n","import type { UMLAttribute, UMLMethod } from \"../../types\";\r\n\r\nexport const visibilityMap = {\r\n public: \"+\",\r\n private: \"-\",\r\n protected: \"#\",\r\n};\r\n\r\n/* 连线类型配置 */\r\nexport const edgeTypes = {\r\n extends: {\r\n strokeDasharray: 0,\r\n targetMarker: {\r\n name: \"block\",\r\n width: 10,\r\n height: 8,\r\n fill: \"white\",\r\n stroke: \"#722ed1\",\r\n strokeWidth: 2,\r\n },\r\n },\r\n implement: {\r\n strokeDasharray: \"8,4\",\r\n targetMarker: {\r\n name: \"block\",\r\n width: 10,\r\n height: 8,\r\n fill: \"white\",\r\n stroke: \"#722ed1\",\r\n strokeWidth: 2,\r\n },\r\n },\r\n composition: {\r\n strokeDasharray: 0,\r\n sourceMarker: {\r\n name: \"diamond\",\r\n width: 12,\r\n height: 8,\r\n fill: \"#722ed1\",\r\n stroke: \"#722ed1\",\r\n },\r\n },\r\n aggregation: {\r\n strokeDasharray: 0,\r\n sourceMarker: {\r\n name: \"diamond\",\r\n width: 12,\r\n height: 8,\r\n fill: \"white\",\r\n stroke: \"#722ed1\",\r\n strokeWidth: 2,\r\n },\r\n },\r\n association: {\r\n strokeDasharray: 0,\r\n targetMarker: { name: \"classic\", size: 8, fill: \"#722ed1\" },\r\n },\r\n};\r\n\r\n/* 端口配置 */\r\nexport const portConfig = [\"top\", \"right\", \"bottom\", \"left\"].reduce(\r\n (acc, pos) => {\r\n const refConfig =\r\n pos === \"top\"\r\n ? { refX: 0.5, refY: 0 }\r\n : pos === \"right\"\r\n ? { refX: 1, refY: 0.5 }\r\n : pos === \"bottom\"\r\n ? { refX: 0.5, refY: 1 }\r\n : { refX: 0, refY: 0.5 };\r\n acc[`port-${pos}`] = {\r\n ref: \"body\",\r\n ...refConfig,\r\n r: 4,\r\n fill: \"#31d0c6\",\r\n stroke: \"#ffffff\",\r\n strokeWidth: 2,\r\n magnet: true,\r\n style: {\r\n cursor: \"crosshair\",\r\n opacity: 0,\r\n transition: \"opacity 0.2s\",\r\n },\r\n };\r\n return acc;\r\n },\r\n {} as any,\r\n);\r\n\r\n/* UML类节点配置 */\r\nexport const classNodeConfig = {\r\n inherit: \"rect\",\r\n markup: [\r\n { tagName: \"rect\", selector: \"body\" },\r\n { tagName: \"rect\", selector: \"name-rect\" },\r\n { tagName: \"rect\", selector: \"attrs-rect\" },\r\n { tagName: \"rect\", selector: \"methods-rect\" },\r\n { tagName: \"text\", selector: \"name-text\" },\r\n { tagName: \"text\", selector: \"attrs-text\" },\r\n { tagName: \"text\", selector: \"methods-text\" },\r\n { tagName: \"circle\", selector: \"port-top\" },\r\n { tagName: \"circle\", selector: \"port-right\" },\r\n { tagName: \"circle\", selector: \"port-bottom\" },\r\n { tagName: \"circle\", selector: \"port-left\" },\r\n ],\r\n attrs: {\r\n rect: { width: 160 },\r\n body: {\r\n stroke: \"#5f95ff\",\r\n strokeWidth: 1,\r\n fill: \"#fff\",\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n \"name-rect\": {\r\n fill: \"#5f95ff\",\r\n stroke: \"#fff\",\r\n strokeWidth: 0.5,\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n \"attrs-rect\": {\r\n fill: \"#eff4ff\",\r\n stroke: \"#fff\",\r\n strokeWidth: 0.5,\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n \"methods-rect\": {\r\n fill: \"#eff4ff\",\r\n stroke: \"#fff\",\r\n strokeWidth: 0.5,\r\n magnet: false,\r\n style: { cursor: \"move\" },\r\n },\r\n \"name-text\": {\r\n ref: \"name-rect\",\r\n refY: 0.5,\r\n refX: 0.5,\r\n textAnchor: \"middle\",\r\n fontWeight: \"bold\",\r\n fill: \"#fff\",\r\n fontSize: 12,\r\n pointerEvents: \"none\",\r\n },\r\n \"attrs-text\": {\r\n ref: \"attrs-rect\",\r\n refY: 0.5,\r\n refX: 5,\r\n textAnchor: \"left\",\r\n fill: \"black\",\r\n fontSize: 10,\r\n pointerEvents: \"none\",\r\n },\r\n \"methods-text\": {\r\n ref: \"methods-rect\",\r\n refY: 0.5,\r\n refX: 5,\r\n textAnchor: \"left\",\r\n fill: \"black\",\r\n fontSize: 10,\r\n pointerEvents: \"none\",\r\n },\r\n ...portConfig,\r\n },\r\n};\r\n\r\n/* 图形配置 */\r\nexport const graphConfig = {\r\n grid: true,\r\n panning: true,\r\n mousewheel: {\r\n enabled: true,\r\n zoomAtMousePosition: true,\r\n modifiers: \"ctrl\",\r\n minScale: 0.5,\r\n maxScale: 3,\r\n },\r\n};\r\n\r\n/* 连接配置 */\r\nexport const connectingConfig = {\r\n router: \"manhattan\",\r\n connector: { name: \"rounded\", args: { radius: 8 } },\r\n allowBlank: false,\r\n allowLoop: false,\r\n allowNode: false,\r\n snap: true,\r\n allowEdge: false,\r\n};\r\n\r\n/* 高亮配置 */\r\nexport const highlightingConfig = {\r\n magnetAvailable: {\r\n name: \"stroke\",\r\n args: { attrs: { fill: \"#31d0c6\", stroke: \"#31d0c6\", opacity: 1 } },\r\n },\r\n magnetAdsorbed: {\r\n name: \"stroke\",\r\n args: { attrs: { fill: \"#5F95FF\", stroke: \"#5F95FF\", opacity: 1 } },\r\n },\r\n};\r\n\r\n/* 默认边配置 */\r\nexport const defaultEdgeConfig = {\r\n shape: \"extends\",\r\n attrs: {\r\n line: {\r\n stroke: \"#722ed1\",\r\n strokeWidth: 2,\r\n targetMarker: {\r\n name: \"block\",\r\n width: 8,\r\n height: 6,\r\n fill: \"#722ed1\",\r\n },\r\n },\r\n },\r\n};\r\n\r\n/* 示例类数据 */\r\nexport const sampleClasses = [\r\n {\r\n id: \"animal\",\r\n name: \"<<Abstract>>\\n动物\",\r\n x: 342,\r\n y: 98,\r\n attributes: [{ name: \"名字\", type: \"string\", visibility: \"public\" }],\r\n methods: [\r\n { name: \"新陈代谢\", returnType: \"void\", visibility: \"public\" },\r\n { name: \"繁殖\", returnType: \"void\", visibility: \"public\" },\r\n ],\r\n },\r\n {\r\n id: \"bird\",\r\n name: \"鸟\",\r\n x: 575,\r\n y: 280,\r\n attributes: [\r\n { name: \"羽毛\", type: \"string\", visibility: \"public\" },\r\n { name: \"下蛋\", type: \"boolean\", visibility: \"public\" },\r\n ],\r\n methods: [],\r\n },\r\n {\r\n id: \"mammal\",\r\n name: \"哺乳动物\",\r\n x: 844,\r\n y: 319,\r\n attributes: [{ name: \"翅膀\", type: \"boolean\", visibility: \"public\" }],\r\n methods: [],\r\n },\r\n {\r\n id: \"dog\",\r\n name: \"狗\",\r\n x: 656,\r\n y: 456,\r\n attributes: [{ name: \"下蛋\", type: \"boolean\", visibility: \"public\" }],\r\n methods: [],\r\n },\r\n {\r\n id: \"enterprise\",\r\n name: \"企鹅\",\r\n x: 984,\r\n y: 456,\r\n attributes: [{ name: \"下蛋\", type: \"boolean\", visibility: \"public\" }],\r\n methods: [],\r\n },\r\n {\r\n id: \"sparrow\",\r\n name: \"麻雀\",\r\n x: 531,\r\n y: 608,\r\n attributes: [{ name: \"学飞\", type: \"boolean\", visibility: \"public\" }],\r\n methods: [],\r\n },\r\n {\r\n id: \"interface-flying\",\r\n name: \"<<interface>>\\n飞翔\",\r\n x: 762,\r\n y: 608,\r\n attributes: [{ name: \"下蛋\", type: \"boolean\", visibility: \"public\" }],\r\n methods: [],\r\n },\r\n { id: \"qemu\", name: \"气球\", x: 981, y: 608, attributes: [], methods: [] },\r\n];\r\n\r\n/* 示例连接关系 */\r\nexport const sampleConnections = [\r\n { id: \"edge-1\", shape: \"extends\", source: \"bird\", target: \"animal\" },\r\n { id: \"edge-2\", shape: \"extends\", source: \"mammal\", target: \"animal\" },\r\n { id: \"edge-3\", shape: \"extends\", source: \"dog\", target: \"mammal\" },\r\n {\r\n id: \"edge-4\",\r\n shape: \"extends\",\r\n source: \"enterprise\",\r\n target: \"mammal\",\r\n },\r\n { id: \"edge-5\", shape: \"extends\", source: \"sparrow\", target: \"bird\" },\r\n {\r\n id: \"edge-6\",\r\n shape: \"implement\",\r\n source: \"sparrow\",\r\n target: \"interface-flying\",\r\n },\r\n {\r\n id: \"edge-7\",\r\n shape: \"implement\",\r\n source: \"enterprise\",\r\n target: \"interface-flying\",\r\n },\r\n {\r\n id: \"edge-8\",\r\n shape: \"association\",\r\n source: \"bird\",\r\n target: \"mammal\",\r\n label: \"1:2\",\r\n },\r\n];\r\n\r\n/* 工具函数 */\r\nexport const getVisibilitySymbol = (visibility: string) =>\r\n visibilityMap[visibility as keyof typeof visibilityMap] || \"+\";\r\n\r\n/* 新类模板 */\r\nexport const newClassTemplate = {\r\n name: \"新类\",\r\n attributes: [\r\n { name: \"attribute\", type: \"string\", visibility: \"private\" },\r\n ] as UMLAttribute[],\r\n methods: [\r\n { name: \"method\", returnType: \"void\", visibility: \"public\" },\r\n ] as UMLMethod[],\r\n position: { x: 100, y: 100 },\r\n};\r\n","<template>\n <div class=\"uml-layout\">\n <div class=\"toolbar\" v-if=\"showToolbar\">\n <NSpace>\n <NButton @click=\"addClass\" type=\"primary\" size=\"small\">\n <template #icon>\n <C_Icon name=\"mdi:plus-box\" :size=\"16\" />\n </template>\n 添加类\n </NButton>\n <NButton @click=\"centerContent\" size=\"small\">\n <template #icon>\n <C_Icon name=\"mdi:image-filter-center-focus\" :size=\"16\" />\n </template>\n 居中\n </NButton>\n <NButton @click=\"zoomToFit\" size=\"small\">\n <template #icon>\n <C_Icon name=\"mdi:fit-to-screen\" :size=\"16\" />\n </template>\n 适应\n </NButton>\n <NDropdown\n :options=\"exportOptions\"\n @select=\"(key: string) => handleExport(key, getCurrentData)\"\n >\n <NButton size=\"small\">\n <template #icon>\n <C_Icon name=\"mdi:export\" :size=\"16\" />\n </template>\n 导出\n </NButton>\n </NDropdown>\n </NSpace>\n </div>\n\n <div\n ref=\"containerRef\"\n class=\"graph-container\"\n :style=\"{ width: props.width, height: props.height }\"\n ></div>\n\n <UMLClassEditor\n :show=\"showEditor\"\n v-model:editing-class=\"editingClass\"\n @update:show=\"showEditor = $event\"\n @save=\"saveClass\"\n @delete=\"deleteClass\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted } from \"vue\";\nimport { NSpace, NButton, NDropdown } from \"naive-ui\";\nimport { Graph, ObjectExt, type Node, type Cell } from \"@antv/x6\";\nimport { useGraphBase } from \"../../composables/useGraphBase\";\nimport { useGraphExport } from \"../../composables/useGraphExport\";\nimport { useEdgeInteraction } from \"../../composables/useEdgeInteraction\";\nimport type { UMLClass, UMLDiagramData } from \"../../types\";\nimport UMLClassEditor from \"./components/UMLClassEditor.vue\";\nimport C_Icon from \"../../../C_Icon/index.vue\";\nimport {\n edgeTypes,\n classNodeConfig,\n connectingConfig,\n highlightingConfig,\n defaultEdgeConfig,\n sampleClasses,\n sampleConnections,\n getVisibilitySymbol,\n newClassTemplate,\n} from \"./data\";\n\ninterface Props {\n data?: UMLDiagramData;\n showToolbar?: boolean;\n readonly?: boolean;\n width?: number | string;\n height?: number | string;\n theme?: \"light\" | \"dark\";\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n showToolbar: true,\n readonly: false,\n width: \"100%\",\n height: \"600px\",\n});\n\nconst emit = defineEmits<{\n ready: [graph: any];\n \"data-change\": [data: UMLDiagramData];\n}>();\n\n// ==================== Composables ====================\nconst containerRef = ref<HTMLDivElement>();\nconst isDark = computed(() => props.theme === \"dark\");\nconst { graph, initGraph, centerContent, zoomToFit } = useGraphBase(\n containerRef,\n isDark,\n);\nconst { exportOptions, handleExport } = useGraphExport(graph, \"uml-diagram\");\nconst { bindInteractions } = useEdgeInteraction(graph, {\n defaultColor: \"#722ed1\",\n portPositions: [\"top\", \"right\", \"bottom\", \"left\"],\n onDataChange: () => emitDataChange(),\n});\n\n// ==================== 编辑器状态 ====================\nconst showEditor = ref(false);\nconst editingClass = ref<UMLClass>();\n\n// ==================== 节点注册 ====================\nconst registerNodes = () => {\n Graph.registerNode(\n \"class\",\n {\n ...classNodeConfig,\n /** @description 节点属性钩子,用于计算 UML 类图节点布局 */\n propHooks(meta: any) {\n const { name, attributes, methods, ...others } = meta;\n if (!(name && attributes && methods)) return meta;\n\n let offsetY = 0;\n [\n { type: \"name\", text: name },\n { type: \"attrs\", text: attributes },\n { type: \"methods\", text: methods },\n ].forEach((rect) => {\n const height = Array.isArray(rect.text)\n ? rect.text.length * 12 + 16\n : 32;\n ObjectExt.setByPath(\n others,\n `attrs/${rect.type}-text/text`,\n Array.isArray(rect.text) ? rect.text.join(\"\\n\") : rect.text,\n );\n ObjectExt.setByPath(others, `attrs/${rect.type}-rect/height`, height);\n ObjectExt.setByPath(\n others,\n `attrs/${rect.type}-rect/transform`,\n `translate(0,${offsetY})`,\n );\n offsetY += height;\n });\n others.size = { width: 160, height: offsetY };\n return others;\n },\n },\n true,\n );\n\n Object.entries(edgeTypes).forEach(([type, config]) => {\n Graph.registerEdge(\n type,\n {\n inherit: \"edge\",\n attrs: { line: { strokeWidth: 2, stroke: \"#722ed1\", ...config } },\n },\n true,\n );\n });\n};\n\n// ==================== 数据加载 ====================\nconst loadData = (data: any[]) => {\n if (!graph.value || !data.length) return;\n const edgeShapes = [\n \"extends\",\n \"composition\",\n \"implement\",\n \"aggregation\",\n \"association\",\n ];\n const cells: Cell[] = [];\n\n data.forEach((item) => {\n if (edgeShapes.includes(item.shape)) {\n cells.push(graph.value!.createEdge(item));\n } else {\n const { data: nodeData, ...displayProps } = item;\n const node = graph.value!.createNode(displayProps);\n if (nodeData) node.setData(nodeData);\n cells.push(node);\n }\n });\n\n graph.value.resetCells(cells);\n setTimeout(() => graph.value!.zoomToFit({ padding: 10, maxScale: 1 }), 200);\n};\n\nconst formatClassDisplay = (cls: {\n name: string;\n attributes: any[];\n methods: any[];\n}) => ({\n name: cls.name,\n attributes: cls.attributes.map(\n (attr) =>\n `${getVisibilitySymbol(attr.visibility)} ${attr.name}: ${attr.type}`,\n ),\n methods: cls.methods.map(\n (method) =>\n `${getVisibilitySymbol(method.visibility)} ${method.name}(): ${method.returnType}`,\n ),\n});\n\n// ==================== 类 CRUD ====================\nconst addClass = () => {\n if (!graph.value) return;\n const newClass: UMLClass = {\n id: `class_${Date.now()}`,\n ...newClassTemplate,\n };\n const nodeData = {\n id: newClass.id,\n shape: \"class\",\n x: newClass.position.x,\n y: newClass.position.y,\n ...formatClassDisplay(newClass),\n data: newClass,\n };\n graph.value.addCell(graph.value.createNode(nodeData));\n emitDataChange();\n};\n\nconst editClass = (umlClass: UMLClass) => {\n editingClass.value = {\n ...umlClass,\n attributes: [...(umlClass.attributes || [])],\n methods: [...(umlClass.methods || [])],\n };\n showEditor.value = true;\n};\n\nconst saveClass = () => {\n if (!graph.value || !editingClass.value) return;\n const node = graph.value.getCellById(editingClass.value.id) as Node;\n if (node) {\n node.setData(editingClass.value);\n node.prop(formatClassDisplay(editingClass.value));\n }\n showEditor.value = false;\n emitDataChange();\n};\n\nconst deleteClass = () => {\n if (!graph.value || !editingClass.value) return;\n graph.value.getCellById(editingClass.value.id)?.remove();\n showEditor.value = false;\n emitDataChange();\n};\n\n// ==================== 数据获取 ====================\nconst getCurrentData = (): UMLDiagramData => ({\n classes:\n graph.value?.getNodes().map((node: Node) => ({\n ...node.getData(),\n position: node.getPosition(),\n })) || [],\n relations:\n graph.value?.getEdges().map((edge: any) => ({\n id: edge.id,\n type: edge.shape as string,\n source: edge.getSourceCellId() || \"\",\n target: edge.getTargetCellId() || \"\",\n })) || [],\n});\n\nconst emitDataChange = () => emit(\"data-change\", getCurrentData());\n\n// ==================== Graph 事件绑定 ====================\nwatch(\n graph,\n (newGraph) => {\n if (!(newGraph instanceof Graph)) return;\n\n registerNodes();\n bindInteractions();\n\n newGraph.on(\"node:dblclick\", ({ node }: { node: Node }) => {\n if (!props.readonly && node.getData()) editClass(node.getData());\n });\n\n emit(\"ready\", newGraph);\n\n const defaultCells = [\n ...sampleClasses.map((cls) => ({\n id: cls.id,\n shape: \"class\",\n x: cls.x,\n y: cls.y,\n ...formatClassDisplay(cls),\n data: {\n id: cls.id,\n name: cls.name,\n attributes: cls.attributes,\n methods: cls.methods,\n position: { x: cls.x, y: cls.y },\n },\n })),\n ...sampleConnections,\n ];\n loadData(defaultCells);\n },\n { immediate: true },\n);\n\nwatch(\n () => props.data,\n (newData) => {\n if (graph.value && newData?.classes) {\n const edgeShapes = [\n \"extends\",\n \"composition\",\n \"implement\",\n \"aggregation\",\n \"association\",\n ];\n const cells: any[] = [\n ...newData.classes.map((cls) => ({\n id: cls.id,\n shape: \"class\",\n x: cls.position?.x ?? 50,\n y: cls.position?.y ?? 50,\n ...formatClassDisplay(cls),\n data: cls,\n })),\n ...(newData.relations || [])\n .filter((r) => edgeShapes.includes(r.type))\n .map((r) => ({\n shape: r.type,\n source: r.source,\n target: r.target,\n })),\n ];\n loadData(cells);\n }\n },\n { deep: true },\n);\n\nonMounted(() => {\n initGraph({\n interacting: true,\n connecting: {\n ...connectingConfig,\n createEdge: () => graph.value!.createEdge(defaultEdgeConfig),\n validateConnection: ({\n sourceView,\n targetView,\n sourceMagnet,\n targetMagnet,\n }: any) =>\n sourceView !== targetView &&\n !!sourceMagnet &&\n !!targetMagnet &&\n sourceMagnet.getAttribute(\"magnet\") === \"true\" &&\n targetMagnet.getAttribute(\"magnet\") === \"true\",\n },\n highlighting: highlightingConfig,\n });\n});\n\ndefineExpose({\n getGraph: () => graph.value,\n getData: getCurrentData,\n addClass,\n centerContent,\n zoomToFit,\n});\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","<template>\n <div class=\"uml-layout\">\n <div class=\"toolbar\" v-if=\"showToolbar\">\n <NSpace>\n <NButton @click=\"addClass\" type=\"primary\" size=\"small\">\n <template #icon>\n <C_Icon name=\"mdi:plus-box\" :size=\"16\" />\n </template>\n 添加类\n </NButton>\n <NButton @click=\"centerContent\" size=\"small\">\n <template #icon>\n <C_Icon name=\"mdi:image-filter-center-focus\" :size=\"16\" />\n </template>\n 居中\n </NButton>\n <NButton @click=\"zoomToFit\" size=\"small\">\n <template #icon>\n <C_Icon name=\"mdi:fit-to-screen\" :size=\"16\" />\n </template>\n 适应\n </NButton>\n <NDropdown\n :options=\"exportOptions\"\n @select=\"(key: string) => handleExport(key, getCurrentData)\"\n >\n <NButton size=\"small\">\n <template #icon>\n <C_Icon name=\"mdi:export\" :size=\"16\" />\n </template>\n 导出\n </NButton>\n </NDropdown>\n </NSpace>\n </div>\n\n <div\n ref=\"containerRef\"\n class=\"graph-container\"\n :style=\"{ width: props.width, height: props.height }\"\n ></div>\n\n <UMLClassEditor\n :show=\"showEditor\"\n v-model:editing-class=\"editingClass\"\n @update:show=\"showEditor = $event\"\n @save=\"saveClass\"\n @delete=\"deleteClass\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted } from \"vue\";\nimport { NSpace, NButton, NDropdown } from \"naive-ui\";\nimport { Graph, ObjectExt, type Node, type Cell } from \"@antv/x6\";\nimport { useGraphBase } from \"../../composables/useGraphBase\";\nimport { useGraphExport } from \"../../composables/useGraphExport\";\nimport { useEdgeInteraction } from \"../../composables/useEdgeInteraction\";\nimport type { UMLClass, UMLDiagramData } from \"../../types\";\nimport UMLClassEditor from \"./components/UMLClassEditor.vue\";\nimport C_Icon from \"../../../C_Icon/index.vue\";\nimport {\n edgeTypes,\n classNodeConfig,\n connectingConfig,\n highlightingConfig,\n defaultEdgeConfig,\n sampleClasses,\n sampleConnections,\n getVisibilitySymbol,\n newClassTemplate,\n} from \"./data\";\n\ninterface Props {\n data?: UMLDiagramData;\n showToolbar?: boolean;\n readonly?: boolean;\n width?: number | string;\n height?: number | string;\n theme?: \"light\" | \"dark\";\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n showToolbar: true,\n readonly: false,\n width: \"100%\",\n height: \"600px\",\n});\n\nconst emit = defineEmits<{\n ready: [graph: any];\n \"data-change\": [data: UMLDiagramData];\n}>();\n\n// ==================== Composables ====================\nconst containerRef = ref<HTMLDivElement>();\nconst isDark = computed(() => props.theme === \"dark\");\nconst { graph, initGraph, centerContent, zoomToFit } = useGraphBase(\n containerRef,\n isDark,\n);\nconst { exportOptions, handleExport } = useGraphExport(graph, \"uml-diagram\");\nconst { bindInteractions } = useEdgeInteraction(graph, {\n defaultColor: \"#722ed1\",\n portPositions: [\"top\", \"right\", \"bottom\", \"left\"],\n onDataChange: () => emitDataChange(),\n});\n\n// ==================== 编辑器状态 ====================\nconst showEditor = ref(false);\nconst editingClass = ref<UMLClass>();\n\n// ==================== 节点注册 ====================\nconst registerNodes = () => {\n Graph.registerNode(\n \"class\",\n {\n ...classNodeConfig,\n /** @description 节点属性钩子,用于计算 UML 类图节点布局 */\n propHooks(meta: any) {\n const { name, attributes, methods, ...others } = meta;\n if (!(name && attributes && methods)) return meta;\n\n let offsetY = 0;\n [\n { type: \"name\", text: name },\n { type: \"attrs\", text: attributes },\n { type: \"methods\", text: methods },\n ].forEach((rect) => {\n const height = Array.isArray(rect.text)\n ? rect.text.length * 12 + 16\n : 32;\n ObjectExt.setByPath(\n others,\n `attrs/${rect.type}-text/text`,\n Array.isArray(rect.text) ? rect.text.join(\"\\n\") : rect.text,\n );\n ObjectExt.setByPath(others, `attrs/${rect.type}-rect/height`, height);\n ObjectExt.setByPath(\n others,\n `attrs/${rect.type}-rect/transform`,\n `translate(0,${offsetY})`,\n );\n offsetY += height;\n });\n others.size = { width: 160, height: offsetY };\n return others;\n },\n },\n true,\n );\n\n Object.entries(edgeTypes).forEach(([type, config]) => {\n Graph.registerEdge(\n type,\n {\n inherit: \"edge\",\n attrs: { line: { strokeWidth: 2, stroke: \"#722ed1\", ...config } },\n },\n true,\n );\n });\n};\n\n// ==================== 数据加载 ====================\nconst loadData = (data: any[]) => {\n if (!graph.value || !data.length) return;\n const edgeShapes = [\n \"extends\",\n \"composition\",\n \"implement\",\n \"aggregation\",\n \"association\",\n ];\n const cells: Cell[] = [];\n\n data.forEach((item) => {\n if (edgeShapes.includes(item.shape)) {\n cells.push(graph.value!.createEdge(item));\n } else {\n const { data: nodeData, ...displayProps } = item;\n const node = graph.value!.createNode(displayProps);\n if (nodeData) node.setData(nodeData);\n cells.push(node);\n }\n });\n\n graph.value.resetCells(cells);\n setTimeout(() => graph.value!.zoomToFit({ padding: 10, maxScale: 1 }), 200);\n};\n\nconst formatClassDisplay = (cls: {\n name: string;\n attributes: any[];\n methods: any[];\n}) => ({\n name: cls.name,\n attributes: cls.attributes.map(\n (attr) =>\n `${getVisibilitySymbol(attr.visibility)} ${attr.name}: ${attr.type}`,\n ),\n methods: cls.methods.map(\n (method) =>\n `${getVisibilitySymbol(method.visibility)} ${method.name}(): ${method.returnType}`,\n ),\n});\n\n// ==================== 类 CRUD ====================\nconst addClass = () => {\n if (!graph.value) return;\n const newClass: UMLClass = {\n id: `class_${Date.now()}`,\n ...newClassTemplate,\n };\n const nodeData = {\n id: newClass.id,\n shape: \"class\",\n x: newClass.position.x,\n y: newClass.position.y,\n ...formatClassDisplay(newClass),\n data: newClass,\n };\n graph.value.addCell(graph.value.createNode(nodeData));\n emitDataChange();\n};\n\nconst editClass = (umlClass: UMLClass) => {\n editingClass.value = {\n ...umlClass,\n attributes: [...(umlClass.attributes || [])],\n methods: [...(umlClass.methods || [])],\n };\n showEditor.value = true;\n};\n\nconst saveClass = () => {\n if (!graph.value || !editingClass.value) return;\n const node = graph.value.getCellById(editingClass.value.id) as Node;\n if (node) {\n node.setData(editingClass.value);\n node.prop(formatClassDisplay(editingClass.value));\n }\n showEditor.value = false;\n emitDataChange();\n};\n\nconst deleteClass = () => {\n if (!graph.value || !editingClass.value) return;\n graph.value.getCellById(editingClass.value.id)?.remove();\n showEditor.value = false;\n emitDataChange();\n};\n\n// ==================== 数据获取 ====================\nconst getCurrentData = (): UMLDiagramData => ({\n classes:\n graph.value?.getNodes().map((node: Node) => ({\n ...node.getData(),\n position: node.getPosition(),\n })) || [],\n relations:\n graph.value?.getEdges().map((edge: any) => ({\n id: edge.id,\n type: edge.shape as string,\n source: edge.getSourceCellId() || \"\",\n target: edge.getTargetCellId() || \"\",\n })) || [],\n});\n\nconst emitDataChange = () => emit(\"data-change\", getCurrentData());\n\n// ==================== Graph 事件绑定 ====================\nwatch(\n graph,\n (newGraph) => {\n if (!(newGraph instanceof Graph)) return;\n\n registerNodes();\n bindInteractions();\n\n newGraph.on(\"node:dblclick\", ({ node }: { node: Node }) => {\n if (!props.readonly && node.getData()) editClass(node.getData());\n });\n\n emit(\"ready\", newGraph);\n\n const defaultCells = [\n ...sampleClasses.map((cls) => ({\n id: cls.id,\n shape: \"class\",\n x: cls.x,\n y: cls.y,\n ...formatClassDisplay(cls),\n data: {\n id: cls.id,\n name: cls.name,\n attributes: cls.attributes,\n methods: cls.methods,\n position: { x: cls.x, y: cls.y },\n },\n })),\n ...sampleConnections,\n ];\n loadData(defaultCells);\n },\n { immediate: true },\n);\n\nwatch(\n () => props.data,\n (newData) => {\n if (graph.value && newData?.classes) {\n const edgeShapes = [\n \"extends\",\n \"composition\",\n \"implement\",\n \"aggregation\",\n \"association\",\n ];\n const cells: any[] = [\n ...newData.classes.map((cls) => ({\n id: cls.id,\n shape: \"class\",\n x: cls.position?.x ?? 50,\n y: cls.position?.y ?? 50,\n ...formatClassDisplay(cls),\n data: cls,\n })),\n ...(newData.relations || [])\n .filter((r) => edgeShapes.includes(r.type))\n .map((r) => ({\n shape: r.type,\n source: r.source,\n target: r.target,\n })),\n ];\n loadData(cells);\n }\n },\n { deep: true },\n);\n\nonMounted(() => {\n initGraph({\n interacting: true,\n connecting: {\n ...connectingConfig,\n createEdge: () => graph.value!.createEdge(defaultEdgeConfig),\n validateConnection: ({\n sourceView,\n targetView,\n sourceMagnet,\n targetMagnet,\n }: any) =>\n sourceView !== targetView &&\n !!sourceMagnet &&\n !!targetMagnet &&\n sourceMagnet.getAttribute(\"magnet\") === \"true\" &&\n targetMagnet.getAttribute(\"magnet\") === \"true\",\n },\n highlighting: highlightingConfig,\n });\n});\n\ndefineExpose({\n getGraph: () => graph.value,\n getData: getCurrentData,\n addClass,\n centerContent,\n zoomToFit,\n});\n</script>\n\n<style lang=\"scss\" scoped>\n@use \"./index.scss\";\n</style>\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-08-01\r\n * @Description: AntV X6 图形编辑器组件(ER/BPMN/UML)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-antv-container\">\r\n <component\r\n :is=\"currentComponent\"\r\n v-bind=\"componentProps\"\r\n @ready=\"handleReady\"\r\n @data-change=\"handleDataChange\"\r\n ref=\"layoutRef\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed } from \"vue\";\r\nimport ERLayout from \"./layout/ER/index.vue\";\r\nimport BPMNLayout from \"./layout/BPMN/index.vue\";\r\nimport UMLLayout from \"./layout/UML/index.vue\";\r\nimport type { DiagramConfig, DiagramData } from \"./types\";\r\n\r\ndefineOptions({ name: \"C_AntV\" });\r\n\r\ninterface Props extends DiagramConfig {\r\n type: \"er\" | \"bpmn\" | \"uml\";\r\n data?: DiagramData;\r\n width?: string | number;\r\n height?: string | number;\r\n readonly?: boolean;\r\n showToolbar?: boolean;\r\n theme?: \"light\" | \"dark\";\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n width: \"100%\",\r\n height: \"600px\",\r\n readonly: false,\r\n showToolbar: true,\r\n theme: \"light\",\r\n});\r\n\r\nconst emit = defineEmits<{\r\n (e: \"ready\", graph: any): void;\r\n (e: \"data-change\", data: DiagramData): void;\r\n}>();\r\n\r\nconst layoutRef = ref();\r\n\r\nconst components = {\r\n er: ERLayout,\r\n bpmn: BPMNLayout,\r\n uml: UMLLayout,\r\n} as const;\r\n\r\nconst currentComponent = computed(() => components[props.type]);\r\n\r\nconst componentProps = computed(() => {\r\n const baseProps = {\r\n width: props.width,\r\n height: props.height,\r\n readonly: props.readonly,\r\n showToolbar: props.showToolbar,\r\n theme: props.theme,\r\n };\r\n\r\n // 处理 BPMN 数据格式转换\r\n let adaptedData: any = props.data;\r\n\r\n if (props.type === \"bpmn\" && props.data) {\r\n // 检查是否为 BPMNDiagramData 格式\r\n const bpmnData = props.data as any;\r\n if (\r\n bpmnData &&\r\n typeof bpmnData === \"object\" &&\r\n \"nodes\" in bpmnData &&\r\n \"edges\" in bpmnData\r\n ) {\r\n // 转换为 BPMNLayout 期望的 BPMNElement[] 格式\r\n adaptedData = [\r\n ...(bpmnData.nodes || []).map((node: any) => ({\r\n ...node,\r\n shape: node.type || node.shape || \"rect\",\r\n x: node.x ?? 0,\r\n y: node.y ?? 0,\r\n })),\r\n ...(bpmnData.edges || []).map((edge: any) => ({\r\n ...edge,\r\n shape: \"edge\",\r\n x: 0,\r\n y: 0,\r\n })),\r\n ];\r\n }\r\n }\r\n\r\n return {\r\n ...baseProps,\r\n data: adaptedData,\r\n } as any;\r\n});\r\n\r\nconst handleReady = (graph: any) => {\r\n emit(\"ready\", graph);\r\n};\r\n\r\nconst handleDataChange = (data: any) => {\r\n let convertedData: DiagramData;\r\n\r\n if (props.type === \"bpmn\" && Array.isArray(data)) {\r\n // 将 BPMNElement[] 转换回 BPMNDiagramData 格式,包含必需的 flows 属性\r\n const nodes = data\r\n .filter((item: any) => item.shape !== \"edge\")\r\n .map((item: any) => {\r\n const { shape, x, y, ...node } = item;\r\n return {\r\n ...node,\r\n type: shape === \"rect\" ? \"task\" : shape,\r\n x: x || 0,\r\n y: y || 0,\r\n };\r\n });\r\n\r\n const edges = data\r\n .filter((item: any) => item.shape === \"edge\")\r\n .map((item: any) => {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const { shape, x, y, ...edge } = item;\r\n return edge;\r\n });\r\n\r\n // 创建完整的 BPMNDiagramData 对象,包含必需的 flows 属性\r\n convertedData = {\r\n nodes,\r\n edges,\r\n flows: [], // 添加必需的 flows 属性,根据实际需求填充\r\n } as unknown as DiagramData; // 使用双重断言确保类型转换\r\n } else {\r\n convertedData = data as DiagramData;\r\n }\r\n\r\n emit(\"data-change\", convertedData);\r\n};\r\n\r\ndefineExpose({\r\n getGraph: () => layoutRef.value?.getGraph?.(),\r\n getData: () => {\r\n const rawData = layoutRef.value?.getData?.();\r\n\r\n // 根据组件类型转换回标准格式\r\n if (props.type === \"bpmn\" && Array.isArray(rawData)) {\r\n const nodes = rawData.filter((item: any) => item.shape !== \"edge\");\r\n const edges = rawData.filter((item: any) => item.shape === \"edge\");\r\n\r\n return {\r\n nodes,\r\n edges,\r\n flows: [], // 确保包含 flows 属性\r\n } as unknown as DiagramData;\r\n }\r\n\r\n return rawData;\r\n },\r\n});\r\n</script>\r\n\r\n<style scoped>\r\n.c-antv-container {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n</style>\r\n","<!--\r\n * @Author: ChenYu ycyplus@gmail.com\r\n * @Date: 2025-08-01\r\n * @Description: AntV X6 图形编辑器组件(ER/BPMN/UML)\r\n * @Migration: naive-ui-components 组件库迁移版本\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <div class=\"c-antv-container\">\r\n <component\r\n :is=\"currentComponent\"\r\n v-bind=\"componentProps\"\r\n @ready=\"handleReady\"\r\n @data-change=\"handleDataChange\"\r\n ref=\"layoutRef\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed } from \"vue\";\r\nimport ERLayout from \"./layout/ER/index.vue\";\r\nimport BPMNLayout from \"./layout/BPMN/index.vue\";\r\nimport UMLLayout from \"./layout/UML/index.vue\";\r\nimport type { DiagramConfig, DiagramData } from \"./types\";\r\n\r\ndefineOptions({ name: \"C_AntV\" });\r\n\r\ninterface Props extends DiagramConfig {\r\n type: \"er\" | \"bpmn\" | \"uml\";\r\n data?: DiagramData;\r\n width?: string | number;\r\n height?: string | number;\r\n readonly?: boolean;\r\n showToolbar?: boolean;\r\n theme?: \"light\" | \"dark\";\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n width: \"100%\",\r\n height: \"600px\",\r\n readonly: false,\r\n showToolbar: true,\r\n theme: \"light\",\r\n});\r\n\r\nconst emit = defineEmits<{\r\n (e: \"ready\", graph: any): void;\r\n (e: \"data-change\", data: DiagramData): void;\r\n}>();\r\n\r\nconst layoutRef = ref();\r\n\r\nconst components = {\r\n er: ERLayout,\r\n bpmn: BPMNLayout,\r\n uml: UMLLayout,\r\n} as const;\r\n\r\nconst currentComponent = computed(() => components[props.type]);\r\n\r\nconst componentProps = computed(() => {\r\n const baseProps = {\r\n width: props.width,\r\n height: props.height,\r\n readonly: props.readonly,\r\n showToolbar: props.showToolbar,\r\n theme: props.theme,\r\n };\r\n\r\n // 处理 BPMN 数据格式转换\r\n let adaptedData: any = props.data;\r\n\r\n if (props.type === \"bpmn\" && props.data) {\r\n // 检查是否为 BPMNDiagramData 格式\r\n const bpmnData = props.data as any;\r\n if (\r\n bpmnData &&\r\n typeof bpmnData === \"object\" &&\r\n \"nodes\" in bpmnData &&\r\n \"edges\" in bpmnData\r\n ) {\r\n // 转换为 BPMNLayout 期望的 BPMNElement[] 格式\r\n adaptedData = [\r\n ...(bpmnData.nodes || []).map((node: any) => ({\r\n ...node,\r\n shape: node.type || node.shape || \"rect\",\r\n x: node.x ?? 0,\r\n y: node.y ?? 0,\r\n })),\r\n ...(bpmnData.edges || []).map((edge: any) => ({\r\n ...edge,\r\n shape: \"edge\",\r\n x: 0,\r\n y: 0,\r\n })),\r\n ];\r\n }\r\n }\r\n\r\n return {\r\n ...baseProps,\r\n data: adaptedData,\r\n } as any;\r\n});\r\n\r\nconst handleReady = (graph: any) => {\r\n emit(\"ready\", graph);\r\n};\r\n\r\nconst handleDataChange = (data: any) => {\r\n let convertedData: DiagramData;\r\n\r\n if (props.type === \"bpmn\" && Array.isArray(data)) {\r\n // 将 BPMNElement[] 转换回 BPMNDiagramData 格式,包含必需的 flows 属性\r\n const nodes = data\r\n .filter((item: any) => item.shape !== \"edge\")\r\n .map((item: any) => {\r\n const { shape, x, y, ...node } = item;\r\n return {\r\n ...node,\r\n type: shape === \"rect\" ? \"task\" : shape,\r\n x: x || 0,\r\n y: y || 0,\r\n };\r\n });\r\n\r\n const edges = data\r\n .filter((item: any) => item.shape === \"edge\")\r\n .map((item: any) => {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const { shape, x, y, ...edge } = item;\r\n return edge;\r\n });\r\n\r\n // 创建完整的 BPMNDiagramData 对象,包含必需的 flows 属性\r\n convertedData = {\r\n nodes,\r\n edges,\r\n flows: [], // 添加必需的 flows 属性,根据实际需求填充\r\n } as unknown as DiagramData; // 使用双重断言确保类型转换\r\n } else {\r\n convertedData = data as DiagramData;\r\n }\r\n\r\n emit(\"data-change\", convertedData);\r\n};\r\n\r\ndefineExpose({\r\n getGraph: () => layoutRef.value?.getGraph?.(),\r\n getData: () => {\r\n const rawData = layoutRef.value?.getData?.();\r\n\r\n // 根据组件类型转换回标准格式\r\n if (props.type === \"bpmn\" && Array.isArray(rawData)) {\r\n const nodes = rawData.filter((item: any) => item.shape !== \"edge\");\r\n const edges = rawData.filter((item: any) => item.shape === \"edge\");\r\n\r\n return {\r\n nodes,\r\n edges,\r\n flows: [], // 确保包含 flows 属性\r\n } as unknown as DiagramData;\r\n }\r\n\r\n return rawData;\r\n },\r\n});\r\n</script>\r\n\r\n<style scoped>\r\n.c-antv-container {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n</style>\r\n"],"mappings":"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"}
|