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,325 @@
1
+ import type { QiuTableColumnConfig, QiuTableHeaderCell } from './types'
2
+ import { QIU_SPECIAL_COL_TYPES } from './types'
3
+
4
+ export type LeafColumn = QiuTableColumnConfig & {
5
+ _key: string
6
+ _defaultSlot?: (scope: any) => any
7
+ _headerSlot?: (scope: any) => any
8
+ }
9
+
10
+ const normalizeSize = (v: string | number) => (typeof v === 'number' ? `${v}px` : String(v))
11
+
12
+ /** 解析列宽为像素;百分比需传入 containerWidth */
13
+ export function parseWidth(w?: string | number, containerWidth = 0) {
14
+ if (w == null || w === '') return 0
15
+ if (typeof w === 'number') return Number.isFinite(w) ? w : 0
16
+ const s = String(w).trim()
17
+ if (!s || s === 'auto') return 0
18
+ if (s.endsWith('%')) {
19
+ const pct = parseFloat(s)
20
+ if (!Number.isFinite(pct) || containerWidth <= 0) return 0
21
+ return (containerWidth * pct) / 100
22
+ }
23
+ return parseFloat(s) || 0
24
+ }
25
+
26
+ export function colStyle(col: LeafColumn) {
27
+ const style: Record<string, string> = {}
28
+ if (col.width != null) style.width = normalizeSize(col.width)
29
+ if (col.minWidth != null) style.minWidth = normalizeSize(col.minWidth)
30
+ if (col.maxWidth != null) style.maxWidth = normalizeSize(col.maxWidth)
31
+ return style
32
+ }
33
+
34
+ export type ColumnSizeHints = {
35
+ /** 显式 width(固定列宽) */
36
+ fixedWidth: number
37
+ minWidth: number
38
+ maxWidth: number
39
+ /** 无 width,仅靠 minWidth 参与剩余空间分配 */
40
+ isFlex: boolean
41
+ }
42
+
43
+ export function getColumnSizeHints(
44
+ col: LeafColumn,
45
+ containerWidth = 0,
46
+ defaults?: { minWidth?: number; maxWidth?: number }
47
+ ): ColumnSizeHints {
48
+ const defaultMin = defaults?.minWidth ?? 80
49
+ const defaultMax = defaults?.maxWidth ?? Number.POSITIVE_INFINITY
50
+ const fixedWidth = parseWidth(col.width, containerWidth)
51
+ const minWidth = Math.max(
52
+ parseWidth(col.minWidth, containerWidth) || (fixedWidth ? 0 : defaultMin),
53
+ 48
54
+ )
55
+ const maxRaw = parseWidth(col.maxWidth, containerWidth)
56
+ const maxWidth = maxRaw > 0 ? maxRaw : defaultMax
57
+ return {
58
+ fixedWidth,
59
+ minWidth: fixedWidth ? Math.min(minWidth || fixedWidth, fixedWidth) || 48 : minWidth,
60
+ maxWidth: Math.max(maxWidth, minWidth || 48),
61
+ isFlex: fixedWidth <= 0,
62
+ }
63
+ }
64
+
65
+ /**
66
+ * 计算每列最终渲染宽度(对齐 vxe:width 固定;仅 minWidth 的列吃剩余空间)
67
+ * resized 优先
68
+ */
69
+ export function computeRenderWidths(
70
+ leafColumns: LeafColumn[],
71
+ opts: {
72
+ containerWidth: number
73
+ showSelection: boolean
74
+ showIndex: boolean
75
+ showRadio?: boolean
76
+ showExpand?: boolean
77
+ fit?: boolean
78
+ resized?: Record<string, number>
79
+ defaults?: { minWidth?: number; maxWidth?: number }
80
+ }
81
+ ): Record<string, number> {
82
+ const {
83
+ containerWidth,
84
+ showSelection,
85
+ showIndex,
86
+ showRadio,
87
+ showExpand,
88
+ fit = true,
89
+ resized = {},
90
+ defaults,
91
+ } = opts
92
+
93
+ let special = 0
94
+ if (showExpand) special += 48
95
+ if (showRadio) special += 48
96
+ if (showSelection) special += 48
97
+ if (showIndex) special += 55
98
+
99
+ const result: Record<string, number> = {}
100
+ const flexKeys: string[] = []
101
+ let fixedSum = 0
102
+
103
+ for (const col of leafColumns) {
104
+ const resizedW = resized[col._key]
105
+ if (resizedW != null && resizedW > 0) {
106
+ result[col._key] = resizedW
107
+ fixedSum += resizedW
108
+ continue
109
+ }
110
+ const hints = getColumnSizeHints(col, containerWidth, defaults)
111
+ if (!hints.isFlex) {
112
+ const w = Math.min(Math.max(hints.fixedWidth, hints.minWidth), hints.maxWidth)
113
+ result[col._key] = w
114
+ fixedSum += w
115
+ } else {
116
+ flexKeys.push(col._key)
117
+ // 先占位 min,后面再分配剩余
118
+ result[col._key] = hints.minWidth
119
+ fixedSum += hints.minWidth
120
+ }
121
+ }
122
+
123
+ if (fit && flexKeys.length && containerWidth > 0) {
124
+ let remain = containerWidth - special - fixedSum
125
+ if (remain > 0) {
126
+ // 按 minWidth 比例分配剩余
127
+ const mins = flexKeys.map((k) => {
128
+ const col = leafColumns.find((c) => c._key === k)!
129
+ return getColumnSizeHints(col, containerWidth, defaults).minWidth
130
+ })
131
+ const minSum = mins.reduce((a, b) => a + b, 0) || flexKeys.length
132
+ let used = 0
133
+ flexKeys.forEach((k, i) => {
134
+ const col = leafColumns.find((c) => c._key === k)!
135
+ const hints = getColumnSizeHints(col, containerWidth, defaults)
136
+ const share =
137
+ i === flexKeys.length - 1
138
+ ? remain - used
139
+ : Math.floor((remain * mins[i]) / minSum)
140
+ used += share
141
+ const next = Math.min(Math.max(hints.minWidth + share, hints.minWidth), hints.maxWidth)
142
+ // 之前已计入 minWidth,这里补差值
143
+ const delta = next - hints.minWidth
144
+ result[k] = next
145
+ // remain 已按 share 消费;fixedSum 不需再改
146
+ void delta
147
+ })
148
+ }
149
+ }
150
+
151
+ return result
152
+ }
153
+
154
+ export function computeTableMinWidth(
155
+ leafColumns: LeafColumn[],
156
+ opts: {
157
+ showSelection: boolean
158
+ showIndex: boolean
159
+ showRadio?: boolean
160
+ showExpand?: boolean
161
+ },
162
+ /** 优先用最终渲染宽 / 拖拽宽 */
163
+ resolveWidth?: (col: LeafColumn) => number | undefined,
164
+ defaults?: { minWidth?: number; maxWidth?: number }
165
+ ) {
166
+ let min = 0
167
+ if (opts.showExpand) min += 48
168
+ if (opts.showRadio) min += 48
169
+ if (opts.showSelection) min += 48
170
+ if (opts.showIndex) min += 55
171
+ for (const col of leafColumns) {
172
+ const resolved = resolveWidth?.(col)
173
+ if (resolved != null && resolved > 0) {
174
+ min += resolved
175
+ continue
176
+ }
177
+ const hints = getColumnSizeHints(col, 0, defaults)
178
+ min += hints.isFlex ? hints.minWidth : hints.fixedWidth || hints.minWidth || 100
179
+ }
180
+ return min
181
+ }
182
+
183
+ export function leftOffsetForColumn(
184
+ leafColumns: LeafColumn[],
185
+ colKey: string,
186
+ opts: {
187
+ showSelection: boolean
188
+ showIndex: boolean
189
+ showRadio?: boolean
190
+ showExpand?: boolean
191
+ },
192
+ resolveWidth?: (col: LeafColumn) => number
193
+ ) {
194
+ let left = 0
195
+ if (opts.showExpand) left += 48
196
+ if (opts.showRadio) left += 48
197
+ if (opts.showSelection) left += 48
198
+ if (opts.showIndex) left += 55
199
+ for (const col of leafColumns) {
200
+ if (col._key === colKey) break
201
+ if (col.fixed === 'left' || col.fixed === true) {
202
+ left +=
203
+ resolveWidth?.(col) ||
204
+ parseWidth(col.width) ||
205
+ parseWidth(col.minWidth) ||
206
+ 120
207
+ }
208
+ }
209
+ return left
210
+ }
211
+
212
+ export function rightOffsetForColumn(
213
+ leafColumns: LeafColumn[],
214
+ colKey: string,
215
+ resolveWidth?: (col: LeafColumn) => number
216
+ ) {
217
+ let right = 0
218
+ for (let i = leafColumns.length - 1; i >= 0; i--) {
219
+ const col = leafColumns[i]
220
+ if (col._key === colKey) break
221
+ if (col.fixed === 'right') {
222
+ right +=
223
+ resolveWidth?.(col) ||
224
+ parseWidth(col.width) ||
225
+ parseWidth(col.minWidth) ||
226
+ 120
227
+ }
228
+ }
229
+ return right
230
+ }
231
+
232
+ /** 是否左侧固定列中的最后一列(用于阴影) */
233
+ export function isLastFixedLeft(leafColumns: LeafColumn[], colKey: string) {
234
+ const lefts = leafColumns.filter((c) => c.fixed === 'left' || c.fixed === true)
235
+ return lefts.length > 0 && lefts[lefts.length - 1]._key === colKey
236
+ }
237
+
238
+ /** 是否右侧固定列中的第一列(从右往左的最内侧,用于阴影) */
239
+ export function isFirstFixedRight(leafColumns: LeafColumn[], colKey: string) {
240
+ const rights = leafColumns.filter((c) => c.fixed === 'right')
241
+ return rights.length > 0 && rights[0]._key === colKey
242
+ }
243
+
244
+ /** 生成稳定且唯一的列 key(同 prop 多列也不会冲突) */
245
+ export function makeColumnKey(
246
+ col: QiuTableColumnConfig,
247
+ index: number,
248
+ prefix = ''
249
+ ): string {
250
+ const keyBase = col.prop || col.field || col.slot || col.type || 'col'
251
+ return prefix ? `${prefix}.${keyBase}#${index}` : `${keyBase}#${index}`
252
+ }
253
+
254
+ export { makeColumnKey as createColumnKey }
255
+
256
+ /** 扁平化叶子列(跳过仅分组的父列) */
257
+ export function flattenLeafColumns(
258
+ columns: QiuTableColumnConfig[],
259
+ prefix = ''
260
+ ): LeafColumn[] {
261
+ const out: LeafColumn[] = []
262
+ columns.forEach((col, i) => {
263
+ const key = makeColumnKey(col, i, prefix)
264
+ if (col.children?.length) {
265
+ out.push(...flattenLeafColumns(col.children, key))
266
+ return
267
+ }
268
+ if (col.type && QIU_SPECIAL_COL_TYPES.has(col.type) && !col.prop && !col.field && !col.editor) {
269
+ // 特殊列仍作为叶子
270
+ }
271
+ out.push({ ...col, _key: key })
272
+ })
273
+ return out
274
+ }
275
+
276
+ function depthOf(col: QiuTableColumnConfig): number {
277
+ if (!col.children?.length) return 1
278
+ return 1 + Math.max(...col.children.map(depthOf))
279
+ }
280
+
281
+ function leafCount(col: QiuTableColumnConfig): number {
282
+ if (!col.children?.length) return 1
283
+ return col.children.reduce((n, c) => n + leafCount(c), 0)
284
+ }
285
+
286
+ /** 生成多级表头矩阵(每行一组 th) */
287
+ export function buildHeaderRows(
288
+ columns: QiuTableColumnConfig[],
289
+ keyPrefix = ''
290
+ ): QiuTableHeaderCell[][] {
291
+ if (!columns.length) return [[]]
292
+ const maxDepth = Math.max(...columns.map(depthOf), 1)
293
+ const rows: QiuTableHeaderCell[][] = Array.from({ length: maxDepth }, () => [])
294
+
295
+ const walk = (
296
+ cols: QiuTableColumnConfig[],
297
+ depth: number,
298
+ startCol: number,
299
+ prefix: string
300
+ ): number => {
301
+ let cursor = startCol
302
+ cols.forEach((col, i) => {
303
+ const key = makeColumnKey(col, i, prefix)
304
+ const leaves = leafCount(col)
305
+ const isLeaf = !col.children?.length
306
+ const rowspan = isLeaf ? maxDepth - depth : 1
307
+ rows[depth].push({
308
+ column: { ...col, _key: key },
309
+ label: col.label || col.title || '',
310
+ colspan: leaves,
311
+ rowspan,
312
+ isLeaf,
313
+ colIndex: cursor,
314
+ })
315
+ if (!isLeaf && col.children) {
316
+ walk(col.children, depth + 1, cursor, key)
317
+ }
318
+ cursor += leaves
319
+ })
320
+ return cursor
321
+ }
322
+
323
+ walk(columns, 0, 0, keyPrefix)
324
+ return rows
325
+ }
@@ -0,0 +1,136 @@
1
+ import { nextTick, ref, type Ref } from 'vue'
2
+ import type { QiuTableColumnConfig, QiuTableEditConfig } from './types'
3
+ import { resolveColumnEditor, resolveColumnProp, resolveEditRender } from './types'
4
+
5
+ export function useTableEdit(opts: {
6
+ editable: Ref<boolean> | (() => boolean)
7
+ editTrigger: Ref<string> | (() => string)
8
+ editConfig: Ref<QiuTableEditConfig | undefined> | (() => QiuTableEditConfig | undefined)
9
+ getRowId: (row: any) => string
10
+ emit: (event: string, payload: any) => void
11
+ }) {
12
+ const editing = ref<{ rowId: string; prop: string } | null>(null)
13
+ /** 刚进入编辑时忽略 blur,避免挂载/聚焦过程中立刻提交造成闪一下 */
14
+ let editGuardUntil = 0
15
+ const inEditGuard = () => Date.now() < editGuardUntil
16
+
17
+ const getEditable = () =>
18
+ typeof opts.editable === 'function' ? opts.editable() : opts.editable.value
19
+
20
+ const getCfg = () =>
21
+ typeof opts.editConfig === 'function' ? opts.editConfig() : opts.editConfig.value
22
+
23
+ const getTrigger = () => {
24
+ const cfg = getCfg()
25
+ if (cfg?.trigger) return cfg.trigger
26
+ return typeof opts.editTrigger === 'function' ? opts.editTrigger() : opts.editTrigger.value
27
+ }
28
+
29
+ const getMode = () => getCfg()?.mode || 'cell'
30
+ const getAutoClear = () => getCfg()?.autoClear !== false
31
+ const getShowIcon = () => {
32
+ const cfg = getCfg()
33
+ // 可编辑表默认显示表头编辑图标(文字前);显式 false 才关闭
34
+ if (cfg?.showIcon === false) return false
35
+ if (cfg?.showIcon === true) return true
36
+ return getEditable()
37
+ }
38
+
39
+ const getColEditor = (col: QiuTableColumnConfig) => resolveColumnEditor(col)
40
+ const getEditRender = (col: QiuTableColumnConfig) => resolveEditRender(col)
41
+ const getProp = (col: QiuTableColumnConfig) => resolveColumnProp(col)
42
+
43
+ const canEditCol = (col: QiuTableColumnConfig) => {
44
+ if (!getEditable()) return false
45
+ const er = getEditRender(col)
46
+ if (er?.enabled === false) return false
47
+ return !!getColEditor(col) && col.editable !== false && !!getProp(col)
48
+ }
49
+
50
+ const hasAlwaysEditor = (col: QiuTableColumnConfig) => {
51
+ if (!canEditCol(col)) return false
52
+ if (getTrigger() === 'always') return true
53
+ return getColEditor(col) === 'switch'
54
+ }
55
+
56
+ const isInputEditor = (col: QiuTableColumnConfig) => getColEditor(col) === 'input'
57
+
58
+ const isEditing = (row: any, col: QiuTableColumnConfig) => {
59
+ if (!canEditCol(col)) return false
60
+ if (hasAlwaysEditor(col)) return true
61
+ if (!editing.value) return false
62
+ const sameRow = editing.value.rowId === opts.getRowId(row)
63
+ if (!sameRow) return false
64
+ if (getMode() === 'row') return true
65
+ return editing.value.prop === getProp(col)
66
+ }
67
+
68
+ const isInputFill = (row: any, col: QiuTableColumnConfig) =>
69
+ isEditing(row, col) && isInputEditor(col)
70
+
71
+ const startEdit = (row: any, col: QiuTableColumnConfig, focusRoot?: HTMLElement | null) => {
72
+ if (!canEditCol(col) || hasAlwaysEditor(col)) return
73
+ const prop = getProp(col)!
74
+ const rowId = opts.getRowId(row)
75
+ // 同一单元格重复进入时不要重挂载,避免闪烁
76
+ if (editing.value?.rowId === rowId && editing.value?.prop === prop) return
77
+ editGuardUntil = Date.now() + 120
78
+ editing.value = { rowId, prop }
79
+ opts.emit('cell-edit-start', { row, column: col })
80
+ nextTick(() => {
81
+ const root = focusRoot
82
+ const active =
83
+ (root?.querySelector(
84
+ `.qiu-table__cell.is-editing .qiu-input__inner`
85
+ ) as HTMLInputElement | null) ||
86
+ (root?.querySelector(`.qiu-table__cell.is-editing input`) as HTMLInputElement | null) ||
87
+ (root?.querySelector(
88
+ `.qiu-table__cell.is-editing .qiu-table__date-input`
89
+ ) as HTMLInputElement | null)
90
+ active?.focus?.({ preventScroll: true })
91
+ })
92
+ }
93
+
94
+ const clearEdit = () => {
95
+ editing.value = null
96
+ }
97
+
98
+ const commitEdit = (row: any, col: QiuTableColumnConfig, value: any) => {
99
+ if (inEditGuard()) return
100
+ const prop = getProp(col)
101
+ if (prop != null && row[prop] !== value) row[prop] = value
102
+ // row 模式:blur 不立刻清整行,交给 autoClear / 切行
103
+ if (getMode() === 'cell') {
104
+ if (
105
+ !hasAlwaysEditor(col) &&
106
+ editing.value?.rowId === opts.getRowId(row) &&
107
+ editing.value?.prop === prop
108
+ ) {
109
+ editing.value = null
110
+ }
111
+ }
112
+ opts.emit('cell-edit-end', { row, column: col, value })
113
+ opts.emit('edit', { row, column: col, value })
114
+ }
115
+
116
+ return {
117
+ editing,
118
+ getColEditor,
119
+ getEditRender,
120
+ getProp,
121
+ canEditCol,
122
+ hasAlwaysEditor,
123
+ isInputEditor,
124
+ isEditing,
125
+ isInputFill,
126
+ startEdit,
127
+ clearEdit,
128
+ commitEdit,
129
+ inEditGuard,
130
+ getTrigger,
131
+ getMode,
132
+ getAutoClear,
133
+ getShowIcon,
134
+ }
135
+ }
136
+
@@ -0,0 +1,115 @@
1
+ import { reactive, ref, type Ref } from 'vue'
2
+
3
+ /** 行展开(非树) */
4
+ export function useExpandRows(opts: { getRowId: (row: any) => string }) {
5
+ const expanded = ref<Set<string>>(new Set())
6
+
7
+ const isRowExpand = (row: any) => expanded.value.has(opts.getRowId(row))
8
+
9
+ const toggleRowExpand = (row: any) => {
10
+ const id = opts.getRowId(row)
11
+ const next = new Set(expanded.value)
12
+ if (next.has(id)) next.delete(id)
13
+ else next.add(id)
14
+ expanded.value = next
15
+ }
16
+
17
+ const setRowExpand = (rows: any[], checked: boolean) => {
18
+ const next = new Set(expanded.value)
19
+ rows.forEach((r) => {
20
+ const id = opts.getRowId(r)
21
+ if (checked) next.add(id)
22
+ else next.delete(id)
23
+ })
24
+ expanded.value = next
25
+ }
26
+
27
+ const clearRowExpand = () => {
28
+ expanded.value = new Set()
29
+ }
30
+
31
+ return { expanded, isRowExpand, toggleRowExpand, setRowExpand, clearRowExpand }
32
+ }
33
+
34
+ /** 单选 radio */
35
+ export function useRadioRow(opts: { getRowId: (row: any) => string }) {
36
+ const radioRowId = ref<string | null>(null)
37
+
38
+ const isRadioChecked = (row: any) => radioRowId.value === opts.getRowId(row)
39
+
40
+ const setRadioRow = (row: any | null) => {
41
+ radioRowId.value = row ? opts.getRowId(row) : null
42
+ }
43
+
44
+ const clearRadioRow = () => {
45
+ radioRowId.value = null
46
+ }
47
+
48
+ return { radioRowId, isRadioChecked, setRadioRow, clearRadioRow }
49
+ }
50
+
51
+ /** keepSource 脏数据追踪 */
52
+ export function useKeepSource(opts: {
53
+ enabled: () => boolean
54
+ getRowId: (row: any) => string
55
+ data: Ref<any[]> | (() => any[])
56
+ }) {
57
+ const sourceMap = reactive<Record<string, string>>({})
58
+
59
+ const getData = () => (typeof opts.data === 'function' ? opts.data() : opts.data.value)
60
+
61
+ const snapshot = () => {
62
+ if (!opts.enabled()) return
63
+ Object.keys(sourceMap).forEach((k) => delete sourceMap[k])
64
+ for (const row of getData() || []) {
65
+ const id = opts.getRowId(row)
66
+ if (id) sourceMap[id] = JSON.stringify(row)
67
+ }
68
+ }
69
+
70
+ const isUpdateByRow = (row: any) => {
71
+ if (!opts.enabled()) return false
72
+ const id = opts.getRowId(row)
73
+ const src = sourceMap[id]
74
+ if (src == null) return false
75
+ return src !== JSON.stringify(row)
76
+ }
77
+
78
+ const getUpdateRecords = () => {
79
+ if (!opts.enabled()) return []
80
+ return (getData() || []).filter((r) => isUpdateByRow(r))
81
+ }
82
+
83
+ const getInsertRecords = () => {
84
+ if (!opts.enabled()) return []
85
+ return (getData() || []).filter((r) => {
86
+ const id = opts.getRowId(r)
87
+ return id && sourceMap[id] == null
88
+ })
89
+ }
90
+
91
+ const reloadRow = (row: any) => {
92
+ const id = opts.getRowId(row)
93
+ const src = sourceMap[id]
94
+ if (!src) return
95
+ Object.assign(row, JSON.parse(src))
96
+ }
97
+
98
+ return { snapshot, isUpdateByRow, getUpdateRecords, getInsertRecords, reloadRow, sourceMap }
99
+ }
100
+
101
+ export type SortItem = { prop: string; order: 'asc' | 'desc' }
102
+
103
+ export function compareRows(a: any, b: any, sorts: SortItem[]) {
104
+ for (const s of sorts) {
105
+ if (!s.order) continue
106
+ const av = a[s.prop]
107
+ const bv = b[s.prop]
108
+ if (av === bv) continue
109
+ if (av == null) return 1
110
+ if (bv == null) return -1
111
+ const cmp = av > bv ? 1 : -1
112
+ return s.order === 'asc' ? cmp : -cmp
113
+ }
114
+ return 0
115
+ }
@@ -0,0 +1,77 @@
1
+ import { ref } from 'vue'
2
+
3
+ export type QiuTableHistoryPatch = {
4
+ rowId: string
5
+ prop: string
6
+ oldValue: any
7
+ newValue: any
8
+ }
9
+
10
+ /**
11
+ * 单元格编辑 undo/redo 栈
12
+ */
13
+ export function useTableHistory(opts: {
14
+ enabled: () => boolean
15
+ size?: () => number
16
+ findRow: (rowId: string) => any | null
17
+ onApply?: (patch: QiuTableHistoryPatch, direction: 'undo' | 'redo') => void
18
+ }) {
19
+ const undoStack = ref<QiuTableHistoryPatch[]>([])
20
+ const redoStack = ref<QiuTableHistoryPatch[]>([])
21
+
22
+ const maxSize = () => Math.max(1, opts.size?.() ?? 50)
23
+
24
+ const push = (patch: QiuTableHistoryPatch) => {
25
+ if (!opts.enabled()) return
26
+ if (patch.oldValue === patch.newValue) return
27
+ undoStack.value.push(patch)
28
+ if (undoStack.value.length > maxSize()) undoStack.value.shift()
29
+ redoStack.value = []
30
+ }
31
+
32
+ const apply = (patch: QiuTableHistoryPatch, value: any, direction: 'undo' | 'redo') => {
33
+ const row = opts.findRow(patch.rowId)
34
+ if (!row) return false
35
+ row[patch.prop] = value
36
+ opts.onApply?.(patch, direction)
37
+ return true
38
+ }
39
+
40
+ const undo = () => {
41
+ if (!opts.enabled()) return false
42
+ const patch = undoStack.value.pop()
43
+ if (!patch) return false
44
+ if (apply(patch, patch.oldValue, 'undo')) {
45
+ redoStack.value.push(patch)
46
+ return true
47
+ }
48
+ return false
49
+ }
50
+
51
+ const redo = () => {
52
+ if (!opts.enabled()) return false
53
+ const patch = redoStack.value.pop()
54
+ if (!patch) return false
55
+ if (apply(patch, patch.newValue, 'redo')) {
56
+ undoStack.value.push(patch)
57
+ return true
58
+ }
59
+ return false
60
+ }
61
+
62
+ const clear = () => {
63
+ undoStack.value = []
64
+ redoStack.value = []
65
+ }
66
+
67
+ return {
68
+ undoStack,
69
+ redoStack,
70
+ push,
71
+ undo,
72
+ redo,
73
+ clear,
74
+ canUndo: () => undoStack.value.length > 0,
75
+ canRedo: () => redoStack.value.length > 0,
76
+ }
77
+ }