hrp-ui-base 1.4.6 → 1.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (373) hide show
  1. package/README.md +51 -51
  2. package/dist/components.cjs +5 -5
  3. package/dist/components.es.js +2476 -2476
  4. package/dist/style.css +1 -1
  5. package/package.json +101 -101
  6. package/packages/approval-process/.eslintrc +6 -6
  7. package/packages/approval-process/README.md +22 -22
  8. package/packages/approval-process/index.ts +65 -65
  9. package/packages/approval-process/package.json +17 -17
  10. package/packages/approval-process/packages/components/choose-member/BO/departBo.ts +8 -8
  11. package/packages/approval-process/packages/components/choose-member/BO/memberBo.ts +14 -14
  12. package/packages/approval-process/packages/components/choose-member/BO/roleBo.ts +16 -16
  13. package/packages/approval-process/packages/components/choose-member/index.vue +496 -496
  14. package/packages/approval-process/packages/components/choose-member/styles/common.scss +133 -133
  15. package/packages/approval-process/packages/components/comment/assets/download.svg +4 -4
  16. package/packages/approval-process/packages/components/comment/assets/mp3.svg +11 -11
  17. package/packages/approval-process/packages/components/comment/assets/mp4.svg +11 -11
  18. package/packages/approval-process/packages/components/comment/assets/other.svg +11 -11
  19. package/packages/approval-process/packages/components/comment/assets/pdf.svg +11 -11
  20. package/packages/approval-process/packages/components/comment/assets/ppt.svg +11 -11
  21. package/packages/approval-process/packages/components/comment/assets/preview.svg +4 -4
  22. package/packages/approval-process/packages/components/comment/assets/word.svg +11 -11
  23. package/packages/approval-process/packages/components/comment/assets/xls.svg +11 -11
  24. package/packages/approval-process/packages/components/comment/index.vue +843 -843
  25. package/packages/approval-process/packages/components/comment/modules/previewMp.vue +53 -53
  26. package/packages/approval-process/packages/components/comment/styles/comment-style.scss +303 -303
  27. package/packages/approval-process/packages/components/image-cropper/index.vue +202 -202
  28. package/packages/approval-process/packages/components/sign/index.vue +766 -766
  29. package/packages/approval-process/packages/components/sign/modules/full-screen-sign.vue +19 -19
  30. package/packages/approval-process/packages/components/urge-dialog/index.vue +120 -120
  31. package/packages/approval-process/packages/components/vue-esign/index.vue +289 -289
  32. package/packages/approval-process/packages/flow/approve-component/approve-success.vue +81 -81
  33. package/packages/approval-process/packages/flow/approve-component/route-params-error.vue +48 -48
  34. package/packages/approval-process/packages/flow/approve-component/submit-success.vue +58 -58
  35. package/packages/approval-process/packages/flow/examine-approve-itr.vue +978 -978
  36. package/packages/approval-process/packages/flow/examine-approve.vue +1065 -1065
  37. package/packages/approval-process/packages/flow/form-component/associated-approval-form/README.md +38 -38
  38. package/packages/approval-process/packages/flow/form-component/associated-approval-form/index.vue +158 -158
  39. package/packages/approval-process/packages/flow/form-component/associated-approval-form/modules/associated-approval-form-mobile.vue +297 -297
  40. package/packages/approval-process/packages/flow/form-component/associated-approval-form/modules/associated-approval-form-pc.vue +314 -314
  41. package/packages/approval-process/packages/flow/form-component/associated-approval-form/style/curd-area-mobile.scss +109 -109
  42. package/packages/approval-process/packages/flow/form-component/associated-approval-form/style/curd-area.scss +95 -95
  43. package/packages/approval-process/packages/flow/form-component/associated-approval-form/style/out-put.scss +47 -47
  44. package/packages/approval-process/packages/flow/form-component/show-sign.vue +27 -27
  45. package/packages/approval-process/packages/flow/styles/common.scss +133 -133
  46. package/packages/approval-process/packages/flow/styles/examine-approve-pc.scss +465 -465
  47. package/packages/approval-process/packages/flow/styles/examine-approve-phone.scss +292 -292
  48. package/packages/approval-process/packages/flow/styles/submit-approve-pc.scss +379 -379
  49. package/packages/approval-process/packages/flow/styles/submit-approve-phone.scss +336 -336
  50. package/packages/approval-process/packages/flow/submit-approve-itr.vue +622 -622
  51. package/packages/approval-process/packages/flow/submit-approve.vue +627 -627
  52. package/packages/approval-process/packages/flow/systemCom/BO/departBo.ts +8 -8
  53. package/packages/approval-process/packages/flow/systemCom/BO/memberBo.ts +14 -14
  54. package/packages/approval-process/packages/flow/systemCom/BO/roleBo.ts +16 -16
  55. package/packages/approval-process/packages/flow/systemCom/choose-depart.vue +398 -398
  56. package/packages/approval-process/packages/flow/systemCom/choose-member-phone.vue +514 -514
  57. package/packages/approval-process/packages/flow/systemCom/choose-member.vue +564 -564
  58. package/packages/approval-process/packages/flow/systemCom/choose-role.vue +300 -300
  59. package/packages/approval-process/packages/styles/common.scss +133 -133
  60. package/packages/approval-process/packages/styles/flex-common.scss +117 -117
  61. package/packages/approval-process/packages/styles/flexCommon.scss +72 -72
  62. package/packages/approval-process/packages/styles/main.css +216 -216
  63. package/packages/approval-process/packages/styles/router-page.scss +370 -370
  64. package/packages/approval-process/packages/styles/style-set.ts +207 -207
  65. package/packages/approval-process/packages/types.d.ts +3 -3
  66. package/packages/approval-process/packages/utils/base.ts +15 -15
  67. package/packages/approval-process/packages/utils/crypto.ts +66 -66
  68. package/packages/approval-process/packages/utils/ddUtils.ts +56 -56
  69. package/packages/approval-process/packages/utils/debounce.ts +35 -35
  70. package/packages/approval-process/packages/utils/des.js +1107 -1107
  71. package/packages/approval-process/packages/utils/download.ts +38 -38
  72. package/packages/approval-process/packages/utils/editor.ts +36 -36
  73. package/packages/approval-process/packages/utils/getEnv.ts +36 -36
  74. package/packages/approval-process/packages/utils/os.ts +20 -20
  75. package/packages/approval-process/packages/utils/path-util.ts +31 -31
  76. package/packages/approval-process/packages/utils/routerUtil.ts +304 -304
  77. package/packages/approval-process/packages/utils/string-utils.ts +13 -13
  78. package/packages/approval-process/packages/utils/throttle.ts +44 -44
  79. package/packages/approval-process/packages/utils/validate.ts +92 -92
  80. package/packages/approval-process/packages/utils/ws.ts +218 -218
  81. package/packages/approval-process/tsconfig.json +72 -72
  82. package/packages/approval-process/vite.config.ts +56 -56
  83. package/src/api/bms/dict/bo/DictConfigBO.ts +23 -23
  84. package/src/api/bms/dict/bo/DictConfigBaseVO.ts +24 -24
  85. package/src/api/bms/dict/bo/DictConfigSearchBO.ts +12 -12
  86. package/src/api/bms/dict/bo/DictImportBO.ts +6 -6
  87. package/src/api/bms/dict/bo/DictVO.ts +21 -21
  88. package/src/api/bms/dict/bo/PageBaseVO.ts +8 -8
  89. package/src/api/bms/dict/bo/TotalDictBO.ts +11 -11
  90. package/src/api/bms/dict/bo/TotalDictPageVO.ts +17 -17
  91. package/src/api/bms/dict/dict-controller.ts +78 -78
  92. package/src/api/bms/file/FileExportController.ts +19 -19
  93. package/src/api/bms/file/FileUploadController.ts +131 -131
  94. package/src/api/bms/file/bo/FileBaseInfo.ts +13 -13
  95. package/src/api/bms/file/bo/FileExportVO.ts +17 -17
  96. package/src/api/bms/file/bo/FilePreviewVO.ts +8 -8
  97. package/src/api/bms/file/bo/FileUploadInfo.ts +22 -22
  98. package/src/api/bms/file/bo/FileUrlVO.ts +10 -10
  99. package/src/api/bms/file/bo/StsTokenVO.ts +20 -20
  100. package/src/api/bms/flow/FlowCommentController.ts +50 -50
  101. package/src/api/bms/flow/FlowInstanceController.ts +179 -179
  102. package/src/api/bms/flow/FlowProcessController.ts +55 -55
  103. package/src/api/bms/flow/FlowSheetController.ts +27 -27
  104. package/src/api/bms/flow/FlowSignController.ts +76 -76
  105. package/src/api/bms/flow/bo/AssociatedApprovalBO.ts +15 -15
  106. package/src/api/bms/flow/bo/AssociatedApprovalVO.ts +35 -35
  107. package/src/api/bms/flow/bo/AuditBaseInfo.ts +39 -39
  108. package/src/api/bms/flow/bo/ButtonVo.ts +7 -7
  109. package/src/api/bms/flow/bo/DingCallbackBo.ts +13 -13
  110. package/src/api/bms/flow/bo/FlowCommentBO.ts +12 -12
  111. package/src/api/bms/flow/bo/FlowCommentVO.ts +23 -23
  112. package/src/api/bms/flow/bo/FlowInstanceBO.ts +14 -14
  113. package/src/api/bms/flow/bo/FlowNodeVO.ts +24 -24
  114. package/src/api/bms/flow/bo/FlowNoticeBO.ts +17 -17
  115. package/src/api/bms/flow/bo/FlowProcessBO.ts +13 -13
  116. package/src/api/bms/flow/bo/FlowProcessVO.ts +9 -9
  117. package/src/api/bms/flow/bo/FlowReplyVO.ts +23 -23
  118. package/src/api/bms/flow/bo/FlowSheetVO.ts +16 -16
  119. package/src/api/bms/flow/bo/InstanceBackBO.ts +9 -9
  120. package/src/api/bms/flow/bo/InstanceNodeBO.ts +13 -13
  121. package/src/api/bms/flow/bo/InstanceNodeVO.ts +21 -21
  122. package/src/api/bms/flow/bo/NodeShowVo.ts +19 -19
  123. package/src/api/bms/flow/bo/ReviewBO.ts +11 -11
  124. package/src/api/bms/flow/bo/SheetSearchBO.ts +11 -11
  125. package/src/api/bms/flow/bo/SystemVO.ts +7 -7
  126. package/src/api/bms/flow/bo/TransmitBO.ts +9 -9
  127. package/src/api/bms/flow/bo/UrgeFlowBO.ts +7 -7
  128. package/src/api/bms/flow/bo/UserBaseInfoVo.ts +13 -13
  129. package/src/api/bms/flow/bo/UserInfoVo.ts +44 -44
  130. package/src/api/bms/flow/bo/UserResultVo.ts +17 -17
  131. package/src/api/bms/flow/bo/ValueMapBo.ts +7 -7
  132. package/src/api/bms/home/HomeController.ts +106 -106
  133. package/src/api/bms/home/bo/CollectedMenuBo.ts +9 -9
  134. package/src/api/bms/home/bo/DeptBaseVo.ts +9 -9
  135. package/src/api/bms/home/bo/DomainVO.ts +13 -13
  136. package/src/api/bms/home/bo/FunPermission.ts +17 -17
  137. package/src/api/bms/home/bo/GroupVO.ts +10 -10
  138. package/src/api/bms/home/bo/HomeMenu.ts +22 -22
  139. package/src/api/bms/home/bo/HomeMenuVo.ts +11 -11
  140. package/src/api/bms/home/bo/PersonalizationBo.ts +17 -17
  141. package/src/api/bms/home/bo/PersonalizationVo.ts +19 -19
  142. package/src/api/bms/home/bo/PhoneMenu.ts +14 -14
  143. package/src/api/bms/home/bo/SearchMenuVo.ts +10 -10
  144. package/src/api/bms/home/bo/UserBaseInfoVo.ts +11 -11
  145. package/src/api/bms/permission-manage/PermissionController.ts +133 -133
  146. package/src/api/bms/permission-manage/bo/DataScopeConfig.ts +17 -17
  147. package/src/api/bms/permission-manage/bo/DataScopePoint.ts +15 -15
  148. package/src/api/bms/permission-manage/bo/DeptBaseVo.ts +9 -9
  149. package/src/api/bms/permission-manage/bo/FunPermissionConfig.ts +18 -18
  150. package/src/api/bms/permission-manage/bo/FunPointVo.ts +9 -9
  151. package/src/api/bms/permission-manage/bo/PermissionGroupBo.ts +11 -11
  152. package/src/api/bms/permission-manage/bo/PermissionGroupMemberVo.ts +18 -18
  153. package/src/api/bms/permission-manage/bo/PermissionGroupPageVo.ts +17 -17
  154. package/src/api/bms/permission-manage/bo/PermissionGroupVo.ts +17 -17
  155. package/src/api/bms/permission-manage/bo/RoleBaseVo.ts +9 -9
  156. package/src/api/bms/permission-manage/bo/TheFirstStepVo.ts +13 -13
  157. package/src/api/bms/permission-manage/bo/TheSecondStepVo.ts +14 -14
  158. package/src/api/bms/permission-manage/bo/UserBaseInfoVo.ts +11 -11
  159. package/src/api/bms/tabulation/TabulationController.ts +78 -78
  160. package/src/api/bms/tabulation/bo/FieldConditionBO.ts +10 -10
  161. package/src/api/bms/tabulation/bo/FieldConditionVO.ts +10 -10
  162. package/src/api/bms/tabulation/bo/OperateButtonVO.ts +9 -9
  163. package/src/api/bms/tabulation/bo/PersonViewVO.ts +33 -33
  164. package/src/api/bms/tabulation/bo/SearchVO.ts +33 -33
  165. package/src/api/bms/tabulation/bo/TabulationBO.ts +14 -14
  166. package/src/api/bms/tabulation/bo/ViewSortBO.ts +7 -7
  167. package/src/api/bms/tabulation/bo/ViewVO.ts +12 -12
  168. package/src/api/common/FileBaseInfo.ts +10 -10
  169. package/src/api/common/ResponseBean.ts +9 -9
  170. package/src/api/common/ResponseBeanList.ts +15 -15
  171. package/src/api/common/ResponseBeanTablePage.ts +21 -21
  172. package/src/api/common/TableQueryCriteriaVO.ts +10 -10
  173. package/src/api/common/bo/PageResult.ts +22 -22
  174. package/src/api/hrms/dept/bo/DeptBaseVo.ts +6 -6
  175. package/src/api/hrms/dept/bo/DeptTreeVo.ts +23 -23
  176. package/src/api/hrms/dept/bo/DeptUserVo.ts +9 -9
  177. package/src/api/hrms/dept/bo/DeptUsersVo.ts +10 -10
  178. package/src/api/hrms/dept/bo/DeptVo.ts +19 -19
  179. package/src/api/hrms/dept/bo/UserBaseInfoVo.ts +7 -7
  180. package/src/api/hrms/dept/deptController.ts +100 -100
  181. package/src/api/hrms/role/bo/RoleBaseVo.ts +6 -6
  182. package/src/api/hrms/role/bo/RoleGroupVo.ts +11 -11
  183. package/src/api/hrms/role/bo/RoleVo.ts +22 -22
  184. package/src/api/hrms/role/roleController.ts +19 -19
  185. package/src/api/hrms/user/bo/UserBaseInfoVo.ts +11 -11
  186. package/src/api/hrms/user/bo/UserCardVO.ts +13 -13
  187. package/src/api/hrms/user/bo/UserDeptBO.ts +13 -13
  188. package/src/api/hrms/user/bo/UserRoleBO.ts +11 -11
  189. package/src/api/hrms/user/bo/UserVO.ts +23 -23
  190. package/src/api/hrms/user/userController.ts +86 -86
  191. package/src/api/index.ts +9 -9
  192. package/src/api/notice/NoticeController.ts +73 -73
  193. package/src/api/notice/bo/NoticePageBO.ts +24 -24
  194. package/src/api/notice/bo/NoticeVO.ts +31 -31
  195. package/src/api/work-order-pc/flow/Bo/ValueMapBo.ts +7 -7
  196. package/src/api/work-order-pc/flow/ItrFlowProcessController.ts +41 -41
  197. package/src/api/work-order-pc/flow/Vo/FlowNodeVO.ts +24 -24
  198. package/src/api/work-order-pc/flow/Vo/UserInfoVo.ts +44 -44
  199. package/src/assets/layout/avatar-default.svg +6 -6
  200. package/src/assets/layout/collect-active.svg +7 -7
  201. package/src/assets/layout/collect-default.svg +7 -7
  202. package/src/assets/layout/download-active.svg +8 -8
  203. package/src/assets/layout/download-default.svg +8 -8
  204. package/src/assets/layout/export-dark.svg +7 -7
  205. package/src/assets/layout/export-default.svg +7 -7
  206. package/src/assets/layout/font-active.svg +6 -6
  207. package/src/assets/layout/font-default.svg +6 -6
  208. package/src/assets/layout/help-active.svg +10 -10
  209. package/src/assets/layout/help-default.svg +10 -10
  210. package/src/assets/layout/home-active.svg +6 -6
  211. package/src/assets/layout/home.svg +6 -6
  212. package/src/assets/layout/menu-expand.svg +6 -6
  213. package/src/assets/layout/menu-position-active.svg +6 -6
  214. package/src/assets/layout/menu-position-default.svg +6 -6
  215. package/src/assets/layout/message-active.svg +9 -9
  216. package/src/assets/layout/message-default.svg +9 -9
  217. package/src/assets/layout/moon.svg +8 -8
  218. package/src/assets/layout/router-all-dark.svg +11 -11
  219. package/src/assets/layout/router-all-default.svg +17 -17
  220. package/src/assets/layout/search-active.svg +20 -20
  221. package/src/assets/layout/search-default.svg +20 -20
  222. package/src/assets/layout/star-default.svg +3 -3
  223. package/src/assets/layout/sun-active.svg +6 -6
  224. package/src/assets/layout/sun-default.svg +6 -6
  225. package/src/assets/layout/switch-moon.svg +3 -3
  226. package/src/assets/layout/switch-sun.svg +41 -41
  227. package/src/assets/layout/todo-active.svg +12 -12
  228. package/src/assets/layout/todo-default.svg +12 -12
  229. package/src/assets/layout/user-dark.svg +13 -13
  230. package/src/assets/layout/user-default.svg +13 -13
  231. package/src/assets/no-permiss-dark.svg +16 -16
  232. package/src/assets/no-permiss-day.svg +16 -16
  233. package/src/assets/process/drawer/manyLevel1close.svg +9 -9
  234. package/src/assets/process/drawer/manyLevel1open.svg +6 -6
  235. package/src/assets/process/drawer/manyLevel2close.svg +6 -6
  236. package/src/assets/process/drawer/manyLevel2open.svg +6 -6
  237. package/src/assets/table-delete/table-delete.svg +2 -2
  238. package/src/components/annex-img-upload/assets/download.svg +4 -4
  239. package/src/components/annex-img-upload/assets/mp3.svg +11 -11
  240. package/src/components/annex-img-upload/assets/mp4.svg +11 -11
  241. package/src/components/annex-img-upload/assets/other.svg +11 -11
  242. package/src/components/annex-img-upload/assets/pdf.svg +11 -11
  243. package/src/components/annex-img-upload/assets/ppt.svg +11 -11
  244. package/src/components/annex-img-upload/assets/preview.svg +4 -4
  245. package/src/components/annex-img-upload/assets/word.svg +11 -11
  246. package/src/components/annex-img-upload/assets/xls.svg +11 -11
  247. package/src/components/annex-img-upload/index.vue +609 -609
  248. package/src/components/annex-img-upload/modules/previewMp.vue +53 -53
  249. package/src/components/annex-upload/assets/download.svg +4 -4
  250. package/src/components/annex-upload/assets/mp3.svg +11 -11
  251. package/src/components/annex-upload/assets/mp4.svg +11 -11
  252. package/src/components/annex-upload/assets/other.svg +11 -11
  253. package/src/components/annex-upload/assets/pdf.svg +11 -11
  254. package/src/components/annex-upload/assets/ppt.svg +11 -11
  255. package/src/components/annex-upload/assets/preview.svg +4 -4
  256. package/src/components/annex-upload/assets/word.svg +11 -11
  257. package/src/components/annex-upload/assets/xls.svg +11 -11
  258. package/src/components/annex-upload/index.vue +800 -798
  259. package/src/components/annex-upload/modules/previewMp.vue +53 -53
  260. package/src/components/annex-upload-weijian/assets/download.svg +4 -4
  261. package/src/components/annex-upload-weijian/assets/mp3.svg +11 -11
  262. package/src/components/annex-upload-weijian/assets/mp4.svg +11 -11
  263. package/src/components/annex-upload-weijian/assets/other.svg +11 -11
  264. package/src/components/annex-upload-weijian/assets/pdf.svg +11 -11
  265. package/src/components/annex-upload-weijian/assets/ppt.svg +11 -11
  266. package/src/components/annex-upload-weijian/assets/preview.svg +4 -4
  267. package/src/components/annex-upload-weijian/assets/word.svg +11 -11
  268. package/src/components/annex-upload-weijian/assets/xls.svg +11 -11
  269. package/src/components/annex-upload-weijian/index.vue +772 -772
  270. package/src/components/annex-upload-weijian/modules/previewMp.vue +53 -53
  271. package/src/components/base-layout/index.vue +199 -199
  272. package/src/components/button.vue +14 -14
  273. package/src/components/layout/ApprovalCenterDrawer.vue +231 -231
  274. package/src/components/layout/ExportCenterDrawer.vue +164 -164
  275. package/src/components/layout/LayoutContainer.vue +542 -542
  276. package/src/components/layout/SysHeader.vue +90 -90
  277. package/src/components/layout/SysHeaderLeft.vue +114 -114
  278. package/src/components/layout/SysHeaderRight.vue +112 -112
  279. package/src/components/layout/SysHeaderTabs.vue +289 -289
  280. package/src/components/layout/components/avatar-component.vue +77 -77
  281. package/src/components/layout/components/dark-component.vue +82 -82
  282. package/src/components/layout/components/download-component.vue +49 -49
  283. package/src/components/layout/components/font-size-component.vue +66 -66
  284. package/src/components/layout/components/menu-position-component.vue +97 -97
  285. package/src/components/layout/components/message-component.vue +64 -64
  286. package/src/components/layout/components/todo-component.vue +55 -55
  287. package/src/components/layout/index.ts +34 -34
  288. package/src/components/layout/message/message-dictionary.ts +27 -27
  289. package/src/components/layout/message/message-icon//345/205/250/351/203/250/351/200/232/347/237/245-/350/223/235.svg +8 -8
  290. package/src/components/layout/message/message-icon//345/205/250/351/203/250/351/200/232/347/237/245-/351/273/221.svg +8 -8
  291. package/src/components/layout/message/message-icon//345/205/250/351/203/250/351/200/232/347/237/245.svg +8 -8
  292. package/src/components/layout/message/message-icon//345/205/254/345/221/212/351/200/232/347/237/245-/350/223/235.svg +12 -12
  293. package/src/components/layout/message/message-icon//345/205/254/345/221/212/351/200/232/347/237/245-/351/273/221.svg +12 -12
  294. package/src/components/layout/message/message-icon//345/205/254/345/221/212/351/200/232/347/237/245.svg +12 -12
  295. package/src/components/layout/message/message-icon//345/256/241/346/211/271/351/200/232/347/237/245-/350/223/235.svg +8 -8
  296. package/src/components/layout/message/message-icon//345/256/241/346/211/271/351/200/232/347/237/245-/351/273/221.svg +8 -8
  297. package/src/components/layout/message/message-icon//345/256/241/346/211/271/351/200/232/347/237/245.svg +8 -8
  298. package/src/components/layout/message/message-icon//345/257/274/345/207/272/351/200/232/347/237/245-/350/223/235.svg +13 -13
  299. package/src/components/layout/message/message-icon//345/257/274/345/207/272/351/200/232/347/237/245-/351/273/221.svg +13 -13
  300. package/src/components/layout/message/message-icon//345/257/274/345/207/272/351/200/232/347/237/245.svg +13 -13
  301. package/src/components/layout/message/message-icon//346/234/252/350/257/273/351/200/232/347/237/245-/350/223/235.svg +11 -11
  302. package/src/components/layout/message/message-icon//346/234/252/350/257/273/351/200/232/347/237/245-/351/273/221.svg +11 -11
  303. package/src/components/layout/message/message-icon//346/234/252/350/257/273/351/200/232/347/237/245.svg +11 -11
  304. package/src/components/layout/message/message-icon//347/251/272/347/212/266/346/200/201.svg +17 -17
  305. package/src/components/layout/message/message-icon//347/263/273/347/273/237/351/200/232/347/237/245-/350/223/235.svg +13 -13
  306. package/src/components/layout/message/message-icon//347/263/273/347/273/237/351/200/232/347/237/245-/351/273/221.svg +13 -13
  307. package/src/components/layout/message/message-icon//347/263/273/347/273/237/351/200/232/347/237/245.svg +13 -13
  308. package/src/components/layout/message/message-notification-drawer.vue +533 -533
  309. package/src/components/layout/personal-sign/ImageCropper.vue +187 -187
  310. package/src/components/layout/personal-sign/PersonalSignDialog.vue +658 -658
  311. package/src/components/layout/personalization-guide-dialog.vue +255 -255
  312. package/src/components/layout/plugin.ts +32 -32
  313. package/src/components/layout/sideMenu-global.scss +115 -115
  314. package/src/components/layout/sideMenu.scss +312 -312
  315. package/src/components/layout/sideMenu.vue +541 -541
  316. package/src/components/layout/sideMenuSonList.vue +185 -185
  317. package/src/components/layout/stores/index.ts +5 -5
  318. package/src/components/layout/stores/useLayoutConfigStore.ts +231 -231
  319. package/src/components/layout/stores/useLayoutMenuStore.ts +232 -232
  320. package/src/components/layout/stores/useLayoutNoticeStore.ts +77 -77
  321. package/src/components/layout/stores/useLayoutTabsStore.ts +367 -367
  322. package/src/components/layout/styles/icon.scss +72 -72
  323. package/src/components/layout/types.ts +98 -98
  324. package/src/components/layout/utils/redirect.ts +144 -144
  325. package/src/components/list-search-content/components/index.ts +11 -11
  326. package/src/components/list-search-content/components/search-date-range.vue +74 -74
  327. package/src/components/list-search-content/components/search-date-time-range.vue +48 -48
  328. package/src/components/list-search-content/components/search-date.vue +97 -97
  329. package/src/components/list-search-content/components/search-input-number.vue +59 -59
  330. package/src/components/list-search-content/components/search-input.vue +46 -46
  331. package/src/components/list-search-content/components/search-multiple_select.vue +69 -69
  332. package/src/components/list-search-content/components/search-select.vue +64 -64
  333. package/src/components/list-search-content/index.vue +803 -803
  334. package/src/components/list-search-content/modules/add-views-package-dialog.vue +147 -147
  335. package/src/components/list-search-content/modules/search-condition-area.vue +252 -252
  336. package/src/components/list-search-content/modules/views-package-manage-dialog.vue +265 -265
  337. package/src/components/switch.vue +16 -16
  338. package/src/components.ts +67 -67
  339. package/src/enum/system/StorageEnum.ts +4 -4
  340. package/src/global.d.ts +19 -19
  341. package/src/index.ts +4 -4
  342. package/src/init.ts +37 -37
  343. package/src/styles/common.scss +133 -133
  344. package/src/styles/flex-common.scss +117 -117
  345. package/src/styles/flexCommon.scss +72 -72
  346. package/src/styles/main.css +277 -277
  347. package/src/styles/router-page.scss +370 -370
  348. package/src/styles/style-set.ts +809 -809
  349. package/src/utils/HttpUtil.ts +427 -427
  350. package/src/utils/base.ts +47 -47
  351. package/src/utils/cell-style.ts +11 -11
  352. package/src/utils/crypto.ts +98 -98
  353. package/src/utils/dd-utils.ts +157 -157
  354. package/src/utils/debounce.ts +35 -35
  355. package/src/utils/debounceleading.ts +48 -48
  356. package/src/utils/download.ts +38 -38
  357. package/src/utils/exitLogin.ts +58 -58
  358. package/src/utils/filter-key.ts +4 -4
  359. package/src/utils/formatter-handler.ts +12 -12
  360. package/src/utils/get-dict.ts +26 -26
  361. package/src/utils/get-env.ts +36 -36
  362. package/src/utils/login-path.ts +35 -35
  363. package/src/utils/path-utils.ts +31 -31
  364. package/src/utils/permit-utils.ts +68 -68
  365. package/src/utils/router-utils.ts +321 -321
  366. package/src/utils/string-utils.ts +166 -166
  367. package/src/utils/style-set.ts +750 -750
  368. package/src/utils/throttle.ts +62 -62
  369. package/src/utils/transform-data.ts +31 -31
  370. package/src/utils/validate.ts +92 -92
  371. package/src/utils/ws.ts +218 -218
  372. package/src/utils/wujie-son.ts +50 -50
  373. package/src/utils.ts +24 -24
@@ -1,542 +1,542 @@
1
- <template>
2
- <div
3
- id="header-sidebar"
4
- ref="sidebarRef"
5
- :class="[
6
- 'menu-position-' + menuPosition,
7
- { 'is-left-collapsed': isLeftMenuCollapsed },
8
- ]"
9
- @mouseleave="onMenuAreaLeave"
10
- @click.stop
11
- >
12
- <!-- 左箭头 -->
13
- <div
14
- v-show="menuPosition === 'top' && showArrows"
15
- class="scroll-arrow scroll-arrow-left"
16
- @click="scrollLeft"
17
- >
18
- <el-icon><ArrowLeft /></el-icon>
19
- </div>
20
-
21
- <!-- 菜单滚动区域 -->
22
- <div
23
- class="menu-scroll-wrapper"
24
- ref="scrollWrapperRef"
25
- @wheel="handleWheel"
26
- >
27
- <div class="menu-scroll-content" ref="scrollContentRef">
28
- <template
29
- v-for="(item, index) in sidebarRouters"
30
- :key="item.menuId + index"
31
- >
32
- <div
33
- :title="isLeftMenuCollapsed ? item.menuName : undefined"
34
- class="menu-tab-item"
35
- :class="{ 'is-active': activeIndex === index || isMenuExpanded(index) || collapsedFlyoutIndex === index || (!drawerVisible && selectedIndex === index) }"
36
- @mouseenter="handleMenuEnter(item, index)"
37
- @click="handleMenuClick(item, index, $event)"
38
- >
39
- <span v-if="menuPosition === 'left'" class="menu-tab-icon">
40
- <img
41
- v-if="getMenuIconDisplay(item).imageName"
42
- :key="getMenuIconDisplay(item).imageName"
43
- class="menu-tab-icon-img"
44
- :src="getMenuIconUrl(getMenuIconDisplay(item).imageName)"
45
- :alt="getMenuIconDisplay(item).imageName"
46
- @error="handleMenuTabIconError($event, item)"
47
- />
48
- <span v-else class="menu-tab-icon-fallback">{{ getMenuShortName(getMenuIconDisplay(item).fallbackName) }}</span>
49
- </span>
50
- <span v-if="!isLeftMenuCollapsed" class="menu-tab-name">{{ item.menuName }}</span>
51
- <el-icon
52
- v-if="shouldShowMenuArrow(item)"
53
- class="menu-tab-arrow"
54
- :class="{ 'is-open': menuPosition === 'left' ? isMenuExpanded(index) : activeIndex === index && drawerVisible }"
55
- ><ArrowDown /></el-icon>
56
- </div>
57
- <div
58
- v-if="menuPosition === 'left' && !isLeftMenuCollapsed && isMenuExpanded(index) && item.children && item.children.length > 0"
59
- class="left-inline-submenu"
60
- >
61
- <template
62
- v-for="child in item.children"
63
- :key="child.menuId || child.url || child.menuName"
64
- >
65
- <div
66
- v-if="child.children && child.children.length > 0"
67
- class="left-submenu-group"
68
- >
69
- <div
70
- class="left-submenu-group-title"
71
- :class="{ 'is-active': isActive(child.url) }"
72
- @click.stop="handleSubMenuClick(child)"
73
- >
74
- {{ child.menuName }}
75
- </div>
76
- <div
77
- v-for="grandchild in child.children"
78
- :key="grandchild.menuId || grandchild.url || grandchild.menuName"
79
- class="left-submenu-item with-icon"
80
- :class="{ 'is-active': isActive(grandchild.url) }"
81
- @click.stop="handleSubMenuClick(grandchild)"
82
- >
83
- <span class="left-page-icon">
84
- <img
85
- v-if="!failedMenuIconSet.has(grandchild.menuName)"
86
- class="left-page-icon-img"
87
- :src="getMenuIconUrl(grandchild.menuName)"
88
- :alt="grandchild.menuName"
89
- @error="handleMenuIconError($event, grandchild.menuName)"
90
- />
91
- <span v-else class="left-page-icon-fallback">{{ getMenuShortName(grandchild.menuName) }}</span>
92
- </span>
93
- <span>{{ grandchild.menuName }}</span>
94
- </div>
95
- </div>
96
- <div
97
- v-else
98
- class="left-submenu-item with-icon"
99
- :class="{ 'is-active': isActive(child.url) }"
100
- @click.stop="handleSubMenuClick(child)"
101
- >
102
- <span class="left-page-icon">
103
- <img
104
- v-if="!failedMenuIconSet.has(child.menuName)"
105
- class="left-page-icon-img"
106
- :src="getMenuIconUrl(child.menuName)"
107
- :alt="child.menuName"
108
- @error="handleMenuIconError($event, child.menuName)"
109
- />
110
- <span v-else class="left-page-icon-fallback">{{ getMenuShortName(child.menuName) }}</span>
111
- </span>
112
- <span>{{ child.menuName }}</span>
113
- </div>
114
- </template>
115
- </div>
116
- </template>
117
- </div>
118
- </div>
119
-
120
- <!-- 右箭头 -->
121
- <div
122
- v-show="menuPosition === 'top' && showArrows"
123
- class="scroll-arrow scroll-arrow-right"
124
- @click="scrollRight"
125
- >
126
- <el-icon><ArrowRight /></el-icon>
127
- </div>
128
-
129
- <div
130
- v-if="menuPosition === 'left'"
131
- class="left-collapse-control"
132
- @click="toggleLeftMenuCollapse"
133
- >
134
- <el-icon>
135
- <Expand v-if="isLeftMenuCollapsed" />
136
- <Fold v-else />
137
- </el-icon>
138
- <span v-if="!isLeftMenuCollapsed">收起菜单</span>
139
- </div>
140
-
141
- <!-- 抽屉内容 -->
142
- <teleport to="body">
143
- <transition name="side-drawer-slide">
144
- <div
145
- v-if="drawerVisible && menuPosition === 'top' && showSubmenuDrawer"
146
- class="side-menu-drawer"
147
- @mouseenter="onDrawerEnter"
148
- @mouseleave="onDrawerLeave"
149
- @click.stop
150
- >
151
- <sideMenuSonList
152
- :currentData="currentMenuChildren"
153
- :currentPath="currentPath"
154
- @menu-click="onSonMenuClick"
155
- />
156
- </div>
157
- </transition>
158
- </teleport>
159
-
160
- <!-- 左侧菜单收起时飞出面板 -->
161
- <teleport to="body">
162
- <transition name="left-collapsed-flyout">
163
- <div
164
- v-if="menuPosition === 'left' && isLeftMenuCollapsed && collapsedFlyoutMenu"
165
- class="left-collapsed-flyout"
166
- :style="{ top: collapsedFlyoutTop + 'px' }"
167
- @click.stop
168
- >
169
- <template
170
- v-for="child in collapsedFlyoutMenu.children"
171
- :key="child.menuId || child.url || child.menuName"
172
- >
173
- <el-collapse
174
- v-if="child.children && child.children.length > 0"
175
- v-model="collapsedPanelNames"
176
- class="left-collapsed-collapse"
177
- >
178
- <el-collapse-item :name="getCollapsedPanelName(child)">
179
- <template #title>
180
- <span>{{ child.menuName }}</span>
181
- </template>
182
- <div
183
- v-for="grandchild in child.children"
184
- :key="grandchild.menuId || grandchild.url || grandchild.menuName"
185
- class="left-submenu-item with-icon"
186
- :class="{ 'is-active': isActive(grandchild.url) }"
187
- @click.stop="handleSubMenuClick(grandchild)"
188
- >
189
- <span class="left-page-icon">
190
- <img
191
- v-if="!failedMenuIconSet.has(grandchild.menuName)"
192
- class="left-page-icon-img"
193
- :src="getMenuIconUrl(grandchild.menuName)"
194
- :alt="grandchild.menuName"
195
- @error="handleMenuIconError($event, grandchild.menuName)"
196
- />
197
- <span v-else class="left-page-icon-fallback">{{ getMenuShortName(grandchild.menuName) }}</span>
198
- </span>
199
- <span>{{ grandchild.menuName }}</span>
200
- </div>
201
- </el-collapse-item>
202
- </el-collapse>
203
- <div
204
- v-else
205
- class="left-submenu-item with-icon"
206
- :class="{ 'is-active': isActive(child.url) }"
207
- @click.stop="handleSubMenuClick(child)"
208
- >
209
- <span class="left-page-icon">
210
- <img
211
- v-if="!failedMenuIconSet.has(child.menuName)"
212
- class="left-page-icon-img"
213
- :src="getMenuIconUrl(child.menuName)"
214
- :alt="child.menuName"
215
- @error="handleMenuIconError($event, child.menuName)"
216
- />
217
- <span v-else class="left-page-icon-fallback">{{ getMenuShortName(child.menuName) }}</span>
218
- </span>
219
- <span>{{ child.menuName }}</span>
220
- </div>
221
- </template>
222
- </div>
223
- </transition>
224
- </teleport>
225
- </div>
226
- </template>
227
-
228
- <script lang="ts" setup>
229
- import { computed, ref, onMounted, onUnmounted, nextTick, watch, PropType } from "vue";
230
- import { ArrowLeft, ArrowRight, ArrowDown, Expand, Fold } from "@element-plus/icons-vue";
231
- import sideMenuSonList from "./sideMenuSonList.vue";
232
- import type HomeMenu from "../../api/bms/home/bo/HomeMenu";
233
-
234
- const props = defineProps({
235
- menuList: {
236
- type: Array as PropType<HomeMenu[]>,
237
- default: () => []
238
- },
239
- menuPosition: {
240
- type: String as PropType<"top" | "left">,
241
- default: "top"
242
- },
243
- showSubmenuDrawer: {
244
- type: Boolean,
245
- default: true
246
- },
247
- currentPath: {
248
- type: String,
249
- default: ''
250
- },
251
- navigationBar: {
252
- type: Boolean,
253
- default: false
254
- }
255
- });
256
-
257
- const emit = defineEmits<{
258
- (event: "parent-click", item: HomeMenu, index: number): void;
259
- (event: "menu-item-click", item: HomeMenu): void;
260
- (event: "collapse-change", collapsed: boolean): void;
261
- }>();
262
-
263
- const sidebarRouters = computed(() => props.menuList);
264
- const menuPosition = computed(() => props.menuPosition);
265
- const isLeftMenuCollapsed = computed(
266
- () => menuPosition.value === "left" && props.navigationBar
267
- );
268
-
269
- // 滚动相关
270
- const scrollWrapperRef = ref<HTMLElement | null>(null);
271
- const scrollContentRef = ref<HTMLElement | null>(null);
272
- const sidebarRef = ref<HTMLElement | null>(null);
273
- const showArrows = ref(false);
274
- const scrollStep = 200;
275
-
276
- // 抽屉相关
277
- const drawerVisible = ref(false);
278
- const activeIndex = ref<number | null>(null);
279
- const expandedIndexList = ref<number[]>([]);
280
- const currentMenuChildren = ref<HomeMenu[]>([]);
281
- const failedMenuIconSet = ref<Set<string>>(new Set());
282
- const menuTabIconStateMap = ref<Record<string, "module" | "page" | "text">>({});
283
- const collapsedFlyoutIndex = ref<number | null>(null);
284
- const collapsedFlyoutTop = ref(0);
285
- const collapsedPanelNames = ref<string[]>([]);
286
-
287
- const collapsedFlyoutMenu = computed(() => {
288
- if (collapsedFlyoutIndex.value === null) return null;
289
- return sidebarRouters.value[collapsedFlyoutIndex.value] || null;
290
- });
291
-
292
- // 根据当前路由匹配选中的菜单索引
293
- const selectedIndex = computed(() => {
294
- const currentPath = props.currentPath;
295
- for (let i = 0; i < sidebarRouters.value.length; i++) {
296
- const item = sidebarRouters.value[i];
297
- if (item.url && item.url === currentPath) return i;
298
- if (item.children) {
299
- for (const child of item.children) {
300
- if (child.url && child.url === currentPath) return i;
301
- if (child.children) {
302
- for (const grandchild of child.children) {
303
- if (grandchild.url && grandchild.url === currentPath) return i;
304
- }
305
- }
306
- }
307
- }
308
- }
309
- return null;
310
- });
311
-
312
- function checkOverflow() {
313
- if (!scrollWrapperRef.value || !scrollContentRef.value) return;
314
- if (menuPosition.value === "left") { showArrows.value = false; return; }
315
- showArrows.value = scrollContentRef.value.scrollWidth > scrollWrapperRef.value.clientWidth;
316
- }
317
-
318
- function handleWheel(e: WheelEvent) {
319
- if (!scrollWrapperRef.value || menuPosition.value !== "top") return;
320
- e.preventDefault();
321
- scrollWrapperRef.value.scrollLeft += e.deltaY;
322
- }
323
-
324
- function scrollLeft() {
325
- if (!scrollWrapperRef.value) return;
326
- scrollWrapperRef.value.scrollBy({ left: -scrollStep, behavior: 'smooth' });
327
- }
328
-
329
- function scrollRight() {
330
- if (!scrollWrapperRef.value) return;
331
- scrollWrapperRef.value.scrollBy({ left: scrollStep, behavior: 'smooth' });
332
- }
333
-
334
- let closeTimer: ReturnType<typeof setTimeout> | null = null;
335
- let openTimer: ReturnType<typeof setTimeout> | null = null;
336
-
337
- function startCloseTimer() {
338
- cancelCloseTimer();
339
- closeTimer = setTimeout(() => { closeDrawer(); }, 150);
340
- }
341
- function cancelCloseTimer() { if (closeTimer) { clearTimeout(closeTimer); closeTimer = null; } }
342
- function cancelOpenTimer() { if (openTimer) { clearTimeout(openTimer); openTimer = null; } }
343
-
344
- function handleMenuEnter(item: HomeMenu, index: number) {
345
- if (menuPosition.value === "left" || !props.showSubmenuDrawer) return;
346
- cancelCloseTimer();
347
- cancelOpenTimer();
348
- if (!item.children || item.children.length === 0) { closeDrawer(); return; }
349
- openTimer = setTimeout(() => {
350
- activeIndex.value = index;
351
- currentMenuChildren.value = item.children;
352
- drawerVisible.value = true;
353
- }, 500);
354
- }
355
-
356
- function onMenuAreaLeave() {
357
- if (menuPosition.value === "left") return;
358
- cancelOpenTimer();
359
- startCloseTimer();
360
- }
361
-
362
- function onDrawerEnter() { cancelCloseTimer(); cancelOpenTimer(); }
363
- function onDrawerLeave() { startCloseTimer(); }
364
-
365
- function handleMenuClick(item: HomeMenu, index: number, event?: MouseEvent) {
366
- if (menuPosition.value === "left") {
367
- closeDrawer();
368
- if (isLeftMenuCollapsed.value && item.children && item.children.length > 0) {
369
- openCollapsedFlyout(index, event); return;
370
- }
371
- if (item.children && item.children.length > 0) {
372
- closeCollapsedFlyout(); toggleExpandedIndex(index); return;
373
- }
374
- if (item.url) { emit("menu-item-click", item); }
375
- return;
376
- }
377
- if (item.children && item.children.length > 0) {
378
- closeCollapsedFlyout();
379
- emit("parent-click", item, index);
380
- return;
381
- }
382
- if (!item.children || item.children.length === 0) {
383
- if (item.url) { emit("menu-item-click", item); }
384
- closeDrawer();
385
- }
386
- }
387
-
388
- function handleSubMenuClick(item: HomeMenu) {
389
- if (!item.url) return;
390
- emit("menu-item-click", item);
391
- closeCollapsedFlyout();
392
- }
393
-
394
- function onSonMenuClick(menu: HomeMenu) {
395
- emit("menu-item-click", menu);
396
- closeDrawer();
397
- }
398
-
399
- function isActive(url?: string) { return !!url && props.currentPath === url; }
400
- function isMenuExpanded(index: number) { return expandedIndexList.value.includes(index); }
401
- function toggleExpandedIndex(index: number) {
402
- if (isMenuExpanded(index)) { expandedIndexList.value = expandedIndexList.value.filter((i) => i !== index); return; }
403
- expandedIndexList.value = [...expandedIndexList.value, index];
404
- }
405
- function setMenuExpanded(index: number) {
406
- if (!isMenuExpanded(index)) expandedIndexList.value = [...expandedIndexList.value, index];
407
- }
408
-
409
- function shouldShowMenuArrow(item: HomeMenu) {
410
- if (isLeftMenuCollapsed.value || !item.children || item.children.length === 0) return false;
411
- return menuPosition.value === "left" || props.showSubmenuDrawer;
412
- }
413
-
414
- function getMenuShortName(menuName?: string) { return (menuName || "-").slice(0, 1); }
415
- function getMenuIconUrl(menuName?: string) { return `./menu-icon/${menuName || ""}.png`; }
416
-
417
- function getMenuIconDisplay(item: HomeMenu) {
418
- const fallbackName = item.menuName;
419
- if (!item.children || item.children.length === 0) {
420
- return { imageName: failedMenuIconSet.value.has(item.menuName) ? "" : item.menuName, fallbackName };
421
- }
422
- const iconKey = getMenuTabIconKey(item);
423
- const iconState = menuTabIconStateMap.value[iconKey] || "module";
424
- if (iconState === "module") return { imageName: item.menuName, fallbackName };
425
- if (iconState === "page") {
426
- const firstPageMenuName = findFirstPageMenuName(item.children);
427
- return { imageName: firstPageMenuName && !failedMenuIconSet.value.has(firstPageMenuName) ? firstPageMenuName : "", fallbackName };
428
- }
429
- return { imageName: "", fallbackName };
430
- }
431
-
432
- function getMenuTabIconKey(item: HomeMenu) { return String(item.menuId || item.url || item.menuName); }
433
-
434
- function findFirstPageMenuName(menuList?: HomeMenu[]): string {
435
- if (!menuList || menuList.length === 0) return "";
436
- for (const item of menuList) {
437
- if (item.url) return item.menuName;
438
- const childMenuName = findFirstPageMenuName(item.children);
439
- if (childMenuName) return childMenuName;
440
- }
441
- return "";
442
- }
443
-
444
- function handleMenuIconError(event: Event, iconName?: string) {
445
- const img = event.target as HTMLImageElement;
446
- if (img.dataset.ext !== "jpg") { img.dataset.ext = "jpg"; img.src = `./menu-icon/${iconName || ""}.jpg`; return; }
447
- const nextSet = new Set(failedMenuIconSet.value); nextSet.add(iconName || ""); failedMenuIconSet.value = nextSet;
448
- }
449
-
450
- function handleMenuTabIconError(event: Event, item: HomeMenu) {
451
- const currentIcon = getMenuIconDisplay(item).imageName;
452
- const img = event.target as HTMLImageElement;
453
- if (img.dataset.ext !== "jpg") { img.dataset.ext = "jpg"; img.src = `./menu-icon/${currentIcon || ""}.jpg`; return; }
454
- if (!item.children || item.children.length === 0) { const nextSet = new Set(failedMenuIconSet.value); nextSet.add(item.menuName); failedMenuIconSet.value = nextSet; return; }
455
- const iconKey = getMenuTabIconKey(item);
456
- const firstPageMenuName = findFirstPageMenuName(item.children);
457
- const nextStateMap = { ...menuTabIconStateMap.value };
458
- if ((nextStateMap[iconKey] || "module") === "module" && firstPageMenuName && firstPageMenuName !== item.menuName && !failedMenuIconSet.value.has(firstPageMenuName)) {
459
- nextStateMap[iconKey] = "page";
460
- } else {
461
- const nextSet = new Set(failedMenuIconSet.value); if (currentIcon) nextSet.add(currentIcon); failedMenuIconSet.value = nextSet; nextStateMap[iconKey] = "text";
462
- }
463
- menuTabIconStateMap.value = nextStateMap;
464
- }
465
-
466
- function openCollapsedFlyout(index: number, event?: MouseEvent) {
467
- event?.stopPropagation();
468
- if (collapsedFlyoutIndex.value === index) { closeCollapsedFlyout(); return; }
469
- const target = event?.currentTarget as HTMLElement | undefined;
470
- const rect = target?.getBoundingClientRect();
471
- collapsedFlyoutTop.value = rect ? Math.min(Math.max(rect.top - 4, 58), Math.max(window.innerHeight - 360, 58)) : 58;
472
- collapsedFlyoutIndex.value = index;
473
- collapsedPanelNames.value = getDefaultCollapsedPanels(sidebarRouters.value[index]);
474
- }
475
-
476
- function closeCollapsedFlyout() { collapsedFlyoutIndex.value = null; collapsedPanelNames.value = []; }
477
- function getCollapsedPanelName(item?: HomeMenu) { return String(item?.menuId || item?.url || item?.menuName || "collapsed-menu"); }
478
-
479
- function getDefaultCollapsedPanels(item?: HomeMenu) {
480
- if (!item?.children) return [];
481
- const activeChild = item.children.find((child) => child.children?.length && hasActiveRoute(child));
482
- if (activeChild) return [getCollapsedPanelName(activeChild)];
483
- const firstGroup = item.children.find((child) => child.children && child.children.length > 0);
484
- return firstGroup ? [getCollapsedPanelName(firstGroup)] : [];
485
- }
486
-
487
- function hasActiveRoute(item: HomeMenu): boolean {
488
- if (isActive(item.url)) return true;
489
- return !!item.children?.some((child) => hasActiveRoute(child));
490
- }
491
-
492
- function toggleLeftMenuCollapse() {
493
- emit("collapse-change", !props.navigationBar);
494
- }
495
-
496
- function closeDrawer() { drawerVisible.value = false; activeIndex.value = null; }
497
-
498
- function handleKeydown(e: KeyboardEvent) {
499
- if (e.key === 'Escape' && drawerVisible.value) closeDrawer();
500
- if (e.key === 'Escape' && menuPosition.value === "left") { expandedIndexList.value = []; closeCollapsedFlyout(); }
501
- }
502
-
503
- function handleDocumentClick() { closeCollapsedFlyout(); }
504
-
505
- let resizeObserver: ResizeObserver | null = null;
506
-
507
- onMounted(() => {
508
- nextTick(() => { checkOverflow(); });
509
- if (scrollContentRef.value) {
510
- resizeObserver = new ResizeObserver(() => { checkOverflow(); });
511
- resizeObserver.observe(scrollContentRef.value);
512
- }
513
- document.addEventListener('keydown', handleKeydown);
514
- document.addEventListener('click', handleDocumentClick);
515
- });
516
-
517
- onUnmounted(() => {
518
- cancelCloseTimer(); cancelOpenTimer();
519
- if (resizeObserver) { resizeObserver.disconnect(); resizeObserver = null; }
520
- document.removeEventListener('keydown', handleKeydown);
521
- document.removeEventListener('click', handleDocumentClick);
522
- });
523
-
524
- watch(() => props.menuList, () => { closeCollapsedFlyout(); nextTick(() => { checkOverflow(); }); }, { deep: true });
525
-
526
- watch(
527
- [selectedIndex, menuPosition],
528
- () => {
529
- if (menuPosition.value === "left" && selectedIndex.value !== null) setMenuExpanded(selectedIndex.value);
530
- if (menuPosition.value === "top") { expandedIndexList.value = []; closeCollapsedFlyout(); }
531
- },
532
- { immediate: true }
533
- );
534
- </script>
535
-
536
- <style lang="scss" scoped>
537
- @use './sideMenu.scss' as *;
538
- </style>
539
-
540
- <style lang="scss">
541
- @use './sideMenu-global.scss' as *;
1
+ <template>
2
+ <div
3
+ id="header-sidebar"
4
+ ref="sidebarRef"
5
+ :class="[
6
+ 'menu-position-' + menuPosition,
7
+ { 'is-left-collapsed': isLeftMenuCollapsed },
8
+ ]"
9
+ @mouseleave="onMenuAreaLeave"
10
+ @click.stop
11
+ >
12
+ <!-- 左箭头 -->
13
+ <div
14
+ v-show="menuPosition === 'top' && showArrows"
15
+ class="scroll-arrow scroll-arrow-left"
16
+ @click="scrollLeft"
17
+ >
18
+ <el-icon><ArrowLeft /></el-icon>
19
+ </div>
20
+
21
+ <!-- 菜单滚动区域 -->
22
+ <div
23
+ class="menu-scroll-wrapper"
24
+ ref="scrollWrapperRef"
25
+ @wheel="handleWheel"
26
+ >
27
+ <div class="menu-scroll-content" ref="scrollContentRef">
28
+ <template
29
+ v-for="(item, index) in sidebarRouters"
30
+ :key="item.menuId + index"
31
+ >
32
+ <div
33
+ :title="isLeftMenuCollapsed ? item.menuName : undefined"
34
+ class="menu-tab-item"
35
+ :class="{ 'is-active': activeIndex === index || isMenuExpanded(index) || collapsedFlyoutIndex === index || (!drawerVisible && selectedIndex === index) }"
36
+ @mouseenter="handleMenuEnter(item, index)"
37
+ @click="handleMenuClick(item, index, $event)"
38
+ >
39
+ <span v-if="menuPosition === 'left'" class="menu-tab-icon">
40
+ <img
41
+ v-if="getMenuIconDisplay(item).imageName"
42
+ :key="getMenuIconDisplay(item).imageName"
43
+ class="menu-tab-icon-img"
44
+ :src="getMenuIconUrl(getMenuIconDisplay(item).imageName)"
45
+ :alt="getMenuIconDisplay(item).imageName"
46
+ @error="handleMenuTabIconError($event, item)"
47
+ />
48
+ <span v-else class="menu-tab-icon-fallback">{{ getMenuShortName(getMenuIconDisplay(item).fallbackName) }}</span>
49
+ </span>
50
+ <span v-if="!isLeftMenuCollapsed" class="menu-tab-name">{{ item.menuName }}</span>
51
+ <el-icon
52
+ v-if="shouldShowMenuArrow(item)"
53
+ class="menu-tab-arrow"
54
+ :class="{ 'is-open': menuPosition === 'left' ? isMenuExpanded(index) : activeIndex === index && drawerVisible }"
55
+ ><ArrowDown /></el-icon>
56
+ </div>
57
+ <div
58
+ v-if="menuPosition === 'left' && !isLeftMenuCollapsed && isMenuExpanded(index) && item.children && item.children.length > 0"
59
+ class="left-inline-submenu"
60
+ >
61
+ <template
62
+ v-for="child in item.children"
63
+ :key="child.menuId || child.url || child.menuName"
64
+ >
65
+ <div
66
+ v-if="child.children && child.children.length > 0"
67
+ class="left-submenu-group"
68
+ >
69
+ <div
70
+ class="left-submenu-group-title"
71
+ :class="{ 'is-active': isActive(child.url) }"
72
+ @click.stop="handleSubMenuClick(child)"
73
+ >
74
+ {{ child.menuName }}
75
+ </div>
76
+ <div
77
+ v-for="grandchild in child.children"
78
+ :key="grandchild.menuId || grandchild.url || grandchild.menuName"
79
+ class="left-submenu-item with-icon"
80
+ :class="{ 'is-active': isActive(grandchild.url) }"
81
+ @click.stop="handleSubMenuClick(grandchild)"
82
+ >
83
+ <span class="left-page-icon">
84
+ <img
85
+ v-if="!failedMenuIconSet.has(grandchild.menuName)"
86
+ class="left-page-icon-img"
87
+ :src="getMenuIconUrl(grandchild.menuName)"
88
+ :alt="grandchild.menuName"
89
+ @error="handleMenuIconError($event, grandchild.menuName)"
90
+ />
91
+ <span v-else class="left-page-icon-fallback">{{ getMenuShortName(grandchild.menuName) }}</span>
92
+ </span>
93
+ <span>{{ grandchild.menuName }}</span>
94
+ </div>
95
+ </div>
96
+ <div
97
+ v-else
98
+ class="left-submenu-item with-icon"
99
+ :class="{ 'is-active': isActive(child.url) }"
100
+ @click.stop="handleSubMenuClick(child)"
101
+ >
102
+ <span class="left-page-icon">
103
+ <img
104
+ v-if="!failedMenuIconSet.has(child.menuName)"
105
+ class="left-page-icon-img"
106
+ :src="getMenuIconUrl(child.menuName)"
107
+ :alt="child.menuName"
108
+ @error="handleMenuIconError($event, child.menuName)"
109
+ />
110
+ <span v-else class="left-page-icon-fallback">{{ getMenuShortName(child.menuName) }}</span>
111
+ </span>
112
+ <span>{{ child.menuName }}</span>
113
+ </div>
114
+ </template>
115
+ </div>
116
+ </template>
117
+ </div>
118
+ </div>
119
+
120
+ <!-- 右箭头 -->
121
+ <div
122
+ v-show="menuPosition === 'top' && showArrows"
123
+ class="scroll-arrow scroll-arrow-right"
124
+ @click="scrollRight"
125
+ >
126
+ <el-icon><ArrowRight /></el-icon>
127
+ </div>
128
+
129
+ <div
130
+ v-if="menuPosition === 'left'"
131
+ class="left-collapse-control"
132
+ @click="toggleLeftMenuCollapse"
133
+ >
134
+ <el-icon>
135
+ <Expand v-if="isLeftMenuCollapsed" />
136
+ <Fold v-else />
137
+ </el-icon>
138
+ <span v-if="!isLeftMenuCollapsed">收起菜单</span>
139
+ </div>
140
+
141
+ <!-- 抽屉内容 -->
142
+ <teleport to="body">
143
+ <transition name="side-drawer-slide">
144
+ <div
145
+ v-if="drawerVisible && menuPosition === 'top' && showSubmenuDrawer"
146
+ class="side-menu-drawer"
147
+ @mouseenter="onDrawerEnter"
148
+ @mouseleave="onDrawerLeave"
149
+ @click.stop
150
+ >
151
+ <sideMenuSonList
152
+ :currentData="currentMenuChildren"
153
+ :currentPath="currentPath"
154
+ @menu-click="onSonMenuClick"
155
+ />
156
+ </div>
157
+ </transition>
158
+ </teleport>
159
+
160
+ <!-- 左侧菜单收起时飞出面板 -->
161
+ <teleport to="body">
162
+ <transition name="left-collapsed-flyout">
163
+ <div
164
+ v-if="menuPosition === 'left' && isLeftMenuCollapsed && collapsedFlyoutMenu"
165
+ class="left-collapsed-flyout"
166
+ :style="{ top: collapsedFlyoutTop + 'px' }"
167
+ @click.stop
168
+ >
169
+ <template
170
+ v-for="child in collapsedFlyoutMenu.children"
171
+ :key="child.menuId || child.url || child.menuName"
172
+ >
173
+ <el-collapse
174
+ v-if="child.children && child.children.length > 0"
175
+ v-model="collapsedPanelNames"
176
+ class="left-collapsed-collapse"
177
+ >
178
+ <el-collapse-item :name="getCollapsedPanelName(child)">
179
+ <template #title>
180
+ <span>{{ child.menuName }}</span>
181
+ </template>
182
+ <div
183
+ v-for="grandchild in child.children"
184
+ :key="grandchild.menuId || grandchild.url || grandchild.menuName"
185
+ class="left-submenu-item with-icon"
186
+ :class="{ 'is-active': isActive(grandchild.url) }"
187
+ @click.stop="handleSubMenuClick(grandchild)"
188
+ >
189
+ <span class="left-page-icon">
190
+ <img
191
+ v-if="!failedMenuIconSet.has(grandchild.menuName)"
192
+ class="left-page-icon-img"
193
+ :src="getMenuIconUrl(grandchild.menuName)"
194
+ :alt="grandchild.menuName"
195
+ @error="handleMenuIconError($event, grandchild.menuName)"
196
+ />
197
+ <span v-else class="left-page-icon-fallback">{{ getMenuShortName(grandchild.menuName) }}</span>
198
+ </span>
199
+ <span>{{ grandchild.menuName }}</span>
200
+ </div>
201
+ </el-collapse-item>
202
+ </el-collapse>
203
+ <div
204
+ v-else
205
+ class="left-submenu-item with-icon"
206
+ :class="{ 'is-active': isActive(child.url) }"
207
+ @click.stop="handleSubMenuClick(child)"
208
+ >
209
+ <span class="left-page-icon">
210
+ <img
211
+ v-if="!failedMenuIconSet.has(child.menuName)"
212
+ class="left-page-icon-img"
213
+ :src="getMenuIconUrl(child.menuName)"
214
+ :alt="child.menuName"
215
+ @error="handleMenuIconError($event, child.menuName)"
216
+ />
217
+ <span v-else class="left-page-icon-fallback">{{ getMenuShortName(child.menuName) }}</span>
218
+ </span>
219
+ <span>{{ child.menuName }}</span>
220
+ </div>
221
+ </template>
222
+ </div>
223
+ </transition>
224
+ </teleport>
225
+ </div>
226
+ </template>
227
+
228
+ <script lang="ts" setup>
229
+ import { computed, ref, onMounted, onUnmounted, nextTick, watch, PropType } from "vue";
230
+ import { ArrowLeft, ArrowRight, ArrowDown, Expand, Fold } from "@element-plus/icons-vue";
231
+ import sideMenuSonList from "./sideMenuSonList.vue";
232
+ import type HomeMenu from "../../api/bms/home/bo/HomeMenu";
233
+
234
+ const props = defineProps({
235
+ menuList: {
236
+ type: Array as PropType<HomeMenu[]>,
237
+ default: () => []
238
+ },
239
+ menuPosition: {
240
+ type: String as PropType<"top" | "left">,
241
+ default: "top"
242
+ },
243
+ showSubmenuDrawer: {
244
+ type: Boolean,
245
+ default: true
246
+ },
247
+ currentPath: {
248
+ type: String,
249
+ default: ''
250
+ },
251
+ navigationBar: {
252
+ type: Boolean,
253
+ default: false
254
+ }
255
+ });
256
+
257
+ const emit = defineEmits<{
258
+ (event: "parent-click", item: HomeMenu, index: number): void;
259
+ (event: "menu-item-click", item: HomeMenu): void;
260
+ (event: "collapse-change", collapsed: boolean): void;
261
+ }>();
262
+
263
+ const sidebarRouters = computed(() => props.menuList);
264
+ const menuPosition = computed(() => props.menuPosition);
265
+ const isLeftMenuCollapsed = computed(
266
+ () => menuPosition.value === "left" && props.navigationBar
267
+ );
268
+
269
+ // 滚动相关
270
+ const scrollWrapperRef = ref<HTMLElement | null>(null);
271
+ const scrollContentRef = ref<HTMLElement | null>(null);
272
+ const sidebarRef = ref<HTMLElement | null>(null);
273
+ const showArrows = ref(false);
274
+ const scrollStep = 200;
275
+
276
+ // 抽屉相关
277
+ const drawerVisible = ref(false);
278
+ const activeIndex = ref<number | null>(null);
279
+ const expandedIndexList = ref<number[]>([]);
280
+ const currentMenuChildren = ref<HomeMenu[]>([]);
281
+ const failedMenuIconSet = ref<Set<string>>(new Set());
282
+ const menuTabIconStateMap = ref<Record<string, "module" | "page" | "text">>({});
283
+ const collapsedFlyoutIndex = ref<number | null>(null);
284
+ const collapsedFlyoutTop = ref(0);
285
+ const collapsedPanelNames = ref<string[]>([]);
286
+
287
+ const collapsedFlyoutMenu = computed(() => {
288
+ if (collapsedFlyoutIndex.value === null) return null;
289
+ return sidebarRouters.value[collapsedFlyoutIndex.value] || null;
290
+ });
291
+
292
+ // 根据当前路由匹配选中的菜单索引
293
+ const selectedIndex = computed(() => {
294
+ const currentPath = props.currentPath;
295
+ for (let i = 0; i < sidebarRouters.value.length; i++) {
296
+ const item = sidebarRouters.value[i];
297
+ if (item.url && item.url === currentPath) return i;
298
+ if (item.children) {
299
+ for (const child of item.children) {
300
+ if (child.url && child.url === currentPath) return i;
301
+ if (child.children) {
302
+ for (const grandchild of child.children) {
303
+ if (grandchild.url && grandchild.url === currentPath) return i;
304
+ }
305
+ }
306
+ }
307
+ }
308
+ }
309
+ return null;
310
+ });
311
+
312
+ function checkOverflow() {
313
+ if (!scrollWrapperRef.value || !scrollContentRef.value) return;
314
+ if (menuPosition.value === "left") { showArrows.value = false; return; }
315
+ showArrows.value = scrollContentRef.value.scrollWidth > scrollWrapperRef.value.clientWidth;
316
+ }
317
+
318
+ function handleWheel(e: WheelEvent) {
319
+ if (!scrollWrapperRef.value || menuPosition.value !== "top") return;
320
+ e.preventDefault();
321
+ scrollWrapperRef.value.scrollLeft += e.deltaY;
322
+ }
323
+
324
+ function scrollLeft() {
325
+ if (!scrollWrapperRef.value) return;
326
+ scrollWrapperRef.value.scrollBy({ left: -scrollStep, behavior: 'smooth' });
327
+ }
328
+
329
+ function scrollRight() {
330
+ if (!scrollWrapperRef.value) return;
331
+ scrollWrapperRef.value.scrollBy({ left: scrollStep, behavior: 'smooth' });
332
+ }
333
+
334
+ let closeTimer: ReturnType<typeof setTimeout> | null = null;
335
+ let openTimer: ReturnType<typeof setTimeout> | null = null;
336
+
337
+ function startCloseTimer() {
338
+ cancelCloseTimer();
339
+ closeTimer = setTimeout(() => { closeDrawer(); }, 150);
340
+ }
341
+ function cancelCloseTimer() { if (closeTimer) { clearTimeout(closeTimer); closeTimer = null; } }
342
+ function cancelOpenTimer() { if (openTimer) { clearTimeout(openTimer); openTimer = null; } }
343
+
344
+ function handleMenuEnter(item: HomeMenu, index: number) {
345
+ if (menuPosition.value === "left" || !props.showSubmenuDrawer) return;
346
+ cancelCloseTimer();
347
+ cancelOpenTimer();
348
+ if (!item.children || item.children.length === 0) { closeDrawer(); return; }
349
+ openTimer = setTimeout(() => {
350
+ activeIndex.value = index;
351
+ currentMenuChildren.value = item.children;
352
+ drawerVisible.value = true;
353
+ }, 500);
354
+ }
355
+
356
+ function onMenuAreaLeave() {
357
+ if (menuPosition.value === "left") return;
358
+ cancelOpenTimer();
359
+ startCloseTimer();
360
+ }
361
+
362
+ function onDrawerEnter() { cancelCloseTimer(); cancelOpenTimer(); }
363
+ function onDrawerLeave() { startCloseTimer(); }
364
+
365
+ function handleMenuClick(item: HomeMenu, index: number, event?: MouseEvent) {
366
+ if (menuPosition.value === "left") {
367
+ closeDrawer();
368
+ if (isLeftMenuCollapsed.value && item.children && item.children.length > 0) {
369
+ openCollapsedFlyout(index, event); return;
370
+ }
371
+ if (item.children && item.children.length > 0) {
372
+ closeCollapsedFlyout(); toggleExpandedIndex(index); return;
373
+ }
374
+ if (item.url) { emit("menu-item-click", item); }
375
+ return;
376
+ }
377
+ if (item.children && item.children.length > 0) {
378
+ closeCollapsedFlyout();
379
+ emit("parent-click", item, index);
380
+ return;
381
+ }
382
+ if (!item.children || item.children.length === 0) {
383
+ if (item.url) { emit("menu-item-click", item); }
384
+ closeDrawer();
385
+ }
386
+ }
387
+
388
+ function handleSubMenuClick(item: HomeMenu) {
389
+ if (!item.url) return;
390
+ emit("menu-item-click", item);
391
+ closeCollapsedFlyout();
392
+ }
393
+
394
+ function onSonMenuClick(menu: HomeMenu) {
395
+ emit("menu-item-click", menu);
396
+ closeDrawer();
397
+ }
398
+
399
+ function isActive(url?: string) { return !!url && props.currentPath === url; }
400
+ function isMenuExpanded(index: number) { return expandedIndexList.value.includes(index); }
401
+ function toggleExpandedIndex(index: number) {
402
+ if (isMenuExpanded(index)) { expandedIndexList.value = expandedIndexList.value.filter((i) => i !== index); return; }
403
+ expandedIndexList.value = [...expandedIndexList.value, index];
404
+ }
405
+ function setMenuExpanded(index: number) {
406
+ if (!isMenuExpanded(index)) expandedIndexList.value = [...expandedIndexList.value, index];
407
+ }
408
+
409
+ function shouldShowMenuArrow(item: HomeMenu) {
410
+ if (isLeftMenuCollapsed.value || !item.children || item.children.length === 0) return false;
411
+ return menuPosition.value === "left" || props.showSubmenuDrawer;
412
+ }
413
+
414
+ function getMenuShortName(menuName?: string) { return (menuName || "-").slice(0, 1); }
415
+ function getMenuIconUrl(menuName?: string) { return `./menu-icon/${menuName || ""}.png`; }
416
+
417
+ function getMenuIconDisplay(item: HomeMenu) {
418
+ const fallbackName = item.menuName;
419
+ if (!item.children || item.children.length === 0) {
420
+ return { imageName: failedMenuIconSet.value.has(item.menuName) ? "" : item.menuName, fallbackName };
421
+ }
422
+ const iconKey = getMenuTabIconKey(item);
423
+ const iconState = menuTabIconStateMap.value[iconKey] || "module";
424
+ if (iconState === "module") return { imageName: item.menuName, fallbackName };
425
+ if (iconState === "page") {
426
+ const firstPageMenuName = findFirstPageMenuName(item.children);
427
+ return { imageName: firstPageMenuName && !failedMenuIconSet.value.has(firstPageMenuName) ? firstPageMenuName : "", fallbackName };
428
+ }
429
+ return { imageName: "", fallbackName };
430
+ }
431
+
432
+ function getMenuTabIconKey(item: HomeMenu) { return String(item.menuId || item.url || item.menuName); }
433
+
434
+ function findFirstPageMenuName(menuList?: HomeMenu[]): string {
435
+ if (!menuList || menuList.length === 0) return "";
436
+ for (const item of menuList) {
437
+ if (item.url) return item.menuName;
438
+ const childMenuName = findFirstPageMenuName(item.children);
439
+ if (childMenuName) return childMenuName;
440
+ }
441
+ return "";
442
+ }
443
+
444
+ function handleMenuIconError(event: Event, iconName?: string) {
445
+ const img = event.target as HTMLImageElement;
446
+ if (img.dataset.ext !== "jpg") { img.dataset.ext = "jpg"; img.src = `./menu-icon/${iconName || ""}.jpg`; return; }
447
+ const nextSet = new Set(failedMenuIconSet.value); nextSet.add(iconName || ""); failedMenuIconSet.value = nextSet;
448
+ }
449
+
450
+ function handleMenuTabIconError(event: Event, item: HomeMenu) {
451
+ const currentIcon = getMenuIconDisplay(item).imageName;
452
+ const img = event.target as HTMLImageElement;
453
+ if (img.dataset.ext !== "jpg") { img.dataset.ext = "jpg"; img.src = `./menu-icon/${currentIcon || ""}.jpg`; return; }
454
+ if (!item.children || item.children.length === 0) { const nextSet = new Set(failedMenuIconSet.value); nextSet.add(item.menuName); failedMenuIconSet.value = nextSet; return; }
455
+ const iconKey = getMenuTabIconKey(item);
456
+ const firstPageMenuName = findFirstPageMenuName(item.children);
457
+ const nextStateMap = { ...menuTabIconStateMap.value };
458
+ if ((nextStateMap[iconKey] || "module") === "module" && firstPageMenuName && firstPageMenuName !== item.menuName && !failedMenuIconSet.value.has(firstPageMenuName)) {
459
+ nextStateMap[iconKey] = "page";
460
+ } else {
461
+ const nextSet = new Set(failedMenuIconSet.value); if (currentIcon) nextSet.add(currentIcon); failedMenuIconSet.value = nextSet; nextStateMap[iconKey] = "text";
462
+ }
463
+ menuTabIconStateMap.value = nextStateMap;
464
+ }
465
+
466
+ function openCollapsedFlyout(index: number, event?: MouseEvent) {
467
+ event?.stopPropagation();
468
+ if (collapsedFlyoutIndex.value === index) { closeCollapsedFlyout(); return; }
469
+ const target = event?.currentTarget as HTMLElement | undefined;
470
+ const rect = target?.getBoundingClientRect();
471
+ collapsedFlyoutTop.value = rect ? Math.min(Math.max(rect.top - 4, 58), Math.max(window.innerHeight - 360, 58)) : 58;
472
+ collapsedFlyoutIndex.value = index;
473
+ collapsedPanelNames.value = getDefaultCollapsedPanels(sidebarRouters.value[index]);
474
+ }
475
+
476
+ function closeCollapsedFlyout() { collapsedFlyoutIndex.value = null; collapsedPanelNames.value = []; }
477
+ function getCollapsedPanelName(item?: HomeMenu) { return String(item?.menuId || item?.url || item?.menuName || "collapsed-menu"); }
478
+
479
+ function getDefaultCollapsedPanels(item?: HomeMenu) {
480
+ if (!item?.children) return [];
481
+ const activeChild = item.children.find((child) => child.children?.length && hasActiveRoute(child));
482
+ if (activeChild) return [getCollapsedPanelName(activeChild)];
483
+ const firstGroup = item.children.find((child) => child.children && child.children.length > 0);
484
+ return firstGroup ? [getCollapsedPanelName(firstGroup)] : [];
485
+ }
486
+
487
+ function hasActiveRoute(item: HomeMenu): boolean {
488
+ if (isActive(item.url)) return true;
489
+ return !!item.children?.some((child) => hasActiveRoute(child));
490
+ }
491
+
492
+ function toggleLeftMenuCollapse() {
493
+ emit("collapse-change", !props.navigationBar);
494
+ }
495
+
496
+ function closeDrawer() { drawerVisible.value = false; activeIndex.value = null; }
497
+
498
+ function handleKeydown(e: KeyboardEvent) {
499
+ if (e.key === 'Escape' && drawerVisible.value) closeDrawer();
500
+ if (e.key === 'Escape' && menuPosition.value === "left") { expandedIndexList.value = []; closeCollapsedFlyout(); }
501
+ }
502
+
503
+ function handleDocumentClick() { closeCollapsedFlyout(); }
504
+
505
+ let resizeObserver: ResizeObserver | null = null;
506
+
507
+ onMounted(() => {
508
+ nextTick(() => { checkOverflow(); });
509
+ if (scrollContentRef.value) {
510
+ resizeObserver = new ResizeObserver(() => { checkOverflow(); });
511
+ resizeObserver.observe(scrollContentRef.value);
512
+ }
513
+ document.addEventListener('keydown', handleKeydown);
514
+ document.addEventListener('click', handleDocumentClick);
515
+ });
516
+
517
+ onUnmounted(() => {
518
+ cancelCloseTimer(); cancelOpenTimer();
519
+ if (resizeObserver) { resizeObserver.disconnect(); resizeObserver = null; }
520
+ document.removeEventListener('keydown', handleKeydown);
521
+ document.removeEventListener('click', handleDocumentClick);
522
+ });
523
+
524
+ watch(() => props.menuList, () => { closeCollapsedFlyout(); nextTick(() => { checkOverflow(); }); }, { deep: true });
525
+
526
+ watch(
527
+ [selectedIndex, menuPosition],
528
+ () => {
529
+ if (menuPosition.value === "left" && selectedIndex.value !== null) setMenuExpanded(selectedIndex.value);
530
+ if (menuPosition.value === "top") { expandedIndexList.value = []; closeCollapsedFlyout(); }
531
+ },
532
+ { immediate: true }
533
+ );
534
+ </script>
535
+
536
+ <style lang="scss" scoped>
537
+ @use './sideMenu.scss' as *;
538
+ </style>
539
+
540
+ <style lang="scss">
541
+ @use './sideMenu-global.scss' as *;
542
542
  </style>