xto-fronted 0.4.86 → 0.4.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (352) hide show
  1. package/dist/assets/404-C9Uh6Uu-.css +1 -0
  2. package/dist/assets/404-zjGLLssH.js +1 -0
  3. package/dist/assets/index-B5xc4gQB.css +1 -0
  4. package/dist/assets/index-BDgOY6Rp.js +1 -0
  5. package/dist/assets/index-BIoRANs0.js +1 -0
  6. package/dist/assets/index-Bz0BgZQ1.js +1 -0
  7. package/dist/assets/index-CAdztNsv.css +1 -0
  8. package/dist/assets/index-CCXrcISf.css +1 -0
  9. package/dist/assets/{index-eQ-JQMk3.css → index-CfpZmcpk.css} +1 -1
  10. package/dist/assets/index-CwJSA85U.js +1 -0
  11. package/dist/assets/index-CwRA10ac.js +1 -0
  12. package/dist/assets/index-D8NDxq9d.js +1 -0
  13. package/dist/assets/index-DEB6-Iv_.js +2 -0
  14. package/dist/assets/index-DM4Ezclc.css +1 -0
  15. package/dist/assets/index-DYv7nImj.css +1 -0
  16. package/dist/assets/index-t-2Y0KhA.css +1 -0
  17. package/dist/assets/vendor-CUVPinTg.js +13 -0
  18. package/dist/assets/{vue-vendor-05sbU7Th.js → vue-vendor-DeJXJVbN.js} +7 -7
  19. package/dist/assets/{xto-base-BSTP-Yn2.js → xto-base-PwLGsxxb.js} +1 -1
  20. package/dist/assets/{xto-core-cL8BAdce.js → xto-core-CtL4zKiV.js} +1 -1
  21. package/dist/assets/{xto-data-Cw0dv5K5.js → xto-data-bCXQa7fT.js} +1 -1
  22. package/dist/assets/{xto-feedback-CTk0sMCW.js → xto-feedback-CPydp0kn.js} +1 -1
  23. package/dist/assets/{xto-form-C5i2lk3C.js → xto-form-bywohdAf.js} +1 -1
  24. package/dist/assets/{xto-navigation-DHsTg0WG.js → xto-navigation-Bbdpine9.js} +1 -1
  25. package/dist/index.html +9 -9
  26. package/package.json +7 -3
  27. package/src/App.vue +48 -19
  28. package/src/assets/styles/_root.scss +183 -139
  29. package/src/assets/styles/_variables.scss +70 -45
  30. package/src/assets/styles/index.scss +267 -42
  31. package/src/components/Layout/Sidebar.vue +43 -2
  32. package/src/components/Layout/TopMenu.vue +37 -12
  33. package/src/components/Layout/index.vue +1 -0
  34. package/src/composables/useI18n.ts +44 -0
  35. package/src/index.ts +15 -1
  36. package/src/stores/index.ts +2 -1
  37. package/src/stores/locale.ts +67 -0
  38. package/src/types/json-bigint.d.ts +18 -0
  39. package/src/types/xto.d.ts +24 -0
  40. package/src/utils/request.ts +18 -1
  41. package/src/views/dashboard/index.vue +545 -283
  42. package/src/views/error/403.vue +215 -20
  43. package/src/views/error/404.vue +217 -20
  44. package/src/views/login/index.vue +483 -91
  45. package/src/views/system/menu/index.vue +690 -381
  46. package/src/views/system/role/index.vue +583 -304
  47. package/src/views/system/user/index.vue +655 -326
  48. package/dist/App.vue.d.ts +0 -2
  49. package/dist/api/auth.d.ts +0 -8
  50. package/dist/api/system.d.ts +0 -16
  51. package/dist/api/user.d.ts +0 -13
  52. package/dist/assets/404-BNfk6aVM.js +0 -1
  53. package/dist/assets/404-ByYjFnhI.js +0 -1
  54. package/dist/assets/404-CH5_LdtS.css +0 -1
  55. package/dist/assets/404-sqW80Hc-.css +0 -1
  56. package/dist/assets/index-BBhC8PX4.js +0 -1
  57. package/dist/assets/index-BOEFG4lP.css +0 -1
  58. package/dist/assets/index-BSa4SMHI.js +0 -1
  59. package/dist/assets/index-BihVoviB.js +0 -1
  60. package/dist/assets/index-Bmux4tGG.js +0 -1
  61. package/dist/assets/index-BrvR0Fn_.css +0 -1
  62. package/dist/assets/index-C4ZCZoPp.js +0 -1
  63. package/dist/assets/index-CMgRqiaT.js +0 -1
  64. package/dist/assets/index-CUh_s55Z.css +0 -1
  65. package/dist/assets/index-CV768Wu1.js +0 -1
  66. package/dist/assets/index-D0OnMilp.js +0 -1
  67. package/dist/assets/index-D9wlAuR_.js +0 -1
  68. package/dist/assets/index-DPkO-STg.js +0 -1
  69. package/dist/assets/index-DawJb02s.css +0 -1
  70. package/dist/assets/index-DcFOybjo.js +0 -1
  71. package/dist/assets/index-DiHSZ6SJ.js +0 -2
  72. package/dist/assets/index-GDP-IkXE.css +0 -1
  73. package/dist/assets/index-Gx75raue.js +0 -2
  74. package/dist/assets/index-JsZ6rkQj.js +0 -1
  75. package/dist/assets/index-PfV8pzQz.css +0 -1
  76. package/dist/assets/index-Swfu6yvD.css +0 -1
  77. package/dist/assets/vendor-42ANG6Sg.js +0 -6
  78. package/dist/assets/vite-Dw-pgLOX.js +0 -1
  79. package/dist/assets/vue-vendor-Br-l7wbK.js +0 -29
  80. package/dist/assets/xto-base-C-IBqjVs.js +0 -1
  81. package/dist/assets/xto-base-C6eqMPdO.css +0 -1
  82. package/dist/assets/xto-core-DZK7Cyg0.js +0 -1
  83. package/dist/assets/xto-data-BFpiDgJi.js +0 -1
  84. package/dist/assets/xto-data-CnAQAQH2.css +0 -1
  85. package/dist/assets/xto-feedback-B2M02fn3.js +0 -1
  86. package/dist/assets/xto-feedback-ByaS-C7_.css +0 -1
  87. package/dist/assets/xto-form-CrsyAjyr.css +0 -1
  88. package/dist/assets/xto-form-NRjKKNcY.js +0 -1
  89. package/dist/assets/xto-layout-D1stVnJI.css +0 -1
  90. package/dist/assets/xto-navigation-BuRQVoD8.css +0 -1
  91. package/dist/assets/xto-navigation-qLRTxo68.js +0 -1
  92. package/dist/components/Layout/Footer.vue.d.ts +0 -2
  93. package/dist/components/Layout/Header.vue.d.ts +0 -5
  94. package/dist/components/Layout/MixTopMenu.vue.d.ts +0 -5
  95. package/dist/components/Layout/Sidebar.vue.d.ts +0 -11
  96. package/dist/components/Layout/SidebarMenuItem.vue.d.ts +0 -5
  97. package/dist/components/Layout/Tabs.vue.d.ts +0 -2
  98. package/dist/components/Layout/TopMenu.vue.d.ts +0 -5
  99. package/dist/components/Layout/index.vue.d.ts +0 -2
  100. package/dist/composables/useApp.d.ts +0 -29
  101. package/dist/composables/useAuth.d.ts +0 -6
  102. package/dist/composables/useForm.d.ts +0 -20
  103. package/dist/composables/useTable.d.ts +0 -29
  104. package/dist/directives/permission.d.ts +0 -4
  105. package/dist/enums/index.d.ts +0 -32
  106. package/dist/index-0h_oG71z.js +0 -345
  107. package/dist/index-1EEezXR3.js +0 -142
  108. package/dist/index-1EkaJDoD.js +0 -142
  109. package/dist/index-1VN-SSaj.js +0 -2873
  110. package/dist/index-23nX2t9j.js +0 -142
  111. package/dist/index-2RwL0s53.js +0 -142
  112. package/dist/index-2tvOdd6w.js +0 -372
  113. package/dist/index-3zeoNaqT.js +0 -345
  114. package/dist/index-8oCLh51t.js +0 -475
  115. package/dist/index-AF5JN8Up.js +0 -142
  116. package/dist/index-B02xiP9g.js +0 -372
  117. package/dist/index-B05xso4D.js +0 -345
  118. package/dist/index-B1VS4tRU.js +0 -475
  119. package/dist/index-B3_VQZ-d.js +0 -372
  120. package/dist/index-B3kL6i_g.js +0 -345
  121. package/dist/index-B4Wny0vt.js +0 -345
  122. package/dist/index-B5RdBQ-f.js +0 -475
  123. package/dist/index-B5rbuoWS.js +0 -2835
  124. package/dist/index-BAFpPlnI.js +0 -475
  125. package/dist/index-BAJakzRz.js +0 -142
  126. package/dist/index-BAOHlfVd.js +0 -142
  127. package/dist/index-BAzJWzWG.js +0 -2852
  128. package/dist/index-BEIxh_R3.js +0 -2982
  129. package/dist/index-BEWrRNps.js +0 -475
  130. package/dist/index-BFtKVmzo.js +0 -142
  131. package/dist/index-BHPrW1wN.js +0 -142
  132. package/dist/index-BHQIqN1E.js +0 -372
  133. package/dist/index-BHZ_y8lp.js +0 -2067
  134. package/dist/index-BHvnTk5Z.js +0 -475
  135. package/dist/index-BIf7CYCW.js +0 -475
  136. package/dist/index-BK1Y1z9_.js +0 -142
  137. package/dist/index-BK8qDl14.js +0 -372
  138. package/dist/index-BKnta6nv.js +0 -372
  139. package/dist/index-BLIem13z.js +0 -345
  140. package/dist/index-BNBv_FCu.js +0 -142
  141. package/dist/index-BNwtCm83.js +0 -345
  142. package/dist/index-BOEMA7WH.js +0 -345
  143. package/dist/index-BOwDukt-.js +0 -2346
  144. package/dist/index-BR9WVjrV.js +0 -2851
  145. package/dist/index-BRMkw154.js +0 -475
  146. package/dist/index-BRQBannD.js +0 -345
  147. package/dist/index-BShKtLTm.js +0 -475
  148. package/dist/index-BVpqTdd2.js +0 -3132
  149. package/dist/index-BWGQANAN.js +0 -2851
  150. package/dist/index-BZKw7U60.js +0 -475
  151. package/dist/index-BadGWG4q.js +0 -475
  152. package/dist/index-BbeWpCd3.js +0 -345
  153. package/dist/index-BeUYNx5P.js +0 -475
  154. package/dist/index-BgiGtxRr.js +0 -142
  155. package/dist/index-BhKJLk9M.js +0 -2824
  156. package/dist/index-BijsKQ3r.js +0 -475
  157. package/dist/index-BjEfspqP.js +0 -475
  158. package/dist/index-BjEnT8WQ.js +0 -372
  159. package/dist/index-BpOcz1m4.js +0 -142
  160. package/dist/index-BrRdLbLB.js +0 -142
  161. package/dist/index-BsHOXfCq.js +0 -372
  162. package/dist/index-Bt5ocakb.js +0 -475
  163. package/dist/index-BtE24Mt4.js +0 -142
  164. package/dist/index-BvcBQjw6.js +0 -2836
  165. package/dist/index-C0krZRWf.js +0 -2859
  166. package/dist/index-C1cKUqmA.js +0 -372
  167. package/dist/index-C3ANmIDM.js +0 -475
  168. package/dist/index-C5JrEkwD.js +0 -345
  169. package/dist/index-C5m4qNMQ.js +0 -2851
  170. package/dist/index-C69vu_ot.js +0 -3147
  171. package/dist/index-C6Um6eFy.js +0 -475
  172. package/dist/index-C75ePQYC.js +0 -372
  173. package/dist/index-C7wKLGhC.js +0 -142
  174. package/dist/index-C8DBDnxx.js +0 -2836
  175. package/dist/index-CAnqlIjX.js +0 -475
  176. package/dist/index-CB36fztK.js +0 -345
  177. package/dist/index-CBKo6Enz.js +0 -345
  178. package/dist/index-CBcuyFIa.js +0 -2326
  179. package/dist/index-CCxIu4ex.js +0 -372
  180. package/dist/index-CD1ZEMzL.js +0 -2836
  181. package/dist/index-CDx-6tvY.js +0 -345
  182. package/dist/index-CGrvOpdb.js +0 -372
  183. package/dist/index-CHJWNf3f.js +0 -475
  184. package/dist/index-CIb06BxE.js +0 -372
  185. package/dist/index-CLiJcB9v.js +0 -142
  186. package/dist/index-CNS6Ohfw.js +0 -2853
  187. package/dist/index-COkjB5Jm.js +0 -142
  188. package/dist/index-CS5h1O5W.js +0 -345
  189. package/dist/index-CT0deRSL.js +0 -372
  190. package/dist/index-CTQQBaf4.js +0 -345
  191. package/dist/index-CUAC0ZFB.js +0 -475
  192. package/dist/index-CVMV9Tfg.js +0 -142
  193. package/dist/index-CWOx59Vc.js +0 -142
  194. package/dist/index-CWdSR99B.js +0 -372
  195. package/dist/index-CWvOcS8Y.js +0 -345
  196. package/dist/index-C_8yJlf1.js +0 -475
  197. package/dist/index-C_MzXmh2.js +0 -2830
  198. package/dist/index-Cb7HXiBR.js +0 -372
  199. package/dist/index-CbA8oUvZ.js +0 -142
  200. package/dist/index-CbEIzXG9.js +0 -475
  201. package/dist/index-Cb_m0zz1.js +0 -475
  202. package/dist/index-Cc6HgGzc.js +0 -142
  203. package/dist/index-CcWdW9Mj.js +0 -372
  204. package/dist/index-CdAqkP8L.js +0 -345
  205. package/dist/index-CeVUHSt9.js +0 -2847
  206. package/dist/index-CejRpy0a.js +0 -475
  207. package/dist/index-Cg5wO_jJ.js +0 -372
  208. package/dist/index-CgZM1vHq.js +0 -372
  209. package/dist/index-CgofFg1D.js +0 -372
  210. package/dist/index-ChheXGDK.js +0 -372
  211. package/dist/index-ChuFHoI0.js +0 -372
  212. package/dist/index-CiOJZ6_b.js +0 -372
  213. package/dist/index-ClCWmz_7.js +0 -2844
  214. package/dist/index-CmajGrKA.js +0 -142
  215. package/dist/index-Cn_4o3fi.js +0 -345
  216. package/dist/index-CoJBI1vE.js +0 -345
  217. package/dist/index-CqLLaQ-P.js +0 -372
  218. package/dist/index-CsRhLwmR.js +0 -475
  219. package/dist/index-CttJvDTG.js +0 -475
  220. package/dist/index-Cu3m9UeX.js +0 -345
  221. package/dist/index-CyQbOMHa.js +0 -2859
  222. package/dist/index-D-NcbLKL.js +0 -345
  223. package/dist/index-D0gstkiI.js +0 -2836
  224. package/dist/index-D0krzDtx.js +0 -475
  225. package/dist/index-D1moFd4V.js +0 -372
  226. package/dist/index-D2Hs4bZj.js +0 -345
  227. package/dist/index-D4QhrTZs.js +0 -475
  228. package/dist/index-D6CC02F-.js +0 -372
  229. package/dist/index-D6s7Za5s.js +0 -142
  230. package/dist/index-D7i5bck2.js +0 -3132
  231. package/dist/index-D8YBeNfn.js +0 -345
  232. package/dist/index-D93bv6lU.js +0 -372
  233. package/dist/index-DAX_bFj5.js +0 -142
  234. package/dist/index-DBii9cjr.js +0 -475
  235. package/dist/index-DBzpSkNi.js +0 -345
  236. package/dist/index-DCuKNBck.js +0 -3153
  237. package/dist/index-DE3uKf0K.js +0 -142
  238. package/dist/index-DGAqp0QX.js +0 -372
  239. package/dist/index-DGh_w_v1.js +0 -475
  240. package/dist/index-DItKvJyI.js +0 -475
  241. package/dist/index-DKAyB0fv.js +0 -345
  242. package/dist/index-DKN4xsXi.js +0 -2851
  243. package/dist/index-DN_iIn8V.js +0 -345
  244. package/dist/index-DONIBpuJ.js +0 -345
  245. package/dist/index-DPDK8Ht4.js +0 -2851
  246. package/dist/index-DPr3ldST.js +0 -2354
  247. package/dist/index-DS1wfdxM.js +0 -142
  248. package/dist/index-DUW5cCh8.js +0 -372
  249. package/dist/index-DUv28uVd.js +0 -142
  250. package/dist/index-DVS-5SZn.js +0 -475
  251. package/dist/index-DWI51JAp.js +0 -372
  252. package/dist/index-DWVmEexu.js +0 -475
  253. package/dist/index-DXf9wUqQ.js +0 -142
  254. package/dist/index-DXmB-sjP.js +0 -345
  255. package/dist/index-DY_e_Dxv.js +0 -372
  256. package/dist/index-DZar-us7.js +0 -142
  257. package/dist/index-D_nwqVrw.js +0 -2847
  258. package/dist/index-DbEeir7h.js +0 -2834
  259. package/dist/index-Dbf5ypbh.js +0 -142
  260. package/dist/index-DcSK-2pt.js +0 -345
  261. package/dist/index-DclK-Mc7.js +0 -2864
  262. package/dist/index-DcnzaxVi.js +0 -142
  263. package/dist/index-Dd8PlF0M.js +0 -2857
  264. package/dist/index-DdkVT39s.js +0 -345
  265. package/dist/index-DeLbU1t-.js +0 -345
  266. package/dist/index-DfV_J8Te.js +0 -345
  267. package/dist/index-DgPnNd8U.js +0 -475
  268. package/dist/index-Dg_JLa7s.js +0 -345
  269. package/dist/index-Di2VPQjn.js +0 -345
  270. package/dist/index-DibHUbqc.js +0 -372
  271. package/dist/index-DjCVSrpw.js +0 -475
  272. package/dist/index-Djdb936p.js +0 -142
  273. package/dist/index-DmFL_GSt.js +0 -142
  274. package/dist/index-DmP4X2k0.js +0 -372
  275. package/dist/index-DmtmRd1r.js +0 -372
  276. package/dist/index-Dn8MA3kh.js +0 -475
  277. package/dist/index-Do7uXDSi.js +0 -2071
  278. package/dist/index-Dpv1M9Hu.js +0 -372
  279. package/dist/index-DqUuZC8f.js +0 -372
  280. package/dist/index-DtEXQIjn.js +0 -372
  281. package/dist/index-Dtw-qZ0V.js +0 -372
  282. package/dist/index-Dv3hIz8H.js +0 -345
  283. package/dist/index-Dv9jnaWp.js +0 -345
  284. package/dist/index-Dw8KZwGJ.js +0 -2354
  285. package/dist/index-DwJILh-Q.js +0 -3149
  286. package/dist/index-DwzGV3B9.js +0 -142
  287. package/dist/index-DyybaRkK.js +0 -345
  288. package/dist/index-DzerABZq.js +0 -372
  289. package/dist/index-F53NVkhc.js +0 -142
  290. package/dist/index-Fl0_k4XF.js +0 -475
  291. package/dist/index-HMYRCPrs.js +0 -2326
  292. package/dist/index-I49wpmT-.js +0 -372
  293. package/dist/index-IPv1O8Zq.js +0 -345
  294. package/dist/index-JLqnaery.js +0 -372
  295. package/dist/index-JRCQ1CYj.js +0 -142
  296. package/dist/index-L86-iO8O.js +0 -345
  297. package/dist/index-Q56EoFor.js +0 -142
  298. package/dist/index-QxKMr6p0.js +0 -2829
  299. package/dist/index-THRvW9Xm.js +0 -2856
  300. package/dist/index-WIUmTlfL.js +0 -345
  301. package/dist/index-WRrsK0pR.js +0 -475
  302. package/dist/index-Wq652QGf.js +0 -2836
  303. package/dist/index-YnSLCdjP.js +0 -475
  304. package/dist/index-Ynf0lvBE.js +0 -142
  305. package/dist/index-_OtTmb9i.js +0 -142
  306. package/dist/index-_oqoy_3D.js +0 -142
  307. package/dist/index-cl4Y-BWw.js +0 -475
  308. package/dist/index-d_eHJkDW.js +0 -475
  309. package/dist/index-dnmEyUWB.js +0 -372
  310. package/dist/index-dz6CwD6A.js +0 -142
  311. package/dist/index-g4rkaRry.js +0 -475
  312. package/dist/index-g9bRMdAX.js +0 -142
  313. package/dist/index-h4z4-a2p.js +0 -2852
  314. package/dist/index-h7BhcQYM.js +0 -475
  315. package/dist/index-hI3qofTF.js +0 -345
  316. package/dist/index-iyQQumAA.js +0 -372
  317. package/dist/index-js_OhKON.js +0 -345
  318. package/dist/index-kgb4MdHr.js +0 -475
  319. package/dist/index-logKl0VM.js +0 -3144
  320. package/dist/index-lrFMrOlR.js +0 -3132
  321. package/dist/index-mEHxtQWj.js +0 -372
  322. package/dist/index-mNm1BV3n.js +0 -2857
  323. package/dist/index-oOzAFXfr.js +0 -142
  324. package/dist/index-s3vGq0ro.js +0 -345
  325. package/dist/index-wt7AbUqc.js +0 -2342
  326. package/dist/index.d.ts +0 -54
  327. package/dist/index.es.js +0 -91
  328. package/dist/index.umd.js +0 -1
  329. package/dist/main.d.ts +0 -0
  330. package/dist/router/dynamicRoutes.d.ts +0 -30
  331. package/dist/router/guards.d.ts +0 -17
  332. package/dist/router/index.d.ts +0 -6
  333. package/dist/router/layoutRoute.d.ts +0 -18
  334. package/dist/router/staticRoutes.d.ts +0 -2
  335. package/dist/stores/app.d.ts +0 -93
  336. package/dist/stores/auth.d.ts +0 -41
  337. package/dist/stores/index.d.ts +0 -9
  338. package/dist/stores/menu.d.ts +0 -77
  339. package/dist/stores/user.d.ts +0 -92
  340. package/dist/style.css +0 -1
  341. package/dist/utils/auth.d.ts +0 -27
  342. package/dist/utils/config.d.ts +0 -30
  343. package/dist/utils/permission.d.ts +0 -18
  344. package/dist/utils/request.d.ts +0 -24
  345. package/dist/utils/storage.d.ts +0 -24
  346. package/dist/views/dashboard/index.vue.d.ts +0 -2
  347. package/dist/views/error/403.vue.d.ts +0 -2
  348. package/dist/views/error/404.vue.d.ts +0 -2
  349. package/dist/views/login/index.vue.d.ts +0 -4
  350. package/dist/views/system/menu/index.vue.d.ts +0 -4
  351. package/dist/views/system/role/index.vue.d.ts +0 -4
  352. package/dist/views/system/user/index.vue.d.ts +0 -4
@@ -15,7 +15,7 @@
15
15
  @use 'dark';
16
16
 
17
17
  // ==============================================
18
- // 全局通用样式
18
+ // 全局通用样式(企业级增强)
19
19
  // ==============================================
20
20
 
21
21
  // 文字截断
@@ -33,6 +33,13 @@
33
33
  overflow: hidden;
34
34
  }
35
35
 
36
+ .text-ellipsis-3 {
37
+ display: -webkit-box;
38
+ -webkit-line-clamp: 3;
39
+ -webkit-box-orient: vertical;
40
+ overflow: hidden;
41
+ }
42
+
36
43
  // Flex 布局
37
44
  .flex {
38
45
  display: flex;
@@ -50,6 +57,18 @@
50
57
  justify-content: space-between;
51
58
  }
52
59
 
60
+ .flex-start {
61
+ display: flex;
62
+ align-items: center;
63
+ justify-content: flex-start;
64
+ }
65
+
66
+ .flex-end {
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: flex-end;
70
+ }
71
+
53
72
  .flex-wrap {
54
73
  flex-wrap: wrap;
55
74
  }
@@ -58,6 +77,31 @@
58
77
  flex: 1;
59
78
  }
60
79
 
80
+ .flex-shrink-0 {
81
+ flex-shrink: 0;
82
+ }
83
+
84
+ // 方向
85
+ .flex-col {
86
+ display: flex;
87
+ flex-direction: column;
88
+ }
89
+
90
+ .flex-col-center {
91
+ display: flex;
92
+ flex-direction: column;
93
+ align-items: center;
94
+ }
95
+
96
+ // Gap 间距(8px 网格系统)
97
+ .gap-4 { gap: 4px; }
98
+ .gap-8 { gap: 8px; }
99
+ .gap-12 { gap: 12px; }
100
+ .gap-16 { gap: 16px; }
101
+ .gap-20 { gap: 20px; }
102
+ .gap-24 { gap: 24px; }
103
+ .gap-32 { gap: 32px; }
104
+
61
105
  // 文字对齐
62
106
  .text-left {
63
107
  text-align: left;
@@ -92,6 +136,14 @@
92
136
  color: var(--color-info);
93
137
  }
94
138
 
139
+ .text-secondary {
140
+ color: var(--color-text-secondary);
141
+ }
142
+
143
+ .text-placeholder {
144
+ color: var(--color-text-placeholder);
145
+ }
146
+
95
147
  // 背景
96
148
  .bg-primary {
97
149
  background-color: var(--color-primary);
@@ -109,81 +161,254 @@
109
161
  background-color: var(--color-danger);
110
162
  }
111
163
 
112
- // 间距
113
- .mt-10 {
114
- margin-top: 10px;
115
- }
116
-
117
- .mt-20 {
118
- margin-top: 20px;
119
- }
120
-
121
- .mb-10 {
122
- margin-bottom: 10px;
164
+ .bg-page {
165
+ background-color: var(--bg-color-page);
123
166
  }
124
167
 
125
- .mb-20 {
126
- margin-bottom: 20px;
127
- }
128
-
129
- .ml-10 {
130
- margin-left: 10px;
131
- }
132
-
133
- .mr-10 {
134
- margin-right: 10px;
168
+ .bg-card {
169
+ background-color: var(--bg-color);
135
170
  }
136
171
 
137
- .p-10 {
138
- padding: 10px;
139
- }
172
+ // 间距(8px 网格系统)
173
+ .mt-4 { margin-top: 4px; }
174
+ .mt-8 { margin-top: 8px; }
175
+ .mt-12 { margin-top: 12px; }
176
+ .mt-16 { margin-top: 16px; }
177
+ .mt-20 { margin-top: 20px; }
178
+ .mt-24 { margin-top: 24px; }
179
+ .mt-32 { margin-top: 32px; }
180
+
181
+ .mb-4 { margin-bottom: 4px; }
182
+ .mb-8 { margin-bottom: 8px; }
183
+ .mb-12 { margin-bottom: 12px; }
184
+ .mb-16 { margin-bottom: 16px; }
185
+ .mb-20 { margin-bottom: 20px; }
186
+ .mb-24 { margin-bottom: 24px; }
187
+ .mb-32 { margin-bottom: 32px; }
188
+
189
+ .ml-4 { margin-left: 4px; }
190
+ .ml-8 { margin-left: 8px; }
191
+ .ml-12 { margin-left: 12px; }
192
+ .ml-16 { margin-left: 16px; }
193
+
194
+ .mr-4 { margin-right: 4px; }
195
+ .mr-8 { margin-right: 8px; }
196
+ .mr-12 { margin-right: 12px; }
197
+ .mr-16 { margin-right: 16px; }
198
+
199
+ .p-4 { padding: 4px; }
200
+ .p-8 { padding: 8px; }
201
+ .p-12 { padding: 12px; }
202
+ .p-16 { padding: 16px; }
203
+ .p-20 { padding: 20px; }
204
+ .p-24 { padding: 24px; }
205
+ .p-32 { padding: 32px; }
206
+
207
+ .px-4 { padding-left: 4px; padding-right: 4px; }
208
+ .px-8 { padding-left: 8px; padding-right: 8px; }
209
+ .px-12 { padding-left: 12px; padding-right: 12px; }
210
+ .px-16 { padding-left: 16px; padding-right: 16px; }
211
+ .px-24 { padding-left: 24px; padding-right: 24px; }
212
+
213
+ .py-4 { padding-top: 4px; padding-bottom: 4px; }
214
+ .py-8 { padding-top: 8px; padding-bottom: 8px; }
215
+ .py-12 { padding-top: 12px; padding-bottom: 12px; }
216
+ .py-16 { padding-top: 16px; padding-bottom: 16px; }
217
+ .py-24 { padding-top: 24px; padding-bottom: 24px; }
218
+
219
+ // 卡片容器(企业级)
220
+ .card {
221
+ background-color: var(--bg-color);
222
+ border-radius: var(--border-radius-large);
223
+ box-shadow: var(--box-shadow-card);
224
+ padding: var(--spacing-lg);
225
+ transition: box-shadow 0.3s ease;
140
226
 
141
- .p-20 {
142
- padding: 20px;
227
+ &:hover {
228
+ box-shadow: var(--box-shadow-card-hover);
229
+ }
143
230
  }
144
231
 
145
- // 卡片容器
146
- .card {
232
+ .card-flat {
147
233
  background-color: var(--bg-color);
148
- border-radius: var(--border-radius-base);
149
- box-shadow: var(--box-shadow-light);
150
- padding: var(--spacing-md);
234
+ border-radius: var(--border-radius-large);
235
+ padding: var(--spacing-lg);
236
+ border: 1px solid var(--color-border-lighter);
151
237
  }
152
238
 
153
239
  // 页面容器
154
240
  .page-container {
155
- padding: var(--spacing-md);
241
+ padding: 12px;
156
242
  min-height: 100%;
243
+ background: var(--bg-color-page);
157
244
  }
158
245
 
159
- // 搜索栏
246
+ // 搜索栏(企业级)
160
247
  .search-bar {
161
248
  display: flex;
162
249
  flex-wrap: wrap;
163
- gap: var(--spacing-sm);
164
- margin-bottom: var(--spacing-md);
250
+ gap: var(--spacing-md);
251
+ margin-bottom: 12px;
252
+ padding: 12px;
253
+ background: var(--bg-color);
254
+ border-radius: var(--border-radius-large);
255
+ box-shadow: var(--box-shadow-card);
165
256
  }
166
257
 
167
- // 工具栏
258
+ // 工具栏(企业级)
168
259
  .toolbar {
169
260
  display: flex;
170
261
  align-items: center;
171
262
  justify-content: space-between;
172
- margin-bottom: var(--spacing-md);
263
+ padding: 12px;
264
+ border-bottom: 1px solid var(--color-border-lighter);
265
+ }
266
+
267
+ .toolbar-left {
268
+ display: flex;
269
+ align-items: center;
270
+ gap: var(--spacing-sm);
271
+ }
272
+
273
+ .toolbar-right {
274
+ display: flex;
275
+ align-items: center;
276
+ gap: var(--spacing-sm);
173
277
  }
174
278
 
175
- // 表格容器
279
+ // 表格容器(企业级)
176
280
  .table-container {
177
281
  background-color: var(--bg-color);
178
- border-radius: var(--border-radius-base);
179
- padding: var(--spacing-md);
282
+ border-radius: var(--border-radius-large);
283
+ box-shadow: var(--box-shadow-card);
284
+ overflow: hidden;
180
285
  }
181
286
 
182
287
  // 分页容器
183
288
  .pagination-container {
184
289
  display: flex;
185
290
  justify-content: flex-end;
186
- margin-top: var(--spacing-md);
291
+ padding: 12px;
292
+ border-top: 1px solid var(--color-border-lighter);
293
+ }
294
+
295
+ // 标签徽章
296
+ .badge {
297
+ display: inline-flex;
298
+ align-items: center;
299
+ justify-content: center;
300
+ min-width: 20px;
301
+ height: 20px;
302
+ padding: 0 6px;
303
+ font-size: 12px;
304
+ font-weight: 500;
305
+ border-radius: 10px;
306
+ background: var(--color-fill);
307
+ color: var(--color-text-secondary);
308
+ }
309
+
310
+ .badge-primary {
311
+ background: var(--color-primary-light-6);
312
+ color: var(--color-primary);
313
+ }
314
+
315
+ .badge-success {
316
+ background: var(--color-success-lighter);
317
+ color: var(--color-success);
318
+ }
319
+
320
+ .badge-warning {
321
+ background: var(--color-warning-lighter);
322
+ color: var(--color-warning);
323
+ }
324
+
325
+ .badge-danger {
326
+ background: var(--color-danger-lighter);
327
+ color: var(--color-danger);
328
+ }
329
+
330
+ // 分隔线
331
+ .divider {
332
+ height: 1px;
333
+ background: var(--color-border-lighter);
334
+ margin: var(--spacing-md) 0;
335
+ }
336
+
337
+ .divider-vertical {
338
+ width: 1px;
339
+ height: 100%;
340
+ background: var(--color-border-lighter);
341
+ margin: 0 var(--spacing-md);
342
+ }
343
+
344
+ // 空状态
345
+ .empty-state {
346
+ display: flex;
347
+ flex-direction: column;
348
+ align-items: center;
349
+ justify-content: center;
350
+ padding: 60px 20px;
351
+ color: var(--color-text-placeholder);
352
+
353
+ .empty-icon {
354
+ width: 64px;
355
+ height: 64px;
356
+ margin-bottom: 16px;
357
+ opacity: 0.5;
358
+ }
359
+
360
+ .empty-text {
361
+ font-size: 14px;
362
+ }
363
+ }
364
+
365
+ // 加载状态
366
+ .loading-state {
367
+ display: flex;
368
+ flex-direction: column;
369
+ align-items: center;
370
+ justify-content: center;
371
+ padding: 60px 20px;
372
+
373
+ .loading-spinner {
374
+ width: 32px;
375
+ height: 32px;
376
+ border: 3px solid var(--color-border-lighter);
377
+ border-top-color: var(--color-primary);
378
+ border-radius: 50%;
379
+ animation: spin 0.8s linear infinite;
380
+ }
381
+
382
+ .loading-text {
383
+ margin-top: 16px;
384
+ font-size: 14px;
385
+ color: var(--color-text-secondary);
386
+ }
387
+ }
388
+
389
+ @keyframes spin {
390
+ to { transform: rotate(360deg); }
391
+ }
392
+
393
+ // 链接样式
394
+ .link {
395
+ color: var(--color-primary);
396
+ text-decoration: none;
397
+ transition: color 0.2s ease;
398
+
399
+ &:hover {
400
+ color: var(--color-primary-dark-1);
401
+ }
402
+ }
403
+
404
+ .link-underline {
405
+ color: var(--color-primary);
406
+ text-decoration: underline;
407
+ text-underline-offset: 2px;
408
+
409
+ &:hover {
410
+ color: var(--color-primary-dark-1);
411
+ }
187
412
  }
188
413
 
189
414
  // ==============================================
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { computed } from 'vue'
2
+ import { computed, ref, watch } from 'vue'
3
3
  import { useRoute, useRouter } from 'vue-router'
4
4
  import { useMenuStore } from '@/stores/menu'
5
5
  import { useUserStore } from '@/stores/user'
@@ -7,6 +7,7 @@ import { useAuthStore } from '@/stores/auth'
7
7
  import { useAppStore } from '@/stores/app'
8
8
  import { Menu } from '@xto/navigation'
9
9
  import { Button } from '@xto/base'
10
+ import { local } from '@/utils/storage'
10
11
  import SidebarMenuItem from './SidebarMenuItem.vue'
11
12
 
12
13
  // Props
@@ -33,6 +34,45 @@ const displayMenuList = computed(() => props.menuList.length > 0 ? props.menuLis
33
34
  const isCollapsed = computed(() => appStore.isCollapsed)
34
35
  const activeMenu = computed(() => route.path)
35
36
 
37
+ // 菜单展开状态持久化
38
+ const OPENED_MENUS_KEY = 'sidebar_opened_menus'
39
+ const openedMenus = ref<string[]>(local.get<string[]>(OPENED_MENUS_KEY) || [])
40
+
41
+ // 监听变化并持久化
42
+ watch(openedMenus, (val) => {
43
+ local.set(OPENED_MENUS_KEY, val)
44
+ }, { deep: true })
45
+
46
+ // 递归查找当前路由对应的父菜单路径
47
+ const findMenuPath = (menus: any[], path: string, parentUrls: string[] = []): string[] | null => {
48
+ for (const menu of menus) {
49
+ // 当前菜单匹配
50
+ if (path === menu.menuUrl || path.startsWith(menu.menuUrl + '/')) {
51
+ return [...parentUrls, menu.menuUrl]
52
+ }
53
+ // 递归查找子菜单
54
+ if (menu.children?.length) {
55
+ const result = findMenuPath(menu.children, path, [...parentUrls, menu.menuUrl])
56
+ if (result) return result
57
+ }
58
+ }
59
+ return null
60
+ }
61
+
62
+ // 监听路由变化,只展开当前路由相关的父菜单
63
+ watch([() => route.path, displayMenuList], ([path, menus]) => {
64
+ if (menus.length > 0) {
65
+ const menuPath = findMenuPath(menus, path)
66
+ if (menuPath) {
67
+ // 只保留路径上的父菜单(不包括当前页面本身)
68
+ openedMenus.value = menuPath.slice(0, -1)
69
+ } else {
70
+ // 如果找不到匹配的菜单,关闭所有
71
+ openedMenus.value = []
72
+ }
73
+ }
74
+ }, { immediate: true })
75
+
36
76
  // 菜单主题相关
37
77
  const menuBgColor = computed(() => appStore.isDark ? '#1d1e1f' : '#fff')
38
78
  const menuTextColor = computed(() => appStore.isDark ? '#cfd3dc' : '#303133')
@@ -64,7 +104,8 @@ const handleLogout = () => {
64
104
 
65
105
  <!-- 菜单 -->
66
106
  <Menu
67
- :model-value="activeMenu"
107
+ v-model="activeMenu"
108
+ v-model:openeds="openedMenus"
68
109
  mode="vertical"
69
110
  :collapse="isCollapsed"
70
111
  :collapse-transition="false"
@@ -322,19 +322,44 @@ onUnmounted(() => {
322
322
  <span class="top-menu__menu-text">{{ menu.menuName }}</span>
323
323
  </span>
324
324
  </template>
325
- <MenuItem
326
- v-for="child in menu.children"
327
- :key="child.menuUrl"
328
- :index="child.menuUrl"
329
- >
330
- <span class="top-menu__menu-content">
331
- <span class="top-menu__menu-icon">
332
- <Icon v-if="iconExists(getMenuIcon(child.icon))" :name="getMenuIcon(child.icon)" :size="16" />
333
- <span v-else class="top-menu__menu-char">{{ getFirstChar(child.menuName) }}</span>
325
+ <!-- 递归渲染子菜单 -->
326
+ <template v-for="child in menu.children" :key="child.menuUrl">
327
+ <SubMenu v-if="child.children && child.children.length > 0" :index="child.menuUrl">
328
+ <template #title>
329
+ <span class="top-menu__menu-content">
330
+ <span class="top-menu__menu-icon">
331
+ <Icon v-if="iconExists(getMenuIcon(child.icon))" :name="getMenuIcon(child.icon)" :size="16" />
332
+ <span v-else class="top-menu__menu-char">{{ getFirstChar(child.menuName) }}</span>
333
+ </span>
334
+ <span class="top-menu__menu-text">{{ child.menuName }}</span>
335
+ </span>
336
+ </template>
337
+ <!-- 三级菜单项 -->
338
+ <MenuItem
339
+ v-for="grandChild in child.children"
340
+ :key="grandChild.menuUrl"
341
+ :index="grandChild.menuUrl"
342
+ >
343
+ <span class="top-menu__menu-content">
344
+ <span class="top-menu__menu-icon">
345
+ <Icon v-if="iconExists(getMenuIcon(grandChild.icon))" :name="getMenuIcon(grandChild.icon)" :size="16" />
346
+ <span v-else class="top-menu__menu-char">{{ getFirstChar(grandChild.menuName) }}</span>
347
+ </span>
348
+ <span class="top-menu__menu-text">{{ grandChild.menuName }}</span>
349
+ </span>
350
+ </MenuItem>
351
+ </SubMenu>
352
+ <!-- 二级菜单项 -->
353
+ <MenuItem v-else :index="child.menuUrl">
354
+ <span class="top-menu__menu-content">
355
+ <span class="top-menu__menu-icon">
356
+ <Icon v-if="iconExists(getMenuIcon(child.icon))" :name="getMenuIcon(child.icon)" :size="16" />
357
+ <span v-else class="top-menu__menu-char">{{ getFirstChar(child.menuName) }}</span>
358
+ </span>
359
+ <span class="top-menu__menu-text">{{ child.menuName }}</span>
334
360
  </span>
335
- <span class="top-menu__menu-text">{{ child.menuName }}</span>
336
- </span>
337
- </MenuItem>
361
+ </MenuItem>
362
+ </template>
338
363
  </SubMenu>
339
364
  <!-- 无子菜单 -->
340
365
  <MenuItem v-else :index="menu.menuUrl">
@@ -187,6 +187,7 @@ const showMixSidebar = computed(() => {
187
187
  flex: 1;
188
188
  overflow: auto;
189
189
  background-color: var(--bg-color-page);
190
+ padding: 0;
190
191
  }
191
192
  }
192
193
  </style>
@@ -0,0 +1,44 @@
1
+ /**
2
+ * 国际化组合式函数
3
+ * 提供便捷的国际化操作
4
+ */
5
+
6
+ import { useLocaleStore } from '@/stores/locale'
7
+ import type { LocaleCode, LocaleMessages } from '@xto/core/locale'
8
+
9
+ /**
10
+ * 使用国际化
11
+ * 封装 locale store,提供更简洁的 API
12
+ */
13
+ export function useI18n() {
14
+ const localeStore = useLocaleStore()
15
+
16
+ return {
17
+ /** 当前语言代码 */
18
+ locale: localeStore.locale,
19
+ /** 当前语言名称 */
20
+ localeName: localeStore.localeName,
21
+ /** 支持的语言列表 */
22
+ locales: localeStore.locales,
23
+ /** 翻译函数 */
24
+ t: localeStore.t,
25
+ /** 当前语言包 */
26
+ messages: localeStore.messages,
27
+ /** 切换语言 */
28
+ setLocale: localeStore.changeLocale,
29
+ /** 添加自定义翻译 */
30
+ addMessages: localeStore.addMessages
31
+ }
32
+ }
33
+
34
+ /**
35
+ * 创建翻译函数
36
+ * 用于在非组件上下文中使用翻译
37
+ */
38
+ export function createTranslator() {
39
+ const localeStore = useLocaleStore()
40
+ return localeStore.t
41
+ }
42
+
43
+ // 导出类型
44
+ export type { LocaleCode, LocaleMessages }
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ import './style.scss'
3
3
 
4
4
  // 配置
5
5
  import { initAppConfig, getAppId, getClientId, getApiBaseUrl } from './utils/config'
6
+ import type { LocaleCode } from '@xto/core/locale'
6
7
 
7
8
  // XtoConfig 类型定义
8
9
  export interface XtoConfig {
@@ -12,6 +13,7 @@ export interface XtoConfig {
12
13
  apiBaseUrl?: string
13
14
  indexPath?: string
14
15
  loginPath?: string
16
+ locale?: LocaleCode
15
17
  }
16
18
 
17
19
  /**
@@ -25,6 +27,15 @@ export function createXtoApp(config: Partial<XtoConfig>) {
25
27
  clientId: config.clientId,
26
28
  apiBaseUrl: config.apiBaseUrl
27
29
  })
30
+
31
+ // 设置初始语言(如果提供)
32
+ if (config.locale) {
33
+ import('./stores/locale').then(({ useLocaleStore }) => {
34
+ const localeStore = useLocaleStore()
35
+ localeStore.changeLocale(config.locale!)
36
+ })
37
+ }
38
+
28
39
  return {
29
40
  config: {
30
41
  appName: config.appName || 'XTO App',
@@ -32,7 +43,8 @@ export function createXtoApp(config: Partial<XtoConfig>) {
32
43
  clientId: getClientId(),
33
44
  apiBaseUrl: getApiBaseUrl(),
34
45
  indexPath: config.indexPath || '/dashboard',
35
- loginPath: config.loginPath || '/login'
46
+ loginPath: config.loginPath || '/login',
47
+ locale: config.locale || 'zh-CN'
36
48
  }
37
49
  }
38
50
  }
@@ -54,6 +66,7 @@ export * from './composables/useApp'
54
66
  export * from './composables/useAuth'
55
67
  export * from './composables/useForm'
56
68
  export * from './composables/useTable'
69
+ export * from './composables/useI18n'
57
70
 
58
71
  // 工具函数
59
72
  export * from './utils/auth'
@@ -67,6 +80,7 @@ export * from './stores/app'
67
80
  export * from './stores/auth'
68
81
  export * from './stores/menu'
69
82
  export * from './stores/user'
83
+ export * from './stores/locale'
70
84
 
71
85
  // 路由
72
86
  export { default as router, resetRouter } from './router'
@@ -12,4 +12,5 @@ export default pinia
12
12
  export * from './user'
13
13
  export * from './auth'
14
14
  export * from './menu'
15
- export * from './app'
15
+ export * from './app'
16
+ export * from './locale'
@@ -0,0 +1,67 @@
1
+ /**
2
+ * 国际化状态管理
3
+ */
4
+
5
+ import { defineStore } from 'pinia'
6
+ import { ref, computed } from 'vue'
7
+ import { local } from '@/utils/storage'
8
+ import {
9
+ useLocale,
10
+ createLocaleProvider,
11
+ getSupportedLocales,
12
+ type LocaleCode,
13
+ type LocaleMessages
14
+ } from '@xto/core/locale'
15
+
16
+ export type { LocaleCode, LocaleMessages }
17
+
18
+ export const useLocaleStore = defineStore('locale', () => {
19
+ // 从本地存储获取语言设置
20
+ const savedLocale = local.get<LocaleCode>('locale') || 'zh-CN'
21
+
22
+ // 创建国际化提供者
23
+ const provider = createLocaleProvider(savedLocale)
24
+
25
+ // 状态
26
+ const locale = ref<LocaleCode>(savedLocale)
27
+ const locales = getSupportedLocales()
28
+
29
+ // 使用国际化组合式函数
30
+ const { t, messages, setLocale, mergeMessages } = useLocale()
31
+
32
+ // 当前语言名称
33
+ const localeName = computed(() => {
34
+ const found = locales.find(l => l.code === locale.value)
35
+ return found?.name || locale.value
36
+ })
37
+
38
+ // 设置语言
39
+ const changeLocale = (code: LocaleCode) => {
40
+ locale.value = code
41
+ setLocale(code)
42
+ local.set('locale', code)
43
+ provider.setLocale(code)
44
+ }
45
+
46
+ // 添加自定义翻译
47
+ const addMessages = (msgs: LocaleMessages) => {
48
+ mergeMessages(msgs)
49
+ }
50
+
51
+ // 初始化
52
+ const initLocale = () => {
53
+ setLocale(savedLocale)
54
+ }
55
+
56
+ return {
57
+ locale,
58
+ localeName,
59
+ locales,
60
+ messages,
61
+ t,
62
+ changeLocale,
63
+ addMessages,
64
+ initLocale,
65
+ provider
66
+ }
67
+ })