foucui 1.0.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 (378) hide show
  1. package/README.md +43 -0
  2. package/components/QiuAffix/index.vue +186 -0
  3. package/components/QiuAlert/index.vue +208 -0
  4. package/components/QiuAnchor/context.ts +18 -0
  5. package/components/QiuAnchor/index.vue +180 -0
  6. package/components/QiuAnchorLink/index.vue +67 -0
  7. package/components/QiuApp/index.vue +9 -0
  8. package/components/QiuAutocomplete/index.vue +408 -0
  9. package/components/QiuAvatar/index.vue +140 -0
  10. package/components/QiuBacktop/index.vue +121 -0
  11. package/components/QiuBadge/api/index.ts +389 -0
  12. package/components/QiuBadge/components/BadgeImagePickerDialog.vue +243 -0
  13. package/components/QiuBadge/components/BadgeLibraryManagerDialog.vue +30 -0
  14. package/components/QiuBadge/components/BadgeLibraryPanel.vue +182 -0
  15. package/components/QiuBadge/composables/useTableHostHeight.ts +53 -0
  16. package/components/QiuBadge/index.ts +18 -0
  17. package/components/QiuBadge/shared/BadgeTemplateRenderer.vue +32 -0
  18. package/components/QiuBadge/shared/assetUrl.ts +26 -0
  19. package/components/QiuBadge/shared/badgeTemplate.ts +309 -0
  20. package/components/QiuBadge/utils/chinaAreaData.ts +44 -0
  21. package/components/QiuBadge/utils/hostRegion.ts +22 -0
  22. package/components/QiuBadge/utils/pca-code.json +1 -0
  23. package/components/QiuBadge/utils/pdfFromElement.ts +348 -0
  24. package/components/QiuBadge/views/BadgeLibraryView.vue +32 -0
  25. package/components/QiuBadge/views/BadgeManageView.vue +1364 -0
  26. package/components/QiuBadge/views/BadgeTemplateEditorView.vue +10 -0
  27. package/components/QiuBadge/views/BadgeTemplateListView.vue +229 -0
  28. package/components/QiuBadge/views/DeskLabelTemplateListView.vue +227 -0
  29. package/components/QiuBadge/views/DeskLabelView.vue +683 -0
  30. package/components/QiuBadgeDot/index.vue +87 -0
  31. package/components/QiuButton/index.vue +247 -0
  32. package/components/QiuButtonGroup/index.vue +63 -0
  33. package/components/QiuCanvasKit/QiuCanvasEditor.vue +5503 -0
  34. package/components/QiuCanvasKit/QiuCanvasRenderer.vue +348 -0
  35. package/components/QiuCanvasKit/assetUrl.ts +11 -0
  36. package/components/QiuCanvasKit/components/DataModulesPanel.vue +352 -0
  37. package/components/QiuCanvasKit/export/html.ts +132 -0
  38. package/components/QiuCanvasKit/export/pdf.ts +48 -0
  39. package/components/QiuCanvasKit/export/png.ts +50 -0
  40. package/components/QiuCanvasKit/index.ts +20 -0
  41. package/components/QiuCanvasKit/modules/badgeCompat.ts +84 -0
  42. package/components/QiuCanvasKit/modules/dataRegistry.ts +207 -0
  43. package/components/QiuCanvasKit/modules/merge.ts +71 -0
  44. package/components/QiuCanvasKit/presets/badge.ts +67 -0
  45. package/components/QiuCanvasKit/presets/banner.ts +79 -0
  46. package/components/QiuCanvasKit/types.ts +138 -0
  47. package/components/QiuCard/index.vue +104 -0
  48. package/components/QiuCarousel/context.ts +16 -0
  49. package/components/QiuCarousel/index.vue +343 -0
  50. package/components/QiuCarouselItem/index.vue +47 -0
  51. package/components/QiuCascader/index.vue +879 -0
  52. package/components/QiuCascader/types.ts +48 -0
  53. package/components/QiuCheckbox/QiuCheckboxGroup.vue +78 -0
  54. package/components/QiuCheckbox/index.vue +231 -0
  55. package/components/QiuCheckbox/types.ts +8 -0
  56. package/components/QiuCode/index.vue +64 -0
  57. package/components/QiuCol/col.scss +55 -0
  58. package/components/QiuCol/index.vue +64 -0
  59. package/components/QiuCollapse/context.ts +10 -0
  60. package/components/QiuCollapse/index.vue +70 -0
  61. package/components/QiuCollapseItem/index.vue +167 -0
  62. package/components/QiuColorField/index.vue +296 -0
  63. package/components/QiuColorPicker/README.md +118 -0
  64. package/components/QiuColorPicker/index.vue +60 -0
  65. package/components/QiuColorfulCard/index.vue +101 -0
  66. package/components/QiuCombobox/index.vue +277 -0
  67. package/components/QiuConfigProvider/index.vue +31 -0
  68. package/components/QiuContextMenu/index.vue +209 -0
  69. package/components/QiuDate/index.vue +1134 -0
  70. package/components/QiuDescriptions/context.ts +20 -0
  71. package/components/QiuDescriptions/index.vue +115 -0
  72. package/components/QiuDescriptionsItem/index.vue +103 -0
  73. package/components/QiuDialog/index.vue +828 -0
  74. package/components/QiuDigitalCard/index.vue +159 -0
  75. package/components/QiuDivider/index.vue +185 -0
  76. package/components/QiuDot/index.vue +83 -0
  77. package/components/QiuDrawer/index.vue +350 -0
  78. package/components/QiuDropdown/QiuDropdownItem.vue +74 -0
  79. package/components/QiuDropdown/QiuDropdownMenu.vue +22 -0
  80. package/components/QiuDropdown/context.ts +9 -0
  81. package/components/QiuDropdown/index.vue +189 -0
  82. package/components/QiuEmpty/index.vue +73 -0
  83. package/components/QiuForm/index.vue +172 -0
  84. package/components/QiuForm/types.ts +39 -0
  85. package/components/QiuFormItem/index.vue +276 -0
  86. package/components/QiuFullscreen/index.vue +11 -0
  87. package/components/QiuGrid/index.vue +408 -0
  88. package/components/QiuHoverCard/index.vue +192 -0
  89. package/components/QiuIcon/index.vue +117 -0
  90. package/components/QiuIconPicker/iconify.libraries.ts +182 -0
  91. package/components/QiuIconPicker/icons.catalog.ts +3072 -0
  92. package/components/QiuIconPicker/index.vue +488 -0
  93. package/components/QiuImage/index.vue +177 -0
  94. package/components/QiuInput/index.vue +328 -0
  95. package/components/QiuInputNumber/index.vue +295 -0
  96. package/components/QiuInputOtp/index.vue +190 -0
  97. package/components/QiuKbd/index.vue +57 -0
  98. package/components/QiuLayoutContainer/index.vue +50 -0
  99. package/components/QiuLinkPreview/index.vue +224 -0
  100. package/components/QiuLoading/index.ts +176 -0
  101. package/components/QiuLoading/spinner.vue +820 -0
  102. package/components/QiuLoading/types.ts +44 -0
  103. package/components/QiuMention/index.vue +299 -0
  104. package/components/QiuMenu/QiuMenuRoot.vue +241 -0
  105. package/components/QiuMenu/components/QiuMenuItem.vue +340 -0
  106. package/components/QiuMenu/components/QiuSubMenu.vue +504 -0
  107. package/components/QiuMenu/context.ts +21 -0
  108. package/components/QiuMenu/index.vue +43 -0
  109. package/components/QiuMenuNav/QiuMenuNavItem.vue +100 -0
  110. package/components/QiuMenuNav/QiuMenuNavSub.vue +120 -0
  111. package/components/QiuMenuNav/context.ts +14 -0
  112. package/components/QiuMenuNav/index.vue +148 -0
  113. package/components/QiuMsg/QiuMsgItem.vue +180 -0
  114. package/components/QiuMsg/index.ts +158 -0
  115. package/components/QiuMsg/types.ts +23 -0
  116. package/components/QiuMsgBox/index.ts +147 -0
  117. package/components/QiuNotification/QiuNotificationItem.vue +168 -0
  118. package/components/QiuNotification/index.ts +155 -0
  119. package/components/QiuNotification/types.ts +14 -0
  120. package/components/QiuPage/index.vue +12 -0
  121. package/components/QiuPageHeader/index.vue +115 -0
  122. package/components/QiuPageMain/index.vue +78 -0
  123. package/components/QiuPagination/index.vue +421 -0
  124. package/components/QiuPasswordStrength/index.vue +101 -0
  125. package/components/QiuPopconfirm/index.vue +196 -0
  126. package/components/QiuPopover/index.vue +277 -0
  127. package/components/QiuProgress/index.vue +235 -0
  128. package/components/QiuQrcode/index.vue +302 -0
  129. package/components/QiuQueryForm/components/QiuQueryFormBottomPanel.vue +13 -0
  130. package/components/QiuQueryForm/components/QiuQueryFormLeftPanel.vue +37 -0
  131. package/components/QiuQueryForm/components/QiuQueryFormRightPanel.vue +37 -0
  132. package/components/QiuQueryForm/components/QiuQueryFormTopPanel.vue +13 -0
  133. package/components/QiuQueryForm/index.vue +117 -0
  134. package/components/QiuRadio/QiuRadioGroup.vue +75 -0
  135. package/components/QiuRadio/index.vue +191 -0
  136. package/components/QiuRadio/types.ts +9 -0
  137. package/components/QiuRate/index.vue +184 -0
  138. package/components/QiuRefresh/index.vue +32 -0
  139. package/components/QiuResult/index.vue +103 -0
  140. package/components/QiuRow/index.vue +60 -0
  141. package/components/QiuRow/types.ts +5 -0
  142. package/components/QiuScrollbar/index.vue +107 -0
  143. package/components/QiuSearchBar/index.vue +154 -0
  144. package/components/QiuSegmented/index.vue +120 -0
  145. package/components/QiuSelect/QiuOption.vue +93 -0
  146. package/components/QiuSelect/index.vue +452 -0
  147. package/components/QiuSelect/types.ts +15 -0
  148. package/components/QiuSkeleton/index.vue +78 -0
  149. package/components/QiuSlider/index.vue +266 -0
  150. package/components/QiuSpace/index.vue +95 -0
  151. package/components/QiuSparkline/index.vue +92 -0
  152. package/components/QiuStatistic/index.vue +4 -0
  153. package/components/QiuStatistics/index.vue +123 -0
  154. package/components/QiuStep/index.vue +220 -0
  155. package/components/QiuSteps/context.ts +25 -0
  156. package/components/QiuSteps/index.vue +84 -0
  157. package/components/QiuSwitch/index.vue +145 -0
  158. package/components/QiuTabBar/index.vue +218 -0
  159. package/components/QiuTabBar/types.ts +19 -0
  160. package/components/QiuTabPane/index.vue +82 -0
  161. package/components/QiuTable/columns.ts +16 -0
  162. package/components/QiuTable/export.ts +102 -0
  163. package/components/QiuTable/index.ts +24 -0
  164. package/components/QiuTable/index.vue +3503 -0
  165. package/components/QiuTable/registry.ts +75 -0
  166. package/components/QiuTable/styles/table.scss +1230 -0
  167. package/components/QiuTable/types.ts +413 -0
  168. package/components/QiuTable/useArea.ts +202 -0
  169. package/components/QiuTable/useColumns.ts +325 -0
  170. package/components/QiuTable/useEdit.ts +136 -0
  171. package/components/QiuTable/useExtras.ts +115 -0
  172. package/components/QiuTable/useHistory.ts +77 -0
  173. package/components/QiuTable/useMerge.ts +105 -0
  174. package/components/QiuTable/useResize.ts +86 -0
  175. package/components/QiuTable/useScrollSync.ts +152 -0
  176. package/components/QiuTable/useVirtual.ts +97 -0
  177. package/components/QiuTable/utils.ts +165 -0
  178. package/components/QiuTableColumn/index.vue +101 -0
  179. package/components/QiuTag/index.vue +143 -0
  180. package/components/QiuText/index.vue +99 -0
  181. package/components/QiuTime/index.vue +548 -0
  182. package/components/QiuTimeAgo/index.vue +103 -0
  183. package/components/QiuTimeline/index.vue +54 -0
  184. package/components/QiuTimelineItem/index.vue +140 -0
  185. package/components/QiuTips/index.vue +323 -0
  186. package/components/QiuTooltip/index.vue +237 -0
  187. package/components/QiuTransfer/index.vue +277 -0
  188. package/components/QiuTree/QiuTreeNode.vue +146 -0
  189. package/components/QiuTree/index.vue +143 -0
  190. package/components/QiuTree/types.ts +30 -0
  191. package/components/QiuTreeSelect/index.vue +259 -0
  192. package/components/QiuTrend/index.vue +92 -0
  193. package/components/QiuUpload/index.vue +628 -0
  194. package/components/QiuUploadCrop/index.vue +1267 -0
  195. package/components/QiuWatermark/index.vue +121 -0
  196. package/components/useBodyScrollLock.ts +28 -0
  197. package/dist/components/QiuAnchor/context.d.ts +15 -0
  198. package/dist/components/QiuAnchorLink/index.vue.d.ts +23 -0
  199. package/dist/components/QiuBadge/api/index.d.ts +110 -0
  200. package/dist/components/QiuBadge/components/BadgeImagePickerDialog.vue.d.ts +16 -0
  201. package/dist/components/QiuBadge/components/BadgeLibraryManagerDialog.vue.d.ts +9 -0
  202. package/dist/components/QiuBadge/components/BadgeLibraryPanel.vue.d.ts +5 -0
  203. package/dist/components/QiuBadge/composables/useTableHostHeight.d.ts +7 -0
  204. package/dist/components/QiuBadge/index.d.ts +18 -0
  205. package/dist/components/QiuBadge/shared/BadgeTemplateRenderer.vue.d.ts +14 -0
  206. package/dist/components/QiuBadge/shared/assetUrl.d.ts +1 -0
  207. package/dist/components/QiuBadge/shared/badgeTemplate.d.ts +132 -0
  208. package/dist/components/QiuBadge/utils/chinaAreaData.d.ts +9 -0
  209. package/dist/components/QiuBadge/utils/hostRegion.d.ts +3 -0
  210. package/dist/components/QiuBadge/utils/pca-code.json.d.ts +3 -0
  211. package/dist/components/QiuBadge/utils/pdfFromElement.d.ts +14 -0
  212. package/dist/components/QiuBadge/views/BadgeLibraryView.vue.d.ts +2 -0
  213. package/dist/components/QiuBadge/views/BadgeManageView.vue.d.ts +7 -0
  214. package/dist/components/QiuBadge/views/BadgeTemplateListView.vue.d.ts +4 -0
  215. package/dist/components/QiuBadge/views/DeskLabelTemplateListView.vue.d.ts +4 -0
  216. package/dist/components/QiuBadge/views/DeskLabelView.vue.d.ts +4 -0
  217. package/dist/components/QiuButton/index.vue.d.ts +52 -0
  218. package/dist/components/QiuCanvasKit/QiuCanvasEditor.vue.d.ts +24 -0
  219. package/dist/components/QiuCanvasKit/QiuCanvasRenderer.vue.d.ts +13 -0
  220. package/dist/components/QiuCanvasKit/assetUrl.d.ts +7 -0
  221. package/dist/components/QiuCanvasKit/components/DataModulesPanel.vue.d.ts +23 -0
  222. package/dist/components/QiuCanvasKit/export/html.d.ts +12 -0
  223. package/dist/components/QiuCanvasKit/export/pdf.d.ts +9 -0
  224. package/dist/components/QiuCanvasKit/export/png.d.ts +8 -0
  225. package/dist/components/QiuCanvasKit/index.d.ts +19 -0
  226. package/dist/components/QiuCanvasKit/modules/badgeCompat.d.ts +8 -0
  227. package/dist/components/QiuCanvasKit/modules/dataRegistry.d.ts +23 -0
  228. package/dist/components/QiuCanvasKit/modules/merge.d.ts +12 -0
  229. package/dist/components/QiuCanvasKit/presets/badge.d.ts +12 -0
  230. package/dist/components/QiuCanvasKit/presets/banner.d.ts +4 -0
  231. package/dist/components/QiuCanvasKit/types.d.ts +119 -0
  232. package/dist/components/QiuCarousel/context.d.ts +13 -0
  233. package/dist/components/QiuCarouselItem/index.vue.d.ts +20 -0
  234. package/dist/components/QiuCascader/types.d.ts +25 -0
  235. package/dist/components/QiuCheckbox/QiuCheckboxGroup.vue.d.ts +33 -0
  236. package/dist/components/QiuCheckbox/index.vue.d.ts +38 -0
  237. package/dist/components/QiuCheckbox/types.d.ts +7 -0
  238. package/dist/components/QiuCode/index.vue.d.ts +15 -0
  239. package/dist/components/QiuCollapse/context.d.ts +8 -0
  240. package/dist/components/QiuCollapseItem/index.vue.d.ts +30 -0
  241. package/dist/components/QiuColorField/index.vue.d.ts +23 -0
  242. package/dist/components/QiuColorPicker/index.vue.d.ts +21 -0
  243. package/dist/components/QiuCombobox/index.vue.d.ts +54 -0
  244. package/dist/components/QiuContextMenu/index.vue.d.ts +46 -0
  245. package/dist/components/QiuDescriptions/context.d.ts +16 -0
  246. package/dist/components/QiuDescriptionsItem/index.vue.d.ts +25 -0
  247. package/dist/components/QiuDigitalCard/index.vue.d.ts +45 -0
  248. package/dist/components/QiuDropdown/QiuDropdownItem.vue.d.ts +30 -0
  249. package/dist/components/QiuDropdown/QiuDropdownMenu.vue.d.ts +17 -0
  250. package/dist/components/QiuDropdown/context.d.ts +7 -0
  251. package/dist/components/QiuDropdown/index.vue.d.ts +46 -0
  252. package/dist/components/QiuForm/types.d.ts +31 -0
  253. package/dist/components/QiuHoverCard/index.vue.d.ts +44 -0
  254. package/dist/components/QiuIcon/index.vue.d.ts +18 -0
  255. package/dist/components/QiuIconPicker/iconify.libraries.d.ts +18 -0
  256. package/dist/components/QiuIconPicker/icons.catalog.d.ts +12 -0
  257. package/dist/components/QiuInput/index.vue.d.ts +71 -0
  258. package/dist/components/QiuInputNumber/index.vue.d.ts +38 -0
  259. package/dist/components/QiuInputOtp/index.vue.d.ts +28 -0
  260. package/dist/components/QiuKbd/index.vue.d.ts +22 -0
  261. package/dist/components/QiuLayoutContainer/index.vue.d.ts +29 -0
  262. package/dist/components/QiuLinkPreview/index.vue.d.ts +43 -0
  263. package/dist/components/QiuLoading/index.d.ts +26 -0
  264. package/dist/components/QiuLoading/spinner.vue.d.ts +14 -0
  265. package/dist/components/QiuLoading/types.d.ts +2 -0
  266. package/dist/components/QiuMention/index.vue.d.ts +35 -0
  267. package/dist/components/QiuMenu/QiuMenuRoot.vue.d.ts +36 -0
  268. package/dist/components/QiuMenu/context.d.ts +19 -0
  269. package/dist/components/QiuMenuNav/QiuMenuNavItem.vue.d.ts +26 -0
  270. package/dist/components/QiuMenuNav/QiuMenuNavSub.vue.d.ts +25 -0
  271. package/dist/components/QiuMenuNav/context.d.ts +12 -0
  272. package/dist/components/QiuMenuNav/index.vue.d.ts +35 -0
  273. package/dist/components/QiuMsg/QiuMsgItem.vue.d.ts +15 -0
  274. package/dist/components/QiuMsg/index.d.ts +30 -0
  275. package/dist/components/QiuMsg/types.d.ts +12 -0
  276. package/dist/components/QiuMsgBox/index.d.ts +14 -0
  277. package/dist/components/QiuNotification/QiuNotificationItem.vue.d.ts +16 -0
  278. package/dist/components/QiuNotification/index.d.ts +30 -0
  279. package/dist/components/QiuNotification/types.d.ts +12 -0
  280. package/dist/components/QiuPageMain/index.vue.d.ts +27 -0
  281. package/dist/components/QiuPagination/index.vue.d.ts +44 -0
  282. package/dist/components/QiuPasswordStrength/index.vue.d.ts +9 -0
  283. package/dist/components/QiuQrcode/index.vue.d.ts +20 -0
  284. package/dist/components/QiuRadio/QiuRadioGroup.vue.d.ts +33 -0
  285. package/dist/components/QiuRadio/types.d.ts +8 -0
  286. package/dist/components/QiuRow/types.d.ts +4 -0
  287. package/dist/components/QiuSearchBar/index.vue.d.ts +38 -0
  288. package/dist/components/QiuSelect/QiuOption.vue.d.ts +24 -0
  289. package/dist/components/QiuSelect/index.vue.d.ts +52 -0
  290. package/dist/components/QiuSelect/types.d.ts +13 -0
  291. package/dist/components/QiuSparkline/index.vue.d.ts +18 -0
  292. package/dist/components/QiuStep/index.vue.d.ts +31 -0
  293. package/dist/components/QiuSteps/context.d.ts +21 -0
  294. package/dist/components/QiuSwitch/index.vue.d.ts +25 -0
  295. package/dist/components/QiuTabBar/index.vue.d.ts +32 -0
  296. package/dist/components/QiuTabBar/types.d.ts +16 -0
  297. package/dist/components/QiuTabPane/index.vue.d.ts +25 -0
  298. package/dist/components/QiuTable/columns.d.ts +1 -0
  299. package/dist/components/QiuTable/export.d.ts +18 -0
  300. package/dist/components/QiuTable/index.d.ts +3 -0
  301. package/dist/components/QiuTable/index.vue.d.ts +322 -0
  302. package/dist/components/QiuTable/registry.d.ts +39 -0
  303. package/dist/components/QiuTable/types.d.ts +353 -0
  304. package/dist/components/QiuTable/useArea.d.ts +51 -0
  305. package/dist/components/QiuTable/useColumns.d.ts +67 -0
  306. package/dist/components/QiuTable/useEdit.d.ts +36 -0
  307. package/dist/components/QiuTable/useExtras.d.ts +38 -0
  308. package/dist/components/QiuTable/useHistory.d.ts +44 -0
  309. package/dist/components/QiuTable/useMerge.d.ts +28 -0
  310. package/dist/components/QiuTable/useResize.d.ts +19 -0
  311. package/dist/components/QiuTable/useScrollSync.d.ts +25 -0
  312. package/dist/components/QiuTable/useVirtual.d.ts +30 -0
  313. package/dist/components/QiuTable/utils.d.ts +54 -0
  314. package/dist/components/QiuTime/index.vue.d.ts +43 -0
  315. package/dist/components/QiuTimeAgo/index.vue.d.ts +35 -0
  316. package/dist/components/QiuTimelineItem/index.vue.d.ts +35 -0
  317. package/dist/components/QiuTooltip/index.vue.d.ts +38 -0
  318. package/dist/components/QiuTree/types.d.ts +13 -0
  319. package/dist/components/QiuTrend/index.vue.d.ts +34 -0
  320. package/dist/components/QiuUpload/index.vue.d.ts +86 -0
  321. package/dist/components/QiuUploadCrop/index.vue.d.ts +136 -0
  322. package/dist/components/useBodyScrollLock.d.ts +4 -0
  323. package/dist/foucui.css +1 -0
  324. package/dist/foucui.js +26509 -0
  325. package/dist/foucui.umd.cjs +125 -0
  326. package/dist/index.d.ts +46 -0
  327. package/dist/src/bridge/@/api/media.d.ts +7 -0
  328. package/dist/src/bridge/@/api/notice.d.ts +5 -0
  329. package/dist/src/bridge/@/config/index.d.ts +29 -0
  330. package/dist/src/bridge/@/config/media.config.d.ts +15 -0
  331. package/dist/src/bridge/@/config/security.config.d.ts +7 -0
  332. package/dist/src/bridge/@/i18n/index.d.ts +7 -0
  333. package/dist/src/bridge/@/store/modules/bing.d.ts +3 -0
  334. package/dist/src/bridge/@/store/modules/errorLog.d.ts +3 -0
  335. package/dist/src/bridge/@/store/modules/media.d.ts +4 -0
  336. package/dist/src/bridge/@/store/modules/routes.d.ts +3 -0
  337. package/dist/src/bridge/@/store/modules/settings.d.ts +3 -0
  338. package/dist/src/bridge/@/store/modules/tabs.d.ts +3 -0
  339. package/dist/src/bridge/@/store/modules/user.d.ts +3 -0
  340. package/dist/src/bridge/@/utils/convertToCamelCase.d.ts +2 -0
  341. package/dist/src/bridge/@/utils/index.d.ts +5 -0
  342. package/dist/src/bridge/@/utils/pageTitle.d.ts +1 -0
  343. package/dist/src/bridge/@/utils/routes.d.ts +11 -0
  344. package/dist/src/bridge/@/utils/validate.d.ts +13 -0
  345. package/dist/src/bridge/@qiu/plugins/shortcuts.d.ts +2 -0
  346. package/dist/src/i18n.d.ts +2 -0
  347. package/package.json +83 -0
  348. package/plugins/qiu.ts +83 -0
  349. package/plugins/shortcuts.ts +69 -0
  350. package/src/bridge/@/api/media.ts +8 -0
  351. package/src/bridge/@/api/notice.ts +5 -0
  352. package/src/bridge/@/config/index.ts +38 -0
  353. package/src/bridge/@/config/media.config.ts +37 -0
  354. package/src/bridge/@/config/security.config.ts +8 -0
  355. package/src/bridge/@/i18n/index.ts +6 -0
  356. package/src/bridge/@/store/modules/bing.ts +9 -0
  357. package/src/bridge/@/store/modules/errorLog.ts +9 -0
  358. package/src/bridge/@/store/modules/media.ts +10 -0
  359. package/src/bridge/@/store/modules/routes.ts +10 -0
  360. package/src/bridge/@/store/modules/settings.ts +9 -0
  361. package/src/bridge/@/store/modules/tabs.ts +9 -0
  362. package/src/bridge/@/store/modules/user.ts +9 -0
  363. package/src/bridge/@/utils/convertToCamelCase.ts +11 -0
  364. package/src/bridge/@/utils/index.ts +9 -0
  365. package/src/bridge/@/utils/pageTitle.ts +4 -0
  366. package/src/bridge/@/utils/routes.ts +14 -0
  367. package/src/bridge/@/utils/validate.ts +17 -0
  368. package/src/bridge/@qiu/plugins/shortcuts.ts +3 -0
  369. package/src/i18n.ts +8 -0
  370. package/src/icons/qiu-logo.svg +1 -0
  371. package/styles/dark.scss +194 -0
  372. package/styles/normalize.css +349 -0
  373. package/styles/plain.scss +423 -0
  374. package/styles/qiu-tokens.scss +40 -0
  375. package/styles/qiu.scss +1149 -0
  376. package/styles/technology.scss +452 -0
  377. package/styles/var.scss +382 -0
  378. package/styles/variables.scss +77 -0
@@ -0,0 +1,182 @@
1
+ <template>
2
+ <div class="badge-library-panel">
3
+ <qiu-card shadow="never" class="toolbar-card">
4
+ <label class="upload-btn">
5
+ <input
6
+ type="file"
7
+ accept="image/jpeg,image/png,image/gif,image/webp,image/bmp"
8
+ class="upload-input"
9
+ @change="onFileChange"
10
+ />
11
+ <qiu-button type="primary" tag="span">上传图片</qiu-button>
12
+ </label>
13
+ <span class="hint">上传后可在模板编辑器的「图片库」中选用。</span>
14
+ </qiu-card>
15
+
16
+ <qiu-card v-qiu-loading="loading" shadow="never">
17
+ <div class="lib-grid">
18
+ <div v-for="it in list" :key="it.id" class="lib-cell">
19
+ <img :src="fullUrl(it.url)" alt="" class="thumb" loading="lazy" />
20
+ <div class="meta" :title="it.orig_name">{{ it.orig_name || '未命名' }}</div>
21
+ <div class="sub">{{ formatSize(it.size) }} · {{ it.create_time }}</div>
22
+ <qiu-button type="danger" link size="small" @click="remove(it)">删除</qiu-button>
23
+ </div>
24
+ </div>
25
+ <qiu-empty v-if="!loading && !list.length" description="暂无图片" />
26
+ <div v-if="total > pageSize" class="pager">
27
+ <qiu-pagination
28
+ v-model:current-page="page"
29
+ :page-size="pageSize"
30
+ layout="total, prev, pager, next"
31
+ :total="total"
32
+ @current-change="load"
33
+ />
34
+ </div>
35
+ </qiu-card>
36
+
37
+ <qiu-dialog v-model="deleteConfirmVisible" title="删除确认" width="400px">
38
+ <p>确定删除「{{ deleteTarget?.orig_name || '该图片' }}」?</p>
39
+ <template #footer>
40
+ <qiu-button @click="deleteConfirmVisible = false">取消</qiu-button>
41
+ <qiu-button type="danger" @click="doRemove">删除</qiu-button>
42
+ </template>
43
+ </qiu-dialog>
44
+ </div>
45
+ </template>
46
+
47
+ <script setup lang="ts">
48
+ import { ref, onMounted } from 'vue'
49
+ import { qiuMsg } from '../../QiuMsg'
50
+ import { getBadgeLibraryImages, uploadBadgeLibraryImage, deleteBadgeLibraryImage } from '../api/index'
51
+ import { resolveAssetUrl } from '../shared/assetUrl'
52
+
53
+ const loading = ref(false)
54
+ const list = ref<any[]>([])
55
+ const total = ref(0)
56
+ const page = ref(1)
57
+ const pageSize = ref(40)
58
+ const deleteConfirmVisible = ref(false)
59
+ const deleteTarget = ref<{ id: number; orig_name?: string } | null>(null)
60
+
61
+ function fullUrl(path: string) {
62
+ return resolveAssetUrl(path)
63
+ }
64
+
65
+ function formatSize(n: unknown) {
66
+ const b = Number(n) || 0
67
+ if (b < 1024) return `${b} B`
68
+ if (b < 1024 * 1024) return `${(b / 1024).toFixed(1)} KB`
69
+ return `${(b / 1024 / 1024).toFixed(2)} MB`
70
+ }
71
+
72
+ async function load() {
73
+ loading.value = true
74
+ try {
75
+ const res: any = await getBadgeLibraryImages({ page: page.value, page_size: pageSize.value })
76
+ list.value = res.data?.list ?? []
77
+ total.value = Number(res.data?.total ?? 0)
78
+ } catch {
79
+ list.value = []
80
+ total.value = 0
81
+ } finally {
82
+ loading.value = false
83
+ }
84
+ }
85
+
86
+ async function onFileChange(e: Event) {
87
+ const input = e.target as HTMLInputElement
88
+ const file = input.files?.[0]
89
+ input.value = ''
90
+ if (!file) return
91
+ try {
92
+ await uploadBadgeLibraryImage(file)
93
+ qiuMsg.success('已上传')
94
+ page.value = 1
95
+ await load()
96
+ } catch {
97
+ /* */
98
+ }
99
+ }
100
+
101
+ function remove(it: { id: number; orig_name?: string }) {
102
+ deleteTarget.value = it
103
+ deleteConfirmVisible.value = true
104
+ }
105
+
106
+ async function doRemove() {
107
+ const it = deleteTarget.value
108
+ if (!it) return
109
+ deleteConfirmVisible.value = false
110
+ try {
111
+ await deleteBadgeLibraryImage(Number(it.id))
112
+ qiuMsg.success('已删除')
113
+ await load()
114
+ } catch {
115
+ /* */
116
+ }
117
+ }
118
+
119
+ onMounted(() => load())
120
+
121
+ defineExpose({ load })
122
+ </script>
123
+
124
+ <style scoped>
125
+ .badge-library-panel .toolbar-card {
126
+ margin-bottom: 16px;
127
+ display: flex;
128
+ align-items: center;
129
+ gap: 16px;
130
+ flex-wrap: wrap;
131
+ }
132
+ .upload-btn {
133
+ position: relative;
134
+ display: inline-flex;
135
+ cursor: pointer;
136
+ }
137
+ .upload-input {
138
+ position: absolute;
139
+ width: 0;
140
+ height: 0;
141
+ opacity: 0;
142
+ pointer-events: none;
143
+ }
144
+ .hint {
145
+ font-size: 13px;
146
+ color: #909399;
147
+ }
148
+ .lib-grid {
149
+ display: grid;
150
+ grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
151
+ gap: 12px;
152
+ }
153
+ .lib-cell {
154
+ border: 1px solid #ebeef5;
155
+ border-radius: 8px;
156
+ padding: 10px;
157
+ }
158
+ .thumb {
159
+ width: 100%;
160
+ height: 120px;
161
+ object-fit: contain;
162
+ background: #f5f7fa;
163
+ border-radius: 6px;
164
+ }
165
+ .meta {
166
+ font-size: 13px;
167
+ margin-top: 8px;
168
+ overflow: hidden;
169
+ text-overflow: ellipsis;
170
+ white-space: nowrap;
171
+ }
172
+ .sub {
173
+ font-size: 12px;
174
+ color: #909399;
175
+ margin: 4px 0 8px;
176
+ }
177
+ .pager {
178
+ margin-top: 16px;
179
+ display: flex;
180
+ justify-content: flex-end;
181
+ }
182
+ </style>
@@ -0,0 +1,53 @@
1
+ import { ref, watch, onUnmounted, nextTick } from 'vue'
2
+
3
+ /** 测量容器高度供 qiu-table 的 `height` 使用,使表格占满剩余区域。
4
+ * 使用 ResizeObserver(宿主为表格外层 div,非表格根节点)+ window resize,避免仅靠窗口尺寸遗漏侧栏折叠等变化。 */
5
+ export function useTableHostHeight(minHeight = 160) {
6
+ const hostRef = ref<HTMLElement | null>(null)
7
+ const tableHeight = ref(Math.max(minHeight, 200))
8
+ let raf = 0
9
+ let ro: ResizeObserver | null = null
10
+ let removeWindowListener: (() => void) | null = null
11
+
12
+ const measure = () => {
13
+ const el = hostRef.value
14
+ if (!el) return
15
+ cancelAnimationFrame(raf)
16
+ raf = requestAnimationFrame(() => {
17
+ const h = Math.floor(el.getBoundingClientRect().height)
18
+ const next = Math.max(minHeight, h)
19
+ if (Math.abs(next - tableHeight.value) > 1) {
20
+ tableHeight.value = next
21
+ }
22
+ })
23
+ }
24
+
25
+ const cleanup = () => {
26
+ removeWindowListener?.()
27
+ removeWindowListener = null
28
+ ro?.disconnect()
29
+ ro = null
30
+ }
31
+
32
+ watch(
33
+ hostRef,
34
+ (el) => {
35
+ cleanup()
36
+ if (!el) return
37
+ nextTick(() => measure())
38
+ const onWinResize = () => measure()
39
+ window.addEventListener('resize', onWinResize, { passive: true })
40
+ removeWindowListener = () => window.removeEventListener('resize', onWinResize)
41
+ ro = new ResizeObserver(() => measure())
42
+ ro.observe(el)
43
+ },
44
+ { flush: 'post' }
45
+ )
46
+
47
+ onUnmounted(() => {
48
+ cleanup()
49
+ cancelAnimationFrame(raf)
50
+ })
51
+
52
+ return { hostRef, tableHeight, recalcTableHeight: measure }
53
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * QiuBadge — 证件 / 桌签制作插件
3
+ * 源码迁自 zhihui web-admin + shared,先落地再调。
4
+ */
5
+ /** 编辑器真源在 QiuCanvasKit;此入口保持兼容 */
6
+ export { default as QiuBadgeTemplateEditor } from '../QiuCanvasKit/QiuCanvasEditor.vue'
7
+ export { default as QiuBadgeTemplateList } from './views/BadgeTemplateListView.vue'
8
+ export { default as QiuBadgeManage } from './views/BadgeManageView.vue'
9
+ export { default as QiuBadgeLibrary } from './views/BadgeLibraryView.vue'
10
+ export { default as QiuDeskLabel } from './views/DeskLabelView.vue'
11
+ export { default as QiuDeskLabelTemplateList } from './views/DeskLabelTemplateListView.vue'
12
+ export { default as QiuBadgeTemplateRenderer } from './shared/BadgeTemplateRenderer.vue'
13
+ export { default as QiuBadgeImagePickerDialog } from './components/BadgeImagePickerDialog.vue'
14
+ export { default as QiuBadgeLibraryManagerDialog } from './components/BadgeLibraryManagerDialog.vue'
15
+ export { default as QiuBadgeLibraryPanel } from './components/BadgeLibraryPanel.vue'
16
+ export * from './shared/badgeTemplate'
17
+ export * from './shared/assetUrl'
18
+ export * as QiuBadgeApi from './api/index'
@@ -0,0 +1,32 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * 兼容旧名:委托 QiuCanvasRenderer
4
+ * @author qiuye
5
+ * @email yjk150@qq.com
6
+ * @date 2026-08-16
7
+ */
8
+ import QiuCanvasRenderer from '../../QiuCanvasKit/QiuCanvasRenderer.vue'
9
+ import type { BadgeTemplateDoc } from './badgeTemplate'
10
+ import type { MergeContext } from '../../QiuCanvasKit/types'
11
+
12
+ defineOptions({ name: 'QiuBadgeTemplateRenderer' })
13
+
14
+ withDefaults(
15
+ defineProps<{
16
+ doc: BadgeTemplateDoc | null
17
+ mergeData?: MergeContext | Record<string, string>
18
+ screenScale?: number
19
+ enableLinks?: boolean
20
+ }>(),
21
+ { screenScale: 1, mergeData: () => ({}), enableLinks: false }
22
+ )
23
+ </script>
24
+
25
+ <template>
26
+ <QiuCanvasRenderer
27
+ :doc="(doc as any)"
28
+ :merge-data="mergeData"
29
+ :screen-scale="screenScale"
30
+ :enable-links="enableLinks"
31
+ />
32
+ </template>
@@ -0,0 +1,26 @@
1
+ export function resolveAssetUrl(src: string | null | undefined): string {
2
+ const value = String(src || '').trim()
3
+ if (!value) return ''
4
+ if (/^data:/i.test(value) || /^blob:/i.test(value)) return value
5
+ if (/^(https?:)?\/\//i.test(value)) {
6
+ try {
7
+ const parsed = new URL(value, window.location.origin)
8
+ if (parsed.pathname.startsWith('/uploads/')) {
9
+ // Always prefer same-origin uploads path so html2canvas/jsPDF can render images
10
+ // without being blocked by cross-origin resource restrictions in production.
11
+ return `${parsed.pathname}${parsed.search}${parsed.hash}`
12
+ }
13
+ } catch {}
14
+ return value
15
+ }
16
+ if (value.startsWith('/uploads/')) {
17
+ return value
18
+ }
19
+
20
+ const raw = import.meta.env.VITE_API_BASE_URL
21
+ const apiBase = typeof raw === 'string' ? raw.trim().replace(/\/$/, '') : ''
22
+ if (!apiBase) return value.startsWith('/') ? value : `/${value}`
23
+
24
+ const staticBase = apiBase.replace(/\/api$/i, '')
25
+ return `${staticBase}${value.startsWith('/') ? value : `/${value}`}`
26
+ }
@@ -0,0 +1,309 @@
1
+ /** 与后端 BadgeData 及 allowedBadgePlaceholderKeys 一致 */
2
+ export const BADGE_PLACEHOLDER_KEYS = [
3
+ 'competition_name',
4
+ 'student_name',
5
+ 'competition_no',
6
+ 'school_name',
7
+ 'school_short_name',
8
+ 'age_group',
9
+ 'competition_room',
10
+ 'seat_no',
11
+ 'floor',
12
+ 'teacher_name',
13
+ 'date',
14
+ 'session',
15
+ 'enroll_teacher_name',
16
+ 'teacher_phone',
17
+ 'signup_teacher_name',
18
+ 'signup_teacher_phone',
19
+ 'signup_teacher_department',
20
+ 'signup_teacher_position',
21
+ 'signup_teacher_id_card',
22
+ 'signup_teacher_email',
23
+ 'signup_teacher_username',
24
+ 'venue_name',
25
+ 'venue_address',
26
+ 'competition_daily_start',
27
+ 'competition_daily_end',
28
+ ] as const
29
+
30
+ export type BadgePlaceholderKey = (typeof BADGE_PLACEHOLDER_KEYS)[number]
31
+
32
+ export const BADGE_PLACEHOLDER_LABELS: Record<string, string> = {
33
+ competition_name: '比赛名称',
34
+ student_name: '学生姓名',
35
+ competition_no: '参赛编号',
36
+ school_name: '学校',
37
+ school_short_name: '学校简称',
38
+ age_group: '年龄段',
39
+ competition_room: '考场/教室',
40
+ seat_no: '座位号',
41
+ floor: '楼层',
42
+ teacher_name: '监考教师',
43
+ date: '比赛日期',
44
+ session: '场次',
45
+ enroll_teacher_name: '报名/带队教师(扩展)',
46
+ teacher_phone: '教师手机(扩展)',
47
+ signup_teacher_name: '报名教师姓名',
48
+ signup_teacher_phone: '报名教师手机',
49
+ signup_teacher_department: '报名教师部门',
50
+ signup_teacher_position: '报名教师职务',
51
+ signup_teacher_id_card: '报名教师身份证',
52
+ signup_teacher_email: '报名教师邮箱',
53
+ signup_teacher_username: '报名教师账号',
54
+ venue_name: '场地名称',
55
+ venue_address: '场地地址',
56
+ competition_daily_start: '比赛当天开始时间',
57
+ competition_daily_end: '比赛当天结束时间',
58
+ }
59
+
60
+ export interface BadgeTemplateCanvas {
61
+ widthMm: number
62
+ heightMm: number
63
+ background?: string
64
+ backgroundImage?: string
65
+ /** 是否绘制画布边框(编辑/预览/打印一致) */
66
+ showBorder?: boolean
67
+ borderColor?: string
68
+ /** 边框宽度(mm) */
69
+ borderWidthMm?: number
70
+ }
71
+
72
+ export interface BadgeCanvasRegion {
73
+ id: string
74
+ name: string
75
+ xMm: number
76
+ yMm: number
77
+ wMm: number
78
+ hMm: number
79
+ background?: string
80
+ backgroundImage?: string
81
+ }
82
+
83
+ /** 元素跳转链接(Banner 热区 / 按钮形态) */
84
+ export type BadgeElementLink = {
85
+ href: string
86
+ target?: '_blank' | '_self'
87
+ }
88
+
89
+ export interface BadgeTextElement {
90
+ id: string
91
+ type: 'text'
92
+ zIndex: number
93
+ xMm: number
94
+ yMm: number
95
+ wMm: number
96
+ hMm: number
97
+ rotation?: number
98
+ flipX?: boolean
99
+ flipY?: boolean
100
+ groupId?: string
101
+ regionId?: string
102
+ align?: string
103
+ text: string
104
+ fontSize: number
105
+ fontFamily: string
106
+ color: string
107
+ textDirection?: 'horizontal' | 'vertical'
108
+ link?: BadgeElementLink
109
+ }
110
+
111
+ export interface BadgeImageElement {
112
+ id: string
113
+ type: 'image' | 'seal'
114
+ zIndex: number
115
+ xMm: number
116
+ yMm: number
117
+ wMm: number
118
+ hMm: number
119
+ rotation?: number
120
+ flipX?: boolean
121
+ flipY?: boolean
122
+ groupId?: string
123
+ regionId?: string
124
+ align?: string
125
+ src: string
126
+ clipboardSource?: 'clipboard'
127
+ clipboardUploadState?: 'pending' | 'uploaded'
128
+ clipboardUploadKey?: string
129
+ clipboardImageId?: number
130
+ clipboardOrigName?: string
131
+ link?: BadgeElementLink
132
+ }
133
+
134
+ export interface BadgeShapeElement {
135
+ id: string
136
+ type: 'shape'
137
+ shape: 'rect' | 'circle' | 'triangle' | 'line' | 'polygon' | 'trapezoid'
138
+ zIndex: number
139
+ xMm: number
140
+ yMm: number
141
+ wMm: number
142
+ hMm: number
143
+ rotation?: number
144
+ flipX?: boolean
145
+ flipY?: boolean
146
+ groupId?: string
147
+ regionId?: string
148
+ background?: string
149
+ lockAspectRatio?: boolean
150
+ showStroke?: boolean
151
+ strokeColor?: string
152
+ strokeWidthMm?: number
153
+ opacity?: number
154
+ polygonSides?: number
155
+ link?: BadgeElementLink
156
+ }
157
+
158
+ export type BadgeElement = BadgeTextElement | BadgeImageElement | BadgeShapeElement
159
+
160
+ export interface BadgeGuideLine {
161
+ id: string
162
+ axis: 'horizontal' | 'vertical'
163
+ offsetMm: number
164
+ }
165
+
166
+ export interface BadgeTemplateDoc {
167
+ version: number
168
+ canvas: BadgeTemplateCanvas
169
+ elements: BadgeElement[]
170
+ guides?: BadgeGuideLine[]
171
+ regions?: BadgeCanvasRegion[]
172
+ /** 可选:画布级数据模块(与 QiuCanvasKit 对齐) */
173
+ dataModules?: Array<{
174
+ id: string
175
+ label: string
176
+ fields: Array<{ key: string; label: string; type?: string }>
177
+ sample?: Record<string, string>
178
+ builtin?: boolean
179
+ enabled?: boolean
180
+ }>
181
+ }
182
+
183
+ export function mergeBadgeText(text: string, data: Record<string, string>) {
184
+ return text.replace(/\{\{\s*([a-zA-Z0-9_.]+)\s*\}\}/g, (_, k: string) => {
185
+ if (k.includes('.')) {
186
+ const [mod, field] = k.split('.')
187
+ const nested = (data as Record<string, unknown>)[mod]
188
+ if (nested && typeof nested === 'object') {
189
+ const v = (nested as Record<string, string>)[field]
190
+ if (v != null && v !== '') return String(v)
191
+ }
192
+ }
193
+ const v = data[k]
194
+ return v != null && v !== '' ? String(v) : ''
195
+ })
196
+ }
197
+
198
+ /** 将接口返回的一条证件(参赛证/工作证等)记录转为占位符合并表 */
199
+ export function flattenBadgeForMerge(
200
+ b: Record<string, unknown>,
201
+ competitionNameFallback?: string
202
+ ): Record<string, string> {
203
+ const cn =
204
+ (b.competition_name != null ? String(b.competition_name) : '') ||
205
+ (competitionNameFallback ?? '')
206
+ const schoolName = String(b.school_name ?? '')
207
+ const schoolShortName =
208
+ String(b.school_short_name ?? b.school_name_short ?? '').trim() || deriveSchoolShortName(schoolName)
209
+ return {
210
+ competition_name: cn,
211
+ student_name: String(b.student_name ?? ''),
212
+ competition_no: String(b.competition_no ?? ''),
213
+ school_name: schoolName,
214
+ school_short_name: schoolShortName,
215
+ age_group: String(b.age_group ?? ''),
216
+ competition_room: String(b.competition_room ?? ''),
217
+ seat_no: String(b.seat_no ?? ''),
218
+ floor: String(b.floor ?? ''),
219
+ teacher_name: String(b.teacher_name ?? ''),
220
+ date: String(b.date ?? b.competition_date ?? ''),
221
+ session: String(b.session ?? b.competition_session ?? ''),
222
+ enroll_teacher_name: String(b.enroll_teacher_name ?? ''),
223
+ teacher_phone: String(b.teacher_phone ?? ''),
224
+ signup_teacher_name: String(b.signup_teacher_name ?? ''),
225
+ signup_teacher_phone: String(b.signup_teacher_phone ?? ''),
226
+ signup_teacher_department: String(b.signup_teacher_department ?? ''),
227
+ signup_teacher_position: String(b.signup_teacher_position ?? ''),
228
+ signup_teacher_id_card: String(b.signup_teacher_id_card ?? ''),
229
+ signup_teacher_email: String(b.signup_teacher_email ?? ''),
230
+ signup_teacher_username: String(b.signup_teacher_username ?? ''),
231
+ venue_name: String(b.venue_name ?? ''),
232
+ venue_address: String(b.venue_address ?? ''),
233
+ competition_daily_start: String(b.competition_daily_start ?? ''),
234
+ competition_daily_end: String(b.competition_daily_end ?? ''),
235
+ }
236
+ }
237
+
238
+ function deriveSchoolShortName(schoolName: string): string {
239
+ let name = String(schoolName ?? '').trim()
240
+ if (!name) return ''
241
+
242
+ name = name.replace(/\s+/g, '')
243
+ name = name.replace(/^[中国中华人民共和國共和国]+/, '')
244
+
245
+ const adminPrefix =
246
+ /^(?:[^省特别行政区]+省|内蒙古自治区|广西壮族自治区|宁夏回族自治区|新疆维吾尔自治区|西藏自治区|北京市|天津市|上海市|重庆市|香港特别行政区|澳门特别行政区|台湾省|[^市]+市|[^区县旗]+区|[^区县旗]+县|[^区县旗]+旗|[^镇乡街道]+镇|[^镇乡街道]+乡|[^镇乡街道]+街道)/
247
+
248
+ let stripped = true
249
+ while (stripped && name) {
250
+ stripped = false
251
+ const next = name.replace(adminPrefix, '')
252
+ if (next !== name) {
253
+ name = next
254
+ stripped = true
255
+ }
256
+ }
257
+
258
+ return name || schoolName.trim()
259
+ }
260
+
261
+ export function sortBadgeElements(els: BadgeElement[]): BadgeElement[] {
262
+ return [...els].sort((a, b) => (a.zIndex ?? 0) - (b.zIndex ?? 0))
263
+ }
264
+
265
+ /** 桌面贴模板可用占位符:与参赛证保持一致,实际值由 DeskLabels 接口尽量补齐 */
266
+ export const DESK_LABEL_PLACEHOLDER_KEYS = BADGE_PLACEHOLDER_KEYS
267
+
268
+ export type DeskLabelPlaceholderKey = BadgePlaceholderKey
269
+
270
+ export const DESK_LABEL_PLACEHOLDER_LABELS: Record<string, string> = BADGE_PLACEHOLDER_LABELS
271
+
272
+ /** 单条桌面贴数据 → 与证件模板相同的合并表(未用字段留空,便于复用 BadgeTemplateRenderer) */
273
+ export function flattenDeskLabelForMerge(
274
+ row: Record<string, unknown>,
275
+ competitionNameFallback?: string
276
+ ): Record<string, string> {
277
+ const cn =
278
+ (row.competition_name != null ? String(row.competition_name) : '') || (competitionNameFallback ?? '')
279
+ const schoolName = String(row.school_name ?? '')
280
+ const schoolShortName =
281
+ String(row.school_short_name ?? row.school_name_short ?? '').trim() || deriveSchoolShortName(schoolName)
282
+ return {
283
+ competition_name: cn,
284
+ student_name: String(row.student_name ?? ''),
285
+ competition_no: String(row.competition_no ?? ''),
286
+ school_name: schoolName,
287
+ school_short_name: schoolShortName,
288
+ age_group: String(row.age_group ?? ''),
289
+ competition_room: String(row.competition_room ?? ''),
290
+ seat_no: String(row.seat_no ?? ''),
291
+ floor: String(row.floor ?? ''),
292
+ teacher_name: String(row.teacher_name ?? ''),
293
+ date: String(row.date ?? row.competition_date ?? ''),
294
+ session: String(row.session ?? row.competition_session ?? ''),
295
+ enroll_teacher_name: String(row.enroll_teacher_name ?? ''),
296
+ teacher_phone: String(row.teacher_phone ?? ''),
297
+ signup_teacher_name: String(row.signup_teacher_name ?? ''),
298
+ signup_teacher_phone: String(row.signup_teacher_phone ?? ''),
299
+ signup_teacher_department: String(row.signup_teacher_department ?? ''),
300
+ signup_teacher_position: String(row.signup_teacher_position ?? ''),
301
+ signup_teacher_id_card: String(row.signup_teacher_id_card ?? ''),
302
+ signup_teacher_email: String(row.signup_teacher_email ?? ''),
303
+ signup_teacher_username: String(row.signup_teacher_username ?? ''),
304
+ venue_name: String(row.venue_name ?? ''),
305
+ venue_address: String(row.venue_address ?? ''),
306
+ competition_daily_start: String(row.competition_daily_start ?? ''),
307
+ competition_daily_end: String(row.competition_daily_end ?? ''),
308
+ }
309
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * 省市区树数据(替代 element-china-area-data)
3
+ * 与旧包 API 对齐:regionData + codeToText,供 QiuBadge 赛区树使用。
4
+ * 使用本地 pca-code.json,避免 Vite 解析 china-division 包入口失败。
5
+ *
6
+ * @author qiuye
7
+ * @email yjk150@qq.com
8
+ * @date 2026-08-16
9
+ */
10
+ import pcaCJson from './pca-code.json'
11
+
12
+ export interface ChinaAreaNode {
13
+ value: string
14
+ label: string
15
+ children?: ChinaAreaNode[]
16
+ }
17
+
18
+ interface PcaCodeNode {
19
+ code: string | number
20
+ name: string
21
+ children?: PcaCodeNode[]
22
+ }
23
+
24
+ function mapNode(n: PcaCodeNode): ChinaAreaNode {
25
+ return {
26
+ value: String(n.code),
27
+ label: String(n.name || ''),
28
+ children: n.children?.length ? n.children.map(mapNode) : undefined,
29
+ }
30
+ }
31
+
32
+ /** 与 element-china-area-data 的 regionData 同形 */
33
+ export const regionData: ChinaAreaNode[] = (pcaCJson as PcaCodeNode[]).map(mapNode)
34
+
35
+ /** code → 中文名 */
36
+ export const codeToText: Record<string, string> = {}
37
+
38
+ function walk(nodes: ChinaAreaNode[]) {
39
+ for (const n of nodes) {
40
+ codeToText[n.value] = n.label
41
+ if (n.children?.length) walk(n.children)
42
+ }
43
+ }
44
+ walk(regionData)
@@ -0,0 +1,22 @@
1
+ /** host_region 存省市区 code 的 JSON 数组字符串,如 ["110000","110100","110105"];旧数据为纯文本则原样展示 */
2
+
3
+ export function parseHostRegionCodes(raw: unknown): string[] {
4
+ if (raw == null) return []
5
+ const s = String(raw).trim()
6
+ if (!s) return []
7
+ try {
8
+ const a = JSON.parse(s)
9
+ if (Array.isArray(a)) return a.map(String).filter(Boolean)
10
+ } catch {
11
+ /* 旧版手填 */
12
+ }
13
+ return []
14
+ }
15
+
16
+ export function formatHostRegionLabel(raw: unknown, codeToText: Record<string, string>): string {
17
+ const codes = parseHostRegionCodes(raw)
18
+ if (codes.length) {
19
+ return codes.map((c) => codeToText[c] || c).filter(Boolean).join(' / ')
20
+ }
21
+ return String(raw ?? '').trim()
22
+ }