smart-admin-web 10.15.0 → 10.20.1

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 (432) hide show
  1. package/README.md +1 -1
  2. package/dist/api/index.d.ts +4 -2
  3. package/dist/api/index.js +1 -1
  4. package/dist/api/index.js.map +1 -1
  5. package/dist/api/schema.d.ts +39 -5
  6. package/dist/assets/icons/ph-subset.json.js +5 -5
  7. package/dist/components/AppIcon.vue.js +9 -9
  8. package/dist/components/AppIcon.vue.js.map +1 -1
  9. package/dist/components/AppWatermark.vue.d.ts +14 -0
  10. package/dist/components/AppWatermark.vue.js +38 -0
  11. package/dist/components/AppWatermark.vue.js.map +1 -0
  12. package/dist/components/AppWatermark2.vue.js +5 -0
  13. package/dist/components/AppWatermark2.vue.js.map +1 -0
  14. package/dist/components/Chart/PieChart.vue.d.ts +1 -1
  15. package/dist/components/Chart/echarts.js +15 -20
  16. package/dist/components/Chart/echarts.js.map +1 -1
  17. package/dist/components/CronEditor/index.vue.js +1 -1
  18. package/dist/components/CronEditor/index2.vue.js +2 -1
  19. package/dist/components/CronEditor/index2.vue.js.map +1 -1
  20. package/dist/components/DetailPage/index.vue.js +2 -2
  21. package/dist/components/DetailPage/index2.vue.js.map +1 -1
  22. package/dist/components/DictTag/index.vue.js.map +1 -1
  23. package/dist/components/ErrorBoundary/index.vue.js +2 -2
  24. package/dist/components/ErrorBoundary/index2.vue.js +1 -1
  25. package/dist/components/ErrorBoundary/index2.vue.js.map +1 -1
  26. package/dist/components/FormContainer/index.vue.js +91 -56
  27. package/dist/components/FormContainer/index.vue.js.map +1 -1
  28. package/dist/components/ImportWizard/index.vue.js +1 -1
  29. package/dist/components/ImportWizard/index2.vue.js +44 -41
  30. package/dist/components/ImportWizard/index2.vue.js.map +1 -1
  31. package/dist/components/MenuSearch.vue.js +2 -2
  32. package/dist/components/MenuSearch2.vue.js +19 -18
  33. package/dist/components/MenuSearch2.vue.js.map +1 -1
  34. package/dist/components/PasswordStrength/index.vue.js +2 -2
  35. package/dist/components/PasswordStrength/index2.vue.js +20 -18
  36. package/dist/components/PasswordStrength/index2.vue.js.map +1 -1
  37. package/dist/components/TableTotal/index.vue.d.ts +6 -0
  38. package/dist/components/{SelectTable → TableTotal}/index.vue.js +1 -1
  39. package/dist/components/TableTotal/index2.vue.js +16 -0
  40. package/dist/components/TableTotal/index2.vue.js.map +1 -0
  41. package/dist/components/TableZoomButton/index.vue.js.map +1 -1
  42. package/dist/components/UserPicker/index.vue.js +2 -2
  43. package/dist/components/UserPicker/index2.vue.js +176 -117
  44. package/dist/components/UserPicker/index2.vue.js.map +1 -1
  45. package/dist/composables/useBatchDelete.js.map +1 -1
  46. package/dist/composables/useLayoutMenu.js +17 -16
  47. package/dist/composables/useLayoutMenu.js.map +1 -1
  48. package/dist/composables/useModule.js +39 -29
  49. package/dist/composables/useModule.js.map +1 -1
  50. package/dist/composables/useShellBreakpoint.d.ts +19 -0
  51. package/dist/composables/useShellBreakpoint.js +37 -0
  52. package/dist/composables/useShellBreakpoint.js.map +1 -0
  53. package/dist/composables/useSite.d.ts +15 -0
  54. package/dist/composables/useSite.js +16 -14
  55. package/dist/composables/useSite.js.map +1 -1
  56. package/dist/composables/useTabTitle.js.map +1 -1
  57. package/dist/composables/useTableTitle.d.ts +6 -0
  58. package/dist/composables/useTableTitle.js +11 -0
  59. package/dist/composables/useTableTitle.js.map +1 -0
  60. package/dist/composables/useTableZoom.d.ts +5 -0
  61. package/dist/composables/useTableZoom.js.map +1 -1
  62. package/dist/composables/useTheme.d.ts +2 -2
  63. package/dist/composables/useTheme.js +23 -20
  64. package/dist/composables/useTheme.js.map +1 -1
  65. package/dist/createSmartAdmin.d.ts +12 -2
  66. package/dist/createSmartAdmin.js +72 -60
  67. package/dist/createSmartAdmin.js.map +1 -1
  68. package/dist/index.d.ts +5 -2
  69. package/dist/index.js +219 -205
  70. package/dist/index.js.map +1 -1
  71. package/dist/layouts/AccentPicker.vue.js +8 -0
  72. package/dist/layouts/AccentPicker.vue.js.map +1 -0
  73. package/dist/layouts/AccentPicker2.vue.js +131 -0
  74. package/dist/layouts/AccentPicker2.vue.js.map +1 -0
  75. package/dist/layouts/AppHeader.vue.d.ts +8 -1
  76. package/dist/layouts/AppHeader.vue.js +2 -2
  77. package/dist/layouts/AppHeader2.vue.js +317 -235
  78. package/dist/layouts/AppHeader2.vue.js.map +1 -1
  79. package/dist/layouts/NoticeBell.vue.js +2 -2
  80. package/dist/layouts/NoticeBell2.vue.js +19 -18
  81. package/dist/layouts/NoticeBell2.vue.js.map +1 -1
  82. package/dist/layouts/PersonalLayout.vue.js +2 -2
  83. package/dist/layouts/PersonalLayout2.vue.js +69 -47
  84. package/dist/layouts/PersonalLayout2.vue.js.map +1 -1
  85. package/dist/layouts/SettingsDrawer.vue.js +3 -3
  86. package/dist/layouts/SettingsDrawer2.vue.js +261 -325
  87. package/dist/layouts/SettingsDrawer2.vue.js.map +1 -1
  88. package/dist/layouts/TabsBar.vue.js +2 -2
  89. package/dist/layouts/TabsBar2.vue.js +97 -69
  90. package/dist/layouts/TabsBar2.vue.js.map +1 -1
  91. package/dist/layouts/components/SideNav.vue.d.ts +3 -0
  92. package/dist/layouts/components/SideNav.vue.js +1 -1
  93. package/dist/layouts/components/SideNav2.vue.js +54 -26
  94. package/dist/layouts/components/SideNav2.vue.js.map +1 -1
  95. package/dist/layouts/default.vue.js +1 -1
  96. package/dist/layouts/default2.vue.js +170 -140
  97. package/dist/layouts/default2.vue.js.map +1 -1
  98. package/dist/lib/loginHero.d.ts +2 -2
  99. package/dist/lib/loginHero.js.map +1 -1
  100. package/dist/lib/runtime.js +1 -1
  101. package/dist/lib/watermark.d.ts +110 -0
  102. package/dist/lib/watermark.js +151 -0
  103. package/dist/lib/watermark.js.map +1 -0
  104. package/dist/locales/en-US.d.ts +221 -15
  105. package/dist/locales/en-US.js +230 -21
  106. package/dist/locales/en-US.js.map +1 -1
  107. package/dist/locales/kernelMenuTitles.d.ts +1 -0
  108. package/dist/locales/kernelMenuTitles.js +128 -0
  109. package/dist/locales/kernelMenuTitles.js.map +1 -0
  110. package/dist/locales/menuTitle.d.ts +3 -0
  111. package/dist/locales/menuTitle.js +14 -12
  112. package/dist/locales/menuTitle.js.map +1 -1
  113. package/dist/locales/zh-CN.d.ts +221 -15
  114. package/dist/locales/zh-CN.js +238 -28
  115. package/dist/locales/zh-CN.js.map +1 -1
  116. package/dist/router/index.js +41 -32
  117. package/dist/router/index.js.map +1 -1
  118. package/dist/router/namedPage.d.ts +4 -0
  119. package/dist/router/namedPage.js +7 -7
  120. package/dist/router/namedPage.js.map +1 -1
  121. package/dist/router/viewRegistry.js +8 -8
  122. package/dist/router/viewRegistry.js.map +1 -1
  123. package/dist/stores/app.d.ts +0 -12
  124. package/dist/stores/app.js +11 -12
  125. package/dist/stores/app.js.map +1 -1
  126. package/dist/stores/tabs.js.map +1 -1
  127. package/dist/stores/user.d.ts +10 -0
  128. package/dist/stores/user.js.map +1 -1
  129. package/dist/style.css +1 -1
  130. package/dist/theme/accentTokens.d.ts +27 -0
  131. package/dist/theme/accentTokens.js +54 -0
  132. package/dist/theme/accentTokens.js.map +1 -0
  133. package/dist/theme/accents.d.ts +21 -1
  134. package/dist/theme/accents.js +11 -2
  135. package/dist/theme/accents.js.map +1 -1
  136. package/dist/theme/mix.d.ts +58 -7
  137. package/dist/theme/mix.js +115 -30
  138. package/dist/theme/mix.js.map +1 -1
  139. package/dist/theme/naive-theme.d.ts +5 -2
  140. package/dist/theme/naive-theme.js +407 -75
  141. package/dist/theme/naive-theme.js.map +1 -1
  142. package/dist/utils/jwt.d.ts +8 -0
  143. package/dist/utils/jwt.js +14 -0
  144. package/dist/utils/jwt.js.map +1 -0
  145. package/dist/utils/menuIcon.d.ts +2 -0
  146. package/dist/utils/menuIcon.js +8 -0
  147. package/dist/utils/menuIcon.js.map +1 -0
  148. package/dist/utils/oauthBrand.js.map +1 -1
  149. package/dist/utils/tableFilter.d.ts +88 -0
  150. package/dist/utils/tableFilter.js +116 -0
  151. package/dist/utils/tableFilter.js.map +1 -0
  152. package/dist/utils/tableToolbar.d.ts +18 -0
  153. package/dist/utils/tableToolbar.js +11 -0
  154. package/dist/utils/tableToolbar.js.map +1 -0
  155. package/dist/utils/treeFilter.d.ts +20 -0
  156. package/dist/utils/treeFilter.js +24 -0
  157. package/dist/utils/treeFilter.js.map +1 -0
  158. package/dist/views/dashboard/ShortcutPicker.vue.js +1 -1
  159. package/dist/views/dashboard/ShortcutPicker2.vue.js +73 -48
  160. package/dist/views/dashboard/ShortcutPicker2.vue.js.map +1 -1
  161. package/dist/views/dashboard/biz.vue.js +1 -1
  162. package/dist/views/dashboard/biz2.vue.js +310 -257
  163. package/dist/views/dashboard/biz2.vue.js.map +1 -1
  164. package/dist/views/dashboard/workbench.vue.js +2 -2
  165. package/dist/views/dashboard/workbench2.vue.js +141 -155
  166. package/dist/views/dashboard/workbench2.vue.js.map +1 -1
  167. package/dist/views/embed/iframe.vue.js +2 -2
  168. package/dist/views/embed/iframe2.vue.js +22 -15
  169. package/dist/views/embed/iframe2.vue.js.map +1 -1
  170. package/dist/views/error/404.vue.js +2 -2
  171. package/dist/views/error/4042.vue.js +33 -24
  172. package/dist/views/error/4042.vue.js.map +1 -1
  173. package/dist/views/error/BootError.vue.js +1 -1
  174. package/dist/views/error/BootError2.vue.js +59 -48
  175. package/dist/views/error/BootError2.vue.js.map +1 -1
  176. package/dist/views/error/MissingRoute.vue.js +2 -2
  177. package/dist/views/error/MissingRoute2.vue.js +34 -15
  178. package/dist/views/error/MissingRoute2.vue.js.map +1 -1
  179. package/dist/views/login/LoginForm.vue.d.ts +7 -1
  180. package/dist/views/login/LoginForm.vue.js +2 -2
  181. package/dist/views/login/LoginForm2.vue.js +580 -488
  182. package/dist/views/login/LoginForm2.vue.js.map +1 -1
  183. package/dist/views/login/components/LoginDesk.vue.d.ts +36 -0
  184. package/dist/views/login/components/LoginDesk.vue.js +9 -0
  185. package/dist/views/login/components/LoginDesk.vue.js.map +1 -0
  186. package/dist/views/login/components/LoginDesk2.vue.js +100 -0
  187. package/dist/views/login/components/LoginDesk2.vue.js.map +1 -0
  188. package/dist/views/login/components/LoginHeroPanel.vue.js +3 -3
  189. package/dist/views/login/components/LoginHeroPanel2.vue.js +34 -39
  190. package/dist/views/login/components/LoginHeroPanel2.vue.js.map +1 -1
  191. package/dist/views/login/index.vue.js +1 -1
  192. package/dist/views/login/index2.vue.js +141 -71
  193. package/dist/views/login/index2.vue.js.map +1 -1
  194. package/dist/views/login/layout.d.ts +11 -0
  195. package/dist/views/login/layout.js +27 -0
  196. package/dist/views/login/layout.js.map +1 -0
  197. package/dist/views/mfa/index.vue.js +2 -2
  198. package/dist/views/mfa/index2.vue.js +367 -321
  199. package/dist/views/mfa/index2.vue.js.map +1 -1
  200. package/dist/views/module/index.vue.js +2 -2
  201. package/dist/views/module/index2.vue.js +132 -99
  202. package/dist/views/module/index2.vue.js.map +1 -1
  203. package/dist/views/oauth/callback.vue.js +2 -2
  204. package/dist/views/oauth/callback2.vue.js +65 -51
  205. package/dist/views/oauth/callback2.vue.js.map +1 -1
  206. package/dist/views/personal/bindings.vue.js +2 -2
  207. package/dist/views/personal/bindings2.vue.js +98 -94
  208. package/dist/views/personal/bindings2.vue.js.map +1 -1
  209. package/dist/views/personal/notice2.vue.js +103 -76
  210. package/dist/views/personal/notice2.vue.js.map +1 -1
  211. package/dist/views/personal/password2.vue.js +47 -40
  212. package/dist/views/personal/password2.vue.js.map +1 -1
  213. package/dist/views/personal/profile.vue.js +3 -3
  214. package/dist/views/personal/profile2.vue.js +24 -18
  215. package/dist/views/personal/profile2.vue.js.map +1 -1
  216. package/dist/views/personal/security.vue.js +2 -2
  217. package/dist/views/personal/security2.vue.js +65 -53
  218. package/dist/views/personal/security2.vue.js.map +1 -1
  219. package/dist/views/personal/sessions.vue.js +2 -2
  220. package/dist/views/personal/sessions2.vue.js +67 -62
  221. package/dist/views/personal/sessions2.vue.js.map +1 -1
  222. package/dist/views/system/ai-model/components/ProviderCard.vue.js +2 -2
  223. package/dist/views/system/ai-model/components/ProviderCard2.vue.js +142 -130
  224. package/dist/views/system/ai-model/components/ProviderCard2.vue.js.map +1 -1
  225. package/dist/views/system/ai-model/components/ProviderForm.vue.js +2 -2
  226. package/dist/views/system/ai-model/components/ProviderForm2.vue.js +71 -70
  227. package/dist/views/system/ai-model/components/ProviderForm2.vue.js.map +1 -1
  228. package/dist/views/system/ai-model/index.vue.js +2 -2
  229. package/dist/views/system/ai-model/index2.vue.js +99 -99
  230. package/dist/views/system/ai-model/index2.vue.js.map +1 -1
  231. package/dist/views/system/ai-model/presets.d.ts +1 -1
  232. package/dist/views/system/ai-model/presets.js +18 -18
  233. package/dist/views/system/ai-model/presets.js.map +1 -1
  234. package/dist/views/system/ai-usage/index.vue.js +2 -2
  235. package/dist/views/system/ai-usage/index2.vue.js +356 -258
  236. package/dist/views/system/ai-usage/index2.vue.js.map +1 -1
  237. package/dist/views/system/api-docs/index.vue.js +5 -2
  238. package/dist/views/system/api-docs/index.vue.js.map +1 -1
  239. package/dist/views/system/api-docs/index2.vue.js +92 -42
  240. package/dist/views/system/api-docs/index2.vue.js.map +1 -1
  241. package/dist/views/system/cache/index.vue.js +2 -2
  242. package/dist/views/system/cache/index2.vue.js +74 -80
  243. package/dist/views/system/cache/index2.vue.js.map +1 -1
  244. package/dist/views/system/config/components/AdminMock.vue.js +2 -2
  245. package/dist/views/system/config/components/AdminMock2.vue.js +60 -43
  246. package/dist/views/system/config/components/AdminMock2.vue.js.map +1 -1
  247. package/dist/views/system/config/components/AdvancedSection.vue.js +5 -2
  248. package/dist/views/system/config/components/AdvancedSection.vue.js.map +1 -1
  249. package/dist/views/system/config/components/AdvancedSection2.vue.js +98 -70
  250. package/dist/views/system/config/components/AdvancedSection2.vue.js.map +1 -1
  251. package/dist/views/system/config/components/BrandSection.vue.js +2 -2
  252. package/dist/views/system/config/components/BrandSection2.vue.js +121 -119
  253. package/dist/views/system/config/components/BrandSection2.vue.js.map +1 -1
  254. package/dist/views/system/config/components/CfgGroup.vue.js +3 -3
  255. package/dist/views/system/config/components/CfgGroup2.vue.js.map +1 -1
  256. package/dist/views/system/config/components/CfgRow.vue.js +1 -1
  257. package/dist/views/system/config/components/CfgRow2.vue.js +24 -23
  258. package/dist/views/system/config/components/CfgRow2.vue.js.map +1 -1
  259. package/dist/views/system/config/components/CfgSegment.vue.js +1 -1
  260. package/dist/views/system/config/components/CfgSegment2.vue.js +16 -15
  261. package/dist/views/system/config/components/CfgSegment2.vue.js.map +1 -1
  262. package/dist/views/system/config/components/ConfigFormModal.vue.js +2 -2
  263. package/dist/views/system/config/components/ConfigFormModal2.vue.js +35 -33
  264. package/dist/views/system/config/components/ConfigFormModal2.vue.js.map +1 -1
  265. package/dist/views/system/config/components/JobSection.vue.js +2 -2
  266. package/dist/views/system/config/components/JobSection2.vue.js +46 -44
  267. package/dist/views/system/config/components/JobSection2.vue.js.map +1 -1
  268. package/dist/views/system/config/components/LoginMock.vue.js +3 -3
  269. package/dist/views/system/config/components/LoginMock2.vue.js +83 -72
  270. package/dist/views/system/config/components/LoginMock2.vue.js.map +1 -1
  271. package/dist/views/system/config/components/LogoCropper.vue.js +1 -1
  272. package/dist/views/system/config/components/LogoCropper2.vue.js.map +1 -1
  273. package/dist/views/system/config/components/LogoEditor.vue.js +2 -2
  274. package/dist/views/system/config/components/LogoEditor2.vue.js +11 -13
  275. package/dist/views/system/config/components/LogoEditor2.vue.js.map +1 -1
  276. package/dist/views/system/config/components/ProviderSheet.vue.js +3 -3
  277. package/dist/views/system/config/components/ProviderSheet2.vue.js.map +1 -1
  278. package/dist/views/system/config/components/SectionLayout.vue.d.ts +4 -2
  279. package/dist/views/system/config/components/SectionLayout.vue.js +2 -2
  280. package/dist/views/system/config/components/SectionLayout2.vue.js +51 -27
  281. package/dist/views/system/config/components/SectionLayout2.vue.js.map +1 -1
  282. package/dist/views/system/config/components/SecuritySection.vue.js +2 -2
  283. package/dist/views/system/config/components/SecuritySection2.vue.js +207 -206
  284. package/dist/views/system/config/components/SecuritySection2.vue.js.map +1 -1
  285. package/dist/views/system/config/components/SensitiveSection.vue.js +2 -2
  286. package/dist/views/system/config/components/SensitiveSection2.vue.js +107 -102
  287. package/dist/views/system/config/components/SensitiveSection2.vue.js.map +1 -1
  288. package/dist/views/system/config/components/UploadSection.vue.js +2 -2
  289. package/dist/views/system/config/components/UploadSection2.vue.js +86 -77
  290. package/dist/views/system/config/components/UploadSection2.vue.js.map +1 -1
  291. package/dist/views/system/config/components/WatermarkSection.vue.js +8 -0
  292. package/dist/views/system/config/components/WatermarkSection.vue.js.map +1 -0
  293. package/dist/views/system/config/components/WatermarkSection2.vue.js +284 -0
  294. package/dist/views/system/config/components/WatermarkSection2.vue.js.map +1 -0
  295. package/dist/views/system/config/draft.d.ts +2 -2
  296. package/dist/views/system/config/draft.js.map +1 -1
  297. package/dist/views/system/config/groups.d.ts +4 -1
  298. package/dist/views/system/config/groups.js +54 -49
  299. package/dist/views/system/config/groups.js.map +1 -1
  300. package/dist/views/system/config/index.vue.js +3 -2
  301. package/dist/views/system/config/index.vue.js.map +1 -1
  302. package/dist/views/system/config/index2.vue.js +173 -148
  303. package/dist/views/system/config/index2.vue.js.map +1 -1
  304. package/dist/views/system/config/layoutMode.d.ts +23 -0
  305. package/dist/views/system/config/layoutMode.js +28 -0
  306. package/dist/views/system/config/layoutMode.js.map +1 -0
  307. package/dist/views/system/dict/index.vue.js +2 -2
  308. package/dist/views/system/dict/index2.vue.js +471 -366
  309. package/dist/views/system/dict/index2.vue.js.map +1 -1
  310. package/dist/views/system/file/index2.vue.js +91 -76
  311. package/dist/views/system/file/index2.vue.js.map +1 -1
  312. package/dist/views/system/job/index.vue.js +3 -3
  313. package/dist/views/system/job/index2.vue.js +897 -828
  314. package/dist/views/system/job/index2.vue.js.map +1 -1
  315. package/dist/views/system/job-log/components/AttemptTable.vue.d.ts +8 -0
  316. package/dist/views/system/job-log/components/AttemptTable.vue.js +5 -0
  317. package/dist/views/system/job-log/components/AttemptTable.vue.js.map +1 -0
  318. package/dist/views/system/job-log/components/AttemptTable2.vue.js +54 -0
  319. package/dist/views/system/job-log/components/AttemptTable2.vue.js.map +1 -0
  320. package/dist/views/system/job-log/index.vue.js +2 -2
  321. package/dist/views/system/job-log/index2.vue.js +193 -207
  322. package/dist/views/system/job-log/index2.vue.js.map +1 -1
  323. package/dist/views/system/job-log/runStatus.d.ts +13 -0
  324. package/dist/views/system/job-log/runStatus.js +26 -0
  325. package/dist/views/system/job-log/runStatus.js.map +1 -0
  326. package/dist/views/system/job-monitor/index.vue.js +2 -2
  327. package/dist/views/system/job-monitor/index2.vue.js +172 -180
  328. package/dist/views/system/job-monitor/index2.vue.js.map +1 -1
  329. package/dist/views/system/log/exception/index.vue.js +2 -2
  330. package/dist/views/system/log/exception/index2.vue.js +135 -96
  331. package/dist/views/system/log/exception/index2.vue.js.map +1 -1
  332. package/dist/views/system/log/login/index2.vue.js +62 -41
  333. package/dist/views/system/log/login/index2.vue.js.map +1 -1
  334. package/dist/views/system/log/op/index.vue.js +2 -2
  335. package/dist/views/system/log/op/index2.vue.js +200 -162
  336. package/dist/views/system/log/op/index2.vue.js.map +1 -1
  337. package/dist/views/system/menu/components/ButtonManager.vue.js +2 -2
  338. package/dist/views/system/menu/components/ButtonManager2.vue.js +206 -190
  339. package/dist/views/system/menu/components/ButtonManager2.vue.js.map +1 -1
  340. package/dist/views/system/menu/components/MenuFormModal.vue.js +2 -2
  341. package/dist/views/system/menu/components/MenuFormModal2.vue.js +127 -118
  342. package/dist/views/system/menu/components/MenuFormModal2.vue.js.map +1 -1
  343. package/dist/views/system/menu/index.vue.js +1 -1
  344. package/dist/views/system/menu/index2.vue.js +216 -183
  345. package/dist/views/system/menu/index2.vue.js.map +1 -1
  346. package/dist/views/system/module/index.vue.js +1 -1
  347. package/dist/views/system/module/index2.vue.js +177 -144
  348. package/dist/views/system/module/index2.vue.js.map +1 -1
  349. package/dist/views/system/monitor/index.vue.js +2 -2
  350. package/dist/views/system/monitor/index2.vue.js +134 -149
  351. package/dist/views/system/monitor/index2.vue.js.map +1 -1
  352. package/dist/views/system/notice/index.vue.js +1 -1
  353. package/dist/views/system/notice/index2.vue.js +209 -181
  354. package/dist/views/system/notice/index2.vue.js.map +1 -1
  355. package/dist/views/system/org/index.vue.js +1 -1
  356. package/dist/views/system/org/index2.vue.js +278 -248
  357. package/dist/views/system/org/index2.vue.js.map +1 -1
  358. package/dist/views/system/position/index.vue.js +5 -2
  359. package/dist/views/system/position/index.vue.js.map +1 -1
  360. package/dist/views/system/position/index2.vue.js +128 -92
  361. package/dist/views/system/position/index2.vue.js.map +1 -1
  362. package/dist/views/system/recycle/index.vue.js +2 -2
  363. package/dist/views/system/recycle/index2.vue.js +90 -67
  364. package/dist/views/system/recycle/index2.vue.js.map +1 -1
  365. package/dist/views/system/role/components/GrantMenuSheet.vue.d.ts +20 -0
  366. package/dist/views/system/role/components/GrantMenuSheet.vue.js +8 -0
  367. package/dist/views/system/role/components/GrantMenuSheet.vue.js.map +1 -0
  368. package/dist/views/system/role/components/GrantMenuSheet2.vue.js +117 -0
  369. package/dist/views/system/role/components/GrantMenuSheet2.vue.js.map +1 -0
  370. package/dist/views/system/role/components/GrantMenuTable.vue.d.ts +6 -4
  371. package/dist/views/system/role/components/GrantMenuTable.vue.js +2 -2
  372. package/dist/views/system/role/components/GrantMenuTable2.vue.js +279 -177
  373. package/dist/views/system/role/components/GrantMenuTable2.vue.js.map +1 -1
  374. package/dist/views/system/role/components/MatchText.vue.d.ts +7 -0
  375. package/dist/views/system/role/components/MatchText.vue.js +8 -0
  376. package/dist/views/system/role/components/MatchText.vue.js.map +1 -0
  377. package/dist/views/system/role/components/MatchText2.vue.js +29 -0
  378. package/dist/views/system/role/components/MatchText2.vue.js.map +1 -0
  379. package/dist/views/system/role/components/grantMenuGroups.d.ts +36 -0
  380. package/dist/views/system/role/components/grantMenuGroups.js +110 -48
  381. package/dist/views/system/role/components/grantMenuGroups.js.map +1 -1
  382. package/dist/views/system/role/index.vue.js +5 -2
  383. package/dist/views/system/role/index.vue.js.map +1 -1
  384. package/dist/views/system/role/index2.vue.js +181 -165
  385. package/dist/views/system/role/index2.vue.js.map +1 -1
  386. package/dist/views/system/session/index2.vue.js +75 -49
  387. package/dist/views/system/session/index2.vue.js.map +1 -1
  388. package/dist/views/system/user/components/ResetPasswordModal.vue.js +2 -2
  389. package/dist/views/system/user/components/ResetPasswordModal2.vue.js +2 -0
  390. package/dist/views/system/user/components/ResetPasswordModal2.vue.js.map +1 -1
  391. package/dist/views/system/user/components/UserFormModal.vue.js +2 -2
  392. package/dist/views/system/user/components/UserFormModal2.vue.js +77 -76
  393. package/dist/views/system/user/components/UserFormModal2.vue.js.map +1 -1
  394. package/dist/views/system/user/index.vue.js +2 -2
  395. package/dist/views/system/user/index2.vue.js +362 -275
  396. package/dist/views/system/user/index2.vue.js.map +1 -1
  397. package/package.json +3 -5
  398. package/dist/components/SelectTable/index.vue.d.ts +0 -76
  399. package/dist/components/SelectTable/index2.vue.js +0 -256
  400. package/dist/components/SelectTable/index2.vue.js.map +0 -1
  401. package/dist/composables/useTableRowSort.d.ts +0 -20
  402. package/dist/composables/useTableRowSort.js +0 -59
  403. package/dist/composables/useTableRowSort.js.map +0 -1
  404. package/dist/layouts/LayoutModeCards.vue.js +0 -8
  405. package/dist/layouts/LayoutModeCards.vue.js.map +0 -1
  406. package/dist/layouts/LayoutModeCards2.vue.js +0 -67
  407. package/dist/layouts/LayoutModeCards2.vue.js.map +0 -1
  408. package/dist/layouts/SettingRow.vue.d.ts +0 -16
  409. package/dist/layouts/SettingRow.vue.js +0 -8
  410. package/dist/layouts/SettingRow.vue.js.map +0 -1
  411. package/dist/layouts/SettingRow2.vue.js +0 -23
  412. package/dist/layouts/SettingRow2.vue.js.map +0 -1
  413. package/dist/views/login/skins/AuroraGlass.vue.js +0 -8
  414. package/dist/views/login/skins/AuroraGlass.vue.js.map +0 -1
  415. package/dist/views/login/skins/AuroraGlass2.vue.js +0 -80
  416. package/dist/views/login/skins/AuroraGlass2.vue.js.map +0 -1
  417. package/dist/views/login/skins/SplitPanel.vue.d.ts +0 -3
  418. package/dist/views/login/skins/SplitPanel.vue.js +0 -8
  419. package/dist/views/login/skins/SplitPanel.vue.js.map +0 -1
  420. package/dist/views/login/skins/SplitPanel2.vue.js +0 -65
  421. package/dist/views/login/skins/SplitPanel2.vue.js.map +0 -1
  422. package/dist/views/login/skins/Spotlight.vue.d.ts +0 -3
  423. package/dist/views/login/skins/Spotlight.vue.js +0 -8
  424. package/dist/views/login/skins/Spotlight.vue.js.map +0 -1
  425. package/dist/views/login/skins/Spotlight2.vue.js +0 -36
  426. package/dist/views/login/skins/Spotlight2.vue.js.map +0 -1
  427. package/dist/views/login/skins.d.ts +0 -8
  428. package/dist/views/login/skins.js +0 -13
  429. package/dist/views/login/skins.js.map +0 -1
  430. /package/dist/components/{SelectTable → TableTotal}/index.vue.js.map +0 -0
  431. /package/dist/layouts/{LayoutModeCards.vue.d.ts → AccentPicker.vue.d.ts} +0 -0
  432. /package/dist/views/{login/skins/AuroraGlass.vue.d.ts → system/config/components/WatermarkSection.vue.d.ts} +0 -0
@@ -1,4 +1,4 @@
1
- import { defineComponent as N, computed as i, openBlock as s, createElementBlock as l, normalizeClass as H, withDirectives as u, createVNode as O, unref as a, createCommentVNode as g, createElementVNode as n, toDisplayString as c, createTextVNode as k, Fragment as K, renderList as Y } from "vue";
1
+ import { defineComponent as N, computed as n, openBlock as i, createElementBlock as l, normalizeClass as H, createElementVNode as t, withDirectives as u, createVNode as L, unref as r, createCommentVNode as g, toDisplayString as c, createTextVNode as O, Fragment as K, renderList as Y } from "vue";
2
2
  import { useI18n as x } from "vue-i18n";
3
3
  import B from "../../../../components/oauth/BrandIcon.vue.js";
4
4
  import { resolveLoginHero as F, splitLoginHeroFeatures as I } from "../../../../lib/loginHero.js";
@@ -9,113 +9,124 @@ import { vFlash as d } from "../flash.js";
9
9
  const J = {
10
10
  key: 0,
11
11
  class: "hero"
12
- }, W = { class: "form" }, q = { class: "welcome" }, Q = { class: "sub" }, X = { class: "modes" }, Z = { class: "on" }, ee = {
12
+ }, W = { class: "form-wrap" }, q = { class: "form" }, Q = { class: "welcome" }, X = { class: "sub" }, Z = { class: "modes" }, ee = { class: "on" }, te = {
13
13
  key: 0,
14
14
  "data-testid": "preview-sms"
15
- }, te = {
15
+ }, oe = {
16
16
  key: 0,
17
17
  class: "captcha"
18
- }, oe = { class: "go" }, se = {
18
+ }, se = { class: "go" }, ie = {
19
19
  class: "oauth",
20
20
  "data-testid": "preview-oauth"
21
- }, le = { class: "divider" }, ie = { class: "btns" }, ne = ["title"], ae = { class: "copy" }, pe = /* @__PURE__ */ N({
21
+ }, le = { class: "divider" }, ne = { class: "btns" }, ae = ["title"], re = { class: "copy" }, fe = /* @__PURE__ */ N({
22
22
  __name: "LoginMock",
23
23
  props: {
24
24
  locale: {},
25
25
  formOnly: { type: Boolean }
26
26
  },
27
27
  setup(v) {
28
- const y = v, C = { char: "A7K2", path: "K9x4", math: "3 + 5 = ?" }, { t: A } = x(), E = U(), { values: t } = E, o = (e) => A(e, {}, { locale: y.locale }), p = i(() => D(y.locale)), h = i(
28
+ const y = v, w = { char: "A7K2", path: "K9x4", math: "3 + 5 = ?" }, { t: A } = x(), E = U(), { values: o } = E, s = (e) => A(e, {}, { locale: y.locale }), p = n(() => D(y.locale)), h = n(
29
29
  () => F(
30
30
  {
31
- headline: t[p.value.headline] ?? "",
32
- highlight: t[p.value.highlight] ?? "",
33
- features: I(t[p.value.features])
31
+ headline: o[p.value.headline] ?? "",
32
+ highlight: o[p.value.highlight] ?? "",
33
+ features: I(o[p.value.features])
34
34
  },
35
35
  {
36
- headline: `${o("login.headlinePre")}${o("login.headlineAccent")}${o("login.headlinePost")}`,
37
- highlight: o("login.headlineAccent"),
38
- features: [o("login.featRbac"), o("login.featScope"), o("login.featPortal")]
36
+ headline: `${s("login.headlinePre")}${s("login.headlineAccent")}${s("login.headlinePost")}`,
37
+ highlight: s("login.headlineAccent"),
38
+ features: [s("login.featRbac"), s("login.featScope"), s("login.featPortal")]
39
39
  },
40
- // 缺省视为开:库里没有这个键时登录页照常显示卖点
41
- t[M] !== "false"
40
+ // 缺省视为开:库里没有这个键时登录页照常显示亮点
41
+ o[M] !== "false"
42
42
  )
43
- ), f = i(() => {
43
+ ), f = n(() => {
44
44
  var e;
45
- return ((e = t[R]) == null ? void 0 : e.trim()) || o("login.subtitle");
46
- }), S = i(() => {
45
+ return ((e = o[R]) == null ? void 0 : e.trim()) || s("login.subtitle");
46
+ }), S = n(() => {
47
47
  var e;
48
- return ((e = t["sys.site.title"]) == null ? void 0 : e.trim()) || "SmartAdmin";
49
- }), b = i(() => {
48
+ return ((e = o["sys.site.title"]) == null ? void 0 : e.trim()) || "SmartAdmin";
49
+ }), b = n(() => {
50
50
  var e;
51
- return ((e = t["sys.site.copyright"]) == null ? void 0 : e.trim()) || S.value;
52
- }), P = i(() => t["sys.security.captcha.enabled"] === "true"), T = i(() => C[t[$] || "char"] ?? "A7K2"), L = i(() => t[z] === "true"), _ = i(
53
- () => E.providerRows.value.filter((e) => e.registered && t[j(e.code)] === "true")
54
- ), w = i(() => _.value.map((e) => e.code).join(","));
55
- return (e, r) => (s(), l("div", {
51
+ return ((e = o["sys.site.copyright"]) == null ? void 0 : e.trim()) || S.value;
52
+ }), C = n(() => o["sys.security.captcha.enabled"] === "true"), P = n(() => w[o[$] || "char"] ?? "A7K2"), k = n(() => o[z] === "true"), _ = n(
53
+ () => E.providerRows.value.filter((e) => e.registered && o[j(e.code)] === "true")
54
+ ), T = n(() => _.value.map((e) => e.code).join(","));
55
+ return (e, a) => (i(), l("div", {
56
56
  class: H(["mock", { "form-only": v.formOnly }])
57
57
  }, [
58
- v.formOnly ? g("", !0) : u((s(), l("div", J, [
59
- O(V, {
58
+ a[3] || (a[3] = t("div", {
59
+ class: "desk",
60
+ "aria-hidden": "true"
61
+ }, [
62
+ t("i"),
63
+ t("i"),
64
+ t("i"),
65
+ t("i")
66
+ ], -1)),
67
+ v.formOnly ? g("", !0) : u((i(), l("div", J, [
68
+ L(V, {
60
69
  headline: h.value.headline,
61
70
  highlight: h.value.highlight,
62
71
  subtitle: f.value,
63
72
  features: h.value.features,
64
73
  title: S.value,
65
- logo: a(t)[a(G)] ?? ""
74
+ logo: r(o)[r(G)] ?? ""
66
75
  }, null, 8, ["headline", "highlight", "subtitle", "features", "title", "logo"])
67
76
  ])), [
68
- [a(d), JSON.stringify(h.value)]
77
+ [r(d), JSON.stringify(h.value)]
69
78
  ]),
70
- n("div", W, [
71
- n("b", q, c(o("login.welcome")), 1),
72
- u((s(), l("span", Q, [
73
- k(c(f.value), 1)
74
- ])), [
75
- [a(d), f.value]
76
- ]),
77
- u((s(), l("div", X, [
78
- n("span", Z, c(o("login.accountLogin")), 1),
79
- L.value ? (s(), l("span", ee, c(o("login.smsLogin")), 1)) : g("", !0)
80
- ])), [
81
- [a(d), L.value]
82
- ]),
83
- r[1] || (r[1] = n("i", { class: "in" }, null, -1)),
84
- r[2] || (r[2] = n("i", { class: "in" }, null, -1)),
85
- P.value ? (s(), l("div", te, [
86
- r[0] || (r[0] = n("i", { class: "in" }, null, -1)),
87
- n("span", null, c(T.value), 1)
88
- ])) : g("", !0),
89
- n("span", oe, c(o("login.submit")), 1),
90
- u((s(), l("div", se, [
91
- _.value.length ? (s(), l(K, { key: 0 }, [
92
- n("div", le, c(a(A)("config.externalAuth.previewOther")), 1),
93
- n("div", ie, [
94
- (s(!0), l(K, null, Y(_.value, (m) => (s(), l("span", {
95
- key: m.code,
96
- title: m.displayName
97
- }, [
98
- O(B, {
99
- code: m.code,
100
- icon: m.icon,
101
- size: 20
102
- }, null, 8, ["code", "icon"])
103
- ], 8, ne))), 128))
104
- ])
105
- ], 64)) : g("", !0)
106
- ])), [
107
- [a(d), w.value]
108
- ]),
109
- u((s(), l("div", ae, [
110
- k("© " + c(b.value), 1)
111
- ])), [
112
- [a(d), b.value]
79
+ t("div", W, [
80
+ t("div", q, [
81
+ t("b", Q, c(s("login.welcome")), 1),
82
+ u((i(), l("span", X, [
83
+ O(c(f.value), 1)
84
+ ])), [
85
+ [r(d), f.value]
86
+ ]),
87
+ u((i(), l("div", Z, [
88
+ t("span", ee, c(s("login.accountLogin")), 1),
89
+ k.value ? (i(), l("span", te, c(s("login.smsLogin")), 1)) : g("", !0)
90
+ ])), [
91
+ [r(d), k.value]
92
+ ]),
93
+ a[1] || (a[1] = t("i", { class: "in" }, null, -1)),
94
+ a[2] || (a[2] = t("i", { class: "in" }, null, -1)),
95
+ C.value ? (i(), l("div", oe, [
96
+ a[0] || (a[0] = t("i", { class: "in" }, null, -1)),
97
+ t("span", null, c(P.value), 1)
98
+ ])) : g("", !0),
99
+ t("span", se, c(s("login.submit")), 1),
100
+ u((i(), l("div", ie, [
101
+ _.value.length ? (i(), l(K, { key: 0 }, [
102
+ t("div", le, c(r(A)("config.externalAuth.previewOther")), 1),
103
+ t("div", ne, [
104
+ (i(!0), l(K, null, Y(_.value, (m) => (i(), l("span", {
105
+ key: m.code,
106
+ title: m.displayName
107
+ }, [
108
+ L(B, {
109
+ code: m.code,
110
+ icon: m.icon,
111
+ size: 20
112
+ }, null, 8, ["code", "icon"])
113
+ ], 8, ae))), 128))
114
+ ])
115
+ ], 64)) : g("", !0)
116
+ ])), [
117
+ [r(d), T.value]
118
+ ]),
119
+ u((i(), l("div", re, [
120
+ O("© " + c(b.value), 1)
121
+ ])), [
122
+ [r(d), b.value]
123
+ ])
113
124
  ])
114
125
  ])
115
126
  ], 2));
116
127
  }
117
128
  });
118
129
  export {
119
- pe as default
130
+ fe as default
120
131
  };
121
132
  //# sourceMappingURL=LoginMock2.vue.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LoginMock2.vue.js","sources":["../../../../../src/views/system/config/components/LoginMock.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// 缩小版登录页(880×540 设计尺寸,外面 ScaleToFit 等比缩放)。form-only 只画右侧登录框(440×540),\n// 给「登录方式」页用。Hero 文案、验证码、短信登录入口、第三方按钮、页脚版权都读草稿——\n// 别的分类改了,这里一样跟着变。\nimport { computed } from 'vue'\nimport { useI18n } from 'vue-i18n'\nimport BrandIcon from '#/components/oauth/BrandIcon.vue'\nimport { resolveLoginHero, splitLoginHeroFeatures } from '#/lib/loginHero'\nimport LoginHeroPanel from '#/views/login/components/LoginHeroPanel.vue'\nimport {\n CAPTCHA_TYPE_KEY,\n heroKeys,\n LOGO_KEY,\n SHOW_FEATURES_KEY,\n SMS_LOGIN_KEY,\n SUBTITLE_KEY,\n type LoginLocale,\n} from '../groups'\nimport { enabledKey, useConfigDraft } from '../draft'\nimport { vFlash } from '../flash'\n\nconst props = defineProps<{ locale: LoginLocale; formOnly?: boolean }>()\n\nconst CAPTCHA_SAMPLE: Record<string, string> = { char: 'A7K2', path: 'K9x4', math: '3 + 5 = ?' }\n\nconst { t } = useI18n()\nconst draft = useConfigDraft()\nconst { values } = draft\nconst tr = (key: string) => t(key, {}, { locale: props.locale })\nconst keys = computed(() => heroKeys(props.locale))\n\nconst hero = computed(() =>\n resolveLoginHero(\n {\n headline: values[keys.value.headline] ?? '',\n highlight: values[keys.value.highlight] ?? '',\n features: splitLoginHeroFeatures(values[keys.value.features]),\n },\n {\n headline: `${tr('login.headlinePre')}${tr('login.headlineAccent')}${tr('login.headlinePost')}`,\n highlight: tr('login.headlineAccent'),\n features: [tr('login.featRbac'), tr('login.featScope'), tr('login.featPortal')],\n },\n // 缺省视为开:库里没有这个键时登录页照常显示卖点\n values[SHOW_FEATURES_KEY] !== 'false',\n ),\n)\nconst subtitle = computed(() => values[SUBTITLE_KEY]?.trim() || tr('login.subtitle'))\nconst siteTitle = computed(() => values['sys.site.title']?.trim() || 'SmartAdmin')\nconst copyright = computed(() => values['sys.site.copyright']?.trim() || siteTitle.value)\nconst captchaOn = computed(() => values['sys.security.captcha.enabled'] === 'true')\nconst captchaSample = computed(() => CAPTCHA_SAMPLE[values[CAPTCHA_TYPE_KEY] || 'char'] ?? 'A7K2')\nconst smsOn = computed(() => values[SMS_LOGIN_KEY] === 'true')\nconst oauth = computed(() =>\n draft.providerRows.value.filter(p => p.registered && values[enabledKey(p.code)] === 'true'),\n)\nconst oauthSig = computed(() => oauth.value.map(p => p.code).join(','))\n</script>\n\n<template>\n <div :class=\"['mock', { 'form-only': formOnly }]\">\n <div v-if=\"!formOnly\" v-flash=\"JSON.stringify(hero)\" class=\"hero\">\n <LoginHeroPanel\n :headline=\"hero.headline\"\n :highlight=\"hero.highlight\"\n :subtitle=\"subtitle\"\n :features=\"hero.features\"\n :title=\"siteTitle\"\n :logo=\"values[LOGO_KEY] ?? ''\"\n />\n </div>\n <div class=\"form\">\n <b class=\"welcome\">{{ tr('login.welcome') }}</b>\n <span v-flash=\"subtitle\" class=\"sub\">{{ subtitle }}</span>\n <div v-flash=\"smsOn\" class=\"modes\">\n <span class=\"on\">{{ tr('login.accountLogin') }}</span>\n <span v-if=\"smsOn\" data-testid=\"preview-sms\">{{ tr('login.smsLogin') }}</span>\n </div>\n <i class=\"in\" />\n <i class=\"in\" />\n <div v-if=\"captchaOn\" class=\"captcha\">\n <i class=\"in\" />\n <span>{{ captchaSample }}</span>\n </div>\n <span class=\"go\">{{ tr('login.submit') }}</span>\n <div v-flash=\"oauthSig\" class=\"oauth\" data-testid=\"preview-oauth\">\n <template v-if=\"oauth.length\">\n <div class=\"divider\">{{ t('config.externalAuth.previewOther') }}</div>\n <div class=\"btns\">\n <span v-for=\"p in oauth\" :key=\"p.code\" :title=\"p.displayName\">\n <BrandIcon :code=\"p.code\" :icon=\"p.icon\" :size=\"20\" />\n </span>\n </div>\n </template>\n </div>\n <div v-flash=\"copyright\" class=\"copy\">© {{ copyright }}</div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.mock {\n display: grid;\n grid-template-columns: 1.15fr 1fr;\n width: 880px;\n height: 540px;\n overflow: hidden;\n border-radius: 10px;\n background: var(--color-bg-container);\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12);\n}\n.mock.form-only {\n grid-template-columns: 1fr;\n width: 440px;\n}\n.hero {\n display: flex;\n align-items: center;\n padding: 32px 36px;\n overflow: hidden;\n background:\n radial-gradient(\n 60% 70% at 20% 15%,\n color-mix(in srgb, var(--color-primary) 18%, transparent),\n transparent 72%\n ),\n var(--color-bg-body);\n}\n.hero :deep(.headline) {\n font-size: 30px;\n line-height: 1.3;\n}\n.hero :deep(.bar) {\n margin: 22px 0 16px;\n}\n.hero :deep(.sub) {\n margin: 12px 0 18px;\n}\n.form {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 44px 40px 18px;\n font-size: 13px;\n}\n.welcome {\n font-size: 22px;\n}\n.sub {\n margin: -8px 0 4px;\n border-radius: 6px;\n color: var(--color-text-secondary);\n}\n.modes {\n display: flex;\n gap: 18px;\n border-radius: 6px;\n color: var(--color-text-secondary);\n}\n.modes .on {\n padding-bottom: 3px;\n border-bottom: 2px solid var(--color-primary);\n color: var(--color-text-primary);\n font-weight: 600;\n}\n.in {\n display: block;\n height: 40px;\n border-radius: 8px;\n background: var(--color-fill);\n}\n.captcha {\n display: flex;\n gap: 8px;\n}\n.captcha .in {\n flex: 1;\n}\n.captcha span {\n display: grid;\n place-items: center;\n width: 104px;\n border-radius: 8px;\n font-weight: 700;\n letter-spacing: 1px;\n color: var(--color-text-secondary);\n background: repeating-linear-gradient(\n 45deg,\n var(--color-fill) 0 4px,\n var(--color-bg-body) 4px 8px\n );\n}\n.go {\n display: grid;\n place-items: center;\n height: 42px;\n border-radius: 8px;\n color: #fff;\n background: var(--color-primary);\n font-weight: 600;\n}\n.oauth {\n min-height: 20px;\n border-radius: 8px;\n}\n.divider {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n color: var(--color-text-tertiary);\n}\n.divider::before,\n.divider::after {\n content: '';\n flex: 1;\n border-top: 1px solid var(--color-border);\n}\n.btns {\n display: flex;\n flex-wrap: wrap;\n justify-content: center;\n gap: 12px;\n margin-top: 12px;\n}\n.btns span {\n display: grid;\n place-items: center;\n width: 40px;\n height: 40px;\n border: 1px solid var(--color-border);\n border-radius: 50%;\n}\n.copy {\n margin-top: auto;\n border-radius: 6px;\n text-align: center;\n font-size: 12px;\n color: var(--color-text-tertiary);\n}\n</style>\n"],"names":["props","__props","CAPTCHA_SAMPLE","t","useI18n","draft","useConfigDraft","values","tr","key","keys","computed","heroKeys","hero","resolveLoginHero","splitLoginHeroFeatures","SHOW_FEATURES_KEY","subtitle","_a","SUBTITLE_KEY","siteTitle","copyright","captchaOn","captchaSample","CAPTCHA_TYPE_KEY","smsOn","SMS_LOGIN_KEY","oauth","p","enabledKey","oauthSig","_createElementBlock","_withDirectives","_openBlock","_hoisted_1","_createVNode","LoginHeroPanel","_unref","LOGO_KEY","_createElementVNode","_hoisted_2","_hoisted_3","_toDisplayString","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_Fragment","_hoisted_11","_hoisted_12","_renderList","BrandIcon","_hoisted_14","_createTextVNode"],"mappings":"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"}
1
+ {"version":3,"file":"LoginMock2.vue.js","sources":["../../../../../src/views/system/config/components/LoginMock.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// 缩小版登录页(880×540 设计尺寸,外面 ScaleToFit 等比缩放),画的是双栏形态:左栏品牌区压在柔光色场上,\n// 右栏是毛玻璃登录卡(与真实登录页同一套视觉语言,色场静止不漂移)。form-only 只画登录卡所在的右栏(440×540),\n// 给「登录方式」页用。Hero 文案、验证码、短信登录入口、第三方按钮、页脚版权都读草稿——\n// 别的分类改了,这里一样跟着变。\nimport { computed } from 'vue'\nimport { useI18n } from 'vue-i18n'\nimport BrandIcon from '#/components/oauth/BrandIcon.vue'\nimport { resolveLoginHero, splitLoginHeroFeatures } from '#/lib/loginHero'\nimport LoginHeroPanel from '#/views/login/components/LoginHeroPanel.vue'\nimport {\n CAPTCHA_TYPE_KEY,\n heroKeys,\n LOGO_KEY,\n SHOW_FEATURES_KEY,\n SMS_LOGIN_KEY,\n SUBTITLE_KEY,\n type LoginLocale,\n} from '../groups'\nimport { enabledKey, useConfigDraft } from '../draft'\nimport { vFlash } from '../flash'\n\nconst props = defineProps<{ locale: LoginLocale; formOnly?: boolean }>()\n\nconst CAPTCHA_SAMPLE: Record<string, string> = { char: 'A7K2', path: 'K9x4', math: '3 + 5 = ?' }\n\nconst { t } = useI18n()\nconst draft = useConfigDraft()\nconst { values } = draft\nconst tr = (key: string) => t(key, {}, { locale: props.locale })\nconst keys = computed(() => heroKeys(props.locale))\n\nconst hero = computed(() =>\n resolveLoginHero(\n {\n headline: values[keys.value.headline] ?? '',\n highlight: values[keys.value.highlight] ?? '',\n features: splitLoginHeroFeatures(values[keys.value.features]),\n },\n {\n headline: `${tr('login.headlinePre')}${tr('login.headlineAccent')}${tr('login.headlinePost')}`,\n highlight: tr('login.headlineAccent'),\n features: [tr('login.featRbac'), tr('login.featScope'), tr('login.featPortal')],\n },\n // 缺省视为开:库里没有这个键时登录页照常显示亮点\n values[SHOW_FEATURES_KEY] !== 'false',\n ),\n)\nconst subtitle = computed(() => values[SUBTITLE_KEY]?.trim() || tr('login.subtitle'))\nconst siteTitle = computed(() => values['sys.site.title']?.trim() || 'SmartAdmin')\nconst copyright = computed(() => values['sys.site.copyright']?.trim() || siteTitle.value)\nconst captchaOn = computed(() => values['sys.security.captcha.enabled'] === 'true')\nconst captchaSample = computed(() => CAPTCHA_SAMPLE[values[CAPTCHA_TYPE_KEY] || 'char'] ?? 'A7K2')\nconst smsOn = computed(() => values[SMS_LOGIN_KEY] === 'true')\nconst oauth = computed(() =>\n draft.providerRows.value.filter(p => p.registered && values[enabledKey(p.code)] === 'true'),\n)\nconst oauthSig = computed(() => oauth.value.map(p => p.code).join(','))\n</script>\n\n<template>\n <div :class=\"['mock', { 'form-only': formOnly }]\">\n <div class=\"desk\" aria-hidden=\"true\">\n <i />\n <i />\n <i />\n <i />\n </div>\n <div v-if=\"!formOnly\" v-flash=\"JSON.stringify(hero)\" class=\"hero\">\n <LoginHeroPanel\n :headline=\"hero.headline\"\n :highlight=\"hero.highlight\"\n :subtitle=\"subtitle\"\n :features=\"hero.features\"\n :title=\"siteTitle\"\n :logo=\"values[LOGO_KEY] ?? ''\"\n />\n </div>\n <div class=\"form-wrap\">\n <div class=\"form\">\n <b class=\"welcome\">{{ tr('login.welcome') }}</b>\n <span v-flash=\"subtitle\" class=\"sub\">{{ subtitle }}</span>\n <div v-flash=\"smsOn\" class=\"modes\">\n <span class=\"on\">{{ tr('login.accountLogin') }}</span>\n <span v-if=\"smsOn\" data-testid=\"preview-sms\">{{ tr('login.smsLogin') }}</span>\n </div>\n <i class=\"in\" />\n <i class=\"in\" />\n <div v-if=\"captchaOn\" class=\"captcha\">\n <i class=\"in\" />\n <span>{{ captchaSample }}</span>\n </div>\n <span class=\"go\">{{ tr('login.submit') }}</span>\n <div v-flash=\"oauthSig\" class=\"oauth\" data-testid=\"preview-oauth\">\n <template v-if=\"oauth.length\">\n <div class=\"divider\">{{ t('config.externalAuth.previewOther') }}</div>\n <div class=\"btns\">\n <span v-for=\"p in oauth\" :key=\"p.code\" :title=\"p.displayName\">\n <BrandIcon :code=\"p.code\" :icon=\"p.icon\" :size=\"20\" />\n </span>\n </div>\n </template>\n </div>\n <div v-flash=\"copyright\" class=\"copy\">© {{ copyright }}</div>\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.mock {\n position: relative;\n display: grid;\n grid-template-columns: 1.15fr 1fr;\n width: 880px;\n height: 540px;\n overflow: hidden;\n border-radius: 10px;\n background: var(--desk-base);\n box-shadow: var(--shadow-2);\n}\n.mock.form-only {\n grid-template-columns: 1fr;\n width: 440px;\n}\n/* 色场:和真实登录页同一组 --desk-1..4,预览里不动 */\n.desk {\n position: absolute;\n inset: -20%;\n pointer-events: none;\n}\n.desk i {\n position: absolute;\n display: block;\n border-radius: 50%;\n filter: blur(70px);\n opacity: var(--desk-op);\n}\n.desk i:nth-child(1) {\n left: 2%;\n top: 4%;\n width: 46%;\n height: 62%;\n background: var(--desk-1);\n}\n.desk i:nth-child(2) {\n left: 26%;\n top: 34%;\n width: 44%;\n height: 56%;\n background: var(--desk-2);\n}\n.desk i:nth-child(3) {\n left: 54%;\n top: -6%;\n width: 40%;\n height: 58%;\n background: var(--desk-3);\n}\n.desk i:nth-child(4) {\n left: 62%;\n top: 46%;\n width: 46%;\n height: 62%;\n background: var(--desk-4);\n}\n.hero {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n padding: 32px 36px;\n overflow: hidden;\n}\n.hero :deep(.login-hero-panel) {\n max-width: 330px;\n}\n.hero :deep(.headline) {\n font-size: 28px;\n line-height: 1.3;\n}\n/* 真实登录页的左栏字号更大(logo 22 / 说明 17 / 亮点 16),预览按 880×540 的画布排版,这里把字号钉成预览尺寸 */\n.hero :deep(.logo) {\n margin-bottom: 20px;\n gap: 11px;\n font-size: 18px;\n}\n.hero :deep(.sub) {\n margin: 0 0 18px;\n font-size: 15px;\n}\n.hero :deep(.points) {\n gap: 14px;\n}\n.hero :deep(.points li) {\n gap: 11px;\n font-size: 14.5px;\n}\n.form-wrap {\n position: relative;\n display: grid;\n place-items: center;\n padding: 16px;\n min-height: 0;\n}\n/* 登录卡:毛玻璃,与真实登录页同一套材质 */\n.form {\n display: flex;\n flex-direction: column;\n gap: 10px;\n width: 100%;\n height: 100%;\n padding: 24px 28px 12px;\n overflow: hidden;\n border: 1px solid var(--glass-border);\n border-radius: 22px;\n background: var(--glass-panel);\n box-shadow: var(--glass-shadow);\n font-size: 13px;\n}\n.mock:not(.form-only) .form {\n max-width: 384px;\n}\n.welcome {\n font-size: 22px;\n font-weight: 600;\n letter-spacing: -0.035em;\n color: var(--text-1);\n}\n.sub {\n margin: -6px 0 2px;\n border-radius: 6px;\n color: var(--text-2);\n}\n.modes {\n display: flex;\n gap: 18px;\n border-radius: 6px;\n color: var(--text-2);\n}\n.modes .on {\n padding-bottom: 3px;\n border-bottom: 2px solid var(--signal);\n color: var(--text-1);\n font-weight: 600;\n}\n.in {\n display: block;\n height: 40px;\n border-radius: 11px;\n background: var(--fill);\n}\n.captcha {\n display: flex;\n gap: 8px;\n}\n.captcha .in {\n flex: 1;\n}\n.captcha span {\n display: grid;\n place-items: center;\n width: 104px;\n border-radius: 11px;\n font-weight: 700;\n letter-spacing: 1px;\n color: var(--text-2);\n background: repeating-linear-gradient(45deg, var(--fill) 0 4px, transparent 4px 8px);\n}\n.go {\n display: grid;\n place-items: center;\n height: 42px;\n border-radius: 11px;\n color: #fff;\n background-image: linear-gradient(120deg, var(--signal), var(--login-accent-2));\n box-shadow: 0 10px 26px -10px var(--signal-glow);\n font-weight: 600;\n}\n.oauth {\n min-height: 20px;\n border-radius: 8px;\n}\n.divider {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n color: var(--text-3);\n}\n.divider::before,\n.divider::after {\n content: '';\n flex: 1;\n border-top: 1px solid var(--hairline);\n}\n.btns {\n display: flex;\n flex-wrap: wrap;\n justify-content: center;\n gap: 12px;\n margin-top: 12px;\n}\n/* 与真实登录页一致:只露品牌标,不加底圈 */\n.btns span {\n display: grid;\n place-items: center;\n width: 40px;\n height: 40px;\n}\n.btns span :deep(.oauth-brand-badge) {\n width: 28px;\n height: 28px;\n}\n.copy {\n margin-top: auto;\n border-radius: 6px;\n text-align: center;\n font-size: 12px;\n color: var(--text-3);\n}\n</style>\n"],"names":["props","__props","CAPTCHA_SAMPLE","t","useI18n","draft","useConfigDraft","values","tr","key","keys","computed","heroKeys","hero","resolveLoginHero","splitLoginHeroFeatures","SHOW_FEATURES_KEY","subtitle","_a","SUBTITLE_KEY","siteTitle","copyright","captchaOn","captchaSample","CAPTCHA_TYPE_KEY","smsOn","SMS_LOGIN_KEY","oauth","p","enabledKey","oauthSig","_createElementBlock","_createElementVNode","_withDirectives","_openBlock","_hoisted_1","_createVNode","LoginHeroPanel","_unref","LOGO_KEY","_hoisted_2","_hoisted_3","_hoisted_4","_toDisplayString","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_Fragment","_hoisted_12","_hoisted_13","_renderList","BrandIcon","_hoisted_15","_createTextVNode"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,UAAMA,IAAQC,GAERC,IAAyC,EAAE,MAAM,QAAQ,MAAM,QAAQ,MAAM,YAAA,GAE7E,EAAE,GAAAC,EAAA,IAAMC,EAAA,GACRC,IAAQC,EAAA,GACR,EAAE,QAAAC,MAAWF,GACbG,IAAK,CAACC,MAAgBN,EAAEM,GAAK,CAAA,GAAI,EAAE,QAAQT,EAAM,QAAQ,GACzDU,IAAOC,EAAS,MAAMC,EAASZ,EAAM,MAAM,CAAC,GAE5Ca,IAAOF;AAAA,MAAS,MACpBG;AAAA,QACE;AAAA,UACE,UAAUP,EAAOG,EAAK,MAAM,QAAQ,KAAK;AAAA,UACzC,WAAWH,EAAOG,EAAK,MAAM,SAAS,KAAK;AAAA,UAC3C,UAAUK,EAAuBR,EAAOG,EAAK,MAAM,QAAQ,CAAC;AAAA,QAAA;AAAA,QAE9D;AAAA,UACE,UAAU,GAAGF,EAAG,mBAAmB,CAAC,GAAGA,EAAG,sBAAsB,CAAC,GAAGA,EAAG,oBAAoB,CAAC;AAAA,UAC5F,WAAWA,EAAG,sBAAsB;AAAA,UACpC,UAAU,CAACA,EAAG,gBAAgB,GAAGA,EAAG,iBAAiB,GAAGA,EAAG,kBAAkB,CAAC;AAAA,QAAA;AAAA;AAAA,QAGhFD,EAAOS,CAAiB,MAAM;AAAA,MAAA;AAAA,IAChC,GAEIC,IAAWN,EAAS,MAAA;;AAAM,eAAAO,IAAAX,EAAOY,CAAY,MAAnB,gBAAAD,EAAsB,WAAUV,EAAG,gBAAgB;AAAA,KAAC,GAC9EY,IAAYT,EAAS,MAAA;;AAAM,eAAAO,IAAAX,EAAO,gBAAgB,MAAvB,gBAAAW,EAA0B,WAAU;AAAA,KAAY,GAC3EG,IAAYV,EAAS;;AAAM,eAAAO,IAAAX,EAAO,oBAAoB,MAA3B,gBAAAW,EAA8B,WAAUE,EAAU;AAAA,KAAK,GAClFE,IAAYX,EAAS,MAAMJ,EAAO,8BAA8B,MAAM,MAAM,GAC5EgB,IAAgBZ,EAAS,MAAMT,EAAeK,EAAOiB,CAAgB,KAAK,MAAM,KAAK,MAAM,GAC3FC,IAAQd,EAAS,MAAMJ,EAAOmB,CAAa,MAAM,MAAM,GACvDC,IAAQhB;AAAA,MAAS,MACrBN,EAAM,aAAa,MAAM,OAAO,CAAAuB,MAAKA,EAAE,cAAcrB,EAAOsB,EAAWD,EAAE,IAAI,CAAC,MAAM,MAAM;AAAA,IAAA,GAEtFE,IAAWnB,EAAS,MAAMgB,EAAM,MAAM,IAAI,CAAAC,MAAKA,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC;2BAIpEG,EA6CM,OAAA;AAAA,MA7CA,iCAA+B9B,EAAA,UAAQ,CAAA;AAAA,IAAA;sBAC3C+B,EAKM,OAAA;AAAA,QALD,OAAM;AAAA,QAAO,eAAY;AAAA,MAAA;QAC5BA,EAAK,GAAA;AAAA,QACLA,EAAK,GAAA;AAAA,QACLA,EAAK,GAAA;AAAA,QACLA,EAAK,GAAA;AAAA,MAAA;MAEK/B,EAAA,uBAAZgC,GAAAC,KAAAH,EASM,OATNI,GASM;AAAA,QARJC,EAOEC,GAAA;AAAA,UANC,UAAUxB,EAAA,MAAK;AAAA,UACf,WAAWA,EAAA,MAAK;AAAA,UAChB,UAAUI,EAAA;AAAA,UACV,UAAUJ,EAAA,MAAK;AAAA,UACf,OAAOO,EAAA;AAAA,UACP,MAAMkB,EAAA/B,CAAA,EAAO+B,EAAAC,CAAA,CAAQ,KAAA;AAAA,QAAA;;eAPK,KAAK,UAAU1B,EAAA,KAAI,CAAA;AAAA,MAAA;MAUlDmB,EA2BM,OA3BNQ,GA2BM;AAAA,QA1BJR,EAyBM,OAzBNS,GAyBM;AAAA,UAxBJT,EAAgD,KAAhDU,GAAgDC,EAA1BnC,EAAE,eAAA,CAAA,GAAA,CAAA;AAAA,UACxByB,GAAAC,EAAA,GAAAH,EAA0D,QAA1Da,GAA0D;AAAA,gBAAlB3B,EAAA,KAAQ,GAAA,CAAA;AAAA,UAAA;mBAAjCA,EAAA,KAAQ;AAAA,UAAA;UACvBgB,GAAAC,EAAA,GAAAH,EAGM,OAHNc,GAGM;AAAA,YAFJb,EAAsD,QAAtDc,IAAsDH,EAAlCnC,EAAE,oBAAA,CAAA,GAAA,CAAA;AAAA,YACViB,EAAA,cAAZM,EAA8E,QAA9EgB,IAA8EJ,EAA9BnC,EAAE,gBAAA,CAAA,GAAA,CAAA;;mBAFtCiB,EAAA,KAAK;AAAA,UAAA;0BAInBO,EAAgB,KAAA,EAAb,OAAM,KAAA,GAAI,MAAA,EAAA;AAAA,0BACbA,EAAgB,KAAA,EAAb,OAAM,KAAA,GAAI,MAAA,EAAA;AAAA,UACFV,EAAA,SAAXY,EAAA,GAAAH,EAGM,OAHNiB,IAGM;AAAA,4BAFJhB,EAAgB,KAAA,EAAb,OAAM,KAAA,GAAI,MAAA,EAAA;AAAA,YACbA,EAAgC,gBAAvBT,EAAA,KAAa,GAAA,CAAA;AAAA,UAAA;UAExBS,EAAgD,QAAhDiB,IAAgDN,EAA5BnC,EAAE,cAAA,CAAA,GAAA,CAAA;AAAA,UACtByB,GAAAC,EAAA,GAAAH,EASM,OATNmB,IASM;AAAA,YARYvB,EAAA,MAAM,eAAtBI,EAOWoB,GAAA,EAAA,KAAA,KAAA;AAAA,cANTnB,EAAsE,OAAtEoB,IAAsET,EAA9CL,EAAAnC,CAAA,EAAC,kCAAA,CAAA,GAAA,CAAA;AAAA,cACzB6B,EAIM,OAJNqB,IAIM;AAAA,wBAHJtB,EAEOoB,GAAA,MAAAG,EAFW3B,EAAA,OAAK,CAAVC,YAAbG,EAEO,QAAA;AAAA,kBAFmB,KAAKH,EAAE;AAAA,kBAAO,OAAOA,EAAE;AAAA,gBAAA;kBAC/CQ,EAAsDmB,GAAA;AAAA,oBAA1C,MAAM3B,EAAE;AAAA,oBAAO,MAAMA,EAAE;AAAA,oBAAO,MAAM;AAAA,kBAAA;;;;;mBAL1CE,EAAA,KAAQ;AAAA,UAAA;UAUtBG,GAAAC,EAAA,GAAAH,EAA6D,OAA7DyB,IAA6D;AAAA,YAAvBC,EAAA,SAAKpC,EAAA,KAAS,GAAA,CAAA;AAAA,UAAA;mBAAtCA,EAAA,KAAS;AAAA,UAAA;;;;;;"}
@@ -1,7 +1,7 @@
1
1
  import o from "./LogoCropper2.vue.js";
2
2
  /* empty css */
3
3
  import r from "../../../../_virtual/_plugin-vue_export-helper.js";
4
- const m = /* @__PURE__ */ r(o, [["__scopeId", "data-v-a92c4a40"]]);
4
+ const m = /* @__PURE__ */ r(o, [["__scopeId", "data-v-f4dc6118"]]);
5
5
  export {
6
6
  m as default
7
7
  };
@@ -1 +1 @@
1
- {"version":3,"file":"LogoCropper2.vue.js","sources":["../../../../../src/views/system/config/components/LogoCropper.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// 正方形 Logo 裁剪:拖动平移、滑块或滚轮缩放,导出 256×256 PNG。\n// 只需要这三件事,所以不引裁剪库;几何计算在 lib/logoCrop.ts(有单测)。\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\nimport { NSlider } from 'naive-ui'\nimport { useI18n } from 'vue-i18n'\nimport { clampOffset, coverScale, sourceRect } from '#/lib/logoCrop'\n\nconst props = defineProps<{ file: File }>()\n\n/** 视口边长与取景框边长(px) */\nconst VIEW = 280\nconst FRAME = 232\nconst OUTPUT = 256\n\nconst { t } = useI18n()\nconst img = ref<HTMLImageElement | null>(null)\nconst url = ref('')\nconst natural = ref({ w: 1, h: 1 })\nconst zoom = ref(1)\nconst offset = ref({ x: 0, y: 0 })\n\nconst base = computed(() => coverScale(natural.value.w, natural.value.h, FRAME))\nconst scale = computed(() => base.value * zoom.value)\nconst state = computed(() => ({\n width: natural.value.w,\n height: natural.value.h,\n frame: FRAME,\n scale: scale.value,\n ...offset.value,\n}))\nconst imgStyle = computed(() => ({\n width: `${natural.value.w * scale.value}px`,\n height: `${natural.value.h * scale.value}px`,\n transform: `translate(calc(-50% + ${offset.value.x}px), calc(-50% + ${offset.value.y}px))`,\n}))\n\nwatch(\n () => props.file,\n file => {\n if (url.value) URL.revokeObjectURL(url.value)\n url.value = URL.createObjectURL(file)\n zoom.value = 1\n offset.value = { x: 0, y: 0 }\n },\n { immediate: true },\n)\nonBeforeUnmount(() => URL.revokeObjectURL(url.value))\n\nfunction onLoad(e: Event) {\n const el = e.target as HTMLImageElement\n natural.value = { w: el.naturalWidth || 1, h: el.naturalHeight || 1 }\n}\n\n// 缩放后重新收边,保证取景框里始终是图\nwatch(zoom, () => {\n offset.value = clampOffset(state.value)\n})\n\nlet drag: { x: number; y: number; ox: number; oy: number } | null = null\nfunction onPointerDown(e: PointerEvent) {\n ;(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId)\n drag = { x: e.clientX, y: e.clientY, ox: offset.value.x, oy: offset.value.y }\n}\nfunction onPointerMove(e: PointerEvent) {\n if (!drag) return\n offset.value = clampOffset({\n ...state.value,\n x: drag.ox + e.clientX - drag.x,\n y: drag.oy + e.clientY - drag.y,\n })\n}\nfunction onPointerUp() {\n drag = null\n}\n/** 键盘替代拖动:方向键平移(Shift 大步),+ / - 缩放 */\nfunction onKey(e: KeyboardEvent) {\n const step = e.shiftKey ? 20 : 5\n const d: Record<string, [number, number]> = {\n ArrowLeft: [-step, 0],\n ArrowRight: [step, 0],\n ArrowUp: [0, -step],\n ArrowDown: [0, step],\n }\n if (d[e.key]) {\n e.preventDefault()\n offset.value = clampOffset({\n ...state.value,\n x: offset.value.x + d[e.key][0],\n y: offset.value.y + d[e.key][1],\n })\n } else if (e.key === '+' || e.key === '=') {\n e.preventDefault()\n zoom.value = Math.min(4, zoom.value + 0.1)\n } else if (e.key === '-') {\n e.preventDefault()\n zoom.value = Math.max(1, zoom.value - 0.1)\n }\n}\n\nfunction onWheel(e: WheelEvent) {\n zoom.value = Math.min(4, Math.max(1, zoom.value - e.deltaY * 0.002))\n}\n\n/** 按当前取景导出 PNG。 */\nfunction crop(): Promise<Blob> {\n const canvas = document.createElement('canvas')\n canvas.width = canvas.height = OUTPUT\n const ctx = canvas.getContext('2d')\n if (!ctx || !img.value) return Promise.reject(new Error('canvas unavailable'))\n const { sx, sy, size } = sourceRect(state.value)\n ctx.imageSmoothingQuality = 'high'\n ctx.drawImage(img.value, sx, sy, size, size, 0, 0, OUTPUT, OUTPUT)\n return new Promise((resolve, reject) =>\n canvas.toBlob(b => (b ? resolve(b) : reject(new Error('toBlob failed'))), 'image/png'),\n )\n}\n\ndefineExpose({ crop })\n</script>\n\n<template>\n <div class=\"cropper\">\n <div\n class=\"viewport\"\n :style=\"{ width: `${VIEW}px`, height: `${VIEW}px` }\"\n tabindex=\"0\"\n role=\"application\"\n :aria-label=\"t('config.logo.cropTip')\"\n @keydown=\"onKey\"\n @pointerdown=\"onPointerDown\"\n @pointermove=\"onPointerMove\"\n @pointerup=\"onPointerUp\"\n @pointercancel=\"onPointerUp\"\n @wheel.prevent=\"onWheel\"\n >\n <img ref=\"img\" :src=\"url\" :style=\"imgStyle\" alt=\"\" draggable=\"false\" @load=\"onLoad\" />\n <div class=\"frame\" :style=\"{ width: `${FRAME}px`, height: `${FRAME}px` }\" />\n </div>\n <div class=\"zoom\">\n <span>{{ t('config.logo.zoom') }}</span>\n <n-slider v-model:value=\"zoom\" :min=\"1\" :max=\"4\" :step=\"0.01\" :tooltip=\"false\" />\n </div>\n <p class=\"tip\">{{ t('config.logo.cropTip') }}</p>\n </div>\n</template>\n\n<style scoped>\n.cropper {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n}\n.viewport {\n position: relative;\n overflow: hidden;\n border-radius: var(--radius-lg);\n cursor: grab;\n touch-action: none;\n user-select: none;\n background: repeating-conic-gradient(#e5e7eb 0 25%, #fff 0 50%) 0 0 / 16px 16px;\n}\n.viewport:active {\n cursor: grabbing;\n}\n.viewport:focus-visible {\n outline: 2px solid var(--color-primary);\n outline-offset: 3px;\n}\n.viewport img {\n position: absolute;\n left: 50%;\n top: 50%;\n max-width: none;\n pointer-events: none;\n}\n.frame {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n border: 2px solid #fff;\n border-radius: 12px;\n box-shadow: 0 0 0 999px rgba(0, 0, 0, 0.45);\n pointer-events: none;\n}\n.zoom {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 280px;\n font-size: var(--font-size-sm);\n color: var(--color-text-tertiary);\n}\n.zoom span {\n flex: none;\n}\n.tip {\n margin: 0;\n font-size: var(--font-size-sm);\n color: var(--color-text-tertiary);\n}\n</style>\n"],"names":["VIEW","FRAME","OUTPUT","props","__props","t","useI18n","img","ref","url","natural","zoom","offset","base","computed","coverScale","scale","state","imgStyle","watch","file","onBeforeUnmount","onLoad","el","clampOffset","drag","onPointerDown","onPointerMove","onPointerUp","onKey","step","d","onWheel","crop","canvas","ctx","sx","sy","size","sourceRect","resolve","reject","b","__expose","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_normalizeStyle","_unref","_hoisted_4","_createVNode","NSlider","$event","_hoisted_5","_toDisplayString"],"mappings":"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"}
1
+ {"version":3,"file":"LogoCropper2.vue.js","sources":["../../../../../src/views/system/config/components/LogoCropper.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// 正方形 Logo 裁剪:拖动平移、滑块或滚轮缩放,导出 256×256 PNG。\n// 只需要这三件事,所以不引裁剪库;几何计算在 lib/logoCrop.ts(有单测)。\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\nimport { NSlider } from 'naive-ui'\nimport { useI18n } from 'vue-i18n'\nimport { clampOffset, coverScale, sourceRect } from '#/lib/logoCrop'\n\nconst props = defineProps<{ file: File }>()\n\n/** 视口边长与取景框边长(px) */\nconst VIEW = 280\nconst FRAME = 232\nconst OUTPUT = 256\n\nconst { t } = useI18n()\nconst img = ref<HTMLImageElement | null>(null)\nconst url = ref('')\nconst natural = ref({ w: 1, h: 1 })\nconst zoom = ref(1)\nconst offset = ref({ x: 0, y: 0 })\n\nconst base = computed(() => coverScale(natural.value.w, natural.value.h, FRAME))\nconst scale = computed(() => base.value * zoom.value)\nconst state = computed(() => ({\n width: natural.value.w,\n height: natural.value.h,\n frame: FRAME,\n scale: scale.value,\n ...offset.value,\n}))\nconst imgStyle = computed(() => ({\n width: `${natural.value.w * scale.value}px`,\n height: `${natural.value.h * scale.value}px`,\n transform: `translate(calc(-50% + ${offset.value.x}px), calc(-50% + ${offset.value.y}px))`,\n}))\n\nwatch(\n () => props.file,\n file => {\n if (url.value) URL.revokeObjectURL(url.value)\n url.value = URL.createObjectURL(file)\n zoom.value = 1\n offset.value = { x: 0, y: 0 }\n },\n { immediate: true },\n)\nonBeforeUnmount(() => URL.revokeObjectURL(url.value))\n\nfunction onLoad(e: Event) {\n const el = e.target as HTMLImageElement\n natural.value = { w: el.naturalWidth || 1, h: el.naturalHeight || 1 }\n}\n\n// 缩放后重新收边,保证取景框里始终是图\nwatch(zoom, () => {\n offset.value = clampOffset(state.value)\n})\n\nlet drag: { x: number; y: number; ox: number; oy: number } | null = null\nfunction onPointerDown(e: PointerEvent) {\n ;(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId)\n drag = { x: e.clientX, y: e.clientY, ox: offset.value.x, oy: offset.value.y }\n}\nfunction onPointerMove(e: PointerEvent) {\n if (!drag) return\n offset.value = clampOffset({\n ...state.value,\n x: drag.ox + e.clientX - drag.x,\n y: drag.oy + e.clientY - drag.y,\n })\n}\nfunction onPointerUp() {\n drag = null\n}\n/** 键盘替代拖动:方向键平移(Shift 大步),+ / - 缩放 */\nfunction onKey(e: KeyboardEvent) {\n const step = e.shiftKey ? 20 : 5\n const d: Record<string, [number, number]> = {\n ArrowLeft: [-step, 0],\n ArrowRight: [step, 0],\n ArrowUp: [0, -step],\n ArrowDown: [0, step],\n }\n if (d[e.key]) {\n e.preventDefault()\n offset.value = clampOffset({\n ...state.value,\n x: offset.value.x + d[e.key][0],\n y: offset.value.y + d[e.key][1],\n })\n } else if (e.key === '+' || e.key === '=') {\n e.preventDefault()\n zoom.value = Math.min(4, zoom.value + 0.1)\n } else if (e.key === '-') {\n e.preventDefault()\n zoom.value = Math.max(1, zoom.value - 0.1)\n }\n}\n\nfunction onWheel(e: WheelEvent) {\n zoom.value = Math.min(4, Math.max(1, zoom.value - e.deltaY * 0.002))\n}\n\n/** 按当前取景导出 PNG。 */\nfunction crop(): Promise<Blob> {\n const canvas = document.createElement('canvas')\n canvas.width = canvas.height = OUTPUT\n const ctx = canvas.getContext('2d')\n if (!ctx || !img.value) return Promise.reject(new Error('canvas unavailable'))\n const { sx, sy, size } = sourceRect(state.value)\n ctx.imageSmoothingQuality = 'high'\n ctx.drawImage(img.value, sx, sy, size, size, 0, 0, OUTPUT, OUTPUT)\n return new Promise((resolve, reject) =>\n canvas.toBlob(b => (b ? resolve(b) : reject(new Error('toBlob failed'))), 'image/png'),\n )\n}\n\ndefineExpose({ crop })\n</script>\n\n<template>\n <div class=\"cropper\">\n <div\n class=\"viewport\"\n :style=\"{ width: `${VIEW}px`, height: `${VIEW}px` }\"\n tabindex=\"0\"\n role=\"application\"\n :aria-label=\"t('config.logo.cropTip')\"\n @keydown=\"onKey\"\n @pointerdown=\"onPointerDown\"\n @pointermove=\"onPointerMove\"\n @pointerup=\"onPointerUp\"\n @pointercancel=\"onPointerUp\"\n @wheel.prevent=\"onWheel\"\n >\n <img ref=\"img\" :src=\"url\" :style=\"imgStyle\" alt=\"\" draggable=\"false\" @load=\"onLoad\" />\n <div class=\"frame\" :style=\"{ width: `${FRAME}px`, height: `${FRAME}px` }\" />\n </div>\n <div class=\"zoom\">\n <span>{{ t('config.logo.zoom') }}</span>\n <n-slider v-model:value=\"zoom\" :min=\"1\" :max=\"4\" :step=\"0.01\" :tooltip=\"false\" />\n </div>\n <p class=\"tip\">{{ t('config.logo.cropTip') }}</p>\n </div>\n</template>\n\n<style scoped>\n.cropper {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n}\n.viewport {\n position: relative;\n max-width: 100%;\n overflow: hidden;\n border-radius: 14px;\n cursor: grab;\n touch-action: none;\n user-select: none;\n background: repeating-conic-gradient(var(--glass-strong) 0 25%, var(--fill) 0 50%) 0 0 / 16px 16px;\n}\n.viewport:active {\n cursor: grabbing;\n}\n.viewport:focus-visible {\n outline: 2px solid var(--signal);\n outline-offset: 3px;\n}\n.viewport img {\n position: absolute;\n left: 50%;\n top: 50%;\n max-width: none;\n pointer-events: none;\n}\n.frame {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n border: 2px solid #fff;\n border-radius: var(--radius-lg);\n box-shadow: 0 0 0 999px rgba(0, 0, 0, 0.45);\n pointer-events: none;\n}\n.zoom {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 280px;\n max-width: 100%;\n font-size: 13px;\n color: var(--text-3);\n}\n.zoom span {\n flex: none;\n}\n.tip {\n margin: 0;\n font-size: 13px;\n color: var(--text-3);\n text-align: center;\n}\n</style>\n"],"names":["VIEW","FRAME","OUTPUT","props","__props","t","useI18n","img","ref","url","natural","zoom","offset","base","computed","coverScale","scale","state","imgStyle","watch","file","onBeforeUnmount","onLoad","el","clampOffset","drag","onPointerDown","onPointerMove","onPointerUp","onKey","step","d","onWheel","crop","canvas","ctx","sx","sy","size","sourceRect","resolve","reject","b","__expose","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_normalizeStyle","_unref","_hoisted_4","_createVNode","NSlider","$event","_hoisted_5","_toDisplayString"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import o from "./LogoEditor2.vue.js";
2
2
  /* empty css */
3
3
  import t from "../../../../_virtual/_plugin-vue_export-helper.js";
4
- const p = /* @__PURE__ */ t(o, [["__scopeId", "data-v-cec63628"]]);
4
+ const m = /* @__PURE__ */ t(o, [["__scopeId", "data-v-deb34bae"]]);
5
5
  export {
6
- p as default
6
+ m as default
7
7
  };
8
8
  //# sourceMappingURL=LogoEditor.vue.js.map
@@ -1,4 +1,4 @@
1
- import { defineComponent as I, computed as w, ref as i, openBlock as k, createElementBlock as j, createVNode as r, unref as l, withCtx as s, createElementVNode as u, withModifiers as x, normalizeClass as z, toDisplayString as v, createBlock as A, createCommentVNode as F, createTextVNode as U } from "vue";
1
+ import { defineComponent as I, computed as w, ref as i, openBlock as C, createElementBlock as j, createVNode as r, unref as l, withCtx as s, createElementVNode as u, withModifiers as k, normalizeClass as z, toDisplayString as v, createBlock as A, createCommentVNode as F, createTextVNode as U } from "vue";
2
2
  import { useMessage as R, NDropdown as $, NModal as L, NButton as N, NInput as G } from "naive-ui";
3
3
  import { useI18n as H } from "vue-i18n";
4
4
  import K from "../../../../components/SmartLogo.vue.js";
@@ -9,10 +9,7 @@ import q from "./LogoCropper.vue.js";
9
9
  const J = { class: "logo-edit" }, Q = ["aria-label"], Z = {
10
10
  class: "ov",
11
11
  "aria-hidden": "true"
12
- }, ee = { class: "dlg-foot" }, oe = {
13
- class: "cfg-hint",
14
- style: { margin: "8px 0 0" }
15
- }, D = 5, ce = /* @__PURE__ */ I({
12
+ }, ee = { class: "dlg-foot" }, oe = { class: "url-hint" }, D = 5, ce = /* @__PURE__ */ I({
16
13
  __name: "LogoEditor",
17
14
  setup(te) {
18
15
  const P = ["image/png", "image/jpeg", "image/webp"], { t } = H(), p = R(), E = W(), c = Y(), g = w(() => c.values[X] ?? ""), m = w(() => E.hasPerm("POST:/api/v1/sys/config/logo")), _ = i(null), f = i(!1), a = i(null), b = i(null), h = i(!1), y = i(!1), d = i(""), O = w(() => {
@@ -23,7 +20,7 @@ const J = { class: "logo-edit" }, Q = ["aria-label"], Z = {
23
20
  var o;
24
21
  e === "upload" ? (o = _.value) == null || o.click() : e === "url" ? (d.value = g.value.startsWith("blob:") ? "" : g.value, y.value = !0) : e === "remove" && c.setPendingLogo(null, "");
25
22
  }
26
- function C(e) {
23
+ function x(e) {
27
24
  if (e) {
28
25
  if (!P.includes(e.type)) return p.warning(t("config.logo.badType"));
29
26
  if (e.size > D * 1024 * 1024)
@@ -34,11 +31,11 @@ const J = { class: "logo-edit" }, Q = ["aria-label"], Z = {
34
31
  function T(e) {
35
32
  var n;
36
33
  const o = e.target;
37
- C((n = o.files) == null ? void 0 : n[0]), o.value = "";
34
+ x((n = o.files) == null ? void 0 : n[0]), o.value = "";
38
35
  }
39
36
  function B(e) {
40
37
  var o;
41
- f.value = !1, m.value && C((o = e.dataTransfer) == null ? void 0 : o.files[0]);
38
+ f.value = !1, m.value && x((o = e.dataTransfer) == null ? void 0 : o.files[0]);
42
39
  }
43
40
  async function M() {
44
41
  if (b.value) {
@@ -59,7 +56,7 @@ const J = { class: "logo-edit" }, Q = ["aria-label"], Z = {
59
56
  return p.warning(t("config.logo.badUrl")), !1;
60
57
  c.setPendingLogo(null, e);
61
58
  }
62
- return (e, o) => (k(), j("div", J, [
59
+ return (e, o) => (C(), j("div", J, [
63
60
  r(l($), {
64
61
  trigger: "click",
65
62
  options: O.value,
@@ -73,9 +70,9 @@ const J = { class: "logo-edit" }, Q = ["aria-label"], Z = {
73
70
  "aria-label": l(t)("config.logo.edit"),
74
71
  "aria-haspopup": "menu",
75
72
  "data-testid": "logo-box",
76
- onDragover: o[0] || (o[0] = x((n) => f.value = m.value, ["prevent"])),
73
+ onDragover: o[0] || (o[0] = k((n) => f.value = m.value, ["prevent"])),
77
74
  onDragleave: o[1] || (o[1] = (n) => f.value = !1),
78
- onDrop: x(B, ["prevent"])
75
+ onDrop: k(B, ["prevent"])
79
76
  }, [
80
77
  r(K, {
81
78
  size: 40,
@@ -99,7 +96,7 @@ const J = { class: "logo-edit" }, Q = ["aria-label"], Z = {
99
96
  show: !!a.value,
100
97
  preset: "card",
101
98
  title: l(t)("config.logo.cropTitle"),
102
- style: { width: "360px" },
99
+ style: { width: "min(360px, calc(100vw - 24px))" },
103
100
  "mask-closable": !1,
104
101
  "onUpdate:show": o[3] || (o[3] = (n) => !n && (a.value = null))
105
102
  }, {
@@ -126,7 +123,7 @@ const J = { class: "logo-edit" }, Q = ["aria-label"], Z = {
126
123
  ])
127
124
  ]),
128
125
  default: s(() => [
129
- a.value ? (k(), A(q, {
126
+ a.value ? (C(), A(q, {
130
127
  key: 0,
131
128
  ref_key: "cropper",
132
129
  ref: b,
@@ -142,6 +139,7 @@ const J = { class: "logo-edit" }, Q = ["aria-label"], Z = {
142
139
  title: l(t)("config.logo.useUrl"),
143
140
  "positive-text": l(t)("common.confirm"),
144
141
  "negative-text": l(t)("common.cancel"),
142
+ style: { width: "min(420px, calc(100vw - 24px))" },
145
143
  onPositiveClick: V
146
144
  }, {
147
145
  default: s(() => [
@@ -1 +1 @@
1
- {"version":3,"file":"LogoEditor2.vue.js","sources":["../../../../../src/views/system/config/components/LogoEditor.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// Logo 编辑,仿 GitHub 换头像:点方块里的当前 Logo 弹出菜单 → 上传新图片(也可直接拖进方块)/\n// 使用图片链接 / 移除。上传的图先裁成正方形,只进草稿做预览,点底部「保存」才真正上传。\nimport { computed, ref } from 'vue'\nimport { NButton, NDropdown, NInput, NModal, useMessage, type DropdownOption } from 'naive-ui'\nimport { useI18n } from 'vue-i18n'\nimport SmartLogo from '#/components/SmartLogo.vue'\nimport { useAuthStore } from '#/stores/auth'\nimport { LOGO_KEY } from '../groups'\nimport { useConfigDraft } from '../draft'\nimport LogoCropper from './LogoCropper.vue'\n\nconst ACCEPT = ['image/png', 'image/jpeg', 'image/webp']\n/** 裁剪前原图上限;裁完导出 256×256 PNG,远小于后端 1 MB 的限制 */\nconst MAX_SOURCE_MB = 5\n\nconst { t } = useI18n()\nconst message = useMessage()\nconst auth = useAuthStore()\nconst draft = useConfigDraft()\nconst logo = computed(() => draft.values[LOGO_KEY] ?? '')\nconst canUpload = computed(() => auth.hasPerm('POST:/api/v1/sys/config/logo'))\n\nconst fileInput = ref<HTMLInputElement | null>(null)\nconst dragging = ref(false)\nconst cropFile = ref<File | null>(null)\nconst cropper = ref<InstanceType<typeof LogoCropper> | null>(null)\nconst cropping = ref(false)\nconst urlOpen = ref(false)\nconst urlValue = ref('')\n\nconst options = computed<DropdownOption[]>(() => {\n const list: DropdownOption[] = []\n if (canUpload.value) list.push({ key: 'upload', label: t('config.logo.upload') })\n list.push({ key: 'url', label: t('config.logo.useUrl') })\n if (logo.value)\n list.push({ key: 'remove', label: t('config.logo.remove'), props: { class: 'logo-remove' } })\n return list\n})\n\nfunction onSelect(key: string) {\n if (key === 'upload') fileInput.value?.click()\n else if (key === 'url') {\n urlValue.value = logo.value.startsWith('blob:') ? '' : logo.value\n urlOpen.value = true\n } else if (key === 'remove') draft.setPendingLogo(null, '')\n}\n\nfunction pick(file: File | undefined) {\n if (!file) return\n if (!ACCEPT.includes(file.type)) return message.warning(t('config.logo.badType'))\n if (file.size > MAX_SOURCE_MB * 1024 * 1024)\n return message.warning(t('config.logo.tooLarge', { mb: MAX_SOURCE_MB }))\n cropFile.value = file\n}\n\nfunction onFileChange(e: Event) {\n const input = e.target as HTMLInputElement\n pick(input.files?.[0])\n input.value = '' // 同一张图可以再选一次\n}\n\nfunction onDrop(e: DragEvent) {\n dragging.value = false\n if (canUpload.value) pick(e.dataTransfer?.files[0])\n}\n\nasync function applyCrop() {\n if (!cropper.value) return\n cropping.value = true\n try {\n const blob = await cropper.value.crop()\n draft.setPendingLogo(blob, URL.createObjectURL(blob))\n cropFile.value = null\n } catch {\n message.error(t('config.logo.cropFailed'))\n } finally {\n cropping.value = false\n }\n}\n\nfunction applyUrl() {\n const v = urlValue.value.trim()\n // 只收 http(s) 绝对地址或站内路径:javascript: 之类的伪协议不能进 <img src>/<link href>\n if (v && !/^(https?:\\/\\/|\\/)/i.test(v)) {\n message.warning(t('config.logo.badUrl'))\n return false\n }\n draft.setPendingLogo(null, v)\n}\n</script>\n\n<template>\n <div class=\"logo-edit\">\n <n-dropdown trigger=\"click\" :options=\"options\" placement=\"bottom-end\" @select=\"onSelect\">\n <button\n type=\"button\"\n :class=\"['logo-box', { dragging }]\"\n :aria-label=\"t('config.logo.edit')\"\n aria-haspopup=\"menu\"\n data-testid=\"logo-box\"\n @dragover.prevent=\"dragging = canUpload\"\n @dragleave=\"dragging = false\"\n @drop.prevent=\"onDrop\"\n >\n <SmartLogo :size=\"40\" :src=\"logo\" />\n <span class=\"ov\" aria-hidden=\"true\">{{ t('common.edit') }}</span>\n </button>\n </n-dropdown>\n <input\n ref=\"fileInput\"\n type=\"file\"\n accept=\"image/png,image/jpeg,image/webp\"\n hidden\n data-testid=\"logo-file\"\n @change=\"onFileChange\"\n />\n\n <n-modal\n :show=\"!!cropFile\"\n preset=\"card\"\n :title=\"t('config.logo.cropTitle')\"\n style=\"width: 360px\"\n :mask-closable=\"false\"\n @update:show=\"v => !v && (cropFile = null)\"\n >\n <LogoCropper v-if=\"cropFile\" ref=\"cropper\" :file=\"cropFile\" />\n <template #footer>\n <div class=\"dlg-foot\">\n <n-button @click=\"cropFile = null\">{{ t('common.cancel') }}</n-button>\n <n-button type=\"primary\" :loading=\"cropping\" @click=\"applyCrop\">\n {{ t('config.logo.apply') }}\n </n-button>\n </div>\n </template>\n </n-modal>\n\n <n-modal\n v-model:show=\"urlOpen\"\n preset=\"dialog\"\n :title=\"t('config.logo.useUrl')\"\n :positive-text=\"t('common.confirm')\"\n :negative-text=\"t('common.cancel')\"\n @positive-click=\"applyUrl\"\n >\n <n-input v-model:value=\"urlValue\" placeholder=\"https://cdn.example.com/logo.png\" />\n <p class=\"cfg-hint\" style=\"margin: 8px 0 0\">{{ t('config.logo.urlHint') }}</p>\n </n-modal>\n </div>\n</template>\n\n<style scoped>\n.logo-box {\n position: relative;\n display: grid;\n place-items: center;\n width: 56px;\n height: 56px;\n padding: 0;\n overflow: hidden;\n border: 0;\n border-radius: 14px;\n background: var(--color-fill);\n cursor: pointer;\n}\n.logo-box:focus-visible {\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n}\n.logo-box.dragging {\n box-shadow: inset 0 0 0 2px var(--color-primary);\n}\n/* 悬停或聚焦时底部浮出「编辑」,和系统设置里换头像一样 */\n.ov {\n position: absolute;\n inset: auto 0 0;\n padding: 2px 0;\n font-size: 10px;\n color: #fff;\n background: rgba(0, 0, 0, 0.5);\n opacity: 0;\n transition: opacity 0.15s;\n}\n.logo-box:hover .ov,\n.logo-box:focus-visible .ov {\n opacity: 1;\n}\n.dlg-foot {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n:global(.logo-remove) {\n color: var(--color-danger);\n}\n</style>\n"],"names":["MAX_SOURCE_MB","ACCEPT","useI18n","message","useMessage","auth","useAuthStore","draft","useConfigDraft","logo","computed","LOGO_KEY","canUpload","fileInput","ref","dragging","cropFile","cropper","cropping","urlOpen","urlValue","options","list","onSelect","key","_a","pick","file","onFileChange","input","onDrop","applyCrop","blob","applyUrl","v","_openBlock","_createElementBlock","_hoisted_1","_createVNode","_unref","NDropdown","_createElementVNode","_cache","_withModifiers","$event","SmartLogo","_hoisted_3","_toDisplayString","NModal","_hoisted_4","NButton","_createBlock","LogoCropper","NInput","_hoisted_5"],"mappings":"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"}
1
+ {"version":3,"file":"LogoEditor2.vue.js","sources":["../../../../../src/views/system/config/components/LogoEditor.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// Logo 编辑,仿 GitHub 换头像:点方块里的当前 Logo 弹出菜单 → 上传新图片(也可直接拖进方块)/\n// 使用图片链接 / 移除。上传的图先裁成正方形,只进草稿做预览,点底部「保存」才真正上传。\nimport { computed, ref } from 'vue'\nimport { NButton, NDropdown, NInput, NModal, useMessage, type DropdownOption } from 'naive-ui'\nimport { useI18n } from 'vue-i18n'\nimport SmartLogo from '#/components/SmartLogo.vue'\nimport { useAuthStore } from '#/stores/auth'\nimport { LOGO_KEY } from '../groups'\nimport { useConfigDraft } from '../draft'\nimport LogoCropper from './LogoCropper.vue'\n\nconst ACCEPT = ['image/png', 'image/jpeg', 'image/webp']\n/** 裁剪前原图上限;裁完导出 256×256 PNG,远小于后端 1 MB 的限制 */\nconst MAX_SOURCE_MB = 5\n\nconst { t } = useI18n()\nconst message = useMessage()\nconst auth = useAuthStore()\nconst draft = useConfigDraft()\nconst logo = computed(() => draft.values[LOGO_KEY] ?? '')\nconst canUpload = computed(() => auth.hasPerm('POST:/api/v1/sys/config/logo'))\n\nconst fileInput = ref<HTMLInputElement | null>(null)\nconst dragging = ref(false)\nconst cropFile = ref<File | null>(null)\nconst cropper = ref<InstanceType<typeof LogoCropper> | null>(null)\nconst cropping = ref(false)\nconst urlOpen = ref(false)\nconst urlValue = ref('')\n\nconst options = computed<DropdownOption[]>(() => {\n const list: DropdownOption[] = []\n if (canUpload.value) list.push({ key: 'upload', label: t('config.logo.upload') })\n list.push({ key: 'url', label: t('config.logo.useUrl') })\n if (logo.value)\n list.push({ key: 'remove', label: t('config.logo.remove'), props: { class: 'logo-remove' } })\n return list\n})\n\nfunction onSelect(key: string) {\n if (key === 'upload') fileInput.value?.click()\n else if (key === 'url') {\n urlValue.value = logo.value.startsWith('blob:') ? '' : logo.value\n urlOpen.value = true\n } else if (key === 'remove') draft.setPendingLogo(null, '')\n}\n\nfunction pick(file: File | undefined) {\n if (!file) return\n if (!ACCEPT.includes(file.type)) return message.warning(t('config.logo.badType'))\n if (file.size > MAX_SOURCE_MB * 1024 * 1024)\n return message.warning(t('config.logo.tooLarge', { mb: MAX_SOURCE_MB }))\n cropFile.value = file\n}\n\nfunction onFileChange(e: Event) {\n const input = e.target as HTMLInputElement\n pick(input.files?.[0])\n input.value = '' // 同一张图可以再选一次\n}\n\nfunction onDrop(e: DragEvent) {\n dragging.value = false\n if (canUpload.value) pick(e.dataTransfer?.files[0])\n}\n\nasync function applyCrop() {\n if (!cropper.value) return\n cropping.value = true\n try {\n const blob = await cropper.value.crop()\n draft.setPendingLogo(blob, URL.createObjectURL(blob))\n cropFile.value = null\n } catch {\n message.error(t('config.logo.cropFailed'))\n } finally {\n cropping.value = false\n }\n}\n\nfunction applyUrl() {\n const v = urlValue.value.trim()\n // 只收 http(s) 绝对地址或站内路径:javascript: 之类的伪协议不能进 <img src>/<link href>\n if (v && !/^(https?:\\/\\/|\\/)/i.test(v)) {\n message.warning(t('config.logo.badUrl'))\n return false\n }\n draft.setPendingLogo(null, v)\n}\n</script>\n\n<template>\n <div class=\"logo-edit\">\n <n-dropdown trigger=\"click\" :options=\"options\" placement=\"bottom-end\" @select=\"onSelect\">\n <button\n type=\"button\"\n :class=\"['logo-box', { dragging }]\"\n :aria-label=\"t('config.logo.edit')\"\n aria-haspopup=\"menu\"\n data-testid=\"logo-box\"\n @dragover.prevent=\"dragging = canUpload\"\n @dragleave=\"dragging = false\"\n @drop.prevent=\"onDrop\"\n >\n <SmartLogo :size=\"40\" :src=\"logo\" />\n <span class=\"ov\" aria-hidden=\"true\">{{ t('common.edit') }}</span>\n </button>\n </n-dropdown>\n <input\n ref=\"fileInput\"\n type=\"file\"\n accept=\"image/png,image/jpeg,image/webp\"\n hidden\n data-testid=\"logo-file\"\n @change=\"onFileChange\"\n />\n\n <n-modal\n :show=\"!!cropFile\"\n preset=\"card\"\n :title=\"t('config.logo.cropTitle')\"\n style=\"width: min(360px, calc(100vw - 24px))\"\n :mask-closable=\"false\"\n @update:show=\"v => !v && (cropFile = null)\"\n >\n <LogoCropper v-if=\"cropFile\" ref=\"cropper\" :file=\"cropFile\" />\n <template #footer>\n <div class=\"dlg-foot\">\n <n-button @click=\"cropFile = null\">{{ t('common.cancel') }}</n-button>\n <n-button type=\"primary\" :loading=\"cropping\" @click=\"applyCrop\">\n {{ t('config.logo.apply') }}\n </n-button>\n </div>\n </template>\n </n-modal>\n\n <n-modal\n v-model:show=\"urlOpen\"\n preset=\"dialog\"\n :title=\"t('config.logo.useUrl')\"\n :positive-text=\"t('common.confirm')\"\n :negative-text=\"t('common.cancel')\"\n style=\"width: min(420px, calc(100vw - 24px))\"\n @positive-click=\"applyUrl\"\n >\n <n-input v-model:value=\"urlValue\" placeholder=\"https://cdn.example.com/logo.png\" />\n <p class=\"url-hint\">{{ t('config.logo.urlHint') }}</p>\n </n-modal>\n </div>\n</template>\n\n<style scoped>\n.logo-box {\n position: relative;\n display: grid;\n place-items: center;\n width: 56px;\n height: 56px;\n padding: 0;\n overflow: hidden;\n border: 0;\n border-radius: 14px;\n background: var(--glass-strong);\n cursor: pointer;\n}\n.logo-box:focus-visible {\n outline: 2px solid var(--signal);\n outline-offset: 2px;\n}\n.logo-box.dragging {\n box-shadow: inset 0 0 0 2px var(--signal);\n}\n/* 悬停或聚焦时底部浮出「编辑」,和系统设置里换头像一样 */\n.ov {\n position: absolute;\n inset: auto 0 0;\n padding: 2px 0;\n font-size: 11px;\n color: #fff;\n background: rgba(0, 0, 0, 0.5);\n opacity: 0;\n transition: opacity var(--transition-fast);\n}\n.logo-box:hover .ov,\n.logo-box:focus-visible .ov {\n opacity: 1;\n}\n.dlg-foot {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n.url-hint {\n margin: 8px 0 0;\n font-size: 13px;\n color: var(--text-3);\n}\n:global(.logo-remove) {\n color: var(--err);\n}\n</style>\n"],"names":["MAX_SOURCE_MB","ACCEPT","useI18n","message","useMessage","auth","useAuthStore","draft","useConfigDraft","logo","computed","LOGO_KEY","canUpload","fileInput","ref","dragging","cropFile","cropper","cropping","urlOpen","urlValue","options","list","onSelect","key","_a","pick","file","onFileChange","input","onDrop","applyCrop","blob","applyUrl","v","_openBlock","_createElementBlock","_hoisted_1","_createVNode","_unref","NDropdown","_createElementVNode","_cache","_withModifiers","$event","SmartLogo","_hoisted_3","_toDisplayString","NModal","_hoisted_4","NButton","_createBlock","LogoCropper","NInput","_hoisted_5"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import o from "./ProviderSheet2.vue.js";
2
2
  /* empty css */
3
- import e from "../../../../_virtual/_plugin-vue_export-helper.js";
4
- const p = /* @__PURE__ */ e(o, [["__scopeId", "data-v-947e55e5"]]);
3
+ import r from "../../../../_virtual/_plugin-vue_export-helper.js";
4
+ const m = /* @__PURE__ */ r(o, [["__scopeId", "data-v-32e1410f"]]);
5
5
  export {
6
- p as default
6
+ m as default
7
7
  };
8
8
  //# sourceMappingURL=ProviderSheet.vue.js.map