@robot-admin/naive-ui-components 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (352) hide show
  1. package/README.md +257 -0
  2. package/dist/C_ActionBar-DWN-woTc.css.map +1 -0
  3. package/dist/C_ActionBar.cjs +5 -0
  4. package/dist/C_ActionBar.d.cts +2 -0
  5. package/dist/C_ActionBar.d.ts +2 -0
  6. package/dist/C_ActionBar.js +4 -0
  7. package/dist/C_ActionBar2.js +196 -0
  8. package/dist/C_ActionBar2.js.map +1 -0
  9. package/dist/C_AntV-AFKyK6hH.css.map +1 -0
  10. package/dist/C_AntV.cjs +8 -0
  11. package/dist/C_AntV.d.cts +2 -0
  12. package/dist/C_AntV.d.ts +2 -0
  13. package/dist/C_AntV.js +4 -0
  14. package/dist/C_AntV2.js +3150 -0
  15. package/dist/C_AntV2.js.map +1 -0
  16. package/dist/C_Barcode-P_EFj8dC.css.map +1 -0
  17. package/dist/C_Barcode.cjs +4 -0
  18. package/dist/C_Barcode.d.cts +2 -0
  19. package/dist/C_Barcode.d.ts +2 -0
  20. package/dist/C_Barcode.js +3 -0
  21. package/dist/C_Barcode2.js +68 -0
  22. package/dist/C_Barcode2.js.map +1 -0
  23. package/dist/C_Captcha-C-ef41xw.css.map +1 -0
  24. package/dist/C_Captcha.cjs +4 -0
  25. package/dist/C_Captcha.d.cts +2 -0
  26. package/dist/C_Captcha.d.ts +2 -0
  27. package/dist/C_Captcha.js +3 -0
  28. package/dist/C_Captcha2.js +155 -0
  29. package/dist/C_Captcha2.js.map +1 -0
  30. package/dist/C_Cascade-D9kNsjsV.css.map +1 -0
  31. package/dist/C_Cascade.cjs +4 -0
  32. package/dist/C_Cascade.d.cts +2 -0
  33. package/dist/C_Cascade.d.ts +2 -0
  34. package/dist/C_Cascade.js +3 -0
  35. package/dist/C_Cascade2.js +103 -0
  36. package/dist/C_Cascade2.js.map +1 -0
  37. package/dist/C_City-BCQ4ipiK.css.map +1 -0
  38. package/dist/C_City.cjs +4 -0
  39. package/dist/C_City.d.cts +2 -0
  40. package/dist/C_City.d.ts +2 -0
  41. package/dist/C_City.js +3 -0
  42. package/dist/C_City2.js +841 -0
  43. package/dist/C_City2.js.map +1 -0
  44. package/dist/C_Code-C9kvvEmO.css.map +1 -0
  45. package/dist/C_Code.cjs +5 -0
  46. package/dist/C_Code.d.cts +2 -0
  47. package/dist/C_Code.d.ts +2 -0
  48. package/dist/C_Code.js +4 -0
  49. package/dist/C_Code2.js +346 -0
  50. package/dist/C_Code2.js.map +1 -0
  51. package/dist/C_CollapsePanel-BUJHuYcU.css.map +1 -0
  52. package/dist/C_CollapsePanel.cjs +6 -0
  53. package/dist/C_CollapsePanel.d.cts +2 -0
  54. package/dist/C_CollapsePanel.d.ts +2 -0
  55. package/dist/C_CollapsePanel.js +4 -0
  56. package/dist/C_CollapsePanel2.js +319 -0
  57. package/dist/C_CollapsePanel2.js.map +1 -0
  58. package/dist/C_Cron-yx2Ob4Jl.css.map +1 -0
  59. package/dist/C_Cron.cjs +15 -0
  60. package/dist/C_Cron.d.cts +2 -0
  61. package/dist/C_Cron.d.ts +2 -0
  62. package/dist/C_Cron.js +4 -0
  63. package/dist/C_Cron2.js +1209 -0
  64. package/dist/C_Cron2.js.map +1 -0
  65. package/dist/C_Date.cjs +4 -0
  66. package/dist/C_Date.d.cts +2 -0
  67. package/dist/C_Date.d.ts +2 -0
  68. package/dist/C_Date.js +3 -0
  69. package/dist/C_Date2.js +219 -0
  70. package/dist/C_Date2.js.map +1 -0
  71. package/dist/C_Draggable-C483syRC.css.map +1 -0
  72. package/dist/C_Draggable.cjs +5 -0
  73. package/dist/C_Draggable.d.cts +2 -0
  74. package/dist/C_Draggable.d.ts +2 -0
  75. package/dist/C_Draggable.js +3 -0
  76. package/dist/C_Draggable2.js +295 -0
  77. package/dist/C_Draggable2.js.map +1 -0
  78. package/dist/C_Editor-Bp0SyIEw.css.map +1 -0
  79. package/dist/C_Editor.cjs +4 -0
  80. package/dist/C_Editor.d.cts +2 -0
  81. package/dist/C_Editor.d.ts +2 -0
  82. package/dist/C_Editor.js +3 -0
  83. package/dist/C_Editor2.js +160 -0
  84. package/dist/C_Editor2.js.map +1 -0
  85. package/dist/C_FilePreview-CPqvhoCy.css.map +1 -0
  86. package/dist/C_FilePreview.cjs +6 -0
  87. package/dist/C_FilePreview.d.cts +2 -0
  88. package/dist/C_FilePreview.d.ts +2 -0
  89. package/dist/C_FilePreview.js +3 -0
  90. package/dist/C_FilePreview2.js +1031 -0
  91. package/dist/C_FilePreview2.js.map +1 -0
  92. package/dist/C_Form-Jx7PY3sT.css.map +1 -0
  93. package/dist/C_Form.cjs +15 -0
  94. package/dist/C_Form.d.cts +2 -0
  95. package/dist/C_Form.d.ts +2 -0
  96. package/dist/C_Form.js +4 -0
  97. package/dist/C_Form2.js +2510 -0
  98. package/dist/C_Form2.js.map +1 -0
  99. package/dist/C_FormSearch-DvRgxlRn.css.map +1 -0
  100. package/dist/C_FormSearch.cjs +6 -0
  101. package/dist/C_FormSearch.d.cts +2 -0
  102. package/dist/C_FormSearch.d.ts +2 -0
  103. package/dist/C_FormSearch.js +3 -0
  104. package/dist/C_FormSearch2.js +356 -0
  105. package/dist/C_FormSearch2.js.map +1 -0
  106. package/dist/C_FormulaEditor-DtGkt4T_.css.map +1 -0
  107. package/dist/C_FormulaEditor.cjs +13 -0
  108. package/dist/C_FormulaEditor.d.cts +2 -0
  109. package/dist/C_FormulaEditor.d.ts +2 -0
  110. package/dist/C_FormulaEditor.js +4 -0
  111. package/dist/C_FormulaEditor2.js +1433 -0
  112. package/dist/C_FormulaEditor2.js.map +1 -0
  113. package/dist/C_FullCalendar-BF7H0YIx.css.map +1 -0
  114. package/dist/C_FullCalendar.cjs +9 -0
  115. package/dist/C_FullCalendar.d.cts +2 -0
  116. package/dist/C_FullCalendar.d.ts +2 -0
  117. package/dist/C_FullCalendar.js +3 -0
  118. package/dist/C_FullCalendar2.js +377 -0
  119. package/dist/C_FullCalendar2.js.map +1 -0
  120. package/dist/C_Guide.cjs +4 -0
  121. package/dist/C_Guide.d.cts +2 -0
  122. package/dist/C_Guide.d.ts +2 -0
  123. package/dist/C_Guide.js +3 -0
  124. package/dist/C_Guide2.js +58 -0
  125. package/dist/C_Guide2.js.map +1 -0
  126. package/dist/C_Icon.cjs +4 -0
  127. package/dist/C_Icon.d.cts +2 -0
  128. package/dist/C_Icon.d.ts +2 -0
  129. package/dist/C_Icon.js +3 -0
  130. package/dist/C_Icon2.js +286 -0
  131. package/dist/C_Icon2.js.map +1 -0
  132. package/dist/C_ImageCropper-BVJfUufl.css.map +1 -0
  133. package/dist/C_ImageCropper.cjs +6 -0
  134. package/dist/C_ImageCropper.d.cts +2 -0
  135. package/dist/C_ImageCropper.d.ts +2 -0
  136. package/dist/C_ImageCropper.js +4 -0
  137. package/dist/C_ImageCropper2.js +723 -0
  138. package/dist/C_ImageCropper2.js.map +1 -0
  139. package/dist/C_Language.cjs +4 -0
  140. package/dist/C_Language.d.cts +2 -0
  141. package/dist/C_Language.d.ts +2 -0
  142. package/dist/C_Language.js +3 -0
  143. package/dist/C_Language2.js +72 -0
  144. package/dist/C_Language2.js.map +1 -0
  145. package/dist/C_Map-DpzeuWdX.css.map +1 -0
  146. package/dist/C_Map.cjs +7 -0
  147. package/dist/C_Map.d.cts +2 -0
  148. package/dist/C_Map.d.ts +2 -0
  149. package/dist/C_Map.js +3 -0
  150. package/dist/C_Map2.js +199 -0
  151. package/dist/C_Map2.js.map +1 -0
  152. package/dist/C_Markdown-BEjxknqd.css.map +1 -0
  153. package/dist/C_Markdown.cjs +4 -0
  154. package/dist/C_Markdown.d.cts +2 -0
  155. package/dist/C_Markdown.d.ts +2 -0
  156. package/dist/C_Markdown.js +3 -0
  157. package/dist/C_Markdown2.js +186 -0
  158. package/dist/C_Markdown2.js.map +1 -0
  159. package/dist/C_NotificationCenter-0l3TY2Gn.css.map +1 -0
  160. package/dist/C_NotificationCenter.cjs +20 -0
  161. package/dist/C_NotificationCenter.d.cts +2 -0
  162. package/dist/C_NotificationCenter.d.ts +2 -0
  163. package/dist/C_NotificationCenter.js +4 -0
  164. package/dist/C_NotificationCenter2.js +1383 -0
  165. package/dist/C_NotificationCenter2.js.map +1 -0
  166. package/dist/C_Progress.cjs +4 -0
  167. package/dist/C_Progress.d.cts +2 -0
  168. package/dist/C_Progress.d.ts +2 -0
  169. package/dist/C_Progress.js +3 -0
  170. package/dist/C_Progress2.js +103 -0
  171. package/dist/C_Progress2.js.map +1 -0
  172. package/dist/C_QRCode-DbdiAIPg.css.map +1 -0
  173. package/dist/C_QRCode.cjs +5 -0
  174. package/dist/C_QRCode.d.cts +2 -0
  175. package/dist/C_QRCode.d.ts +2 -0
  176. package/dist/C_QRCode.js +3 -0
  177. package/dist/C_QRCode2.js +218 -0
  178. package/dist/C_QRCode2.js.map +1 -0
  179. package/dist/C_Signature-zhHCbra9.css.map +1 -0
  180. package/dist/C_Signature.cjs +8 -0
  181. package/dist/C_Signature.d.cts +2 -0
  182. package/dist/C_Signature.d.ts +2 -0
  183. package/dist/C_Signature.js +4 -0
  184. package/dist/C_Signature2.js +618 -0
  185. package/dist/C_Signature2.js.map +1 -0
  186. package/dist/C_SplitPane-C6sBsfKY.css.map +1 -0
  187. package/dist/C_SplitPane.cjs +6 -0
  188. package/dist/C_SplitPane.d.cts +2 -0
  189. package/dist/C_SplitPane.d.ts +2 -0
  190. package/dist/C_SplitPane.js +4 -0
  191. package/dist/C_SplitPane2.js +356 -0
  192. package/dist/C_SplitPane2.js.map +1 -0
  193. package/dist/C_Steps-CODHN5Hs.css.map +1 -0
  194. package/dist/C_Steps.cjs +4 -0
  195. package/dist/C_Steps.d.cts +2 -0
  196. package/dist/C_Steps.d.ts +2 -0
  197. package/dist/C_Steps.js +3 -0
  198. package/dist/C_Steps2.js +82 -0
  199. package/dist/C_Steps2.js.map +1 -0
  200. package/dist/C_Table-DSNsntmT.css.map +1 -0
  201. package/dist/C_Table.cjs +19 -0
  202. package/dist/C_Table.d.cts +2 -0
  203. package/dist/C_Table.d.ts +2 -0
  204. package/dist/C_Table.js +5 -0
  205. package/dist/C_Table2.js +3009 -0
  206. package/dist/C_Table2.js.map +1 -0
  207. package/dist/C_Theme.cjs +4 -0
  208. package/dist/C_Theme.d.cts +2 -0
  209. package/dist/C_Theme.d.ts +2 -0
  210. package/dist/C_Theme.js +3 -0
  211. package/dist/C_Theme2.js +60 -0
  212. package/dist/C_Theme2.js.map +1 -0
  213. package/dist/C_Time-BvZLYraL.css.map +1 -0
  214. package/dist/C_Time.cjs +5 -0
  215. package/dist/C_Time.d.cts +2 -0
  216. package/dist/C_Time.d.ts +2 -0
  217. package/dist/C_Time.js +3 -0
  218. package/dist/C_Time2.js +199 -0
  219. package/dist/C_Time2.js.map +1 -0
  220. package/dist/C_Tree-0GDv--jX.css.map +1 -0
  221. package/dist/C_Tree.cjs +7 -0
  222. package/dist/C_Tree.d.cts +2 -0
  223. package/dist/C_Tree.d.ts +2 -0
  224. package/dist/C_Tree.js +4 -0
  225. package/dist/C_Tree2.js +441 -0
  226. package/dist/C_Tree2.js.map +1 -0
  227. package/dist/C_Upload-BXd3YYLx.css.map +1 -0
  228. package/dist/C_Upload.cjs +12 -0
  229. package/dist/C_Upload.d.cts +2 -0
  230. package/dist/C_Upload.d.ts +2 -0
  231. package/dist/C_Upload.js +4 -0
  232. package/dist/C_Upload2.js +1388 -0
  233. package/dist/C_Upload2.js.map +1 -0
  234. package/dist/C_VideoPlayer-DYG3RL0Q.css.map +1 -0
  235. package/dist/C_VideoPlayer.cjs +23 -0
  236. package/dist/C_VideoPlayer.d.cts +2 -0
  237. package/dist/C_VideoPlayer.d.ts +2 -0
  238. package/dist/C_VideoPlayer.js +3 -0
  239. package/dist/C_VideoPlayer2.js +1932 -0
  240. package/dist/C_VideoPlayer2.js.map +1 -0
  241. package/dist/C_VtableGantt-fhItIiHE.css.map +1 -0
  242. package/dist/C_VtableGantt.cjs +6 -0
  243. package/dist/C_VtableGantt.d.cts +2 -0
  244. package/dist/C_VtableGantt.d.ts +2 -0
  245. package/dist/C_VtableGantt.js +4 -0
  246. package/dist/C_VtableGantt2.js +873 -0
  247. package/dist/C_VtableGantt2.js.map +1 -0
  248. package/dist/C_WaterFall-8sQDFXKg.css.map +1 -0
  249. package/dist/C_WaterFall.cjs +13 -0
  250. package/dist/C_WaterFall.d.cts +2 -0
  251. package/dist/C_WaterFall.d.ts +2 -0
  252. package/dist/C_WaterFall.js +3 -0
  253. package/dist/C_WaterFall2.js +365 -0
  254. package/dist/C_WaterFall2.js.map +1 -0
  255. package/dist/C_WorkFlow-J-dyIuh9.css.map +1 -0
  256. package/dist/C_WorkFlow.cjs +8 -0
  257. package/dist/C_WorkFlow.d.cts +2 -0
  258. package/dist/C_WorkFlow.d.ts +2 -0
  259. package/dist/C_WorkFlow.js +4 -0
  260. package/dist/C_WorkFlow2.js +1984 -0
  261. package/dist/C_WorkFlow2.js.map +1 -0
  262. package/dist/chunk.js +22 -0
  263. package/dist/city.js +4817 -0
  264. package/dist/city.js.map +1 -0
  265. package/dist/constants.d.ts +273 -0
  266. package/dist/constants.d.ts.map +1 -0
  267. package/dist/constants2.d.ts +178 -0
  268. package/dist/constants2.d.ts.map +1 -0
  269. package/dist/constants3.d.ts +475 -0
  270. package/dist/constants3.d.ts.map +1 -0
  271. package/dist/constants4.d.ts +430 -0
  272. package/dist/constants4.d.ts.map +1 -0
  273. package/dist/constants5.d.ts +4283 -0
  274. package/dist/constants5.d.ts.map +1 -0
  275. package/dist/data.d.ts +67 -0
  276. package/dist/data.d.ts.map +1 -0
  277. package/dist/export-helper.js +9 -0
  278. package/dist/index.cjs +409 -0
  279. package/dist/index.d.cts +96 -0
  280. package/dist/index.d.cts.map +1 -0
  281. package/dist/index.d.ts +103 -0
  282. package/dist/index.d.ts.map +1 -0
  283. package/dist/index.js +230 -0
  284. package/dist/index.js.map +1 -0
  285. package/dist/index.vue.d.ts +80 -0
  286. package/dist/index.vue.d.ts.map +1 -0
  287. package/dist/index10.vue.d.ts +72 -0
  288. package/dist/index10.vue.d.ts.map +1 -0
  289. package/dist/index11.vue.d.ts +26 -0
  290. package/dist/index11.vue.d.ts.map +1 -0
  291. package/dist/index12.vue.d.ts +81 -0
  292. package/dist/index12.vue.d.ts.map +1 -0
  293. package/dist/index13.vue.d.ts +55 -0
  294. package/dist/index13.vue.d.ts.map +1 -0
  295. package/dist/index14.vue.d.ts +33 -0
  296. package/dist/index14.vue.d.ts.map +1 -0
  297. package/dist/index15.vue.d.ts +18 -0
  298. package/dist/index15.vue.d.ts.map +1 -0
  299. package/dist/index16.vue.d.ts +662 -0
  300. package/dist/index16.vue.d.ts.map +1 -0
  301. package/dist/index2.vue.d.ts +38 -0
  302. package/dist/index2.vue.d.ts.map +1 -0
  303. package/dist/index3.vue.d.ts +45 -0
  304. package/dist/index3.vue.d.ts.map +1 -0
  305. package/dist/index4.vue.d.ts +31 -0
  306. package/dist/index4.vue.d.ts.map +1 -0
  307. package/dist/index5.vue.d.ts +35 -0
  308. package/dist/index5.vue.d.ts.map +1 -0
  309. package/dist/index6.vue.d.ts +48 -0
  310. package/dist/index6.vue.d.ts.map +1 -0
  311. package/dist/index7.vue.d.ts +56 -0
  312. package/dist/index7.vue.d.ts.map +1 -0
  313. package/dist/index8.vue.d.ts +41 -0
  314. package/dist/index8.vue.d.ts.map +1 -0
  315. package/dist/index9.vue.d.ts +30 -0
  316. package/dist/index9.vue.d.ts.map +1 -0
  317. package/dist/storage.js +31 -0
  318. package/dist/storage.js.map +1 -0
  319. package/dist/style.css +7725 -0
  320. package/dist/useCalendarEvents.d.ts +148 -0
  321. package/dist/useCalendarEvents.d.ts.map +1 -0
  322. package/dist/useCollapsePanel.d.ts +132 -0
  323. package/dist/useCollapsePanel.d.ts.map +1 -0
  324. package/dist/useCropperCore.d.ts +102 -0
  325. package/dist/useCropperCore.d.ts.map +1 -0
  326. package/dist/useDraggableLayout.d.ts +194 -0
  327. package/dist/useDraggableLayout.d.ts.map +1 -0
  328. package/dist/useDynamicFormState.d.ts +4248 -0
  329. package/dist/useDynamicFormState.d.ts.map +1 -0
  330. package/dist/useEdgeInteraction.d.ts +7614 -0
  331. package/dist/useEdgeInteraction.d.ts.map +1 -0
  332. package/dist/useFullscreen.d.ts +166 -0
  333. package/dist/useFullscreen.d.ts.map +1 -0
  334. package/dist/useInfiniteScroll.d.ts +169 -0
  335. package/dist/useInfiniteScroll.d.ts.map +1 -0
  336. package/dist/useModalEdit.d.ts +960 -0
  337. package/dist/useModalEdit.d.ts.map +1 -0
  338. package/dist/useQRCode.d.ts +87 -0
  339. package/dist/useQRCode.d.ts.map +1 -0
  340. package/dist/useSearchState.d.ts +180 -0
  341. package/dist/useSearchState.d.ts.map +1 -0
  342. package/dist/useSignatureHistory.d.ts +189 -0
  343. package/dist/useSignatureHistory.d.ts.map +1 -0
  344. package/dist/useSplitResize.d.ts +158 -0
  345. package/dist/useSplitResize.d.ts.map +1 -0
  346. package/dist/useTimeSelection.d.ts +105 -0
  347. package/dist/useTimeSelection.d.ts.map +1 -0
  348. package/dist/useTreeOperations.d.ts +183 -0
  349. package/dist/useTreeOperations.d.ts.map +1 -0
  350. package/dist/useWorkflowValidation.d.ts +1052 -0
  351. package/dist/useWorkflowValidation.d.ts.map +1 -0
  352. package/package.json +342 -0
@@ -0,0 +1,3009 @@
1
+ import { n as __require } from "./chunk.js";
2
+ import { t as C_Icon_default } from "./C_Icon2.js";
3
+ import { t as export_helper_default } from "./export-helper.js";
4
+ import { t as C_Form_default } from "./C_Form2.js";
5
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, h, isRef, mergeProps, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, watch, watchEffect, withCtx } from "vue";
6
+ import { NButton, NDatePicker, NDropdown, NInput, NInputNumber, NSelect, NSpace, NSwitch, useDialog, useMessage } from "naive-ui";
7
+ import html2canvas from "html2canvas";
8
+ import { NButton as NButton$1, NButtonGroup as NButtonGroup$1, NCheckbox as NCheckbox$1, NDataTable, NDrawer as NDrawer$1, NDrawerContent as NDrawerContent$1, NDropdown as NDropdown$1, NInput as NInput$1, NModal as NModal$1, NPagination as NPagination$1, NSpace as NSpace$1, NSpin as NSpin$1, NSwitch as NSwitch$1, NTag as NTag$1, NText as NText$1, NTooltip as NTooltip$1, useMessage as useMessage$1 } from "naive-ui/es";
9
+ import printJS from "print-js";
10
+
11
+ //#region src/components/C_Table/composables/useTableConfig.ts
12
+ const EDIT_DISABLED = {
13
+ editable: false,
14
+ editMode: "none",
15
+ showRowActions: false,
16
+ modalTitle: "编辑数据",
17
+ modalWidth: 600
18
+ };
19
+ const resolveEdit = (edit) => {
20
+ if (edit === false || edit === void 0) return EDIT_DISABLED;
21
+ if (edit === true) return {
22
+ editable: true,
23
+ editMode: "modal",
24
+ showRowActions: true,
25
+ modalTitle: "编辑数据",
26
+ modalWidth: 600
27
+ };
28
+ return {
29
+ editable: edit.enabled !== false && edit.mode !== "none",
30
+ editMode: edit.mode || "modal",
31
+ showRowActions: edit.showRowActions !== false && edit.mode !== "none",
32
+ modalTitle: edit.modalTitle || "编辑数据",
33
+ modalWidth: edit.modalWidth || 600
34
+ };
35
+ };
36
+ const resolveExpand = (expand) => {
37
+ if (!expand) return {
38
+ expandable: false,
39
+ defaultExpandedKeys: void 0,
40
+ onLoadExpandData: void 0,
41
+ renderExpandContent: void 0,
42
+ rowExpandable: void 0
43
+ };
44
+ if (expand === true) return {
45
+ expandable: true,
46
+ defaultExpandedKeys: void 0,
47
+ onLoadExpandData: void 0,
48
+ renderExpandContent: void 0,
49
+ rowExpandable: void 0
50
+ };
51
+ return {
52
+ expandable: expand.enabled !== false,
53
+ defaultExpandedKeys: expand.defaultExpandedKeys,
54
+ onLoadExpandData: expand.onLoadData,
55
+ renderExpandContent: expand.renderContent,
56
+ rowExpandable: expand.rowExpandable
57
+ };
58
+ };
59
+ const resolveSelection = (selection) => {
60
+ if (!selection) return {
61
+ enableSelection: false,
62
+ defaultCheckedKeys: void 0,
63
+ rowCheckable: void 0,
64
+ maxSelection: void 0,
65
+ enableChildSelection: false,
66
+ childRowCheckable: void 0,
67
+ enableParentChildLink: false,
68
+ parentChildLinkMode: "loose"
69
+ };
70
+ if (selection === true) return {
71
+ enableSelection: true,
72
+ defaultCheckedKeys: void 0,
73
+ rowCheckable: void 0,
74
+ maxSelection: void 0,
75
+ enableChildSelection: false,
76
+ childRowCheckable: void 0,
77
+ enableParentChildLink: false,
78
+ parentChildLinkMode: "loose"
79
+ };
80
+ const child = selection.childSelection || {};
81
+ const link = selection.parentChildLink || {};
82
+ return {
83
+ enableSelection: selection.enabled !== false,
84
+ defaultCheckedKeys: selection.defaultCheckedKeys,
85
+ rowCheckable: selection.rowCheckable,
86
+ maxSelection: selection.maxSelection,
87
+ enableChildSelection: child.enabled || false,
88
+ childRowCheckable: child.childRowCheckable,
89
+ enableParentChildLink: link.enabled || false,
90
+ parentChildLinkMode: link.mode || "loose"
91
+ };
92
+ };
93
+ const resolvePagination = (pagination) => {
94
+ const defaults = {
95
+ enabled: true,
96
+ page: 1,
97
+ pageSize: 10,
98
+ showSizePicker: true,
99
+ showQuickJumper: true,
100
+ pageSizes: [
101
+ 10,
102
+ 20,
103
+ 50,
104
+ 100
105
+ ],
106
+ simple: false,
107
+ size: "medium"
108
+ };
109
+ if (pagination === false) return { pagination: null };
110
+ if (pagination === true || pagination === void 0) return { pagination: defaults };
111
+ return { pagination: {
112
+ ...defaults,
113
+ ...pagination
114
+ } };
115
+ };
116
+ const resolveDynamicRows = (dynamicRows) => {
117
+ if (!dynamicRows) return { dynamicRows: void 0 };
118
+ if (dynamicRows === true) return { dynamicRows: {
119
+ enableRadioSelection: true,
120
+ enableAdd: true,
121
+ enableInsert: true,
122
+ enableDelete: true,
123
+ enableCopy: true,
124
+ enableMove: true,
125
+ enablePrint: true
126
+ } };
127
+ return { dynamicRows };
128
+ };
129
+ const DISPLAY_DEFAULTS = {
130
+ striped: true,
131
+ bordered: true,
132
+ singleLine: true,
133
+ size: "medium",
134
+ maxHeight: void 0,
135
+ scrollX: void 0,
136
+ columnWidth: 180
137
+ };
138
+ /** 解析 display 配置,合并默认值 */
139
+ function resolveDisplay(display) {
140
+ if (!display) return { ...DISPLAY_DEFAULTS };
141
+ return {
142
+ striped: display.striped ?? DISPLAY_DEFAULTS.striped,
143
+ bordered: display.bordered ?? DISPLAY_DEFAULTS.bordered,
144
+ singleLine: display.singleLine ?? DISPLAY_DEFAULTS.singleLine,
145
+ size: display.size ?? DISPLAY_DEFAULTS.size,
146
+ maxHeight: display.maxHeight,
147
+ scrollX: display.scrollX,
148
+ columnWidth: display.columnWidth ?? DISPLAY_DEFAULTS.columnWidth
149
+ };
150
+ }
151
+ const resolveToolbar = (toolbar) => ({
152
+ showToolbar: toolbar?.show !== false,
153
+ enableColumnSettings: toolbar?.columnSettings !== false
154
+ });
155
+ /**
156
+ * 将 config 单一对象解析为内部扁平化配置
157
+ */
158
+ function resolveConfig(config = {}) {
159
+ return {
160
+ ...resolveEdit(config.edit),
161
+ ...resolveExpand(config.expand),
162
+ ...resolveSelection(config.selection),
163
+ ...resolvePagination(config.pagination),
164
+ ...resolveDynamicRows(config.dynamicRows),
165
+ ...resolveDisplay(config.display),
166
+ ...resolveToolbar(config.toolbar)
167
+ };
168
+ }
169
+ const createEditModeChecker = (config) => ({
170
+ isNonEditable: (column) => !config.editable || column.editable === false || config.editMode === "none",
171
+ isRowEditMode: () => ["row", "both"].includes(config.editMode),
172
+ isCellEditMode: () => ["cell", "both"].includes(config.editMode)
173
+ });
174
+
175
+ //#endregion
176
+ //#region src/components/C_Table/composables/useRowEdit.ts
177
+ /**
178
+ * 可编辑行组合函数,提供表格整行的编辑功能
179
+ */
180
+ function useRowEdit(options) {
181
+ const editingRowKey = ref(null);
182
+ const editingData = ref({});
183
+ /**
184
+ * 检查指定行是否正在编辑状态
185
+ */
186
+ const isEditingRow = (rowKey) => {
187
+ return editingRowKey.value === rowKey;
188
+ };
189
+ /**
190
+ * 根据rowKey实时查找最新的行数据
191
+ */
192
+ const findRowData = (rowKey) => {
193
+ const currentData = options.data();
194
+ if (!currentData || !Array.isArray(currentData)) return null;
195
+ return currentData.find((row) => options.rowKey(row) === rowKey);
196
+ };
197
+ /**
198
+ * 开始编辑指定行,将原始数据复制到编辑缓存中
199
+ */
200
+ const startEditRow = (rowKey) => {
201
+ const rowData = findRowData(rowKey);
202
+ if (!rowData) return;
203
+ editingRowKey.value = rowKey;
204
+ editingData.value[rowKey] = { ...rowData };
205
+ };
206
+ /**
207
+ * 取消当前行编辑,调用取消回调并清理编辑状态
208
+ */
209
+ const cancelEditRow = async () => {
210
+ if (!editingRowKey.value) return;
211
+ const currentData = options.data();
212
+ if (!currentData || !Array.isArray(currentData)) return;
213
+ const rowIndex = currentData.findIndex((row) => options.rowKey(row) === editingRowKey.value);
214
+ if (rowIndex > -1) await options.onCancel?.(currentData[rowIndex], rowIndex);
215
+ editingRowKey.value = null;
216
+ editingData.value = {};
217
+ };
218
+ /**
219
+ * 保存当前行编辑,调用保存回调并清理编辑状态
220
+ */
221
+ const saveEditRow = async () => {
222
+ if (!editingRowKey.value) return;
223
+ const rowKey = editingRowKey.value;
224
+ const currentData = options.data();
225
+ if (!currentData || !Array.isArray(currentData)) return;
226
+ const rowIndex = currentData.findIndex((row) => options.rowKey(row) === rowKey);
227
+ if (rowIndex === -1) return;
228
+ const updatedData = editingData.value[rowKey];
229
+ if (!updatedData) return;
230
+ await options.onSave?.(updatedData, rowIndex);
231
+ editingRowKey.value = null;
232
+ editingData.value = {};
233
+ return {
234
+ updatedData,
235
+ rowIndex
236
+ };
237
+ };
238
+ /**
239
+ * 获取指定行的编辑中数据
240
+ */
241
+ const getEditingRowData = (rowKey) => {
242
+ return editingData.value[rowKey];
243
+ };
244
+ /**
245
+ * 更新指定行编辑中的字段值
246
+ */
247
+ const updateEditingRowData = (rowKey, field, value) => {
248
+ if (!editingData.value[rowKey]) return;
249
+ editingData.value[rowKey][field] = value;
250
+ };
251
+ return {
252
+ editingRowKey,
253
+ isEditingRow,
254
+ startEditRow,
255
+ cancelEditRow,
256
+ saveEditRow,
257
+ getEditingRowData,
258
+ updateEditingRowData,
259
+ findRowData
260
+ };
261
+ }
262
+
263
+ //#endregion
264
+ //#region src/components/C_Table/composables/useCellEdit.ts
265
+ /**
266
+ * 可编辑单元格组合函数,提供表格单元格的编辑功能
267
+ */
268
+ function useCellEdit(options) {
269
+ const editingCell = ref({
270
+ rowKey: null,
271
+ columnKey: null
272
+ });
273
+ const editingData = ref({});
274
+ /**
275
+ * 检查指定单元格是否正在编辑状态
276
+ */
277
+ const isEditingCell = (rowKey, columnKey) => {
278
+ return editingCell.value.rowKey === rowKey && editingCell.value.columnKey === columnKey;
279
+ };
280
+ /**
281
+ * 根据rowKey实时查找最新的行数据
282
+ */
283
+ const findRowData = (rowKey) => {
284
+ const currentData = options.data();
285
+ if (!currentData || !Array.isArray(currentData)) return null;
286
+ return currentData.find((row) => options.rowKey(row) === rowKey);
287
+ };
288
+ /**
289
+ * 开始编辑指定单元格,将原值存储到编辑缓存中
290
+ */
291
+ const startEditCell = (rowKey, columnKey) => {
292
+ const rowData = findRowData(rowKey);
293
+ if (!rowData) return;
294
+ editingCell.value = {
295
+ rowKey,
296
+ columnKey
297
+ };
298
+ editingData.value[`${rowKey}-${columnKey}`] = rowData[columnKey];
299
+ };
300
+ /**
301
+ * 保存当前编辑的单元格,调用保存回调并清理编辑状态
302
+ */
303
+ const saveEditCell = async () => {
304
+ const { rowKey, columnKey } = editingCell.value;
305
+ if (!rowKey || !columnKey) return;
306
+ const currentData = options.data();
307
+ if (!currentData || !Array.isArray(currentData)) return;
308
+ const rowIndex = currentData.findIndex((row) => options.rowKey(row) === rowKey);
309
+ if (rowIndex === -1) return;
310
+ const cellKey = `${rowKey}-${columnKey}`;
311
+ const newValue = editingData.value[cellKey];
312
+ const updatedData = {
313
+ ...currentData[rowIndex],
314
+ [columnKey]: newValue
315
+ };
316
+ await options.onSave?.(updatedData, rowIndex, columnKey);
317
+ editingCell.value = {
318
+ rowKey: null,
319
+ columnKey: null
320
+ };
321
+ delete editingData.value[cellKey];
322
+ return {
323
+ updatedData,
324
+ rowIndex,
325
+ columnKey
326
+ };
327
+ };
328
+ /**
329
+ * 取消当前单元格编辑,清理编辑状态和缓存数据
330
+ */
331
+ const cancelEditCell = () => {
332
+ const { rowKey, columnKey } = editingCell.value;
333
+ if (rowKey && columnKey) delete editingData.value[`${rowKey}-${columnKey}`];
334
+ editingCell.value = {
335
+ rowKey: null,
336
+ columnKey: null
337
+ };
338
+ };
339
+ /**
340
+ * 获取指定单元格的编辑中数值
341
+ */
342
+ const getEditingCellValue = (rowKey, columnKey) => {
343
+ return editingData.value[`${rowKey}-${columnKey}`];
344
+ };
345
+ /**
346
+ * 更新指定单元格的编辑中数值
347
+ */
348
+ const updateEditingCellValue = (rowKey, columnKey, value) => {
349
+ editingData.value[`${rowKey}-${columnKey}`] = value;
350
+ };
351
+ return {
352
+ editingCell,
353
+ isEditingCell,
354
+ startEditCell,
355
+ saveEditCell,
356
+ cancelEditCell,
357
+ getEditingCellValue,
358
+ updateEditingCellValue,
359
+ findRowData
360
+ };
361
+ }
362
+
363
+ //#endregion
364
+ //#region src/components/C_Table/composables/useModalEdit.ts
365
+ /**
366
+ * 模态框编辑组合函数,提供弹窗形式的数据编辑功能
367
+ */
368
+ function useModalEdit(options) {
369
+ const isModalVisible = ref(false);
370
+ const editingRowKey = ref(null);
371
+ const editingData = ref({});
372
+ /**
373
+ * 计算属性:获取当前编辑行的索引
374
+ */
375
+ const editingRowIndex = computed(() => {
376
+ if (!editingRowKey.value) return -1;
377
+ const currentData = options.data();
378
+ if (!currentData || !Array.isArray(currentData)) return -1;
379
+ return currentData.findIndex((row) => options.rowKey(row) === editingRowKey.value);
380
+ });
381
+ /**
382
+ * 重置编辑状态
383
+ */
384
+ const resetEditingState = () => {
385
+ editingRowKey.value = null;
386
+ editingData.value = {};
387
+ };
388
+ /**
389
+ * 开始编辑指定行
390
+ */
391
+ const startEdit = (rowKey) => {
392
+ console.log("🚀 开始编辑:", rowKey);
393
+ const currentData = options.data();
394
+ if (!currentData || !Array.isArray(currentData)) {
395
+ console.warn("数据源为空或不是数组");
396
+ return;
397
+ }
398
+ const rowIndex = currentData.findIndex((row) => options.rowKey(row) === rowKey);
399
+ if (rowIndex === -1) {
400
+ console.warn("未找到对应的行数据:", rowKey);
401
+ return;
402
+ }
403
+ const rowData = currentData[rowIndex];
404
+ console.log("找到行数据:", rowData);
405
+ editingRowKey.value = rowKey;
406
+ editingData.value = JSON.parse(JSON.stringify(rowData));
407
+ console.log("编辑数据已准备:", editingData.value);
408
+ isModalVisible.value = true;
409
+ };
410
+ /**
411
+ * 保存编辑
412
+ */
413
+ const saveEdit = async (formData) => {
414
+ const dataToSave = formData || editingData.value;
415
+ const currentIndex = editingRowIndex.value;
416
+ console.log("💾 保存编辑:", {
417
+ rowKey: editingRowKey.value,
418
+ index: currentIndex,
419
+ data: dataToSave
420
+ });
421
+ if (currentIndex === -1) {
422
+ console.warn("无法找到编辑行的索引");
423
+ return;
424
+ }
425
+ try {
426
+ await options.onSave?.(dataToSave, currentIndex);
427
+ isModalVisible.value = false;
428
+ resetEditingState();
429
+ console.log("✅ 保存成功");
430
+ } catch (error) {
431
+ console.error("❌ 保存失败:", error);
432
+ throw error;
433
+ }
434
+ };
435
+ /**
436
+ * 取消编辑
437
+ */
438
+ const cancelEdit = async () => {
439
+ console.log("🚫 取消编辑");
440
+ try {
441
+ const currentIndex = editingRowIndex.value;
442
+ if (editingRowKey.value && currentIndex > -1) {
443
+ const currentData = options.data();
444
+ if (currentData && currentData[currentIndex]) await options.onCancel?.(currentData[currentIndex], currentIndex);
445
+ }
446
+ } finally {
447
+ isModalVisible.value = false;
448
+ resetEditingState();
449
+ }
450
+ };
451
+ /**
452
+ * 更新编辑数据
453
+ */
454
+ const updateEditingData = (data) => {
455
+ editingData.value = { ...data };
456
+ };
457
+ /**
458
+ * 获取当前编辑的行数据
459
+ */
460
+ const getEditingRowData = (rowKey) => {
461
+ if (editingRowKey.value === rowKey) return editingData.value;
462
+ return null;
463
+ };
464
+ /**
465
+ * 检查是否正在编辑指定行
466
+ */
467
+ const isEditingRow = (rowKey) => {
468
+ return editingRowKey.value === rowKey && isModalVisible.value;
469
+ };
470
+ return {
471
+ isModalVisible,
472
+ editingData,
473
+ editingRowKey,
474
+ editingRowIndex,
475
+ startEdit,
476
+ saveEdit,
477
+ cancelEdit,
478
+ updateEditingData,
479
+ resetEditingState,
480
+ isEditingRow,
481
+ getEditingRowData
482
+ };
483
+ }
484
+
485
+ //#endregion
486
+ //#region src/components/C_Table/composables/useTableExpand.ts
487
+ const useExpandState = (options) => {
488
+ return {
489
+ expandedKeys: ref([...options.defaultExpandedKeys || []]),
490
+ expandDataMap: ref(/* @__PURE__ */ new Map()),
491
+ loadingMap: ref(/* @__PURE__ */ new Map()),
492
+ checkedKeys: options.enableSelection ? ref([...options.defaultCheckedKeys || []]) : ref([]),
493
+ childSelections: options.enableChildSelection ? ref(/* @__PURE__ */ new Map()) : ref(/* @__PURE__ */ new Map())
494
+ };
495
+ };
496
+ const useDataUtils = (options) => {
497
+ const data = computed(() => unref(options.data));
498
+ const getRowKey = options.rowKey;
499
+ const getChildRowKey = options.childRowKey || ((child) => child.id);
500
+ const findRow = (key) => data.value.find((row) => getRowKey(row) === key);
501
+ return {
502
+ data,
503
+ getRowKey,
504
+ getChildRowKey,
505
+ findRow,
506
+ isRowExpandable: options.rowExpandable || (() => true),
507
+ isRowCheckable: options.rowCheckable || (() => true),
508
+ isChildRowCheckable: options.childRowCheckable || (() => true)
509
+ };
510
+ };
511
+ const useExpandLogic = (state, utils, options) => {
512
+ const loadData = async (row) => {
513
+ if (!options.onLoadData) return [];
514
+ const key = utils.getRowKey(row);
515
+ const existingData = state.expandDataMap.value.get(key);
516
+ if (existingData) return existingData;
517
+ state.loadingMap.value.set(key, true);
518
+ try {
519
+ const result = await options.onLoadData(row) || [];
520
+ state.expandDataMap.value.set(key, result);
521
+ if (options.enableChildSelection && !state.childSelections.value.has(key)) state.childSelections.value.set(key, []);
522
+ return result;
523
+ } catch (error) {
524
+ console.error("加载展开数据失败:", error);
525
+ return [];
526
+ } finally {
527
+ state.loadingMap.value.set(key, false);
528
+ }
529
+ };
530
+ const handleRowExpand = async (row, expanded) => {
531
+ const key = utils.getRowKey(row);
532
+ if (expanded) {
533
+ await loadData(row);
534
+ if (!state.expandedKeys.value.includes(key)) state.expandedKeys.value = [...state.expandedKeys.value, key];
535
+ } else state.expandedKeys.value = state.expandedKeys.value.filter((k) => k !== key);
536
+ options.onExpandChange?.(state.expandedKeys.value);
537
+ };
538
+ const expandAll = async () => {
539
+ const expandableRows = utils.data.value.filter(utils.isRowExpandable);
540
+ await Promise.allSettled(expandableRows.map(loadData));
541
+ state.expandedKeys.value = expandableRows.map(utils.getRowKey);
542
+ options.onExpandChange?.(state.expandedKeys.value);
543
+ };
544
+ const collapseAll = () => {
545
+ state.expandedKeys.value = [];
546
+ state.childSelections.value.clear();
547
+ options.onExpandChange?.(state.expandedKeys.value);
548
+ };
549
+ const handleExpandChange = async (keys) => {
550
+ const newExpandedKeys = keys.filter((key) => !state.expandedKeys.value.includes(key));
551
+ const collapsedKeys = state.expandedKeys.value.filter((key) => !keys.includes(key));
552
+ await Promise.all(newExpandedKeys.map(async (key) => {
553
+ const row = utils.findRow(key);
554
+ if (row) await loadData(row);
555
+ }));
556
+ for (const key of collapsedKeys) state.childSelections.value.delete(key);
557
+ state.expandedKeys.value = keys;
558
+ options.onExpandChange?.(keys);
559
+ };
560
+ return {
561
+ loadData,
562
+ handleRowExpand,
563
+ expandAll,
564
+ collapseAll,
565
+ handleExpandChange
566
+ };
567
+ };
568
+ const useSelectionLogic = (state, utils, options) => {
569
+ const selectableRows = computed(() => utils.data.value.filter(utils.isRowCheckable));
570
+ const selectedRowsCount = computed(() => state.checkedKeys.value.length);
571
+ const selectAll = () => {
572
+ if (!options.enableSelection) return;
573
+ const keys = selectableRows.value.map(utils.getRowKey);
574
+ const finalKeys = options.maxSelection ? keys.slice(0, options.maxSelection) : keys;
575
+ state.checkedKeys.value = finalKeys;
576
+ const selectedRows = selectableRows.value.filter((row) => finalKeys.includes(utils.getRowKey(row)));
577
+ options.onSelectionChange?.(finalKeys, selectedRows, state.childSelections.value);
578
+ };
579
+ const clearSelection = () => {
580
+ if (!options.enableSelection) return;
581
+ state.checkedKeys.value = [];
582
+ options.onSelectionChange?.([], [], state.childSelections.value);
583
+ };
584
+ const handleSelectionChange = (keys) => {
585
+ if (!options.enableSelection) return;
586
+ state.checkedKeys.value = keys;
587
+ const selectedRows = utils.data.value.filter((row) => keys.includes(utils.getRowKey(row)));
588
+ options.onSelectionChange?.(keys, selectedRows, state.childSelections.value);
589
+ };
590
+ return {
591
+ selectAll,
592
+ clearSelection,
593
+ handleSelectionChange,
594
+ selectedRowsCount,
595
+ selectableRows
596
+ };
597
+ };
598
+ const useParentChildLink = (state, options) => {
599
+ const isLinkEnabled = Boolean(options.enableParentChildLink && options.enableSelection && options.enableChildSelection);
600
+ const handleParentChildLink = (parentKey, selectedChildKeys, totalChildren) => {
601
+ if (!isLinkEnabled) return;
602
+ const shouldSelectParent = options.parentChildLinkMode === "strict" ? selectedChildKeys.length === totalChildren && totalChildren > 0 : selectedChildKeys.length > 0;
603
+ const currentKeys = [...state.checkedKeys.value];
604
+ const isParentSelected = currentKeys.includes(parentKey);
605
+ if (shouldSelectParent && !isParentSelected) state.checkedKeys.value = [...currentKeys, parentKey];
606
+ else if (!shouldSelectParent && isParentSelected) state.checkedKeys.value = currentKeys.filter((k) => k !== parentKey);
607
+ };
608
+ return {
609
+ handleParentChildLink,
610
+ isLinkEnabled
611
+ };
612
+ };
613
+ const useChildSelectionLogic = (state, utils, parentChildLink, options) => {
614
+ const totalChildSelections = computed(() => {
615
+ if (!options.enableChildSelection) return 0;
616
+ return Array.from(state.childSelections.value.values()).reduce((total, keys) => total + keys.length, 0);
617
+ });
618
+ const clearAllSelections = () => {
619
+ state.checkedKeys.value = [];
620
+ state.childSelections.value.clear();
621
+ options.onSelectionChange?.([], [], state.childSelections.value);
622
+ };
623
+ const handleChildSelectionChange = (parentKey, childKeys) => {
624
+ if (!options.enableChildSelection) return;
625
+ state.childSelections.value.set(parentKey, childKeys);
626
+ const expandData = state.expandDataMap.value.get(parentKey) || [];
627
+ const selectedChildren = expandData.filter((child) => childKeys.includes(utils.getChildRowKey(child)));
628
+ options.onChildSelectionChange?.(parentKey, childKeys, selectedChildren);
629
+ if (parentChildLink.isLinkEnabled) parentChildLink.handleParentChildLink(parentKey, childKeys, expandData.length);
630
+ };
631
+ return {
632
+ totalChildSelections,
633
+ clearAllSelections,
634
+ handleChildSelectionChange
635
+ };
636
+ };
637
+ const createChildSelectionState = (parentKey, state, utils, childLogic, options) => {
638
+ if (!options.enableChildSelection) return void 0;
639
+ const selectedKeys = state.childSelections.value.get(parentKey) || [];
640
+ const expandData = state.expandDataMap.value.get(parentKey) || [];
641
+ const parent = utils.findRow(parentKey);
642
+ if (!parent) return void 0;
643
+ const checkableChildren = expandData.filter((child) => utils.isChildRowCheckable(child, parent));
644
+ return {
645
+ selectedKeys,
646
+ isAllChecked: checkableChildren.length > 0 && checkableChildren.every((child) => selectedKeys.includes(utils.getChildRowKey(child))),
647
+ selectAll: () => {
648
+ const allKeys = checkableChildren.map((child) => utils.getChildRowKey(child));
649
+ childLogic.handleChildSelectionChange(parentKey, allKeys);
650
+ },
651
+ clearAll: () => {
652
+ childLogic.handleChildSelectionChange(parentKey, []);
653
+ }
654
+ };
655
+ };
656
+ const createLoadingView = () => {
657
+ return h("div", { class: "flex justify-center items-center py-8" }, [h(NSpin$1, { size: "small" }), h("span", { class: "ml-2 text-gray-500" }, "加载中...")]);
658
+ };
659
+ const createEmptyView = () => {
660
+ return h("div", { class: "text-center py-8 text-gray-400" }, "暂无数据");
661
+ };
662
+ const createDefaultColumns = (expandData) => {
663
+ if (!expandData.length) return [];
664
+ const firstItem = expandData[0];
665
+ if (!firstItem || typeof firstItem !== "object") return [];
666
+ return [{
667
+ title: "序号",
668
+ key: "_index",
669
+ width: 60,
670
+ render: (_, index) => index + 1
671
+ }, ...Object.keys(firstItem).filter((key) => !["id", "key"].includes(key)).map((key) => ({
672
+ key,
673
+ title: key.charAt(0).toUpperCase() + key.slice(1),
674
+ width: 120,
675
+ ellipsis: { tooltip: true }
676
+ }))];
677
+ };
678
+ const createDefaultTable = (key, expandData, childSelection, utils, childLogic, options) => {
679
+ const columns = [];
680
+ if (options.enableChildSelection) columns.push({
681
+ type: "selection",
682
+ multiple: true
683
+ });
684
+ columns.push(...createDefaultColumns(expandData));
685
+ return h("div", { class: "p-4 bg-gray-50" }, [h("div", { class: "mb-2 text-sm text-gray-600" }, `详细信息 (${expandData.length} 条)`), h(NDataTable, {
686
+ data: expandData,
687
+ columns,
688
+ size: "small",
689
+ striped: true,
690
+ checkedRowKeys: childSelection?.selectedKeys || [],
691
+ rowKey: (row) => utils.getChildRowKey(row),
692
+ onUpdateCheckedRowKeys: options.enableChildSelection ? (keys) => {
693
+ childLogic.handleChildSelectionChange(key, keys);
694
+ } : void 0
695
+ })]);
696
+ };
697
+ const useRenderer = (state, utils, childLogic, expandLogic, options) => {
698
+ const renderExpandContent = (row) => {
699
+ const key = utils.getRowKey(row);
700
+ const expandData = state.expandDataMap.value.get(key) || [];
701
+ const loading = state.loadingMap.value.get(key) || false;
702
+ if (!expandData.length && !loading && state.expandedKeys.value.includes(key)) nextTick(() => {
703
+ expandLogic.loadData(row);
704
+ });
705
+ const childSelection = createChildSelectionState(key, state, utils, childLogic, options);
706
+ if (options.renderContent) return options.renderContent(row, expandData, loading, childSelection);
707
+ if (loading) return createLoadingView();
708
+ if (!expandData.length) return createEmptyView();
709
+ return createDefaultTable(key, expandData, childSelection, utils, childLogic, options);
710
+ };
711
+ const getTableColumns = (originalColumns) => {
712
+ return originalColumns.map((column) => {
713
+ if (column.type === "selection" && options.enableSelection) return {
714
+ type: "selection",
715
+ disabled: (row) => !utils.isRowCheckable(row),
716
+ multiple: !options.maxSelection || options.maxSelection > 1
717
+ };
718
+ if (column.type === "expand" && (options.onLoadData || options.renderContent)) return {
719
+ type: "expand",
720
+ expandable: utils.isRowExpandable,
721
+ renderExpand: renderExpandContent
722
+ };
723
+ return column;
724
+ });
725
+ };
726
+ return { getTableColumns };
727
+ };
728
+ function useTableExpand(options) {
729
+ const state = useExpandState(options);
730
+ const utils = useDataUtils(options);
731
+ const expandLogic = useExpandLogic(state, utils, options);
732
+ const selectionLogic = useSelectionLogic(state, utils, options);
733
+ const childLogic = useChildSelectionLogic(state, utils, useParentChildLink(state, options), options);
734
+ const renderer = useRenderer(state, utils, childLogic, expandLogic, options);
735
+ if (options.onSelectionChange && options.enableSelection) watchEffect(() => {
736
+ if (!options.onSelectionChange) return;
737
+ const selectedRows = utils.data.value.filter((row) => state.checkedKeys.value.includes(utils.getRowKey(row)));
738
+ const hasSelection = state.checkedKeys.value.length > 0;
739
+ const hasData = utils.data.value.length > 0;
740
+ if (hasSelection || !hasData) options.onSelectionChange(state.checkedKeys.value, selectedRows, state.childSelections.value);
741
+ });
742
+ const expandRow = async (key) => {
743
+ if (state.expandedKeys.value.includes(key)) return;
744
+ const row = utils.findRow(key);
745
+ if (!row) return;
746
+ await expandLogic.loadData(row);
747
+ state.expandedKeys.value = [...state.expandedKeys.value, key];
748
+ options.onExpandChange?.(state.expandedKeys.value, row, true);
749
+ };
750
+ const initializeData = async () => {
751
+ const keysToLoad = options.defaultExpandedKeys || [];
752
+ if (keysToLoad.length === 0) return;
753
+ const loadPromises = keysToLoad.map(async (key) => {
754
+ const row = utils.findRow(key);
755
+ if (row && !state.expandDataMap.value.has(key)) await expandLogic.loadData(row);
756
+ });
757
+ await Promise.allSettled(loadPromises);
758
+ };
759
+ if (options.defaultExpandedKeys?.length) nextTick(initializeData);
760
+ return {
761
+ expandedKeys: state.expandedKeys,
762
+ checkedKeys: state.checkedKeys,
763
+ childSelections: state.childSelections,
764
+ selectedRowsCount: selectionLogic.selectedRowsCount,
765
+ totalChildSelections: childLogic.totalChildSelections,
766
+ expandAll: expandLogic.expandAll,
767
+ collapseAll: expandLogic.collapseAll,
768
+ expandRow,
769
+ handleExpandChange: expandLogic.handleExpandChange,
770
+ selectAll: selectionLogic.selectAll,
771
+ clearSelection: selectionLogic.clearSelection,
772
+ clearAllSelections: childLogic.clearAllSelections,
773
+ handleSelectionChange: selectionLogic.handleSelectionChange,
774
+ getTableColumns: renderer.getTableColumns,
775
+ expandDataMap: state.expandDataMap,
776
+ loadingMap: state.loadingMap
777
+ };
778
+ }
779
+
780
+ //#endregion
781
+ //#region src/components/C_Table/composables/usePrintWatermark.ts
782
+ const DEFAULT_WATERMARK = {
783
+ text: "Robot Admin",
784
+ textSize: 16,
785
+ textColor: "rgba(128, 128, 128, 0.3)",
786
+ font: "Microsoft JhengHei",
787
+ opacity: .3,
788
+ rotate: -20,
789
+ position: "repeat",
790
+ xGap: 200,
791
+ yGap: 120
792
+ };
793
+ const DEFAULT_CAPTURE = {
794
+ scale: 1,
795
+ quality: .92,
796
+ format: "png",
797
+ backgroundColor: "#ffffff",
798
+ logging: false,
799
+ allowTaint: true,
800
+ useCORS: true
801
+ };
802
+ const DEFAULT_PRINT = {
803
+ orientation: "portrait",
804
+ paperSize: "A4",
805
+ margin: "10mm 10mm 0 10mm",
806
+ style: "@page { margin: 10mm 10mm 0 10mm; } @media print { body { margin: 0; } }",
807
+ header: "",
808
+ footer: "",
809
+ showModal: false,
810
+ modalMessage: "正在准备打印...",
811
+ onLoadingStart: () => {},
812
+ onLoadingEnd: () => {},
813
+ onPrintDialogClose: () => {}
814
+ };
815
+ function drawCenterWatermark(ctx, width, height, config) {
816
+ ctx.save();
817
+ ctx.translate(width / 2, height / 2);
818
+ ctx.rotate(config.rotate * Math.PI / 180);
819
+ ctx.fillText(config.text, 0, 0);
820
+ ctx.restore();
821
+ }
822
+ function drawCornerWatermark(ctx, width, height, config) {
823
+ const offset = 50;
824
+ [
825
+ [offset, offset],
826
+ [width - offset, offset],
827
+ [offset, height - offset],
828
+ [width - offset, height - offset]
829
+ ].forEach(([x, y]) => {
830
+ ctx.save();
831
+ ctx.translate(x, y);
832
+ ctx.rotate(config.rotate * Math.PI / 180);
833
+ ctx.fillText(config.text, 0, 0);
834
+ ctx.restore();
835
+ });
836
+ }
837
+ function drawDiagonalWatermark(ctx, width, height, config) {
838
+ const diagonal = Math.sqrt(width * width + height * height);
839
+ const centerX = width / 2;
840
+ const centerY = height / 2;
841
+ ctx.save();
842
+ ctx.translate(centerX, centerY);
843
+ ctx.rotate(Math.atan2(height, width));
844
+ const count = Math.floor(diagonal / config.xGap);
845
+ const start = -diagonal / 2;
846
+ for (let i = 0; i <= count; i++) {
847
+ const x = start + i * config.xGap;
848
+ ctx.fillText(config.text, x, 0);
849
+ }
850
+ ctx.restore();
851
+ }
852
+ function drawRepeatWatermark(ctx, width, height, config) {
853
+ const cols = Math.ceil(width / config.xGap) + 1;
854
+ const rows = Math.ceil(height / config.yGap) + 1;
855
+ for (let row = 0; row < rows; row++) for (let col = 0; col < cols; col++) {
856
+ const x = col * config.xGap + config.xGap / 2;
857
+ const y = row * config.yGap + config.yGap / 2;
858
+ ctx.save();
859
+ ctx.translate(x, y);
860
+ ctx.rotate(config.rotate * Math.PI / 180);
861
+ ctx.fillText(config.text, 0, 0);
862
+ ctx.restore();
863
+ }
864
+ }
865
+ function drawWatermark(canvas, config) {
866
+ const ctx = canvas.getContext("2d");
867
+ if (!ctx) return canvas;
868
+ const finalConfig = {
869
+ ...DEFAULT_WATERMARK,
870
+ ...config
871
+ };
872
+ const { width, height } = canvas;
873
+ ctx.save();
874
+ ctx.globalAlpha = finalConfig.opacity;
875
+ ctx.font = `${finalConfig.textSize}px ${finalConfig.font}`;
876
+ ctx.fillStyle = finalConfig.textColor;
877
+ ctx.textAlign = "center";
878
+ ctx.textBaseline = "middle";
879
+ const drawFunctions = {
880
+ center: drawCenterWatermark,
881
+ corner: drawCornerWatermark,
882
+ diagonal: drawDiagonalWatermark,
883
+ repeat: drawRepeatWatermark
884
+ };
885
+ (drawFunctions[finalConfig.position] || drawFunctions.repeat)(ctx, width, height, finalConfig);
886
+ ctx.restore();
887
+ return canvas;
888
+ }
889
+ async function captureElement(element, config = {}) {
890
+ const finalConfig = {
891
+ ...DEFAULT_CAPTURE,
892
+ ...config
893
+ };
894
+ return await html2canvas(element, {
895
+ logging: finalConfig.logging,
896
+ scale: finalConfig.scale,
897
+ allowTaint: finalConfig.allowTaint,
898
+ useCORS: finalConfig.useCORS,
899
+ backgroundColor: finalConfig.backgroundColor,
900
+ onclone: (clonedDoc) => {
901
+ const clonedElement = clonedDoc.body;
902
+ clonedElement.style.transform = "scale(1)";
903
+ }
904
+ });
905
+ }
906
+ function canvasToDataURL(canvas, format = "png", quality = .92) {
907
+ const mimeType = `image/${format}`;
908
+ return format === "png" ? canvas.toDataURL(mimeType) : canvas.toDataURL(mimeType, quality);
909
+ }
910
+ function downloadCanvas(canvas, filename = `screenshot-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.png`, format = "png") {
911
+ const dataURL = canvasToDataURL(canvas, format);
912
+ const link = document.createElement("a");
913
+ link.download = filename;
914
+ link.href = dataURL;
915
+ document.body.appendChild(link);
916
+ link.click();
917
+ document.body.removeChild(link);
918
+ }
919
+ let focusInterval = null;
920
+ function startFocusKeep() {
921
+ focusInterval = setInterval(() => {
922
+ window.dispatchEvent(new Event("focus"));
923
+ }, 500);
924
+ }
925
+ function stopFocusKeep() {
926
+ if (focusInterval) {
927
+ clearInterval(focusInterval);
928
+ focusInterval = null;
929
+ }
930
+ }
931
+ function printImage(imageDataURL, config = {}) {
932
+ const finalConfig = {
933
+ ...DEFAULT_PRINT,
934
+ ...config
935
+ };
936
+ return new Promise((resolve, reject) => {
937
+ try {
938
+ startFocusKeep();
939
+ finalConfig.onLoadingStart?.();
940
+ printJS({
941
+ printable: imageDataURL,
942
+ type: "image",
943
+ style: finalConfig.style,
944
+ showModal: finalConfig.showModal,
945
+ modalMessage: finalConfig.modalMessage,
946
+ onLoadingEnd: finalConfig.onLoadingEnd,
947
+ onPrintDialogClose: () => {
948
+ stopFocusKeep();
949
+ finalConfig.onPrintDialogClose?.();
950
+ resolve();
951
+ }
952
+ });
953
+ } catch (error) {
954
+ stopFocusKeep();
955
+ reject(error);
956
+ }
957
+ });
958
+ }
959
+ function calculateMergedCanvasSize(canvases, orientation, spacing) {
960
+ let totalWidth = 0;
961
+ let totalHeight = 0;
962
+ canvases.forEach((canvas) => {
963
+ const { width, height } = canvas;
964
+ if (orientation === "horizontal") {
965
+ totalWidth += width;
966
+ totalHeight = Math.max(totalHeight, height);
967
+ } else {
968
+ totalWidth = Math.max(totalWidth, width);
969
+ totalHeight += height;
970
+ }
971
+ });
972
+ const spacingTotal = (canvases.length - 1) * spacing;
973
+ if (orientation === "horizontal") totalWidth += spacingTotal;
974
+ else totalHeight += spacingTotal;
975
+ return {
976
+ totalWidth,
977
+ totalHeight
978
+ };
979
+ }
980
+ function createMergedCanvas(canvases, options) {
981
+ const { orientation, spacing, backgroundColor, totalWidth, totalHeight } = options;
982
+ const mergedCanvas = document.createElement("canvas");
983
+ mergedCanvas.width = totalWidth;
984
+ mergedCanvas.height = totalHeight;
985
+ const ctx = mergedCanvas.getContext("2d");
986
+ if (!ctx) throw new Error("无法创建画布上下文");
987
+ ctx.fillStyle = backgroundColor;
988
+ ctx.fillRect(0, 0, totalWidth, totalHeight);
989
+ let currentX = 0;
990
+ let currentY = 0;
991
+ canvases.forEach((canvas) => {
992
+ ctx.drawImage(canvas, currentX, currentY);
993
+ if (orientation === "horizontal") currentX += canvas.width + spacing;
994
+ else currentY += canvas.height + spacing;
995
+ });
996
+ return mergedCanvas;
997
+ }
998
+ function validateAndGetMergeOptions(elements, mergeOptions, message) {
999
+ if (!elements.length) {
1000
+ message.warning("没有要打印的元素");
1001
+ return null;
1002
+ }
1003
+ return {
1004
+ orientation: mergeOptions.orientation || "vertical",
1005
+ spacing: mergeOptions.spacing || 20,
1006
+ backgroundColor: mergeOptions.backgroundColor || "#ffffff"
1007
+ };
1008
+ }
1009
+ async function captureAndMergeCanvas(elements, options, validatedOptions, updateProgress) {
1010
+ const { orientation, spacing, backgroundColor } = validatedOptions;
1011
+ updateProgress(10);
1012
+ const canvases = await Promise.all(elements.map((element) => captureElement(element, options.capture)));
1013
+ updateProgress(50);
1014
+ const { totalWidth, totalHeight } = calculateMergedCanvasSize(canvases, orientation, spacing);
1015
+ updateProgress(60);
1016
+ return createMergedCanvas(canvases, {
1017
+ orientation,
1018
+ spacing,
1019
+ backgroundColor,
1020
+ totalWidth,
1021
+ totalHeight
1022
+ });
1023
+ }
1024
+ async function addWatermarkAndPrint(mergedCanvas, options, elementsCount, updateProgress, message) {
1025
+ updateProgress(70);
1026
+ if (options.watermark) drawWatermark(mergedCanvas, options.watermark);
1027
+ updateProgress(90);
1028
+ await printImage(canvasToDataURL(mergedCanvas, options.capture?.format, options.capture?.quality), options.print);
1029
+ updateProgress(100);
1030
+ message.success(`合并打印完成,共合并 ${elementsCount} 个元素`);
1031
+ }
1032
+ function usePrintWatermark() {
1033
+ let message;
1034
+ try {
1035
+ const { useMessage: _useMessage } = __require("naive-ui");
1036
+ message = _useMessage();
1037
+ } catch {
1038
+ message = {
1039
+ success: (msg) => console.log("[PrintWatermark]", msg),
1040
+ error: (msg) => console.error("[PrintWatermark]", msg),
1041
+ warning: (msg) => console.warn("[PrintWatermark]", msg)
1042
+ };
1043
+ }
1044
+ const loading = ref(false);
1045
+ const progress = ref(0);
1046
+ const updateProgress = (value) => {
1047
+ progress.value = Math.max(0, Math.min(100, value));
1048
+ };
1049
+ const captureWithWatermark = async (element, options = {}) => {
1050
+ try {
1051
+ updateProgress(0);
1052
+ updateProgress(30);
1053
+ const canvas = await captureElement(element, options.capture);
1054
+ updateProgress(60);
1055
+ if (options.watermark) drawWatermark(canvas, options.watermark);
1056
+ updateProgress(90);
1057
+ const dataURL = canvasToDataURL(canvas, options.capture?.format || "png", options.capture?.quality || .92);
1058
+ updateProgress(100);
1059
+ return dataURL;
1060
+ } catch (error) {
1061
+ console.error("截图失败:", error);
1062
+ throw new Error(`截图失败: ${error instanceof Error ? error.message : "未知错误"}`);
1063
+ }
1064
+ };
1065
+ const printWithWatermark = async (element, options = {}) => {
1066
+ loading.value = true;
1067
+ updateProgress(0);
1068
+ try {
1069
+ await nextTick();
1070
+ const imageDataURL = await captureWithWatermark(element, options);
1071
+ updateProgress(95);
1072
+ await printImage(imageDataURL, options.print);
1073
+ updateProgress(100);
1074
+ message.success("打印完成");
1075
+ } catch (error) {
1076
+ console.error("打印失败:", error);
1077
+ message.error(`打印失败: ${error instanceof Error ? error.message : "未知错误"}`);
1078
+ throw error;
1079
+ } finally {
1080
+ loading.value = false;
1081
+ updateProgress(0);
1082
+ }
1083
+ };
1084
+ const downloadScreenshot = async (element, filename, options = {}) => {
1085
+ loading.value = true;
1086
+ try {
1087
+ await nextTick();
1088
+ const canvas = await captureElement(element, options.capture);
1089
+ if (options.watermark) drawWatermark(canvas, options.watermark);
1090
+ const format = options.capture?.format || "png";
1091
+ const defaultFilename = `screenshot-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace(/:/g, "-")}.${format}`;
1092
+ downloadCanvas(canvas, filename || defaultFilename, format);
1093
+ message.success("下载完成");
1094
+ } catch (error) {
1095
+ console.error("下载失败:", error);
1096
+ message.error("下载失败");
1097
+ throw error;
1098
+ } finally {
1099
+ loading.value = false;
1100
+ }
1101
+ };
1102
+ const quickPrint = async (element, watermarkText = "Robot Admin") => {
1103
+ return printWithWatermark(element, { watermark: {
1104
+ text: watermarkText,
1105
+ position: "repeat",
1106
+ textColor: "rgba(128, 128, 128, 0.3)"
1107
+ } });
1108
+ };
1109
+ const batchCapture = async (elements, options = {}) => {
1110
+ const total = elements.length;
1111
+ updateProgress(10);
1112
+ const capturePromises = elements.map(async (element, index) => {
1113
+ const url = await captureWithWatermark(element, options);
1114
+ updateProgress(10 + (index + 1) / total * 70);
1115
+ return url;
1116
+ });
1117
+ return Promise.all(capturePromises);
1118
+ };
1119
+ const serialPrint = async (imageUrls, printConfig = {}) => {
1120
+ await imageUrls.reduce(async (prevPromise, imageUrl, index) => {
1121
+ await prevPromise;
1122
+ await printImage(imageUrl, printConfig);
1123
+ if (index < imageUrls.length - 1) await new Promise((resolve) => {
1124
+ setTimeout(() => resolve(), 1e3);
1125
+ });
1126
+ }, Promise.resolve());
1127
+ };
1128
+ const batchPrint = async (elements, options = {}) => {
1129
+ if (!elements.length) {
1130
+ message.warning("没有要打印的元素");
1131
+ return;
1132
+ }
1133
+ loading.value = true;
1134
+ try {
1135
+ updateProgress(0);
1136
+ const imageUrls = await batchCapture(elements, options);
1137
+ updateProgress(80);
1138
+ await serialPrint(imageUrls, options.print);
1139
+ updateProgress(100);
1140
+ message.success(`批量打印完成,共 ${elements.length} 个元素`);
1141
+ } catch (error) {
1142
+ console.error("批量打印失败:", error);
1143
+ message.error("批量打印失败");
1144
+ throw error;
1145
+ } finally {
1146
+ loading.value = false;
1147
+ updateProgress(0);
1148
+ }
1149
+ };
1150
+ const mergePrint = async (elements, options = {}, mergeOptions = {}) => {
1151
+ const validatedOptions = validateAndGetMergeOptions(elements, mergeOptions, message);
1152
+ if (!validatedOptions) return;
1153
+ loading.value = true;
1154
+ try {
1155
+ await addWatermarkAndPrint(await captureAndMergeCanvas(elements, options, validatedOptions, updateProgress), options, elements.length, updateProgress, message);
1156
+ } catch (error) {
1157
+ console.error("合并打印失败:", error);
1158
+ message.error("合并打印失败");
1159
+ throw error;
1160
+ } finally {
1161
+ loading.value = false;
1162
+ updateProgress(0);
1163
+ }
1164
+ };
1165
+ const createPreset = (name, options) => {
1166
+ return {
1167
+ use: (element) => printWithWatermark(element, options),
1168
+ download: (element, filename) => downloadScreenshot(element, filename, options)
1169
+ };
1170
+ };
1171
+ return {
1172
+ loading,
1173
+ progress,
1174
+ captureWithWatermark,
1175
+ printWithWatermark,
1176
+ downloadScreenshot,
1177
+ quickPrint,
1178
+ batchCapture,
1179
+ batchPrint,
1180
+ mergePrint,
1181
+ createPreset,
1182
+ updateProgress,
1183
+ utils: {
1184
+ captureElement,
1185
+ drawWatermark,
1186
+ canvasToDataURL,
1187
+ downloadCanvas,
1188
+ printImage
1189
+ }
1190
+ };
1191
+ }
1192
+ const printPresets = {
1193
+ table: {
1194
+ watermark: {
1195
+ text: "Robot Admin - 数据表格",
1196
+ position: "repeat",
1197
+ textColor: "rgba(100, 100, 100, 0.25)",
1198
+ textSize: 14,
1199
+ xGap: 250,
1200
+ yGap: 120
1201
+ },
1202
+ capture: { scale: 1.2 },
1203
+ print: {
1204
+ orientation: "landscape",
1205
+ style: "@page { margin: 8mm; } body { font-family: Arial, sans-serif; }"
1206
+ }
1207
+ },
1208
+ form: {
1209
+ watermark: {
1210
+ text: "Robot Admin - 表单数据",
1211
+ position: "diagonal",
1212
+ textColor: "rgba(150, 150, 150, 0.2)",
1213
+ textSize: 16
1214
+ },
1215
+ print: { orientation: "portrait" }
1216
+ },
1217
+ report: {
1218
+ watermark: {
1219
+ text: "Robot Admin - 机密报告",
1220
+ position: "center",
1221
+ textColor: "rgba(200, 50, 50, 0.15)",
1222
+ textSize: 24
1223
+ },
1224
+ capture: {
1225
+ quality: .95,
1226
+ format: "png"
1227
+ }
1228
+ }
1229
+ };
1230
+
1231
+ //#endregion
1232
+ //#region src/components/C_Table/composables/useDynamicRow.ts
1233
+ /** 生成唯一ID */
1234
+ function generateUniqueId() {
1235
+ return `row_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1236
+ }
1237
+ /** 获取行键值 */
1238
+ function getRowKey(row, rowKey) {
1239
+ return typeof rowKey === "function" ? rowKey(row) : row[rowKey];
1240
+ }
1241
+ /** 创建新行数据 */
1242
+ function createNewRow(defaultRowData, rowKey) {
1243
+ const newRow = defaultRowData?.() || {};
1244
+ const keyField = typeof rowKey === "string" ? rowKey : "id";
1245
+ return {
1246
+ ...newRow,
1247
+ [keyField]: generateUniqueId()
1248
+ };
1249
+ }
1250
+ /**
1251
+ * 表格动态行操作功能组合
1252
+ */
1253
+ function useDynamicRows(data, options = {}) {
1254
+ const message = useMessage$1();
1255
+ const finalOptions = {
1256
+ rowKey: "id",
1257
+ enableRadioSelection: true,
1258
+ enableAdd: true,
1259
+ enableInsert: true,
1260
+ enableDelete: true,
1261
+ enableCopy: true,
1262
+ enableMove: true,
1263
+ enablePrint: true,
1264
+ confirmDelete: true,
1265
+ deleteConfirmText: "确定要删除选中的行吗?此操作不可撤销。",
1266
+ printPreset: "table",
1267
+ printTargetSelector: ".c-table-wrapper",
1268
+ defaultRowData: () => ({}),
1269
+ ...options
1270
+ };
1271
+ const selectedRowKey = ref(null);
1272
+ const deleteConfirmVisible = ref(false);
1273
+ const selectedRowData = computed(() => {
1274
+ if (selectedRowKey.value === null) return null;
1275
+ return data.value.find((row) => getRowKey(row, finalOptions.rowKey) === selectedRowKey.value) || null;
1276
+ });
1277
+ const selectedRowIndex = computed(() => {
1278
+ if (!selectedRowData.value) return -1;
1279
+ return data.value.findIndex((row) => row === selectedRowData.value);
1280
+ });
1281
+ const canMoveUp = computed(() => selectedRowIndex.value > 0);
1282
+ const canMoveDown = computed(() => selectedRowIndex.value >= 0 && selectedRowIndex.value < data.value.length - 1);
1283
+ const { loading: printLoading, progress: printProgress, printWithWatermark, downloadScreenshot, quickPrint } = usePrintWatermark();
1284
+ /** 获取打印配置选项 */
1285
+ const getPrintOptions = () => {
1286
+ if (finalOptions.printOptions) return finalOptions.printOptions;
1287
+ const baseConfig = printPresets[finalOptions.printPreset || "table"];
1288
+ if (finalOptions.printWatermarkText && baseConfig.watermark) return {
1289
+ ...baseConfig,
1290
+ watermark: {
1291
+ ...baseConfig.watermark,
1292
+ text: finalOptions.printWatermarkText
1293
+ }
1294
+ };
1295
+ return baseConfig;
1296
+ };
1297
+ /** 更新表格数据 */
1298
+ const updateData = (newData) => {
1299
+ data.value = newData;
1300
+ finalOptions.onRowChange?.(newData);
1301
+ };
1302
+ /** 添加新行到表格末尾 */
1303
+ const addRow = () => {
1304
+ if (!finalOptions.enableAdd) return;
1305
+ const newRow = createNewRow(finalOptions.defaultRowData, finalOptions.rowKey);
1306
+ updateData([...data.value, newRow]);
1307
+ finalOptions.onRowAdd?.(newRow);
1308
+ message.success("添加行成功");
1309
+ };
1310
+ /** 在选中行后插入新行 */
1311
+ const insertRow = () => {
1312
+ if (!finalOptions.enableInsert || !selectedRowData.value) {
1313
+ message.warning("请先选择一行数据");
1314
+ return;
1315
+ }
1316
+ const newRow = createNewRow(finalOptions.defaultRowData, finalOptions.rowKey);
1317
+ const newData = [...data.value];
1318
+ newData.splice(selectedRowIndex.value + 1, 0, newRow);
1319
+ updateData(newData);
1320
+ finalOptions.onRowAdd?.(newRow);
1321
+ message.success("插入行成功");
1322
+ };
1323
+ /** 删除选中的行 */
1324
+ const deleteRow = () => {
1325
+ if (!finalOptions.enableDelete || !selectedRowData.value) {
1326
+ message.warning("请先选择要删除的行");
1327
+ return;
1328
+ }
1329
+ if (finalOptions.confirmDelete) deleteConfirmVisible.value = true;
1330
+ else confirmDeleteFn();
1331
+ };
1332
+ /** 确认删除操作 */
1333
+ const confirmDeleteFn = () => {
1334
+ if (!selectedRowData.value) return;
1335
+ const deletedRow = selectedRowData.value;
1336
+ const deletedIndex = selectedRowIndex.value;
1337
+ updateData(data.value.filter((_, index) => index !== deletedIndex));
1338
+ selectedRowKey.value = null;
1339
+ finalOptions.onSelectionChange?.(null, null);
1340
+ finalOptions.onRowDelete?.(deletedRow, deletedIndex);
1341
+ message.success("删除行成功");
1342
+ deleteConfirmVisible.value = false;
1343
+ };
1344
+ /** 复制选中的行 */
1345
+ const copyRow = () => {
1346
+ if (!finalOptions.enableCopy || !selectedRowData.value) {
1347
+ message.warning("请先选择要复制的行");
1348
+ return;
1349
+ }
1350
+ const originalRow = selectedRowData.value;
1351
+ const keyField = typeof finalOptions.rowKey === "string" ? finalOptions.rowKey : "id";
1352
+ const { [keyField]: _originalKey, ...rowData } = originalRow;
1353
+ const newRow = {
1354
+ ...rowData,
1355
+ [keyField]: generateUniqueId()
1356
+ };
1357
+ updateData([...data.value, newRow]);
1358
+ finalOptions.onRowCopy?.(originalRow, newRow);
1359
+ message.success("复制行成功");
1360
+ };
1361
+ /** 将选中行向上移动 */
1362
+ const moveRowUp = () => {
1363
+ if (!finalOptions.enableMove || !canMoveUp.value) return;
1364
+ const currentIndex = selectedRowIndex.value;
1365
+ const newData = [...data.value];
1366
+ const movingRow = newData[currentIndex];
1367
+ [newData[currentIndex], newData[currentIndex - 1]] = [newData[currentIndex - 1], newData[currentIndex]];
1368
+ updateData(newData);
1369
+ finalOptions.onRowMove?.(movingRow, currentIndex, currentIndex - 1);
1370
+ message.success("行已上移");
1371
+ };
1372
+ /** 将选中行向下移动 */
1373
+ const moveRowDown = () => {
1374
+ if (!finalOptions.enableMove || !canMoveDown.value) return;
1375
+ const currentIndex = selectedRowIndex.value;
1376
+ const newData = [...data.value];
1377
+ const movingRow = newData[currentIndex];
1378
+ [newData[currentIndex], newData[currentIndex + 1]] = [newData[currentIndex + 1], newData[currentIndex]];
1379
+ updateData(newData);
1380
+ finalOptions.onRowMove?.(movingRow, currentIndex, currentIndex + 1);
1381
+ message.success("行已下移");
1382
+ };
1383
+ /** 选中指定行 */
1384
+ const selectRow = (key) => {
1385
+ const row = data.value.find((row) => getRowKey(row, finalOptions.rowKey) === key);
1386
+ if (row) {
1387
+ selectedRowKey.value = key;
1388
+ finalOptions.onSelectionChange?.(key, row);
1389
+ }
1390
+ };
1391
+ /** 清空选择状态 */
1392
+ const clearSelection = () => {
1393
+ selectedRowKey.value = null;
1394
+ finalOptions.onSelectionChange?.(null, null);
1395
+ };
1396
+ /** 处理打印操作 */
1397
+ const handlePrint = async (elementRef) => {
1398
+ if (!elementRef.value) {
1399
+ message.error("打印元素未找到");
1400
+ return;
1401
+ }
1402
+ const printOptions = getPrintOptions();
1403
+ await printWithWatermark(elementRef.value, printOptions);
1404
+ };
1405
+ /** 处理下载操作 */
1406
+ const handleDownload = async (elementRef, filename) => {
1407
+ if (!elementRef.value) {
1408
+ message.error("下载元素未找到");
1409
+ return;
1410
+ }
1411
+ const printOptions = getPrintOptions();
1412
+ await downloadScreenshot(elementRef.value, filename, printOptions);
1413
+ };
1414
+ /** 处理快速打印操作 */
1415
+ const handleQuickPrint = async (elementRef) => {
1416
+ if (!elementRef.value) {
1417
+ message.error("打印元素未找到");
1418
+ return;
1419
+ }
1420
+ const watermarkText = finalOptions.printWatermarkText || "Robot Admin";
1421
+ await quickPrint(elementRef.value, watermarkText);
1422
+ };
1423
+ /** 增强表格列配置,添加单选列 */
1424
+ const enhanceColumns = (columns) => {
1425
+ const enhancedColumns = [...columns];
1426
+ if (finalOptions.enableRadioSelection) enhancedColumns.unshift({
1427
+ key: "_radio_selection",
1428
+ title: "选择",
1429
+ width: 80,
1430
+ align: "center",
1431
+ editable: false,
1432
+ render: (rowData) => {
1433
+ const rowKeyVal = getRowKey(rowData, finalOptions.rowKey);
1434
+ return h("div", { class: "flex justify-center" }, [h("input", {
1435
+ type: "radio",
1436
+ name: "table-radio-selection",
1437
+ checked: selectedRowKey.value === rowKeyVal,
1438
+ class: "cursor-pointer accent-blue-500 scale-110",
1439
+ onChange: (e) => {
1440
+ if (e.target.checked) selectRow(rowKeyVal);
1441
+ }
1442
+ })]);
1443
+ }
1444
+ });
1445
+ return enhancedColumns;
1446
+ };
1447
+ /** 渲染工具栏 */
1448
+ const renderToolbar = () => {
1449
+ const buttons = [];
1450
+ if (finalOptions.enablePrint) buttons.push(h(NButton$1, {
1451
+ loading: printLoading.value,
1452
+ type: "primary",
1453
+ ghost: true,
1454
+ onClick: async () => {
1455
+ try {
1456
+ const tableElement = document.querySelector(finalOptions.printTargetSelector);
1457
+ if (tableElement) await handlePrint(ref(tableElement));
1458
+ else console.warn("未找到表格容器元素");
1459
+ } catch (error) {
1460
+ console.error("打印失败:", error);
1461
+ }
1462
+ }
1463
+ }, {
1464
+ icon: () => h(C_Icon_default, {
1465
+ name: "mdi:printer",
1466
+ title: "打印"
1467
+ }),
1468
+ default: () => "打印"
1469
+ }));
1470
+ const rowButtons = [];
1471
+ if (finalOptions.enableAdd) rowButtons.push(h(NButton$1, {
1472
+ onClick: addRow,
1473
+ type: "primary"
1474
+ }, {
1475
+ icon: () => h(C_Icon_default, {
1476
+ name: "mdi:plus",
1477
+ title: "增行"
1478
+ }),
1479
+ default: () => "增行"
1480
+ }));
1481
+ if (finalOptions.enableInsert) rowButtons.push(h(NTooltip$1, { disabled: !!selectedRowData.value }, {
1482
+ trigger: () => h(NButton$1, {
1483
+ onClick: insertRow,
1484
+ disabled: !selectedRowData.value,
1485
+ type: "primary",
1486
+ ghost: true
1487
+ }, {
1488
+ icon: () => h(C_Icon_default, {
1489
+ name: "mdi:table-row-plus-after",
1490
+ title: "插行"
1491
+ }),
1492
+ default: () => "插行"
1493
+ }),
1494
+ default: () => "请先选择一行数据"
1495
+ }));
1496
+ if (finalOptions.enableDelete) rowButtons.push(h(NTooltip$1, { disabled: !!selectedRowData.value }, {
1497
+ trigger: () => h(NButton$1, {
1498
+ onClick: deleteRow,
1499
+ disabled: !selectedRowData.value,
1500
+ type: "error",
1501
+ ghost: true
1502
+ }, {
1503
+ icon: () => h(C_Icon_default, {
1504
+ name: "mdi:delete",
1505
+ title: "删除行"
1506
+ }),
1507
+ default: () => "删除行"
1508
+ }),
1509
+ default: () => "请先选择要删除的行"
1510
+ }));
1511
+ if (finalOptions.enableCopy) rowButtons.push(h(NTooltip$1, { disabled: !!selectedRowData.value }, {
1512
+ trigger: () => h(NButton$1, {
1513
+ onClick: copyRow,
1514
+ disabled: !selectedRowData.value,
1515
+ type: "info",
1516
+ ghost: true
1517
+ }, {
1518
+ icon: () => h(C_Icon_default, {
1519
+ name: "mdi:content-copy",
1520
+ title: "复制行"
1521
+ }),
1522
+ default: () => "复制行"
1523
+ }),
1524
+ default: () => "请先选择要复制的行"
1525
+ }));
1526
+ if (finalOptions.enableMove) rowButtons.push(h(NTooltip$1, { disabled: canMoveUp.value }, {
1527
+ trigger: () => h(NButton$1, {
1528
+ onClick: moveRowUp,
1529
+ disabled: !canMoveUp.value,
1530
+ type: "warning",
1531
+ ghost: true
1532
+ }, {
1533
+ icon: () => h(C_Icon_default, {
1534
+ name: "mdi:arrow-up",
1535
+ title: "上移"
1536
+ }),
1537
+ default: () => "上移"
1538
+ }),
1539
+ default: () => !selectedRowData.value ? "请先选择数据" : "已经是第一行"
1540
+ }), h(NTooltip$1, { disabled: canMoveDown.value }, {
1541
+ trigger: () => h(NButton$1, {
1542
+ onClick: moveRowDown,
1543
+ disabled: !canMoveDown.value,
1544
+ type: "warning",
1545
+ ghost: true
1546
+ }, {
1547
+ icon: () => h(C_Icon_default, {
1548
+ name: "mdi:arrow-down",
1549
+ title: "下移"
1550
+ }),
1551
+ default: () => "下移"
1552
+ }),
1553
+ default: () => !selectedRowData.value ? "请先选择数据" : "已经是最后一行"
1554
+ }));
1555
+ if (rowButtons.length > 0) buttons.push(h(NButtonGroup$1, {}, () => rowButtons));
1556
+ return h("div", { class: "dynamic-rows-toolbar mb-4 flex justify-end" }, [h(NSpace$1, {}, () => buttons)]);
1557
+ };
1558
+ /** 渲染删除确认模态框 */
1559
+ const renderConfirmModal = () => {
1560
+ return h(NModal$1, {
1561
+ show: deleteConfirmVisible.value,
1562
+ "onUpdate:show": (show) => {
1563
+ deleteConfirmVisible.value = show;
1564
+ },
1565
+ preset: "dialog",
1566
+ title: "确认删除",
1567
+ content: finalOptions.deleteConfirmText,
1568
+ positiveText: "确认删除",
1569
+ negativeText: "取消",
1570
+ onPositiveClick: confirmDeleteFn
1571
+ });
1572
+ };
1573
+ onBeforeUnmount(() => {
1574
+ selectedRowKey.value = null;
1575
+ deleteConfirmVisible.value = false;
1576
+ });
1577
+ return {
1578
+ selectedRowKey,
1579
+ selectedRowData,
1580
+ selectedRowIndex,
1581
+ canMoveUp,
1582
+ canMoveDown,
1583
+ deleteConfirmVisible,
1584
+ printLoading,
1585
+ printProgress,
1586
+ addRow,
1587
+ insertRow,
1588
+ deleteRow,
1589
+ confirmDelete: confirmDeleteFn,
1590
+ copyRow,
1591
+ moveRowUp,
1592
+ moveRowDown,
1593
+ selectRow,
1594
+ clearSelection,
1595
+ handlePrint,
1596
+ handleDownload,
1597
+ handleQuickPrint,
1598
+ enhanceColumns,
1599
+ renderToolbar,
1600
+ renderConfirmModal
1601
+ };
1602
+ }
1603
+
1604
+ //#endregion
1605
+ //#region src/components/C_Table/composables/useTableManager.ts
1606
+ /**
1607
+ * 表格统一状态管理器
1608
+ */
1609
+ function useTableManager(params) {
1610
+ const { config, data, rowKey, emit } = params;
1611
+ /** 创建事件处理器集合 */
1612
+ const createEventHandlers = () => ({
1613
+ onSave: async (rowData, rowIndex, columnKey) => {
1614
+ if (!rowData || rowIndex < 0 || rowIndex >= data().length) return;
1615
+ const newData = [...data()];
1616
+ newData[rowIndex] = {
1617
+ ...newData[rowIndex],
1618
+ ...rowData
1619
+ };
1620
+ emit("update:data", newData);
1621
+ await nextTick();
1622
+ emit("save", newData[rowIndex], rowIndex, columnKey);
1623
+ },
1624
+ onCancel: (rowData, rowIndex) => {
1625
+ emit("cancel", rowData, rowIndex);
1626
+ },
1627
+ onExpandChange: (keys, row, expanded) => {
1628
+ emit("expand-change", keys, row, expanded);
1629
+ },
1630
+ onSelectionChange: (checkedKeys, checkedRows, childSelections) => {
1631
+ emit("selection-change", checkedKeys, checkedRows, childSelections);
1632
+ },
1633
+ onChildSelectionChange: (parentKey, childKeys, childRows) => {
1634
+ emit("child-selection-change", parentKey, childKeys, childRows);
1635
+ },
1636
+ onRowChange: (data) => {
1637
+ emit("update:data", data);
1638
+ config.dynamicRows?.onRowChange?.(data);
1639
+ },
1640
+ onRowSelectionChange: (selectedKey, selectedRow) => {
1641
+ emit("row-selection-change", selectedKey, selectedRow);
1642
+ config.dynamicRows?.onSelectionChange?.(selectedKey, selectedRow);
1643
+ },
1644
+ onRowAdd: (newRow) => {
1645
+ emit("row-add", newRow);
1646
+ config.dynamicRows?.onRowAdd?.(newRow);
1647
+ },
1648
+ onRowDelete: (deletedRow, index) => {
1649
+ emit("row-delete", deletedRow, index);
1650
+ config.dynamicRows?.onRowDelete?.(deletedRow, index);
1651
+ },
1652
+ onRowCopy: (originalRow, newRow) => {
1653
+ emit("row-copy", originalRow, newRow);
1654
+ config.dynamicRows?.onRowCopy?.(originalRow, newRow);
1655
+ },
1656
+ onRowMove: (row, fromIndex, toIndex) => {
1657
+ emit("row-move", row, fromIndex, toIndex);
1658
+ config.dynamicRows?.onRowMove?.(row, fromIndex, toIndex);
1659
+ }
1660
+ });
1661
+ const eventHandlers = createEventHandlers();
1662
+ /** 初始化编辑功能状态 */
1663
+ const initEditStates = () => {
1664
+ return {
1665
+ rowEdit: useRowEdit({
1666
+ data,
1667
+ rowKey,
1668
+ onSave: eventHandlers.onSave,
1669
+ onCancel: eventHandlers.onCancel
1670
+ }),
1671
+ cellEdit: useCellEdit({
1672
+ data,
1673
+ rowKey,
1674
+ onSave: eventHandlers.onSave
1675
+ }),
1676
+ modalEdit: useModalEdit({
1677
+ data,
1678
+ rowKey,
1679
+ onSave: eventHandlers.onSave,
1680
+ onCancel: eventHandlers.onCancel
1681
+ })
1682
+ };
1683
+ };
1684
+ /** 初始化展开功能状态 */
1685
+ const initExpandState = () => {
1686
+ if (!(config.expandable || config.enableSelection || config.enableChildSelection)) return null;
1687
+ return useTableExpand({
1688
+ data: computed(() => data()),
1689
+ rowKey,
1690
+ childRowKey: (child) => child.id,
1691
+ defaultExpandedKeys: config.defaultExpandedKeys,
1692
+ onLoadData: config.onLoadExpandData,
1693
+ renderContent: config.renderExpandContent,
1694
+ rowExpandable: config.rowExpandable,
1695
+ enableSelection: config.enableSelection,
1696
+ defaultCheckedKeys: config.defaultCheckedKeys,
1697
+ rowCheckable: config.rowCheckable,
1698
+ maxSelection: config.maxSelection,
1699
+ enableChildSelection: config.enableChildSelection,
1700
+ childRowCheckable: config.childRowCheckable,
1701
+ enableParentChildLink: config.enableParentChildLink,
1702
+ parentChildLinkMode: config.parentChildLinkMode,
1703
+ onExpandChange: eventHandlers.onExpandChange,
1704
+ onSelectionChange: eventHandlers.onSelectionChange,
1705
+ onChildSelectionChange: eventHandlers.onChildSelectionChange
1706
+ });
1707
+ };
1708
+ /** 初始化动态行功能状态 */
1709
+ const initDynamicRowsState = () => {
1710
+ if (!config.dynamicRows) return null;
1711
+ const dynamicOptions = {
1712
+ ...config.dynamicRows,
1713
+ onRowChange: eventHandlers.onRowChange,
1714
+ onSelectionChange: eventHandlers.onRowSelectionChange,
1715
+ onRowAdd: eventHandlers.onRowAdd,
1716
+ onRowDelete: eventHandlers.onRowDelete,
1717
+ onRowCopy: eventHandlers.onRowCopy,
1718
+ onRowMove: eventHandlers.onRowMove
1719
+ };
1720
+ return useDynamicRows(computed(() => data()), dynamicOptions);
1721
+ };
1722
+ const editStates = initEditStates();
1723
+ const expandState = initExpandState();
1724
+ const dynamicRowsState = initDynamicRowsState();
1725
+ /** 创建统一的状态管理器 */
1726
+ const createStateManager = () => {
1727
+ return {
1728
+ edit: {
1729
+ start(rowKey, columnKey) {
1730
+ const mode = config.editMode;
1731
+ if (mode === "modal") editStates.modalEdit.startEdit(rowKey);
1732
+ else if (mode === "cell" && columnKey) editStates.cellEdit.startEditCell(rowKey, columnKey);
1733
+ else if (mode === "row" || mode === "both") editStates.rowEdit.startEditRow(rowKey);
1734
+ },
1735
+ cancel() {
1736
+ if (editStates.modalEdit.isModalVisible.value) editStates.modalEdit.cancelEdit();
1737
+ else if (editStates.cellEdit.editingCell.value.rowKey) editStates.cellEdit.cancelEditCell();
1738
+ else if (editStates.rowEdit.editingRowKey.value) editStates.rowEdit.cancelEditRow();
1739
+ },
1740
+ async save() {
1741
+ if (editStates.modalEdit.isModalVisible.value) await editStates.modalEdit.saveEdit();
1742
+ else if (editStates.cellEdit.editingCell.value.rowKey) await editStates.cellEdit.saveEditCell();
1743
+ else if (editStates.rowEdit.editingRowKey.value) await editStates.rowEdit.saveEditRow();
1744
+ },
1745
+ isEditing(rowKey, columnKey) {
1746
+ if (config.editMode === "modal") return editStates.modalEdit.isEditingRow(rowKey);
1747
+ if (columnKey) return editStates.cellEdit.isEditingCell(rowKey, columnKey);
1748
+ return editStates.rowEdit.isEditingRow(rowKey);
1749
+ },
1750
+ getEditingData() {
1751
+ if (editStates.modalEdit.isModalVisible.value) return editStates.modalEdit.editingData;
1752
+ if (editStates.rowEdit.editingRowKey.value) return editStates.rowEdit.getEditingRowData(editStates.rowEdit.editingRowKey.value);
1753
+ return null;
1754
+ }
1755
+ },
1756
+ expand: {
1757
+ async row(rowKey) {
1758
+ if (expandState) {
1759
+ const currentKeys = [...expandState.expandedKeys.value];
1760
+ if (!currentKeys.includes(rowKey)) {
1761
+ currentKeys.push(rowKey);
1762
+ expandState.handleExpandChange(currentKeys);
1763
+ }
1764
+ }
1765
+ },
1766
+ collapse(rowKey) {
1767
+ if (expandState) {
1768
+ const currentKeys = expandState.expandedKeys.value.filter((key) => key !== rowKey);
1769
+ expandState.handleExpandChange(currentKeys);
1770
+ }
1771
+ },
1772
+ async toggle(rowKey) {
1773
+ if (expandState?.expandedKeys.value.includes(rowKey)) this.collapse(rowKey);
1774
+ else await this.row(rowKey);
1775
+ },
1776
+ async all() {
1777
+ await expandState?.expandAll();
1778
+ },
1779
+ collapseAll() {
1780
+ expandState?.collapseAll();
1781
+ },
1782
+ isExpanded(rowKey) {
1783
+ return expandState?.expandedKeys.value.includes(rowKey) ?? false;
1784
+ }
1785
+ },
1786
+ selection: {
1787
+ select(rowKey) {
1788
+ if (expandState?.checkedKeys.value && !expandState.checkedKeys.value.includes(rowKey)) {
1789
+ const newKeys = [...expandState.checkedKeys.value, rowKey];
1790
+ expandState.handleSelectionChange(newKeys);
1791
+ }
1792
+ },
1793
+ unselect(rowKey) {
1794
+ if (expandState?.checkedKeys.value) {
1795
+ const newKeys = expandState.checkedKeys.value.filter((key) => key !== rowKey);
1796
+ expandState.handleSelectionChange(newKeys);
1797
+ }
1798
+ },
1799
+ all() {
1800
+ expandState?.selectAll();
1801
+ },
1802
+ clear() {
1803
+ expandState?.clearSelection();
1804
+ },
1805
+ isSelected(rowKey) {
1806
+ return expandState?.checkedKeys.value.includes(rowKey) ?? false;
1807
+ },
1808
+ getSelected() {
1809
+ if (!expandState?.checkedKeys.value) return [];
1810
+ return data().filter((row) => expandState.checkedKeys.value.includes(rowKey(row)));
1811
+ }
1812
+ },
1813
+ childSelection: {
1814
+ select(parentKey, childKey) {
1815
+ if (expandState?.childSelections.value) {
1816
+ const current = expandState.childSelections.value.get(parentKey) || [];
1817
+ if (!current.includes(childKey)) {
1818
+ const newSelection = [...current, childKey];
1819
+ expandState.childSelections.value.set(parentKey, newSelection);
1820
+ emit("child-selection-change", parentKey, newSelection, []);
1821
+ }
1822
+ }
1823
+ },
1824
+ unselect(parentKey, childKey) {
1825
+ if (expandState?.childSelections.value) {
1826
+ const newSelection = (expandState.childSelections.value.get(parentKey) || []).filter((k) => k !== childKey);
1827
+ expandState.childSelections.value.set(parentKey, newSelection);
1828
+ emit("child-selection-change", parentKey, newSelection, []);
1829
+ }
1830
+ },
1831
+ selectAll(parentKey) {
1832
+ if (expandState?.childSelections.value && expandState.expandDataMap?.value) {
1833
+ const expandData = expandState.expandDataMap.value.get(parentKey) || [];
1834
+ const allChildKeys = expandData.map((child) => child.id);
1835
+ expandState.childSelections.value.set(parentKey, allChildKeys);
1836
+ emit("child-selection-change", parentKey, allChildKeys, expandData);
1837
+ }
1838
+ },
1839
+ clear(parentKey) {
1840
+ if (expandState?.childSelections.value) {
1841
+ expandState.childSelections.value.set(parentKey, []);
1842
+ emit("child-selection-change", parentKey, [], []);
1843
+ }
1844
+ },
1845
+ getSelected(parentKey) {
1846
+ if (!expandState?.childSelections.value || !expandState.expandDataMap?.value) return [];
1847
+ const selectedKeys = expandState.childSelections.value.get(parentKey) || [];
1848
+ return (expandState.expandDataMap.value.get(parentKey) || []).filter((child) => selectedKeys.includes(child.id));
1849
+ }
1850
+ },
1851
+ dynamicRows: {
1852
+ add() {
1853
+ dynamicRowsState?.addRow();
1854
+ },
1855
+ insert() {
1856
+ dynamicRowsState?.insertRow();
1857
+ },
1858
+ delete() {
1859
+ dynamicRowsState?.deleteRow();
1860
+ },
1861
+ copy() {
1862
+ dynamicRowsState?.copyRow();
1863
+ },
1864
+ moveUp() {
1865
+ dynamicRowsState?.moveRowUp();
1866
+ },
1867
+ moveDown() {
1868
+ dynamicRowsState?.moveRowDown();
1869
+ },
1870
+ clearSelection() {
1871
+ dynamicRowsState?.clearSelection();
1872
+ },
1873
+ getSelected() {
1874
+ return dynamicRowsState?.selectedRowData.value || null;
1875
+ },
1876
+ async print(elementRef) {
1877
+ if (dynamicRowsState && elementRef) await dynamicRowsState.handlePrint(ref(elementRef));
1878
+ },
1879
+ async download(elementRef, filename) {
1880
+ if (dynamicRowsState && elementRef) await dynamicRowsState.handleDownload(ref(elementRef), filename);
1881
+ }
1882
+ },
1883
+ clearAllSelections() {
1884
+ expandState?.clearAllSelections();
1885
+ }
1886
+ };
1887
+ };
1888
+ return {
1889
+ editStates,
1890
+ expandState,
1891
+ dynamicRowsState,
1892
+ stateManager: createStateManager(),
1893
+ expandedKeys: computed(() => expandState?.expandedKeys.value ?? []),
1894
+ checkedKeys: computed(() => expandState?.checkedKeys.value ?? []),
1895
+ eventHandlers
1896
+ };
1897
+ }
1898
+
1899
+ //#endregion
1900
+ //#region src/components/C_Table/composables/usePagination.ts
1901
+ const DEFAULT_PAGINATION_CONFIG = {
1902
+ enabled: true,
1903
+ page: 1,
1904
+ pageSize: 10,
1905
+ showSizePicker: true,
1906
+ showQuickJumper: true,
1907
+ pageSizes: [
1908
+ 10,
1909
+ 20,
1910
+ 50,
1911
+ 100
1912
+ ],
1913
+ simple: false,
1914
+ size: "medium"
1915
+ };
1916
+ function usePagination(options) {
1917
+ const { data, config, emit } = options;
1918
+ const currentPage = ref(1);
1919
+ const currentPageSize = ref(10);
1920
+ const dataSource = computed(() => {
1921
+ if (typeof data === "function") return data() || [];
1922
+ return unref(data) || [];
1923
+ });
1924
+ /** 分页后的数据 */
1925
+ const paginatedData = computed(() => {
1926
+ if (!config.value?.enabled) return dataSource.value;
1927
+ const start = (currentPage.value - 1) * currentPageSize.value;
1928
+ const end = start + currentPageSize.value;
1929
+ return dataSource.value.slice(start, end);
1930
+ });
1931
+ /** 分页配置对象 */
1932
+ const paginationConfig = computed(() => {
1933
+ if (!config.value?.enabled) return null;
1934
+ return {
1935
+ page: currentPage.value,
1936
+ pageSize: currentPageSize.value,
1937
+ itemCount: dataSource.value.length,
1938
+ showSizePicker: config.value.showSizePicker ?? DEFAULT_PAGINATION_CONFIG.showSizePicker,
1939
+ showQuickJumper: config.value.showQuickJumper ?? DEFAULT_PAGINATION_CONFIG.showQuickJumper,
1940
+ pageSizes: config.value.pageSizes ?? DEFAULT_PAGINATION_CONFIG.pageSizes,
1941
+ simple: config.value.simple ?? DEFAULT_PAGINATION_CONFIG.simple,
1942
+ size: config.value.size ?? DEFAULT_PAGINATION_CONFIG.size,
1943
+ prefix: (info) => `共 ${info.itemCount} 条`,
1944
+ suffix: (info) => `第 ${info.startIndex + 1}-${info.endIndex} 条`,
1945
+ "onUpdate:page": handlePageChange,
1946
+ "onUpdate:pageSize": handlePageSizeChange
1947
+ };
1948
+ });
1949
+ /** 页码变化处理 */
1950
+ const handlePageChange = (page) => {
1951
+ currentPage.value = page;
1952
+ emit?.("pagination-change", page, currentPageSize.value);
1953
+ };
1954
+ /** 页面大小变化处理 */
1955
+ const handlePageSizeChange = (pageSize) => {
1956
+ currentPageSize.value = pageSize;
1957
+ currentPage.value = 1;
1958
+ emit?.("pagination-change", 1, pageSize);
1959
+ };
1960
+ /** 重置到第一页 */
1961
+ const resetToFirstPage = () => {
1962
+ if (currentPage.value !== 1) handlePageChange(1);
1963
+ };
1964
+ /** 获取总页数 */
1965
+ const getTotalPages = () => {
1966
+ if (!config.value?.enabled || currentPageSize.value === 0) return 1;
1967
+ return Math.ceil(dataSource.value.length / currentPageSize.value);
1968
+ };
1969
+ /** 初始化分页配置 */
1970
+ watchEffect(() => {
1971
+ if (config.value?.enabled) {
1972
+ currentPage.value = config.value.page ?? DEFAULT_PAGINATION_CONFIG.page;
1973
+ currentPageSize.value = config.value.pageSize ?? DEFAULT_PAGINATION_CONFIG.pageSize;
1974
+ }
1975
+ });
1976
+ /** 监听数据变化,确保分页状态正确 */
1977
+ watch(() => dataSource.value.length, (newLength) => {
1978
+ if (config.value?.enabled && currentPage.value > 1) {
1979
+ const maxPage = Math.ceil(newLength / currentPageSize.value);
1980
+ if (currentPage.value > maxPage) currentPage.value = Math.max(1, maxPage);
1981
+ }
1982
+ });
1983
+ return {
1984
+ currentPage,
1985
+ currentPageSize,
1986
+ paginatedData,
1987
+ paginationConfig,
1988
+ handlePageChange,
1989
+ handlePageSizeChange,
1990
+ resetToFirstPage,
1991
+ getTotalPages
1992
+ };
1993
+ }
1994
+
1995
+ //#endregion
1996
+ //#region src/components/C_Table/composables/useTableActions.ts
1997
+ /**
1998
+ * 表格操作Hook
1999
+ */
2000
+ function useTableActions(options) {
2001
+ const { actions, config, tableManager, rowKey, emit, onViewDetail } = options;
2002
+ const message = useMessage();
2003
+ const dialog = useDialog();
2004
+ const isActionEnabled = (key) => actions.value?.[key] !== false;
2005
+ const isValidApiFunction = (action) => {
2006
+ return action !== false && typeof action === "function";
2007
+ };
2008
+ const extractApiResponseData = (response) => {
2009
+ if (response && typeof response === "object" && "data" in response) return response.data;
2010
+ return response;
2011
+ };
2012
+ const createButton = (icon, title, type = "primary", onClick) => h(NButton, {
2013
+ size: "small",
2014
+ type,
2015
+ quaternary: true,
2016
+ onClick
2017
+ }, () => [h(C_Icon_default, {
2018
+ name: icon,
2019
+ size: 14,
2020
+ title
2021
+ })]);
2022
+ const handleEdit = (row, _index) => {
2023
+ const rowKeyValue = rowKey(row);
2024
+ const editAction = actions.value?.edit;
2025
+ if (config.value.editMode === "modal") tableManager.editStates.modalEdit.startEdit(rowKeyValue, { ...row }, editAction);
2026
+ else tableManager.editStates.rowEdit.startEditRow(rowKeyValue, editAction);
2027
+ };
2028
+ const executeDelete = async (deleteAction, row, index) => {
2029
+ try {
2030
+ await deleteAction(row, index);
2031
+ message.success("删除成功");
2032
+ emit("row-delete", row, index);
2033
+ } catch (error) {
2034
+ console.error("删除失败:", error);
2035
+ message.error("删除失败");
2036
+ throw error;
2037
+ }
2038
+ };
2039
+ const handleDelete = (row, index) => {
2040
+ const deleteAction = actions.value?.delete;
2041
+ if (!isValidApiFunction(deleteAction)) return;
2042
+ dialog.warning({
2043
+ title: "确认删除",
2044
+ content: "确定要删除这条记录吗?",
2045
+ positiveText: "确定",
2046
+ negativeText: "取消",
2047
+ onPositiveClick: () => executeDelete(deleteAction, row, index)
2048
+ });
2049
+ };
2050
+ const handleDetail = async (row, index) => {
2051
+ const detailAction = actions.value?.detail;
2052
+ if (!isValidApiFunction(detailAction)) {
2053
+ onViewDetail?.(row);
2054
+ return;
2055
+ }
2056
+ try {
2057
+ const detailData = extractApiResponseData(await detailAction(row, index));
2058
+ onViewDetail?.(detailData || row);
2059
+ } catch (error) {
2060
+ console.error("获取详情失败:", error);
2061
+ message.error("获取详情失败");
2062
+ onViewDetail?.(row);
2063
+ }
2064
+ };
2065
+ const renderRowEditButtons = (rowKeyValue) => {
2066
+ if (tableManager.editStates.rowEdit.isEditingRow(rowKeyValue)) return [createButton("mdi:check", "保存", "primary", () => tableManager.editStates.rowEdit.saveEditRow()), createButton("mdi:close", "取消", "default", () => tableManager.editStates.rowEdit.cancelEditRow())];
2067
+ return [createButton("mdi:pencil", "编辑", "warning", () => tableManager.editStates.rowEdit.startEditRow(rowKeyValue))];
2068
+ };
2069
+ const renderBasicActions = (row, index) => {
2070
+ const buttons = [];
2071
+ if (isActionEnabled("detail")) buttons.push(createButton("mdi:eye", "详情", "info", () => handleDetail(row, index)));
2072
+ if (config.value.editMode === "modal" && (isActionEnabled("edit") || config.value.editable)) buttons.push(createButton("mdi:pencil", "编辑", "warning", () => handleEdit(row, index)));
2073
+ if (isActionEnabled("delete")) buttons.push(createButton("mdi:delete", "删除", "error", () => handleDelete(row, index)));
2074
+ return buttons;
2075
+ };
2076
+ const renderCustomDropdown = (row, index) => {
2077
+ const customActions = actions.value?.custom;
2078
+ if (!customActions?.length) return null;
2079
+ const visibleActions = customActions.filter((action) => action.show ? action.show(row, index) : true);
2080
+ if (!visibleActions.length) return null;
2081
+ return h(NDropdown, {
2082
+ options: visibleActions.map((action) => {
2083
+ const label = typeof action.label === "function" ? action.label(row, index) : action.label;
2084
+ const icon = typeof action.icon === "function" ? action.icon(row, index) : action.icon;
2085
+ return {
2086
+ label,
2087
+ key: action.key,
2088
+ icon: () => h(C_Icon_default, {
2089
+ name: icon,
2090
+ size: 14
2091
+ }),
2092
+ disabled: action.disabled?.(row, index) || false
2093
+ };
2094
+ }),
2095
+ onSelect: (key) => {
2096
+ const action = visibleActions.find((a) => a.key === key);
2097
+ if (action) try {
2098
+ action.onClick(row, index);
2099
+ } catch (error) {
2100
+ console.error(`操作"${action.label}"执行失败:`, error);
2101
+ message.error(`${action.label}失败`);
2102
+ }
2103
+ }
2104
+ }, () => createButton("mdi:dots-horizontal", "更多操作", "default", () => {}));
2105
+ };
2106
+ const renderActions = (row, index) => {
2107
+ if (actions.value?.render) return actions.value.render(row, index);
2108
+ const rowKeyValue = rowKey(row);
2109
+ const isRowEditMode = ["row", "both"].includes(config.value.editMode);
2110
+ if (isRowEditMode && tableManager.editStates.rowEdit.isEditingRow(rowKeyValue)) return h(NSpace, {
2111
+ size: 2,
2112
+ wrap: false
2113
+ }, () => renderRowEditButtons(rowKeyValue));
2114
+ const allButtons = [...isRowEditMode ? renderRowEditButtons(rowKeyValue) : [], ...renderBasicActions(row, index)];
2115
+ const dropdown = renderCustomDropdown(row, index);
2116
+ if (dropdown) allButtons.push(dropdown);
2117
+ return h(NSpace, {
2118
+ size: 2,
2119
+ wrap: false
2120
+ }, () => allButtons);
2121
+ };
2122
+ return {
2123
+ renderActions,
2124
+ isActionEnabled
2125
+ };
2126
+ }
2127
+
2128
+ //#endregion
2129
+ //#region src/components/C_Table/data.ts
2130
+ const EDIT_COMPONENTS = {
2131
+ number: NInputNumber,
2132
+ switch: NSwitch,
2133
+ input: NInput,
2134
+ email: NInput,
2135
+ mobile: NInput,
2136
+ date: (props) => h(NDatePicker, {
2137
+ ...props,
2138
+ type: "date",
2139
+ format: "yyyy-MM-dd"
2140
+ }),
2141
+ select: (props) => h(NSelect, {
2142
+ ...props,
2143
+ options: props.options || []
2144
+ }),
2145
+ textarea: (props) => h(NInput, {
2146
+ ...props,
2147
+ type: "textarea",
2148
+ rows: 3
2149
+ })
2150
+ };
2151
+ const EDIT_TO_FORM_TYPE = {
2152
+ number: "inputNumber",
2153
+ date: "datePicker",
2154
+ textarea: "textarea",
2155
+ select: "select",
2156
+ switch: "switch"
2157
+ };
2158
+ /**
2159
+ * 根据可编辑列配置自动生成表单选项(用于编辑弹窗)
2160
+ */
2161
+ const generateFormOptions = (columns) => columns.map((column) => {
2162
+ const rules = column.required ? [{
2163
+ required: true,
2164
+ message: `请输入${column.title}`,
2165
+ trigger: ["blur", "input"],
2166
+ validator: async (_, value) => {
2167
+ if (!value && value !== 0 && value !== false) throw new Error(`请输入${column.title}`);
2168
+ }
2169
+ }] : [];
2170
+ return {
2171
+ prop: column.key,
2172
+ label: column.title || column.key,
2173
+ type: EDIT_TO_FORM_TYPE[column.editType || "input"] || "input",
2174
+ placeholder: `请输入${column.title}`,
2175
+ rules,
2176
+ attrs: column.editProps || {},
2177
+ layout: { span: 1 },
2178
+ show: true
2179
+ };
2180
+ });
2181
+
2182
+ //#endregion
2183
+ //#region src/components/C_Table/composables/useTableColumns.ts
2184
+ /**
2185
+ * 渲染编辑组件(行编辑/单元格编辑通用)
2186
+ */
2187
+ function renderEditComponent(column, value, onUpdate) {
2188
+ if (column.editRender) return column.editRender(value, {}, 0);
2189
+ const col = column;
2190
+ const componentProps = {
2191
+ value,
2192
+ "onUpdate:value": onUpdate,
2193
+ placeholder: `请输入${col.title ?? ""}`,
2194
+ style: { width: "100%" },
2195
+ ...column.editProps
2196
+ };
2197
+ return h(EDIT_COMPONENTS[column.editType || "input"] || EDIT_COMPONENTS.input, componentProps);
2198
+ }
2199
+ /**
2200
+ * 渲染只读单元格
2201
+ */
2202
+ function renderDisplayCell(column, rowData, rowIndex, value) {
2203
+ return column.render ? column.render(rowData, rowIndex) ?? String(value ?? "") : String(value ?? "");
2204
+ }
2205
+ /**
2206
+ * 渲染编辑中的单元格(带保存/取消按钮)
2207
+ */
2208
+ function renderEditingCell(column, value, onUpdate, onSave, onCancel) {
2209
+ const actionBtn = (name, title, onClick) => h("button", {
2210
+ class: `cell-action-btn cell-action-${name}`,
2211
+ title,
2212
+ type: "button",
2213
+ onClick: (e) => {
2214
+ e.stopPropagation();
2215
+ e.preventDefault();
2216
+ onClick(e);
2217
+ }
2218
+ }, [h(C_Icon_default, {
2219
+ name: `mdi:${name === "save" ? "check" : "close"}`,
2220
+ title: name === "save" ? "保存" : "取消",
2221
+ size: 12
2222
+ })]);
2223
+ return h("div", { class: "cell-editing-container" }, [h("div", { class: "cell-editing-input" }, [renderEditComponent(column, value, onUpdate)]), h("div", { class: "cell-editing-actions" }, [actionBtn("save", "保存", onSave), actionBtn("cancel", "取消", onCancel)])]);
2224
+ }
2225
+ /**
2226
+ * 渲染可编辑单元格(显示值 + 编辑图标)
2227
+ */
2228
+ function renderEditableCell(column, rowData, rowIndex, value, onStartEdit) {
2229
+ return h("div", { class: "cell-edit-wrapper" }, [h("span", { class: "cell-value" }, column.render ? column.render(rowData, rowIndex) ?? String(value ?? "") : String(value ?? "")), h(C_Icon_default, {
2230
+ name: "mdi:square-edit-outline",
2231
+ title: "编辑",
2232
+ class: "cell-edit-icon",
2233
+ size: 14,
2234
+ clickable: true,
2235
+ onClick: (e) => {
2236
+ e.stopPropagation();
2237
+ onStartEdit();
2238
+ }
2239
+ })]);
2240
+ }
2241
+ /**
2242
+ * 表格列处理引擎
2243
+ */
2244
+ function useTableColumns(options) {
2245
+ const { rawColumns, config, columnWidth, rowKey, tableManager, actionsRenderer, editModeChecker } = options;
2246
+ const reactiveColumns = ref([]);
2247
+ const showSettingsPanel = ref(false);
2248
+ /** 同步外部列配置到响应式状态 */
2249
+ const syncColumns = (newColumns) => {
2250
+ const existingActions = reactiveColumns.value.find((col) => col.key === "_actions");
2251
+ reactiveColumns.value = [...newColumns, existingActions || {
2252
+ key: "_actions",
2253
+ title: "操作",
2254
+ width: 180,
2255
+ editable: false,
2256
+ visible: true,
2257
+ fixed: "right"
2258
+ }];
2259
+ };
2260
+ watch(rawColumns, (cols) => {
2261
+ if (cols?.length) syncColumns(cols);
2262
+ }, {
2263
+ deep: true,
2264
+ immediate: true
2265
+ });
2266
+ /** 单元格编辑模式渲染 */
2267
+ const renderCellEdit = (column, rowData, rowIndex, rowKeyVal) => {
2268
+ const colKey = column.key ?? "";
2269
+ const value = rowData[colKey];
2270
+ const { isEditingCell, getEditingCellValue, updateEditingCellValue, saveEditCell, cancelEditCell, startEditCell } = tableManager.editStates.cellEdit;
2271
+ if (isEditingCell(rowKeyVal, colKey)) return renderEditingCell(column, getEditingCellValue(rowKeyVal, colKey) ?? value, (val) => updateEditingCellValue(rowKeyVal, colKey, val), () => saveEditCell(), () => cancelEditCell());
2272
+ return renderEditableCell(column, rowData, rowIndex, value, () => startEditCell(rowKeyVal, colKey));
2273
+ };
2274
+ /** 统一单元格渲染入口 */
2275
+ const renderCell = (column, rowData, rowIndex) => {
2276
+ const colKey = column.key ?? "";
2277
+ const value = rowData[colKey];
2278
+ const key = rowKey(rowData);
2279
+ const checker = editModeChecker.value;
2280
+ if (checker.isNonEditable(column)) return renderDisplayCell(column, rowData, rowIndex, value);
2281
+ if (checker.isRowEditMode() && tableManager.editStates.rowEdit.isEditingRow(key)) return renderEditComponent(column, tableManager.editStates.rowEdit.getEditingRowData(key)?.[colKey] ?? value, (val) => tableManager.editStates.rowEdit.updateEditingRowData(key, colKey, val));
2282
+ if (checker.isCellEditMode()) return renderCellEdit(column, rowData, rowIndex, key);
2283
+ return renderDisplayCell(column, rowData, rowIndex, value);
2284
+ };
2285
+ const getColWidth = (col) => {
2286
+ const w = col.width || columnWidth || 180;
2287
+ return typeof w === "number" ? w : 180;
2288
+ };
2289
+ /** 序号列 */
2290
+ const mapIndexColumn = (column) => {
2291
+ const col = column;
2292
+ return {
2293
+ key: "_index",
2294
+ title: col.title || "序号",
2295
+ width: typeof (col.width || 50) === "number" ? col.width || 50 : 50,
2296
+ titleAlign: "center",
2297
+ align: "center",
2298
+ render: (_, index) => index + 1,
2299
+ fixed: column.fixed
2300
+ };
2301
+ };
2302
+ /** 普通数据列 */
2303
+ const mapRegularColumn = (column) => {
2304
+ const col = column;
2305
+ const base = {
2306
+ ...col,
2307
+ width: getColWidth(column),
2308
+ titleAlign: col.titleAlign || "center",
2309
+ align: col.align || "center",
2310
+ render: column.render || ((rowData, rowIndex) => renderCell(column, rowData, rowIndex))
2311
+ };
2312
+ if (column.fixed) base.fixed = column.fixed;
2313
+ if (column.resizable && typeof base.width === "number") {
2314
+ base.resizable = true;
2315
+ base.minWidth = column.minWidth || 80;
2316
+ base.maxWidth = column.maxWidth || 500;
2317
+ }
2318
+ return base;
2319
+ };
2320
+ const computedColumns = computed(() => {
2321
+ let cols = reactiveColumns.value.filter((c) => {
2322
+ const col = c;
2323
+ return col.visible !== false && col.key !== "_actions";
2324
+ }).map((c) => {
2325
+ return c.type === "index" ? mapIndexColumn(c) : mapRegularColumn(c);
2326
+ });
2327
+ if (tableManager.dynamicRowsState) cols = tableManager.dynamicRowsState.enhanceColumns(cols);
2328
+ if (tableManager.expandState && (config.value.expandable || config.value.enableSelection)) cols = tableManager.expandState.getTableColumns(cols);
2329
+ const actionsMeta = reactiveColumns.value.find((c) => c.key === "_actions");
2330
+ cols.push({
2331
+ key: "_actions",
2332
+ title: "操作",
2333
+ align: "center",
2334
+ titleAlign: "center",
2335
+ render: actionsRenderer,
2336
+ fixed: actionsMeta?.fixed
2337
+ });
2338
+ return cols;
2339
+ });
2340
+ const computedScrollX = computed(() => {
2341
+ if (options.scrollX !== void 0) return options.scrollX;
2342
+ if (!reactiveColumns.value.some((c) => {
2343
+ const col = c;
2344
+ return col.fixed && col.visible !== false;
2345
+ })) return void 0;
2346
+ return reactiveColumns.value.filter((c) => c.visible !== false).reduce((sum, c) => sum + getColWidth(c), 0) + 200;
2347
+ });
2348
+ const handleColumnChange = (columns) => {
2349
+ reactiveColumns.value = columns.map((col) => {
2350
+ const c = col;
2351
+ return {
2352
+ ...col,
2353
+ visible: c.visible !== false,
2354
+ fixed: col.fixed,
2355
+ width: c.width || columnWidth,
2356
+ align: c.align || "center",
2357
+ titleAlign: c.titleAlign || "center"
2358
+ };
2359
+ });
2360
+ };
2361
+ return {
2362
+ reactiveColumns,
2363
+ showSettingsPanel,
2364
+ computedColumns,
2365
+ computedScrollX,
2366
+ handleColumnChange
2367
+ };
2368
+ }
2369
+
2370
+ //#endregion
2371
+ //#region src/components/C_Table/components/ColumnSettings/data.ts
2372
+ /** 固定列下拉选项 */
2373
+ const getFixedOptions = (column) => [
2374
+ {
2375
+ label: column.fixed ? "✓ 取消固定" : "不固定",
2376
+ key: "none",
2377
+ disabled: !column.fixed
2378
+ },
2379
+ {
2380
+ label: column.fixed === "left" ? "✓ 固定左侧" : "固定左侧",
2381
+ key: "left",
2382
+ disabled: false
2383
+ },
2384
+ {
2385
+ label: column.fixed === "right" ? "✓ 固定右侧" : "固定右侧",
2386
+ key: "right",
2387
+ disabled: false
2388
+ }
2389
+ ];
2390
+ /** 不可操作的特殊列 key */
2391
+ const SPECIAL_COLUMN_KEYS = ["_actions"];
2392
+ /** 不可拖拽的列 type */
2393
+ const SPECIAL_COLUMN_TYPES = ["selection", "expand"];
2394
+ /** 判断是否为特殊列(不可调宽、不可拖拽) */
2395
+ const isSpecialColumn = (column) => SPECIAL_COLUMN_KEYS.includes(column.key) || SPECIAL_COLUMN_TYPES.includes(column.type);
2396
+
2397
+ //#endregion
2398
+ //#region src/components/C_Table/components/ColumnSettings/index.vue?vue&type=script&setup=true&lang.ts
2399
+ const _hoisted_1$1 = { class: "column-management-tab" };
2400
+ const _hoisted_2$1 = { class: "search-row" };
2401
+ const _hoisted_3$1 = { class: "resizable-control" };
2402
+ const _hoisted_4$1 = { class: "top-actions-bar" };
2403
+ const _hoisted_5 = { class: "stats-info" };
2404
+ const _hoisted_6 = { class: "quick-actions" };
2405
+ const _hoisted_7 = [
2406
+ "draggable",
2407
+ "onDragstart",
2408
+ "onDragover",
2409
+ "onDrop"
2410
+ ];
2411
+ const _hoisted_8 = { class: "column-info" };
2412
+ const _hoisted_9 = { class: "column-controls" };
2413
+ const _hoisted_10 = { class: "column-details" };
2414
+ const _hoisted_11 = { class: "column-actions" };
2415
+ const _hoisted_12 = { class: "drag-controls" };
2416
+ var index_vue_vue_type_script_setup_true_lang_default$1 = /* @__PURE__ */ defineComponent({
2417
+ name: "ColumnSettings",
2418
+ __name: "index",
2419
+ props: { columns: {} },
2420
+ emits: ["change"],
2421
+ setup(__props, { emit: __emit }) {
2422
+ const props = __props;
2423
+ const emit = __emit;
2424
+ const localColumns = ref([...props.columns]);
2425
+ const searchText = ref("");
2426
+ const listRef = ref();
2427
+ const draggedIndex = ref(null);
2428
+ const dragOverIndex = ref(null);
2429
+ const enableResizable = ref(false);
2430
+ onMounted(() => {
2431
+ enableResizable.value = localColumns.value.some((col) => col.resizable === true);
2432
+ });
2433
+ const filteredColumns = computed(() => {
2434
+ if (!searchText.value) return localColumns.value;
2435
+ const search = searchText.value.toLowerCase();
2436
+ return localColumns.value.filter((col) => col.title?.toLowerCase().includes(search) || col.key.toLowerCase().includes(search));
2437
+ });
2438
+ const visibleCount = computed(() => localColumns.value.filter((col) => col.visible !== false).length);
2439
+ const totalCount = computed(() => localColumns.value.length);
2440
+ const setAllColumnsVisible = (visible) => {
2441
+ localColumns.value.forEach((col) => {
2442
+ if (col.key !== "_actions") col.visible = visible;
2443
+ });
2444
+ applyChanges();
2445
+ };
2446
+ const selectAll = () => setAllColumnsVisible(true);
2447
+ const selectNone = () => setAllColumnsVisible(false);
2448
+ const findOriginalIndex = (filteredIndex) => {
2449
+ const column = filteredColumns.value[filteredIndex];
2450
+ return localColumns.value.findIndex((col) => col.key === column.key);
2451
+ };
2452
+ const updateColumnProperty = (index, updater) => {
2453
+ const originalIndex = findOriginalIndex(index);
2454
+ if (originalIndex !== -1) {
2455
+ updater(localColumns.value[originalIndex]);
2456
+ applyChanges();
2457
+ }
2458
+ };
2459
+ const toggleColumnVisibility = (index, visible) => {
2460
+ updateColumnProperty(index, (col) => {
2461
+ col.visible = visible;
2462
+ });
2463
+ };
2464
+ const handleFixedSelect = (index, value) => {
2465
+ updateColumnProperty(index, (col) => {
2466
+ col.fixed = value === "none" ? void 0 : value;
2467
+ });
2468
+ };
2469
+ const applyChanges = () => emit("change", [...localColumns.value]);
2470
+ const resetColumns = () => {
2471
+ localColumns.value = [...props.columns];
2472
+ applyChanges();
2473
+ };
2474
+ const handleResizableChange = (value) => {
2475
+ localColumns.value.forEach((col) => {
2476
+ if (!isSpecialColumn(col)) {
2477
+ col.resizable = value;
2478
+ if (value) {
2479
+ col.minWidth = col.minWidth || 80;
2480
+ col.maxWidth = col.maxWidth || 500;
2481
+ }
2482
+ }
2483
+ });
2484
+ applyChanges();
2485
+ };
2486
+ const moveColumn = (fromIndex, toIndex) => {
2487
+ const originalFromIndex = findOriginalIndex(fromIndex);
2488
+ const originalToIndex = findOriginalIndex(toIndex);
2489
+ if (originalFromIndex !== -1 && originalToIndex !== -1) {
2490
+ const [movedColumn] = localColumns.value.splice(originalFromIndex, 1);
2491
+ localColumns.value.splice(originalToIndex, 0, movedColumn);
2492
+ applyChanges();
2493
+ }
2494
+ };
2495
+ const handleDragStart = (index, event) => {
2496
+ if (filteredColumns.value[index].key === "_actions") {
2497
+ event.preventDefault();
2498
+ return;
2499
+ }
2500
+ draggedIndex.value = index;
2501
+ if (event.dataTransfer) event.dataTransfer.effectAllowed = "move";
2502
+ };
2503
+ const handleDragOver = (index, event) => {
2504
+ event.preventDefault();
2505
+ if (draggedIndex.value === null || filteredColumns.value[index].key === "_actions") return;
2506
+ dragOverIndex.value = index;
2507
+ if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
2508
+ };
2509
+ const handleDrop = (toIndex) => {
2510
+ if (draggedIndex.value === null || filteredColumns.value[toIndex].key === "_actions") return;
2511
+ moveColumn(draggedIndex.value, toIndex);
2512
+ draggedIndex.value = null;
2513
+ dragOverIndex.value = null;
2514
+ };
2515
+ const handleDragEnd = () => {
2516
+ draggedIndex.value = null;
2517
+ dragOverIndex.value = null;
2518
+ };
2519
+ return (_ctx, _cache) => {
2520
+ return openBlock(), createElementBlock("div", _hoisted_1$1, [
2521
+ createCommentVNode(" 搜索框和列宽调整开关 "),
2522
+ createElementVNode("div", _hoisted_2$1, [createVNode(unref(NInput$1), {
2523
+ value: searchText.value,
2524
+ "onUpdate:value": _cache[0] || (_cache[0] = ($event) => searchText.value = $event),
2525
+ placeholder: "搜索列名...",
2526
+ clearable: "",
2527
+ class: "search-input"
2528
+ }, {
2529
+ prefix: withCtx(() => [createVNode(C_Icon_default, { name: "mdi:magnify" })]),
2530
+ _: 1
2531
+ }, 8, ["value"]), createElementVNode("div", _hoisted_3$1, [
2532
+ createVNode(C_Icon_default, {
2533
+ name: "mdi:arrow-split-vertical",
2534
+ size: "14",
2535
+ title: enableResizable.value ? "开启后可拖拽列边界调整宽度" : "允许调整列宽"
2536
+ }, null, 8, ["title"]),
2537
+ createVNode(unref(NText$1), { style: {
2538
+ fontSize: "12px",
2539
+ marginLeft: "4px"
2540
+ } }, {
2541
+ default: withCtx(() => _cache[2] || (_cache[2] = [createTextVNode(" 列宽调整 ", -1)])),
2542
+ _: 1,
2543
+ __: [2]
2544
+ }),
2545
+ createVNode(unref(NSwitch$1), {
2546
+ value: enableResizable.value,
2547
+ "onUpdate:value": [_cache[1] || (_cache[1] = ($event) => enableResizable.value = $event), handleResizableChange],
2548
+ size: "small",
2549
+ style: { "margin-left": "6px" }
2550
+ }, null, 8, ["value"])
2551
+ ])]),
2552
+ createCommentVNode(" 顶部操作栏:统计信息和快捷操作按钮 "),
2553
+ createElementVNode("div", _hoisted_4$1, [createElementVNode("div", _hoisted_5, [createVNode(unref(NText$1), {
2554
+ depth: "3",
2555
+ style: { fontSize: "13px" }
2556
+ }, {
2557
+ default: withCtx(() => [createTextVNode(" 已选 " + toDisplayString(visibleCount.value) + " / 总共 " + toDisplayString(totalCount.value) + " 列 ", 1)]),
2558
+ _: 1
2559
+ })]), createElementVNode("div", _hoisted_6, [createVNode(unref(NSpace$1), { size: 6 }, {
2560
+ default: withCtx(() => [
2561
+ createVNode(unref(NButton$1), {
2562
+ size: "tiny",
2563
+ onClick: selectAll
2564
+ }, {
2565
+ default: withCtx(() => _cache[3] || (_cache[3] = [createTextVNode(" 全选 ", -1)])),
2566
+ _: 1,
2567
+ __: [3]
2568
+ }),
2569
+ createVNode(unref(NButton$1), {
2570
+ size: "tiny",
2571
+ onClick: selectNone
2572
+ }, {
2573
+ default: withCtx(() => _cache[4] || (_cache[4] = [createTextVNode(" 全不选 ", -1)])),
2574
+ _: 1,
2575
+ __: [4]
2576
+ }),
2577
+ createVNode(unref(NButton$1), {
2578
+ size: "tiny",
2579
+ onClick: resetColumns
2580
+ }, {
2581
+ default: withCtx(() => _cache[5] || (_cache[5] = [createTextVNode(" 重置 ", -1)])),
2582
+ _: 1,
2583
+ __: [5]
2584
+ })
2585
+ ]),
2586
+ _: 1
2587
+ })])]),
2588
+ createCommentVNode(" 列列表 "),
2589
+ createElementVNode("div", {
2590
+ ref_key: "listRef",
2591
+ ref: listRef,
2592
+ class: "column-list"
2593
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(filteredColumns.value, (column, index) => {
2594
+ return openBlock(), createElementBlock("div", {
2595
+ key: column.key,
2596
+ class: normalizeClass(["column-item", {
2597
+ disabled: column.key === "_actions",
2598
+ "fixed-left": column.fixed === "left",
2599
+ "fixed-right": column.fixed === "right"
2600
+ }]),
2601
+ draggable: column.key !== "_actions",
2602
+ onDragstart: ($event) => handleDragStart(index, $event),
2603
+ onDragover: ($event) => handleDragOver(index, $event),
2604
+ onDragend: handleDragEnd,
2605
+ onDrop: ($event) => handleDrop(index)
2606
+ }, [createElementVNode("div", _hoisted_8, [createElementVNode("div", _hoisted_9, [createVNode(C_Icon_default, {
2607
+ name: "mdi:drag",
2608
+ size: "16",
2609
+ class: normalizeClass(["drag-handle", { disabled: column.key === "_actions" }])
2610
+ }, null, 8, ["class"]), createVNode(unref(NCheckbox$1), {
2611
+ checked: column.visible !== false,
2612
+ disabled: column.key === "_actions",
2613
+ "onUpdate:checked": (value) => toggleColumnVisibility(index, value)
2614
+ }, null, 8, [
2615
+ "checked",
2616
+ "disabled",
2617
+ "onUpdate:checked"
2618
+ ])]), createElementVNode("div", _hoisted_10, [createVNode(unref(NSpace$1), {
2619
+ align: "center",
2620
+ size: 6
2621
+ }, {
2622
+ default: withCtx(() => [
2623
+ createVNode(unref(NText$1), {
2624
+ strong: "",
2625
+ style: { fontSize: "13px" }
2626
+ }, {
2627
+ default: withCtx(() => [createTextVNode(toDisplayString(column.title || column.key), 1)]),
2628
+ _: 2
2629
+ }, 1024),
2630
+ column.fixed === "left" ? (openBlock(), createBlock(unref(NTag$1), {
2631
+ key: 0,
2632
+ size: "tiny",
2633
+ type: "info"
2634
+ }, {
2635
+ default: withCtx(() => _cache[6] || (_cache[6] = [createTextVNode(" 左固定 ", -1)])),
2636
+ _: 1,
2637
+ __: [6]
2638
+ })) : createCommentVNode("v-if", true),
2639
+ column.fixed === "right" ? (openBlock(), createBlock(unref(NTag$1), {
2640
+ key: 1,
2641
+ size: "tiny",
2642
+ type: "warning"
2643
+ }, {
2644
+ default: withCtx(() => _cache[7] || (_cache[7] = [createTextVNode(" 右固定 ", -1)])),
2645
+ _: 1,
2646
+ __: [7]
2647
+ })) : createCommentVNode("v-if", true)
2648
+ ]),
2649
+ _: 2
2650
+ }, 1024), createVNode(unref(NText$1), {
2651
+ depth: "3",
2652
+ style: { fontSize: "11px" }
2653
+ }, {
2654
+ default: withCtx(() => [createTextVNode(toDisplayString(column.key), 1)]),
2655
+ _: 2
2656
+ }, 1024)])]), createElementVNode("div", _hoisted_11, [createElementVNode("div", _hoisted_12, [createVNode(C_Icon_default, {
2657
+ name: "mdi:chevron-up",
2658
+ size: "14",
2659
+ title: "上移",
2660
+ clickable: index !== 0,
2661
+ class: normalizeClass({ disabled: index === 0 }),
2662
+ onClick: ($event) => index !== 0 && moveColumn(index, index - 1)
2663
+ }, null, 8, [
2664
+ "clickable",
2665
+ "class",
2666
+ "onClick"
2667
+ ]), createVNode(C_Icon_default, {
2668
+ name: "mdi:chevron-down",
2669
+ size: "14",
2670
+ title: "下移",
2671
+ clickable: index !== filteredColumns.value.length - 1,
2672
+ class: normalizeClass({ disabled: index === filteredColumns.value.length - 1 }),
2673
+ onClick: ($event) => index !== filteredColumns.value.length - 1 && moveColumn(index, index + 1)
2674
+ }, null, 8, [
2675
+ "clickable",
2676
+ "class",
2677
+ "onClick"
2678
+ ])]), createVNode(unref(NDropdown$1), {
2679
+ options: unref(getFixedOptions)(column),
2680
+ onSelect: (value) => handleFixedSelect(index, value)
2681
+ }, {
2682
+ default: withCtx(() => [createVNode(C_Icon_default, {
2683
+ name: "mdi:pin",
2684
+ size: "14",
2685
+ title: "固定列",
2686
+ clickable: "",
2687
+ style: normalizeStyle({ color: column.fixed ? "var(--n-primary-color)" : void 0 })
2688
+ }, null, 8, ["style"])]),
2689
+ _: 2
2690
+ }, 1032, ["options", "onSelect"])])], 42, _hoisted_7);
2691
+ }), 128))], 512)
2692
+ ]);
2693
+ };
2694
+ }
2695
+ });
2696
+
2697
+ //#endregion
2698
+ //#region src/components/C_Table/components/ColumnSettings/index.vue
2699
+ var ColumnSettings_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default$1, [["__scopeId", "data-v-80dbeb1b"]]);
2700
+
2701
+ //#endregion
2702
+ //#region src/components/C_Table/index.vue?vue&type=script&setup=true&lang.ts
2703
+ const _hoisted_1 = { class: "c-table-wrapper" };
2704
+ const _hoisted_2 = {
2705
+ key: 1,
2706
+ class: "table-toolbar"
2707
+ };
2708
+ const _hoisted_3 = { class: "toolbar-left" };
2709
+ const _hoisted_4 = { class: "toolbar-right" };
2710
+ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
2711
+ name: "C_Table",
2712
+ inheritAttrs: false,
2713
+ __name: "index",
2714
+ props: {
2715
+ columns: {},
2716
+ data: {},
2717
+ loading: { default: false },
2718
+ rowKey: {
2719
+ type: Function,
2720
+ default: (row) => row.id
2721
+ },
2722
+ config: { default: () => ({}) },
2723
+ crud: {}
2724
+ },
2725
+ emits: [
2726
+ "pagination-change",
2727
+ "row-delete",
2728
+ "expand-change",
2729
+ "selection-change",
2730
+ "child-selection-change",
2731
+ "parent-child-link-change",
2732
+ "update:data",
2733
+ "save",
2734
+ "cancel",
2735
+ "row-add",
2736
+ "row-copy",
2737
+ "row-move",
2738
+ "row-selection-change",
2739
+ "view-detail",
2740
+ "column-change"
2741
+ ],
2742
+ setup(__props, { expose: __expose, emit: __emit }) {
2743
+ const props = __props;
2744
+ const emit = __emit;
2745
+ /** 包装 emit:在触发事件的同时自动调用 crud 对应的方法 */
2746
+ const bridgedEmit = (event, ...args) => {
2747
+ emit(event, ...args);
2748
+ if (!props.crud) return;
2749
+ ({
2750
+ save: props.crud.save,
2751
+ cancel: props.crud.handleCancel,
2752
+ "pagination-change": props.crud.handlePaginationChange,
2753
+ "row-delete": props.crud.handleRowDelete,
2754
+ "view-detail": props.crud.detail?.show
2755
+ })[event]?.(...args);
2756
+ };
2757
+ /** 合并 crud 返回的 actions/pagination 到用户 config */
2758
+ const effectiveConfig = computed(() => {
2759
+ if (!props.crud) return props.config || {};
2760
+ const fromCrud = {};
2761
+ if (props.crud.actions) fromCrud.actions = props.crud.actions.value;
2762
+ if (props.crud.pagination) fromCrud.pagination = props.crud.pagination.value;
2763
+ return {
2764
+ ...fromCrud,
2765
+ ...props.config
2766
+ };
2767
+ });
2768
+ const effectiveColumns = computed(() => props.columns ?? props.crud?.columns.value ?? []);
2769
+ const resolved = computed(() => resolveConfig(effectiveConfig.value));
2770
+ const editModeChecker = computed(() => createEditModeChecker(resolved.value));
2771
+ const unwrapRef = (val) => val && typeof val === "object" && "value" in val ? val.value : val;
2772
+ const normalizedData = computed(() => unwrapRef(props.data) ?? props.crud?.data.value ?? []);
2773
+ const normalizedLoading = computed(() => unwrapRef(props.loading) ?? props.crud?.loading.value ?? false);
2774
+ const pagination = usePagination({
2775
+ data: normalizedData,
2776
+ config: computed(() => resolved.value.pagination),
2777
+ emit: bridgedEmit
2778
+ });
2779
+ const tableManager = useTableManager({
2780
+ config: resolved.value,
2781
+ data: () => normalizedData.value,
2782
+ rowKey: props.rowKey,
2783
+ emit: bridgedEmit
2784
+ });
2785
+ const tableActions = useTableActions({
2786
+ actions: computed(() => effectiveConfig.value.actions || {}),
2787
+ config: resolved,
2788
+ tableManager,
2789
+ rowKey: props.rowKey,
2790
+ emit: bridgedEmit,
2791
+ onViewDetail: (data) => bridgedEmit("view-detail", data)
2792
+ });
2793
+ const columnState = useTableColumns({
2794
+ rawColumns: effectiveColumns,
2795
+ config: resolved,
2796
+ columnWidth: resolved.value.columnWidth,
2797
+ scrollX: resolved.value.scrollX,
2798
+ rowKey: props.rowKey,
2799
+ tableManager,
2800
+ actionsRenderer: tableActions.renderActions,
2801
+ editModeChecker
2802
+ });
2803
+ const { showSettingsPanel, reactiveColumns, computedColumns, computedScrollX } = columnState;
2804
+ const tableRef = ref();
2805
+ const computedTableProps = computed(() => ({
2806
+ striped: resolved.value.striped,
2807
+ bordered: resolved.value.bordered,
2808
+ singleLine: resolved.value.singleLine,
2809
+ size: resolved.value.size,
2810
+ maxHeight: resolved.value.maxHeight
2811
+ }));
2812
+ const editFormRef = ref();
2813
+ const modalSubmitLoading = ref(false);
2814
+ const localEditingData = ref({});
2815
+ const modalVisible = computed({
2816
+ get: () => tableManager.editStates.modalEdit.isModalVisible.value,
2817
+ set: (val) => {
2818
+ tableManager.editStates.modalEdit.isModalVisible.value = val;
2819
+ }
2820
+ });
2821
+ const editableColumns = computed(() => effectiveColumns.value.filter((col) => col.editable !== false));
2822
+ const formKey = computed(() => `edit-form-${tableManager.editStates.modalEdit.editingRowKey.value || "new"}`);
2823
+ const formOptions = computed(() => generateFormOptions(editableColumns.value));
2824
+ watch(() => tableManager.editStates.modalEdit.editingData.value, (newData) => {
2825
+ if (newData && Object.keys(newData).length > 0) localEditingData.value = JSON.parse(JSON.stringify(newData));
2826
+ }, {
2827
+ immediate: true,
2828
+ deep: true
2829
+ });
2830
+ let modalCloseTimer = null;
2831
+ watch(modalVisible, (visible) => {
2832
+ if (!visible) modalCloseTimer = setTimeout(() => {
2833
+ localEditingData.value = {};
2834
+ modalCloseTimer = null;
2835
+ }, 300);
2836
+ });
2837
+ const handleModalSave = async () => {
2838
+ if (!editFormRef.value) return;
2839
+ modalSubmitLoading.value = true;
2840
+ try {
2841
+ await editFormRef.value.validate();
2842
+ await tableManager.editStates.modalEdit.saveEdit(localEditingData.value);
2843
+ } catch {} finally {
2844
+ modalSubmitLoading.value = false;
2845
+ }
2846
+ };
2847
+ const handleModalCancel = () => {
2848
+ localEditingData.value = {};
2849
+ tableManager.editStates.modalEdit.cancelEdit();
2850
+ };
2851
+ const onColumnSettingsChange = (columns) => {
2852
+ columnState.handleColumnChange(columns);
2853
+ emit("column-change", columnState.reactiveColumns.value);
2854
+ };
2855
+ const { edit, expand, selection, dynamicRows } = tableManager.stateManager;
2856
+ const exposedApi = {
2857
+ startEdit: edit.start,
2858
+ expandAll: expand.all,
2859
+ collapseAll: expand.collapseAll,
2860
+ selectAll: selection.all,
2861
+ clearSelection: selection.clear,
2862
+ clearAllSelections: tableManager.stateManager.clearAllSelections,
2863
+ clearRowSelection: dynamicRows?.clearSelection,
2864
+ resetToFirstPage: pagination.resetToFirstPage,
2865
+ getSelectedRows: selection.getSelected,
2866
+ getEditingData: edit.getEditingData,
2867
+ isEditing: edit.isEditing,
2868
+ isExpanded: expand.isExpanded,
2869
+ getManager: () => tableManager.stateManager
2870
+ };
2871
+ __expose(exposedApi);
2872
+ onMounted(() => {
2873
+ const crudRef = props.crud?.tableRef;
2874
+ if (crudRef) crudRef.value = exposedApi;
2875
+ });
2876
+ onBeforeUnmount(() => {
2877
+ if (modalCloseTimer) clearTimeout(modalCloseTimer);
2878
+ });
2879
+ return (_ctx, _cache) => {
2880
+ return openBlock(), createElementBlock("div", _hoisted_1, [
2881
+ createCommentVNode(" 动态行工具栏 "),
2882
+ unref(tableManager).dynamicRowsState ? (openBlock(), createBlock(resolveDynamicComponent(unref(tableManager).dynamicRowsState.renderToolbar()), { key: 0 })) : createCommentVNode("v-if", true),
2883
+ createCommentVNode(" 表格工具栏 "),
2884
+ resolved.value.showToolbar ? (openBlock(), createElementBlock("div", _hoisted_2, [createElementVNode("div", _hoisted_3, [renderSlot(_ctx.$slots, "toolbar-left", {}, void 0, true)]), createElementVNode("div", _hoisted_4, [renderSlot(_ctx.$slots, "toolbar-right", {}, void 0, true), resolved.value.enableColumnSettings ? (openBlock(), createBlock(C_Icon_default, {
2885
+ key: 0,
2886
+ name: "mdi:cog",
2887
+ size: "18",
2888
+ title: "表格设置",
2889
+ clickable: "",
2890
+ class: "column-settings-btn",
2891
+ onClick: _cache[0] || (_cache[0] = ($event) => showSettingsPanel.value = true)
2892
+ })) : createCommentVNode("v-if", true)])])) : createCommentVNode("v-if", true),
2893
+ createCommentVNode(" 表格主体 "),
2894
+ createVNode(unref(NDataTable), mergeProps({
2895
+ ref_key: "tableRef",
2896
+ ref: tableRef
2897
+ }, {
2898
+ ...computedTableProps.value,
2899
+ ..._ctx.$attrs
2900
+ }, {
2901
+ columns: unref(computedColumns),
2902
+ data: normalizedData.value,
2903
+ loading: normalizedLoading.value,
2904
+ "row-key": _ctx.rowKey,
2905
+ "expanded-row-keys": unref(tableManager).expandedKeys.value,
2906
+ "checked-row-keys": unref(tableManager).checkedKeys.value,
2907
+ "onUpdate:expandedRowKeys": unref(tableManager).expandState?.handleExpandChange,
2908
+ "onUpdate:checkedRowKeys": unref(tableManager).expandState?.handleSelectionChange,
2909
+ "scroll-x": unref(computedScrollX),
2910
+ style: { "width": "100%" }
2911
+ }), null, 16, [
2912
+ "columns",
2913
+ "data",
2914
+ "loading",
2915
+ "row-key",
2916
+ "expanded-row-keys",
2917
+ "checked-row-keys",
2918
+ "onUpdate:expandedRowKeys",
2919
+ "onUpdate:checkedRowKeys",
2920
+ "scroll-x"
2921
+ ]),
2922
+ createCommentVNode(" 分页 "),
2923
+ unref(pagination).paginationConfig.value ? (openBlock(), createBlock(unref(NPagination$1), mergeProps({ key: 2 }, unref(pagination).paginationConfig.value, { class: "pagination-wrapper" }), null, 16)) : createCommentVNode("v-if", true),
2924
+ createCommentVNode(" 编辑弹窗 "),
2925
+ resolved.value.editMode === "modal" || resolved.value.editMode === "both" ? (openBlock(), createBlock(unref(NModal$1), {
2926
+ key: 3,
2927
+ show: modalVisible.value,
2928
+ "onUpdate:show": _cache[2] || (_cache[2] = ($event) => modalVisible.value = $event),
2929
+ title: resolved.value.modalTitle,
2930
+ width: resolved.value.modalWidth,
2931
+ preset: "card",
2932
+ "mask-closable": false,
2933
+ "close-on-esc": false,
2934
+ class: "w60%",
2935
+ closable: false
2936
+ }, {
2937
+ action: withCtx(() => [createVNode(unref(NSpace$1), { justify: "end" }, {
2938
+ default: withCtx(() => [createVNode(unref(NButton$1), { onClick: handleModalCancel }, {
2939
+ default: withCtx(() => _cache[4] || (_cache[4] = [createTextVNode("取消", -1)])),
2940
+ _: 1,
2941
+ __: [4]
2942
+ }), createVNode(unref(NButton$1), {
2943
+ type: "primary",
2944
+ loading: modalSubmitLoading.value,
2945
+ onClick: handleModalSave
2946
+ }, {
2947
+ default: withCtx(() => _cache[5] || (_cache[5] = [createTextVNode(" 保存 ", -1)])),
2948
+ _: 1,
2949
+ __: [5]
2950
+ }, 8, ["loading"])]),
2951
+ _: 1
2952
+ })]),
2953
+ default: withCtx(() => [modalVisible.value && formOptions.value.length ? (openBlock(), createBlock(C_Form_default, {
2954
+ ref_key: "editFormRef",
2955
+ ref: editFormRef,
2956
+ key: formKey.value,
2957
+ modelValue: localEditingData.value,
2958
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => localEditingData.value = $event),
2959
+ options: formOptions.value,
2960
+ config: {
2961
+ layout: "grid",
2962
+ grid: {
2963
+ cols: 2,
2964
+ xGap: 16,
2965
+ yGap: 16
2966
+ },
2967
+ showActions: false
2968
+ }
2969
+ }, null, 8, ["modelValue", "options"])) : createCommentVNode("v-if", true)]),
2970
+ _: 1
2971
+ }, 8, [
2972
+ "show",
2973
+ "title",
2974
+ "width"
2975
+ ])) : createCommentVNode("v-if", true),
2976
+ createCommentVNode(" 动态行确认删除弹窗 "),
2977
+ unref(tableManager).dynamicRowsState ? (openBlock(), createBlock(resolveDynamicComponent(unref(tableManager).dynamicRowsState.renderConfirmModal()), { key: 4 })) : createCommentVNode("v-if", true),
2978
+ createCommentVNode(" 列设置抽屉 "),
2979
+ createVNode(unref(NDrawer$1), {
2980
+ show: unref(showSettingsPanel),
2981
+ "onUpdate:show": _cache[3] || (_cache[3] = ($event) => isRef(showSettingsPanel) ? showSettingsPanel.value = $event : null),
2982
+ width: 420,
2983
+ placement: "right",
2984
+ "mask-closable": true
2985
+ }, {
2986
+ default: withCtx(() => [createVNode(unref(NDrawerContent$1), {
2987
+ title: "列设置",
2988
+ closable: ""
2989
+ }, {
2990
+ default: withCtx(() => [createVNode(ColumnSettings_default, {
2991
+ columns: unref(reactiveColumns),
2992
+ onChange: onColumnSettingsChange
2993
+ }, null, 8, ["columns"])]),
2994
+ _: 1
2995
+ })]),
2996
+ _: 1
2997
+ }, 8, ["show"])
2998
+ ]);
2999
+ };
3000
+ }
3001
+ });
3002
+
3003
+ //#endregion
3004
+ //#region src/components/C_Table/index.vue
3005
+ var C_Table_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-cbdb9723"]]);
3006
+
3007
+ //#endregion
3008
+ export { useTableManager as a, usePrintWatermark as c, useCellEdit as d, useRowEdit as f, usePagination as i, useTableExpand as l, resolveConfig as m, useTableColumns as n, useDynamicRows as o, createEditModeChecker as p, useTableActions as r, printPresets as s, C_Table_default as t, useModalEdit as u };
3009
+ //# sourceMappingURL=C_Table2.js.map