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,105 @@
1
+ import type { QiuTableColumnConfig, QiuTableMergeCell, QiuTableSpanMethod } from './types'
2
+
3
+ export type SpanResult = { rowspan: number; colspan: number; visible: boolean }
4
+
5
+ /**
6
+ * 根据 spanMethod / mergeCells 计算单元格合并。
7
+ * columnIndex 为叶子数据列下标(不含 selection/index)。
8
+ */
9
+ export function resolveCellSpan(opts: {
10
+ row: any
11
+ column: QiuTableColumnConfig
12
+ rowIndex: number
13
+ columnIndex: number
14
+ data: any[]
15
+ spanMethod?: QiuTableSpanMethod
16
+ mergeCells?: QiuTableMergeCell[]
17
+ /** 预计算:被合并覆盖的格子 key `${rowIndex}:${columnIndex}` */
18
+ covered?: Set<string>
19
+ }): SpanResult {
20
+ const key = `${opts.rowIndex}:${opts.columnIndex}`
21
+ if (opts.covered?.has(key)) {
22
+ return { rowspan: 0, colspan: 0, visible: false }
23
+ }
24
+
25
+ let rowspan = 1
26
+ let colspan = 1
27
+
28
+ if (opts.mergeCells?.length) {
29
+ const hit = opts.mergeCells.find(
30
+ (m) => m.row === opts.rowIndex && m.col === opts.columnIndex
31
+ )
32
+ if (hit) {
33
+ rowspan = hit.rowspan
34
+ colspan = hit.colspan
35
+ }
36
+ }
37
+
38
+ if (opts.spanMethod) {
39
+ const res = opts.spanMethod({
40
+ row: opts.row,
41
+ column: opts.column,
42
+ rowIndex: opts.rowIndex,
43
+ columnIndex: opts.columnIndex,
44
+ data: opts.data,
45
+ })
46
+ if (Array.isArray(res)) {
47
+ rowspan = Number(res[0] ?? 1)
48
+ colspan = Number(res[1] ?? 1)
49
+ } else if (res && typeof res === 'object') {
50
+ rowspan = Number(res.rowspan ?? 1)
51
+ colspan = Number(res.colspan ?? 1)
52
+ }
53
+ }
54
+
55
+ if (rowspan === 0 || colspan === 0) {
56
+ return { rowspan: 0, colspan: 0, visible: false }
57
+ }
58
+ return { rowspan, colspan, visible: true }
59
+ }
60
+
61
+ /** 根据 mergeCells 生成被覆盖格子集合 */
62
+ export function buildMergeCoveredSet(mergeCells?: QiuTableMergeCell[]): Set<string> {
63
+ const covered = new Set<string>()
64
+ if (!mergeCells?.length) return covered
65
+ for (const m of mergeCells) {
66
+ for (let r = m.row; r < m.row + m.rowspan; r++) {
67
+ for (let c = m.col; c < m.col + m.colspan; c++) {
68
+ if (r === m.row && c === m.col) continue
69
+ covered.add(`${r}:${c}`)
70
+ }
71
+ }
72
+ }
73
+ return covered
74
+ }
75
+
76
+ /**
77
+ * 将 mergeHeaderCells 应用到表头矩阵(按 row/col 下标合并 th)
78
+ * children 多级表头已自动合并;本 API 用于扁平表头额外合并。
79
+ */
80
+ export function applyMergeHeaderCells(
81
+ headerRows: import('./types').QiuTableHeaderCell[][],
82
+ merges?: QiuTableMergeCell[]
83
+ ): import('./types').QiuTableHeaderCell[][] {
84
+ if (!merges?.length || !headerRows.length) return headerRows
85
+ const covered = buildMergeCoveredSet(merges)
86
+ return headerRows.map((row, ri) => {
87
+ const next: typeof row = []
88
+ for (const cell of row) {
89
+ const key = `${ri}:${cell.colIndex}`
90
+ if (covered.has(key)) continue
91
+ const hit = merges.find((m) => m.row === ri && m.col === cell.colIndex)
92
+ if (hit) {
93
+ next.push({
94
+ ...cell,
95
+ rowspan: hit.rowspan,
96
+ colspan: hit.colspan,
97
+ })
98
+ } else {
99
+ next.push(cell)
100
+ }
101
+ }
102
+ return next
103
+ })
104
+ }
105
+
@@ -0,0 +1,86 @@
1
+ import { onBeforeUnmount, onMounted, reactive, type Ref } from 'vue'
2
+
3
+ /** 列宽拖拽:写入 columnWidths,供 colgroup / 单元格样式使用 */
4
+ export function useColumnResize(opts?: { minWidth?: number; maxWidth?: number }) {
5
+ const columnWidths = reactive<Record<string, number>>({})
6
+ const defaultMin = opts?.minWidth ?? 48
7
+ const defaultMax = opts?.maxWidth ?? Number.POSITIVE_INFINITY
8
+ let dragging: {
9
+ key: string
10
+ startX: number
11
+ startW: number
12
+ min: number
13
+ max: number
14
+ } | null = null
15
+
16
+ const getWidth = (key: string, fallback?: string | number) => {
17
+ if (columnWidths[key] != null) return columnWidths[key]
18
+ if (fallback == null) return undefined
19
+ return typeof fallback === 'number' ? fallback : parseFloat(String(fallback)) || undefined
20
+ }
21
+
22
+ const onResizeStart = (
23
+ key: string,
24
+ currentWidth: number,
25
+ e: MouseEvent,
26
+ bounds?: { minWidth?: number; maxWidth?: number }
27
+ ) => {
28
+ e.preventDefault()
29
+ e.stopPropagation()
30
+ const min = Math.max(bounds?.minWidth ?? defaultMin, 48)
31
+ const max = Math.max(bounds?.maxWidth ?? defaultMax, min)
32
+ dragging = {
33
+ key,
34
+ startX: e.clientX,
35
+ startW: currentWidth || 100,
36
+ min,
37
+ max,
38
+ }
39
+ document.addEventListener('mousemove', onMove)
40
+ document.addEventListener('mouseup', onUp)
41
+ document.body.style.cursor = 'col-resize'
42
+ document.body.style.userSelect = 'none'
43
+ }
44
+
45
+ const onMove = (e: MouseEvent) => {
46
+ if (!dragging) return
47
+ const delta = e.clientX - dragging.startX
48
+ const next = dragging.startW + delta
49
+ columnWidths[dragging.key] = Math.min(dragging.max, Math.max(dragging.min, next))
50
+ }
51
+
52
+ const onUp = () => {
53
+ dragging = null
54
+ document.removeEventListener('mousemove', onMove)
55
+ document.removeEventListener('mouseup', onUp)
56
+ document.body.style.cursor = ''
57
+ document.body.style.userSelect = ''
58
+ }
59
+
60
+ const setColumnWidth = (key: string, width: number) => {
61
+ columnWidths[key] = Math.max(48, width)
62
+ }
63
+
64
+ onBeforeUnmount(() => {
65
+ document.removeEventListener('mousemove', onMove)
66
+ document.removeEventListener('mouseup', onUp)
67
+ })
68
+
69
+ return { columnWidths, getWidth, onResizeStart, setColumnWidth }
70
+ }
71
+
72
+ export function bindAutoClearEdit(opts: {
73
+ rootRef: Ref<HTMLElement | null>
74
+ enabled: () => boolean
75
+ clearEdit: () => void
76
+ }) {
77
+ const onDoc = (e: MouseEvent) => {
78
+ if (!opts.enabled()) return
79
+ const root = opts.rootRef.value
80
+ if (!root) return
81
+ if (root.contains(e.target as Node)) return
82
+ opts.clearEdit()
83
+ }
84
+ onMounted(() => document.addEventListener('mousedown', onDoc, true))
85
+ onBeforeUnmount(() => document.removeEventListener('mousedown', onDoc, true))
86
+ }
@@ -0,0 +1,152 @@
1
+ import { onBeforeUnmount, onMounted, ref, type Ref } from 'vue'
2
+
3
+ /** 探针测量系统纵向滚动条宽度 */
4
+ let cachedBarWidth = 0
5
+ function probeScrollbarWidth() {
6
+ if (typeof document === 'undefined') return 0
7
+ if (cachedBarWidth > 0) return cachedBarWidth
8
+ const outer = document.createElement('div')
9
+ outer.style.cssText =
10
+ 'position:absolute;top:-9999px;width:100px;height:100px;overflow:scroll;visibility:hidden'
11
+ document.body.appendChild(outer)
12
+ cachedBarWidth = Math.max(0, outer.offsetWidth - outer.clientWidth)
13
+ document.body.removeChild(outer)
14
+ return cachedBarWidth
15
+ }
16
+
17
+ /**
18
+ * 表头 / 表体 / 表尾横向滚动同步。
19
+ * 对齐策略(双表经典坑):
20
+ * 1. 量出 body 纵向滚动条占用
21
+ * 2. header/footer wrap 用 paddingRight 留出同宽空隙
22
+ * 3. 强制 header/footer 内 table 的像素宽 = body table 宽
23
+ * 4. 把 body 各 col 的实际像素宽抄到 header/footer
24
+ * 5. 有纵向条时由根节点 --qiu-table-v-scrollbar + --scroll-y 在 padding 内侧补竖线
25
+ *
26
+ * @author qiuye
27
+ * @email yjk150@qq.com
28
+ * @date 2026-08-16
29
+ */
30
+ export function useScrollSync(opts: {
31
+ headerWrapRef: Ref<HTMLElement | null>
32
+ bodyWrapRef: Ref<HTMLElement | null>
33
+ footerWrapRef: Ref<HTMLElement | null>
34
+ onLayoutChange?: () => void
35
+ }) {
36
+ const scrollbarSize = ref(0)
37
+ let syncing = false
38
+ let resizeObserver: ResizeObserver | null = null
39
+ let rafId = 0
40
+
41
+ const measureBar = (el: HTMLElement) => {
42
+ let size = Math.max(0, el.offsetWidth - el.clientWidth)
43
+ if (size <= 0 && el.scrollHeight > el.clientHeight + 1) {
44
+ size = probeScrollbarWidth()
45
+ }
46
+ return size
47
+ }
48
+
49
+ const syncColWidths = (fromTable: HTMLElement, toTable: HTMLElement) => {
50
+ // 优先用首行 td 实测宽(比 col 的 getBoundingClientRect 更稳)
51
+ const row = fromTable.querySelector(
52
+ 'tbody tr.qiu-table__row:not(.qiu-table__virtual-pad):not(.qiu-table__row--empty)',
53
+ ) as HTMLElement | null
54
+ const toCols = toTable.querySelectorAll(':scope > colgroup > col')
55
+ if (row) {
56
+ const cells = [...row.children] as HTMLElement[]
57
+ const n = Math.min(cells.length, toCols.length)
58
+ for (let i = 0; i < n; i++) {
59
+ const w = cells[i].getBoundingClientRect().width
60
+ if (w > 0) {
61
+ const col = toCols[i] as HTMLElement
62
+ col.style.width = `${w}px`
63
+ col.style.minWidth = `${w}px`
64
+ }
65
+ }
66
+ return
67
+ }
68
+ const fromCols = fromTable.querySelectorAll(':scope > colgroup > col')
69
+ const n = Math.min(fromCols.length, toCols.length)
70
+ for (let i = 0; i < n; i++) {
71
+ const w = (fromCols[i] as HTMLElement).getBoundingClientRect().width
72
+ if (w > 0) {
73
+ const col = toCols[i] as HTMLElement
74
+ col.style.width = `${w}px`
75
+ col.style.minWidth = `${w}px`
76
+ }
77
+ }
78
+ }
79
+
80
+ const applyFixedTable = (wrap: HTMLElement | null, bodyTable: HTMLElement, bar: number) => {
81
+ if (!wrap) return
82
+ wrap.style.paddingRight = `${bar}px`
83
+ wrap.style.boxSizing = 'border-box'
84
+ const table = wrap.querySelector(':scope > table') as HTMLElement | null
85
+ if (!table) return
86
+ const w = Math.round(bodyTable.getBoundingClientRect().width)
87
+ if (w > 0) {
88
+ table.style.width = `${w}px`
89
+ table.style.minWidth = `${w}px`
90
+ }
91
+ syncColWidths(bodyTable, table)
92
+ }
93
+
94
+ const measureAndAlign = () => {
95
+ const body = opts.bodyWrapRef.value
96
+ if (!body) return
97
+ const bar = measureBar(body)
98
+ if (scrollbarSize.value !== bar) scrollbarSize.value = bar
99
+
100
+ const bodyTable = body.querySelector(':scope > table') as HTMLElement | null
101
+ if (!bodyTable) return
102
+
103
+ applyFixedTable(opts.headerWrapRef.value, bodyTable, bar)
104
+ applyFixedTable(opts.footerWrapRef.value, bodyTable, bar)
105
+ }
106
+
107
+ const syncFromBody = () => {
108
+ if (syncing) return
109
+ const body = opts.bodyWrapRef.value
110
+ if (!body) return
111
+ syncing = true
112
+ const left = body.scrollLeft
113
+ if (opts.headerWrapRef.value) opts.headerWrapRef.value.scrollLeft = left
114
+ if (opts.footerWrapRef.value) opts.footerWrapRef.value.scrollLeft = left
115
+ measureAndAlign()
116
+ requestAnimationFrame(() => {
117
+ syncing = false
118
+ })
119
+ }
120
+
121
+ const scheduleLayout = () => {
122
+ if (rafId) cancelAnimationFrame(rafId)
123
+ rafId = requestAnimationFrame(() => {
124
+ rafId = 0
125
+ measureAndAlign()
126
+ syncFromBody()
127
+ opts.onLayoutChange?.()
128
+ })
129
+ }
130
+
131
+ onMounted(() => {
132
+ measureAndAlign()
133
+ requestAnimationFrame(() => measureAndAlign())
134
+ // 字体/行高落地后再对齐一次
135
+ setTimeout(() => measureAndAlign(), 50)
136
+ window.addEventListener('resize', scheduleLayout)
137
+ const body = opts.bodyWrapRef.value
138
+ if (body && typeof ResizeObserver !== 'undefined') {
139
+ resizeObserver = new ResizeObserver(() => scheduleLayout())
140
+ resizeObserver.observe(body)
141
+ }
142
+ })
143
+
144
+ onBeforeUnmount(() => {
145
+ window.removeEventListener('resize', scheduleLayout)
146
+ resizeObserver?.disconnect()
147
+ resizeObserver = null
148
+ if (rafId) cancelAnimationFrame(rafId)
149
+ })
150
+
151
+ return { scrollbarSize, measureScrollbar: measureAndAlign, syncFromBody, scheduleLayout }
152
+ }
@@ -0,0 +1,97 @@
1
+ import { computed, ref, watch, type Ref } from 'vue'
2
+
3
+ export interface VirtualYConfig {
4
+ enabled?: boolean
5
+ /** 超过该行数才启用虚拟滚动;默认 0(enabled 时立即启用) */
6
+ gt?: number
7
+ /** 上下额外渲染行数 */
8
+ oSize?: number
9
+ /** 预估行高 */
10
+ rowHeight?: number
11
+ }
12
+
13
+ /** 纵向虚拟滚动:仅渲染可视区附近行 */
14
+ export function useVirtualY(opts: {
15
+ bodyWrapRef: Ref<HTMLElement | null>
16
+ rows: Ref<any[]> | (() => any[])
17
+ config: Ref<VirtualYConfig | boolean | undefined> | (() => VirtualYConfig | boolean | undefined)
18
+ defaultRowHeight?: number
19
+ }) {
20
+ const scrollTop = ref(0)
21
+ const viewportHeight = ref(0)
22
+
23
+ const resolved = computed((): VirtualYConfig => {
24
+ const c = typeof opts.config === 'function' ? opts.config() : opts.config.value
25
+ if (c === true) return { enabled: true }
26
+ if (c && typeof c === 'object') return { enabled: c.enabled !== false, ...c }
27
+ return { enabled: false }
28
+ })
29
+
30
+ const getRows = () => (typeof opts.rows === 'function' ? opts.rows() : opts.rows.value)
31
+ const total = computed(() => getRows().length)
32
+
33
+ const rowHeight = computed(
34
+ () => resolved.value.rowHeight || opts.defaultRowHeight || 48
35
+ )
36
+
37
+ const overscan = computed(() => resolved.value.oSize ?? 6)
38
+
39
+ const enabled = computed(() => {
40
+ if (!resolved.value.enabled) return false
41
+ const gt = resolved.value.gt ?? 0
42
+ return total.value > gt
43
+ })
44
+
45
+ const range = computed(() => {
46
+ if (!enabled.value) {
47
+ return { start: 0, end: total.value, padTop: 0, padBottom: 0 }
48
+ }
49
+ const rh = Math.max(1, rowHeight.value)
50
+ // 视口尚未量到时按约一屏估算,避免先渲染全部行
51
+ const vh = Math.max(viewportHeight.value || 0, rh * 10)
52
+ const start = Math.max(0, Math.floor(scrollTop.value / rh) - overscan.value)
53
+ const visible = Math.ceil(vh / rh) + overscan.value * 2
54
+ const end = Math.min(total.value, start + Math.max(visible, 1))
55
+ return {
56
+ start,
57
+ end,
58
+ padTop: start * rh,
59
+ padBottom: Math.max(0, (total.value - end) * rh),
60
+ }
61
+ })
62
+
63
+ const measure = () => {
64
+ const el = opts.bodyWrapRef.value
65
+ if (!el) return
66
+ const h = el.clientHeight
67
+ if (h > 0) viewportHeight.value = h
68
+ }
69
+
70
+ const onScroll = () => {
71
+ const el = opts.bodyWrapRef.value
72
+ if (!el) return
73
+ scrollTop.value = el.scrollTop
74
+ if (el.clientHeight > 0) viewportHeight.value = el.clientHeight
75
+ }
76
+
77
+ watch(
78
+ () => opts.bodyWrapRef.value,
79
+ (el, _prev, onCleanup) => {
80
+ measure()
81
+ if (!el || typeof ResizeObserver === 'undefined') return
82
+ const ro = new ResizeObserver(() => measure())
83
+ ro.observe(el)
84
+ onCleanup(() => ro.disconnect())
85
+ },
86
+ { immediate: true, flush: 'post' }
87
+ )
88
+
89
+ watch(
90
+ () => [enabled.value, total.value, rowHeight.value] as const,
91
+ () => {
92
+ requestAnimationFrame(() => measure())
93
+ }
94
+ )
95
+
96
+ return { enabled, range, rowHeight, onScroll, measure, scrollTop, viewportHeight }
97
+ }
@@ -0,0 +1,165 @@
1
+ import type { QiuTableColumnConfig } from './types'
2
+
3
+ export interface QiuTableMenuItem {
4
+ code: string
5
+ name: string
6
+ disabled?: boolean
7
+ visible?: boolean
8
+ children?: QiuTableMenuItem[]
9
+ }
10
+
11
+ export interface QiuTableMenuConfig {
12
+ enabled?: boolean
13
+ body?: {
14
+ options?: QiuTableMenuItem[][]
15
+ }
16
+ header?: {
17
+ options?: QiuTableMenuItem[][]
18
+ }
19
+ /** 点击菜单项回调;也可监听 @menu-click */
20
+ visibleMethod?: (params: {
21
+ type: 'body' | 'header'
22
+ row?: any
23
+ column?: QiuTableColumnConfig
24
+ options: QiuTableMenuItem[][]
25
+ }) => boolean
26
+ }
27
+
28
+ export interface QiuTableCustomConfig {
29
+ enabled?: boolean
30
+ storage?: boolean
31
+ checkMethod?: (column: QiuTableColumnConfig) => boolean
32
+ }
33
+
34
+ export interface QiuTableValidRule {
35
+ required?: boolean
36
+ min?: number
37
+ max?: number
38
+ pattern?: RegExp | string
39
+ message?: string
40
+ validator?: (params: {
41
+ cellValue: any
42
+ row: any
43
+ column: QiuTableColumnConfig
44
+ }) => Error | string | boolean | void | Promise<any>
45
+ }
46
+
47
+ export type QiuTableEditRules = Record<string, QiuTableValidRule | QiuTableValidRule[]>
48
+
49
+ export interface QiuTableValidConfig {
50
+ autoClear?: boolean
51
+ showMessage?: boolean
52
+ }
53
+
54
+ export async function validateCell(opts: {
55
+ rules?: QiuTableValidRule | QiuTableValidRule[]
56
+ cellValue: any
57
+ row: any
58
+ column: QiuTableColumnConfig
59
+ }): Promise<string | null> {
60
+ const list = !opts.rules ? [] : Array.isArray(opts.rules) ? opts.rules : [opts.rules]
61
+ for (const rule of list) {
62
+ const val = opts.cellValue
63
+ if (rule.required && (val == null || val === '')) {
64
+ return rule.message || '必填'
65
+ }
66
+ if (rule.min != null && typeof val === 'number' && val < rule.min) {
67
+ return rule.message || `不能小于 ${rule.min}`
68
+ }
69
+ if (rule.max != null && typeof val === 'number' && val > rule.max) {
70
+ return rule.message || `不能大于 ${rule.max}`
71
+ }
72
+ if (rule.pattern) {
73
+ const re = typeof rule.pattern === 'string' ? new RegExp(rule.pattern) : rule.pattern
74
+ if (val != null && val !== '' && !re.test(String(val))) {
75
+ return rule.message || '格式不正确'
76
+ }
77
+ }
78
+ if (rule.validator) {
79
+ try {
80
+ const res = await rule.validator({
81
+ cellValue: val,
82
+ row: opts.row,
83
+ column: opts.column,
84
+ })
85
+ if (res instanceof Error) return res.message
86
+ if (typeof res === 'string' && res) return res
87
+ if (res === false) return rule.message || '校验失败'
88
+ } catch (e: any) {
89
+ return e?.message || rule.message || '校验失败'
90
+ }
91
+ }
92
+ }
93
+ return null
94
+ }
95
+
96
+ export function parseCsv(text: string): string[][] {
97
+ const rows: string[][] = []
98
+ let cur: string[] = []
99
+ let cell = ''
100
+ let inQuote = false
101
+ const pushCell = () => {
102
+ cur.push(cell)
103
+ cell = ''
104
+ }
105
+ const pushRow = () => {
106
+ pushCell()
107
+ if (cur.some((c) => c !== '')) rows.push(cur)
108
+ cur = []
109
+ }
110
+ for (let i = 0; i < text.length; i++) {
111
+ const ch = text[i]
112
+ if (inQuote) {
113
+ if (ch === '"') {
114
+ if (text[i + 1] === '"') {
115
+ cell += '"'
116
+ i++
117
+ } else inQuote = false
118
+ } else cell += ch
119
+ continue
120
+ }
121
+ if (ch === '"') {
122
+ inQuote = true
123
+ continue
124
+ }
125
+ if (ch === ',') {
126
+ pushCell()
127
+ continue
128
+ }
129
+ if (ch === '\n') {
130
+ pushRow()
131
+ continue
132
+ }
133
+ if (ch === '\r') continue
134
+ cell += ch
135
+ }
136
+ if (cell || cur.length) pushRow()
137
+ return rows
138
+ }
139
+
140
+ export function csvToObjects(
141
+ rows: string[][],
142
+ columns: QiuTableColumnConfig[]
143
+ ): any[] {
144
+ if (!rows.length) return []
145
+ const header = rows[0].map((h) => String(h ?? '').trim())
146
+ const cols = columns.filter((c) => c.prop || c.field)
147
+ const mapIdx = cols.map((c) => {
148
+ const prop = String(c.prop || c.field || '')
149
+ const label = String(c.label || '').trim()
150
+ let i = header.findIndex((h) => h === prop)
151
+ if (i < 0 && label) i = header.findIndex((h) => h === label)
152
+ return i
153
+ })
154
+ // 若表头对不上,按列顺序映射
155
+ const useOrder = mapIdx.every((i) => i < 0)
156
+ return rows.slice(1).map((r) => {
157
+ const obj: any = {}
158
+ cols.forEach((c, i) => {
159
+ const p = String(c.prop || c.field || '')
160
+ const idx = useOrder ? i : mapIdx[i] >= 0 ? mapIdx[i] : i
161
+ obj[p] = r[idx] ?? ''
162
+ })
163
+ return obj
164
+ })
165
+ }
@@ -0,0 +1,101 @@
1
+ <template>
2
+ <!-- 声明式列:向 QiuTable 注册配置与插槽,不渲染独立 DOM -->
3
+ </template>
4
+
5
+ <script lang="ts" setup>
6
+ /**
7
+ * QiuTableColumn — 声明式列,可嵌套插槽内容(如 QiuButton)
8
+ *
9
+ * @example
10
+ * <qiu-table :data="list">
11
+ * <qiu-table-column prop="name" label="姓名" />
12
+ * <qiu-table-column label="操作" width="160">
13
+ * <template #default="{ row }">
14
+ * <qiu-button type="primary" link>编辑</qiu-button>
15
+ * </template>
16
+ * </qiu-table-column>
17
+ * </qiu-table>
18
+ */
19
+ import type { QiuTableColumnConfig, QiuTableRegisterContext } from '../QiuTable/types'
20
+ import { QIU_TABLE_REGISTER_KEY } from '../QiuTable/types'
21
+
22
+ defineOptions({
23
+ name: 'QiuTableColumn',
24
+ })
25
+
26
+ const props = withDefaults(
27
+ defineProps<{
28
+ label?: string
29
+ /** vxe 别名 */
30
+ title?: string
31
+ prop?: string
32
+ width?: string | number
33
+ minWidth?: string | number
34
+ maxWidth?: string | number
35
+ fixed?: boolean | 'left' | 'right'
36
+ sortable?: boolean | 'custom'
37
+ filterable?: boolean
38
+ children?: QiuTableColumnConfig[]
39
+ aggFunc?: 'sum' | 'avg' | 'count'
40
+ align?: 'left' | 'center' | 'right'
41
+ headerAlign?: 'left' | 'center' | 'right'
42
+ showOverflowTooltip?: boolean
43
+ resizable?: boolean
44
+ className?: string
45
+ headerClassName?: string
46
+ labelClassName?: string
47
+ /** selection/index,或编辑器类型:input/switch/select/number/date/datetime/time/text */
48
+ type?: string
49
+ index?: number | ((index: number) => number)
50
+ columnKey?: string
51
+ filters?: { text: string; value: any }[]
52
+ filterMethod?: (value: any, row: any, column: any) => boolean
53
+ filteredValue?: any[]
54
+ filterPlacement?: string
55
+ filterMultiple?: boolean
56
+ treeNode?: boolean
57
+ dragSort?: boolean
58
+ editor?: QiuTableColumnConfig['editor']
59
+ editorProps?: Record<string, any>
60
+ options?: { label: string; value: any }[]
61
+ editable?: boolean
62
+ formatter?: (row: any, column: any, cellValue: any, index: number) => any
63
+ }>(),
64
+ {
65
+ align: 'left',
66
+ resizable: true,
67
+ showOverflowTooltip: true,
68
+ }
69
+ )
70
+
71
+ const slots = useSlots()
72
+ const registerCtx = inject<QiuTableRegisterContext | null>(QIU_TABLE_REGISTER_KEY, null)
73
+ const colId = Symbol('qiuTableColumn')
74
+
75
+ const buildRegistration = () => ({
76
+ id: colId,
77
+ props: { ...props },
78
+ slots: {
79
+ default: slots.default,
80
+ header: slots.header,
81
+ },
82
+ })
83
+
84
+ if (registerCtx) {
85
+ onMounted(() => {
86
+ registerCtx.register(buildRegistration())
87
+ })
88
+
89
+ watch(
90
+ () => ({ ...props }),
91
+ () => {
92
+ registerCtx.update(buildRegistration())
93
+ },
94
+ { deep: true }
95
+ )
96
+
97
+ onBeforeUnmount(() => {
98
+ registerCtx.unregister(colId)
99
+ })
100
+ }
101
+ </script>