@qynpm/ui 1.0.26 → 1.0.28

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 (210) hide show
  1. package/README.md +291 -5
  2. package/dist/index.cjs +11 -5
  3. package/dist/index.mjs +70 -43
  4. package/dist/qy-action-bar/index.cjs +1 -1
  5. package/dist/qy-action-bar/index.mjs +1 -1
  6. package/dist/qy-alert/index.cjs +1 -0
  7. package/dist/qy-alert/index.mjs +7 -0
  8. package/dist/qy-avatar/index.cjs +1 -0
  9. package/dist/qy-avatar/index.mjs +7 -0
  10. package/dist/qy-badge/index.cjs +1 -0
  11. package/dist/qy-badge/index.mjs +7 -0
  12. package/dist/qy-button/index.cjs +1 -1
  13. package/dist/qy-button/index.mjs +1 -1
  14. package/dist/qy-card/index.cjs +1 -0
  15. package/dist/qy-card/index.mjs +7 -0
  16. package/dist/qy-cascader/index.cjs +1 -0
  17. package/dist/qy-cascader/index.mjs +7 -0
  18. package/dist/qy-checkbox/index.cjs +1 -1
  19. package/dist/qy-checkbox/index.mjs +1 -1
  20. package/dist/qy-checkbox-group/index.cjs +1 -1
  21. package/dist/qy-checkbox-group/index.mjs +1 -1
  22. package/dist/qy-collapse/index.cjs +1 -0
  23. package/dist/qy-collapse/index.mjs +7 -0
  24. package/dist/qy-collapse-item/index.cjs +1 -0
  25. package/dist/qy-collapse-item/index.mjs +7 -0
  26. package/dist/qy-descriptions/index.cjs +1 -0
  27. package/dist/qy-descriptions/index.mjs +7 -0
  28. package/dist/qy-descriptions-item/index.cjs +1 -0
  29. package/dist/qy-descriptions-item/index.mjs +7 -0
  30. package/dist/qy-dialog/index.cjs +1 -1
  31. package/dist/qy-dialog/index.mjs +1 -1
  32. package/dist/qy-divider/index.cjs +1 -0
  33. package/dist/qy-divider/index.mjs +7 -0
  34. package/dist/qy-dropdown/index.cjs +1 -1
  35. package/dist/qy-dropdown/index.mjs +1 -1
  36. package/dist/qy-empty/index.cjs +1 -0
  37. package/dist/qy-empty/index.mjs +7 -0
  38. package/dist/qy-file-picker/index.cjs +1 -1
  39. package/dist/qy-file-picker/index.mjs +1 -1
  40. package/dist/qy-form-section/index.cjs +1 -1
  41. package/dist/qy-form-section/index.mjs +2 -2
  42. package/dist/qy-image/index.cjs +1 -1
  43. package/dist/qy-image/index.mjs +1 -1
  44. package/dist/qy-image-upload/index.cjs +1 -1
  45. package/dist/qy-image-upload/index.mjs +1 -1
  46. package/dist/qy-legacy-selection-dialog/index.cjs +1 -1
  47. package/dist/qy-legacy-selection-dialog/index.mjs +2 -2
  48. package/dist/qy-link/index.cjs +1 -0
  49. package/dist/qy-link/index.mjs +7 -0
  50. package/dist/qy-menu-actions/index.cjs +1 -1
  51. package/dist/qy-menu-actions/index.mjs +1 -1
  52. package/dist/qy-money-input/index.cjs +1 -1
  53. package/dist/qy-money-input/index.mjs +1 -1
  54. package/dist/qy-popover/index.cjs +1 -1
  55. package/dist/qy-popover/index.mjs +1 -1
  56. package/dist/qy-progress/index.cjs +1 -0
  57. package/dist/qy-progress/index.mjs +7 -0
  58. package/dist/qy-radio/index.cjs +1 -1
  59. package/dist/qy-radio/index.mjs +1 -1
  60. package/dist/qy-radio-group/index.cjs +1 -1
  61. package/dist/qy-radio-group/index.mjs +1 -1
  62. package/dist/qy-record-quote-search/index.cjs +1 -1
  63. package/dist/qy-record-quote-search/index.mjs +1 -1
  64. package/dist/qy-remark-image/index.cjs +1 -1
  65. package/dist/qy-remark-image/index.mjs +1 -1
  66. package/dist/qy-remote-select/index.cjs +1 -1
  67. package/dist/qy-remote-select/index.mjs +1 -1
  68. package/dist/qy-scrollbar/index.cjs +1 -0
  69. package/dist/qy-scrollbar/index.mjs +7 -0
  70. package/dist/qy-search-input/index.cjs +1 -1
  71. package/dist/qy-search-input/index.mjs +1 -1
  72. package/dist/qy-select/index.cjs +1 -1
  73. package/dist/qy-select/index.mjs +1 -1
  74. package/dist/qy-selection-dialog/index.cjs +1 -1
  75. package/dist/qy-selection-dialog/index.mjs +1 -1
  76. package/dist/qy-skeleton/index.cjs +1 -0
  77. package/dist/qy-skeleton/index.mjs +7 -0
  78. package/dist/qy-skeleton-item/index.cjs +1 -0
  79. package/dist/qy-skeleton-item/index.mjs +7 -0
  80. package/dist/qy-step/index.cjs +1 -0
  81. package/dist/qy-step/index.mjs +7 -0
  82. package/dist/qy-steps/index.cjs +1 -0
  83. package/dist/qy-steps/index.mjs +7 -0
  84. package/dist/qy-switch/index.cjs +1 -1
  85. package/dist/qy-switch/index.mjs +1 -1
  86. package/dist/qy-tab-pane/index.cjs +1 -0
  87. package/dist/qy-tab-pane/index.mjs +7 -0
  88. package/dist/qy-table-column-settings/index.cjs +1 -1
  89. package/dist/qy-table-column-settings/index.mjs +1 -1
  90. package/dist/qy-tabs/index.cjs +1 -0
  91. package/dist/qy-tabs/index.mjs +7 -0
  92. package/dist/qy-tag/index.cjs +1 -1
  93. package/dist/qy-tag/index.mjs +1 -1
  94. package/dist/qy-tooltip/index.cjs +1 -1
  95. package/dist/qy-tooltip/index.mjs +1 -1
  96. package/dist/qy-tree/index.cjs +1 -0
  97. package/dist/qy-tree/index.mjs +7 -0
  98. package/dist/qy-tree-select/index.cjs +1 -1
  99. package/dist/qy-tree-select/index.mjs +5 -4
  100. package/dist/qy-upload/index.cjs +1 -1
  101. package/dist/qy-upload/index.mjs +1 -1
  102. package/dist/shared/index-B8phg478.cjs +1 -0
  103. package/dist/shared/{index-9v7CIwzO.cjs → index-B9RYNZUh.cjs} +1 -1
  104. package/dist/shared/index-BTL45WYB.cjs +1 -0
  105. package/dist/shared/{index-B7uyWUhS.mjs → index-C7V-LeFg.mjs} +1 -1
  106. package/dist/shared/{index-R5B1rjXo.mjs → index-CVoiIRas.mjs} +10 -10
  107. package/dist/shared/{index-Du2IqeCI.mjs → index-CYn7TvRx.mjs} +1 -1
  108. package/dist/shared/{index-DmhpD4Cp.cjs → index-CpvFUems.cjs} +1 -1
  109. package/dist/shared/{index-C1YwUATr.cjs → index-DEkng5wh.cjs} +1 -1
  110. package/dist/shared/index-DHJf8Zto.mjs +377 -0
  111. package/dist/shared/index-DjyaOKUS.cjs +1 -0
  112. package/dist/shared/{index-C98mN7sQ.mjs → index-DleLvEzf.mjs} +1198 -1134
  113. package/dist/shared/{index-DZroPZ8B.mjs → index-hEy-3mcr.mjs} +8 -8
  114. package/dist/shared/index.vue_vue_type_script_lang-69zSOotQ.mjs +47 -0
  115. package/dist/shared/index.vue_vue_type_script_lang-BGAdXWIL.mjs +78 -0
  116. package/dist/shared/index.vue_vue_type_script_lang-BO9Ju_i0.cjs +1 -0
  117. package/dist/shared/index.vue_vue_type_script_lang-Bc3tktk9.cjs +1 -0
  118. package/dist/shared/index.vue_vue_type_script_lang-BkoqbceR.cjs +1 -0
  119. package/dist/shared/index.vue_vue_type_script_lang-C4JHCuXz.mjs +54 -0
  120. package/dist/shared/index.vue_vue_type_script_lang-C9X0V5AK.mjs +71 -0
  121. package/dist/shared/index.vue_vue_type_script_lang-CIOi2ahp.cjs +1 -0
  122. package/dist/shared/index.vue_vue_type_script_lang-CZK0hDYa.mjs +77 -0
  123. package/dist/shared/index.vue_vue_type_script_lang-Cv4Pf58E.cjs +1 -0
  124. package/dist/shared/index.vue_vue_type_script_lang-CwrbII5c.cjs +1 -0
  125. package/dist/shared/index.vue_vue_type_script_lang-D42aRlO2.cjs +1 -0
  126. package/dist/shared/index.vue_vue_type_script_lang-D7b9ABei.mjs +113 -0
  127. package/dist/shared/index.vue_vue_type_script_lang-D7nzeBUR.mjs +35 -0
  128. package/dist/shared/index.vue_vue_type_script_lang-DIKHRo0o.mjs +72 -0
  129. package/dist/shared/index.vue_vue_type_script_lang-DLmUPDR5.cjs +1 -0
  130. package/dist/shared/index.vue_vue_type_script_lang-DMrpLmWN.cjs +1 -0
  131. package/dist/shared/index.vue_vue_type_script_lang-DOOT2grg.mjs +54 -0
  132. package/dist/shared/index.vue_vue_type_script_lang-Dfq7D3mJ.mjs +18 -0
  133. package/dist/shared/index.vue_vue_type_script_lang-DpSaB5eg.cjs +1 -0
  134. package/dist/shared/index.vue_vue_type_script_lang-WJ63_A7F.cjs +1 -0
  135. package/dist/shared/index.vue_vue_type_script_lang-chBiq2cG.mjs +31 -0
  136. package/dist/shared/index.vue_vue_type_script_setup_true_lang-4KZSABSM.cjs +1 -0
  137. package/dist/shared/index.vue_vue_type_script_setup_true_lang-B4JrNUDc.mjs +43 -0
  138. package/dist/shared/index.vue_vue_type_script_setup_true_lang-BJe7Uo6S.mjs +42 -0
  139. package/dist/shared/index.vue_vue_type_script_setup_true_lang-BWi3g3mb.cjs +1 -0
  140. package/dist/shared/index.vue_vue_type_script_setup_true_lang-Bdz9oDDW.mjs +62 -0
  141. package/dist/shared/index.vue_vue_type_script_setup_true_lang-C96ZaggL.cjs +1 -0
  142. package/dist/shared/{index.vue_vue_type_script_setup_true_lang-CKZHI_y-.mjs → index.vue_vue_type_script_setup_true_lang-CUox3Lm-.mjs} +1 -1
  143. package/dist/shared/index.vue_vue_type_script_setup_true_lang-CmQLfhRo.cjs +1 -0
  144. package/dist/shared/index.vue_vue_type_script_setup_true_lang-DUEhuwGQ.cjs +1 -0
  145. package/dist/shared/{index.vue_vue_type_script_setup_true_lang-C3F8M9sD.cjs → index.vue_vue_type_script_setup_true_lang-DXGjuA2f.cjs} +1 -1
  146. package/dist/shared/{index.vue_vue_type_script_setup_true_lang-N12Nn2uu.mjs → index.vue_vue_type_script_setup_true_lang-DXtovY1E.mjs} +1 -1
  147. package/dist/shared/index.vue_vue_type_script_setup_true_lang-Dd_nKJvH.mjs +19 -0
  148. package/dist/shared/index.vue_vue_type_script_setup_true_lang-DobP199g.mjs +63 -0
  149. package/dist/shared/{index.vue_vue_type_script_setup_true_lang-CsKjCWIN.cjs → index.vue_vue_type_script_setup_true_lang-kje3Rtlw.cjs} +1 -1
  150. package/dist/shared/index.vue_vue_type_style_index_0_lang-B-FeHatv.mjs +98 -0
  151. package/dist/shared/index.vue_vue_type_style_index_0_lang-BXTkWo5P.cjs +1 -0
  152. package/dist/shared/index.vue_vue_type_style_index_0_lang-C1n-zAZh.mjs +67 -0
  153. package/dist/shared/index.vue_vue_type_style_index_0_lang-Cb4yMk-r.cjs +1 -0
  154. package/dist/shared/index.vue_vue_type_style_index_0_lang-Cn3P9d4L.cjs +1 -0
  155. package/dist/shared/index.vue_vue_type_style_index_0_lang-CnL4aeg1.cjs +1 -0
  156. package/dist/shared/index.vue_vue_type_style_index_0_lang-DIMCVnQm.mjs +286 -0
  157. package/dist/shared/index.vue_vue_type_style_index_0_lang-DOfJV2oz.cjs +1 -0
  158. package/dist/shared/index.vue_vue_type_style_index_0_lang-DzfGx6ce.mjs +298 -0
  159. package/dist/shared/index.vue_vue_type_style_index_0_lang-dLpQXf6x.mjs +87 -0
  160. package/index.d.ts +249 -1
  161. package/package.json +128 -2
  162. package/qy-alert/index.d.ts +64 -0
  163. package/qy-autocomplete/index.d.ts +5 -5
  164. package/qy-avatar/index.d.ts +67 -0
  165. package/qy-badge/index.d.ts +63 -0
  166. package/qy-card/index.d.ts +64 -0
  167. package/qy-cascader/index.d.ts +198 -0
  168. package/qy-collapse/index.d.ts +59 -0
  169. package/qy-collapse-item/index.d.ts +45 -0
  170. package/qy-descriptions/index.d.ts +47 -0
  171. package/qy-descriptions-item/index.d.ts +46 -0
  172. package/qy-divider/index.d.ts +53 -0
  173. package/qy-empty/index.d.ts +51 -0
  174. package/qy-image/index.d.ts +28 -28
  175. package/qy-image-preview/index.d.ts +20 -20
  176. package/qy-link/index.d.ts +69 -0
  177. package/qy-menu-actions/index.d.ts +29 -29
  178. package/qy-progress/index.d.ts +74 -0
  179. package/qy-scrollbar/index.d.ts +85 -0
  180. package/qy-skeleton/index.d.ts +54 -0
  181. package/qy-skeleton-item/index.d.ts +48 -0
  182. package/qy-step/index.d.ts +55 -0
  183. package/qy-steps/index.d.ts +62 -0
  184. package/qy-tab-pane/index.d.ts +40 -0
  185. package/qy-table-column-settings/index.d.ts +18 -18
  186. package/qy-tabs/index.d.ts +84 -0
  187. package/qy-tree/index.d.ts +132 -0
  188. package/qy-tree-select/index.d.ts +123 -5
  189. package/dist/shared/index-BF1_Rib_.cjs +0 -1
  190. package/dist/shared/index-BTPk2zzq.cjs +0 -1
  191. package/dist/shared/index.vue_vue_type_script_setup_true_lang-C-Pf9TJ0.mjs +0 -152
  192. package/dist/shared/index.vue_vue_type_script_setup_true_lang-DWS8bsiP.cjs +0 -1
  193. /package/dist/shared/{index-C1p86ezL.cjs → index-BDdhBEFr.cjs} +0 -0
  194. /package/dist/shared/{index-QQkDJv3q.cjs → index-BqV6vW9P.cjs} +0 -0
  195. /package/dist/shared/{index-DrJuMzr1.mjs → index-CUITnlPr.mjs} +0 -0
  196. /package/dist/shared/{index-CuusBxhR.cjs → index-DA3GVIZY.cjs} +0 -0
  197. /package/dist/shared/{index-BYLXkIxS.mjs → index-DEZF-Fkt.mjs} +0 -0
  198. /package/dist/shared/{index-ClUqUsAv.cjs → index-DIs6iPjF.cjs} +0 -0
  199. /package/dist/shared/{index-EGnVOaC9.cjs → index-DMiZy6gD.cjs} +0 -0
  200. /package/dist/shared/{index-Cl5cuyVG.mjs → index-DvA3Wy_F.mjs} +0 -0
  201. /package/dist/shared/{index-BcCZMWAj.cjs → index-PlyLRNmb.cjs} +0 -0
  202. /package/dist/shared/{index-zJN0M-bx.cjs → index-UGOgNLvm.cjs} +0 -0
  203. /package/dist/shared/{index-yf2Ijz_G.mjs → index-WP9Dbscv.mjs} +0 -0
  204. /package/dist/shared/{index-CbCpXtYr.mjs → index-YsBzyp9n.mjs} +0 -0
  205. /package/dist/shared/{index-C6jcSQSF.mjs → index-mTWXYnLm.mjs} +0 -0
  206. /package/dist/shared/{index-Cy_Glkc-.mjs → index-seQHtqdh.mjs} +0 -0
  207. /package/dist/shared/{index.vue_vue_type_style_index_0_lang-BZQLyvw8.cjs → index.vue_vue_type_style_index_0_lang-C6urLjSf.cjs} +0 -0
  208. /package/dist/shared/{index.vue_vue_type_style_index_0_lang-ztD-It-2.mjs → index.vue_vue_type_style_index_0_lang-CVxWn-Vs.mjs} +0 -0
  209. /package/dist/shared/{index.vue_vue_type_style_index_0_lang-1cTut9Ql.cjs → index.vue_vue_type_style_index_0_lang-CWz689KH.cjs} +0 -0
  210. /package/dist/shared/{index.vue_vue_type_style_index_0_lang-DSur831A.mjs → index.vue_vue_type_style_index_0_lang-D1kpIund.mjs} +0 -0
package/README.md CHANGED
@@ -39,8 +39,21 @@ import {
39
39
  QyFilePicker,
40
40
  QySwitch,
41
41
  QyTag,
42
+ QyBadge,
43
+ QyCascader,
42
44
  QyTooltip,
43
45
  QyPopover,
46
+ QySkeleton,
47
+ QySkeletonItem,
48
+ QyTabs,
49
+ QyTabPane,
50
+ QySteps,
51
+ QyStep,
52
+ QyLink,
53
+ QyDivider,
54
+ QyEmpty,
55
+ QyScrollbar,
56
+ QyProgress,
44
57
  QyImage,
45
58
  QyImagePreview,
46
59
  QyImageUpload,
@@ -90,8 +103,21 @@ import QyUpload from '@qynpm/ui/qy-upload'
90
103
  import QyFilePicker from '@qynpm/ui/qy-file-picker'
91
104
  import QySwitch from '@qynpm/ui/qy-switch'
92
105
  import QyTag from '@qynpm/ui/qy-tag'
106
+ import QyBadge from '@qynpm/ui/qy-badge'
107
+ import QyCascader from '@qynpm/ui/qy-cascader'
108
+ import QyTree from '@qynpm/ui/qy-tree'
93
109
  import QyTooltip from '@qynpm/ui/qy-tooltip'
94
110
  import QyPopover from '@qynpm/ui/qy-popover'
111
+ import QySkeleton from '@qynpm/ui/qy-skeleton'
112
+ import QySkeletonItem from '@qynpm/ui/qy-skeleton-item'
113
+ import QyTabs from '@qynpm/ui/qy-tabs'
114
+ import QyTabPane from '@qynpm/ui/qy-tab-pane'
115
+ import QySteps from '@qynpm/ui/qy-steps'
116
+ import QyStep from '@qynpm/ui/qy-step'
117
+ import QyLink from '@qynpm/ui/qy-link'
118
+ import QyEmpty from '@qynpm/ui/qy-empty'
119
+ import QyScrollbar from '@qynpm/ui/qy-scrollbar'
120
+ import QyProgress from '@qynpm/ui/qy-progress'
95
121
  import QyImage from '@qynpm/ui/qy-image'
96
122
  import QyImagePreview from '@qynpm/ui/qy-image-preview'
97
123
  import QyImageUpload from '@qynpm/ui/qy-image-upload'
@@ -123,6 +149,80 @@ pnpm install --frozen-lockfile --ignore-scripts
123
149
 
124
150
  ## 组件说明
125
151
 
152
+ ### `QyEmpty`
153
+
154
+ `QyEmpty` 使用 Element Plus `ElEmpty` 渲染只读空状态,支持 `image`、`imageSize` 和 `description` 属性,以及 `image`、`description`、默认三个原生插槽。组件不判断数据,不内置加载、错误、重试或按钮点击逻辑。
155
+
156
+ ```vue
157
+ <QyEmpty description="暂无记录">
158
+ <template #image><img src="/empty.svg" alt="暂无记录" /></template>
159
+ <template #default>
160
+ <QyButton @click="createRecord">新建记录</QyButton>
161
+ </template>
162
+ </QyEmpty>
163
+ ```
164
+
165
+ `imageSize` 直接沿用 Element Plus 的数值语义;`image` / `description` 插槽遵循 Element Plus 的属性优先级。`class`、`style`、`id`、`title`、`role`、`data-*` 和 `aria-*` 安全透传到根节点,消费者传入的宽度、高度、margin、padding 均可覆盖,事件监听器和底层实例不对外暴露。
166
+
167
+ ### `QyScrollbar`
168
+
169
+ `QyScrollbar` 以 Element Plus 2.14.3 的 `ElScrollbar` 作为唯一滚动实现。默认插槽直接承载滚动内容,支持固定高度、最大高度、纵向/横向滚动、原生/自定义滚动模式、`always`、滚动层样式与类名,以及 `tabindex`、`id`、`role`、`ariaLabel` 和 `ariaOrientation`。
170
+
171
+ ```vue
172
+ <QyScrollbar height="240px" max-height="360px" always aria-label="消息列表">
173
+ <div v-for="message in messages" :key="message.id">{{ message.text }}</div>
174
+ </QyScrollbar>
175
+
176
+ <QyScrollbar
177
+ height="160px"
178
+ :distance="12"
179
+ @scroll="handleScroll"
180
+ @end-reached="loadMore"
181
+ >
182
+ <div class="wide-content">横向内容由局部容器滚动</div>
183
+ </QyScrollbar>
184
+ ```
185
+
186
+ `scroll` 只返回只读快照 `{ scrollTop, scrollLeft }`;`end-reached` 返回 `top`、`bottom`、`left` 或 `right`,阈值由 Element Plus 的 `distance` 处理。实例只公开 `scrollTo(x, y)`、`scrollTo(options)`、`setScrollTop(value)`、`setScrollLeft(value)` 和 `update()`,挂载前或卸载后调用均为空操作。不显式暴露内部 `ElScrollbar` 实例、`wrapRef`、`handleScroll` 或 DOM ref;Vue 公共实例自带的 `$el` 不属于适配器承诺的稳定 API,消费者不得依赖。
187
+
188
+ 根节点仅安全透传 `class`、`style`、`title`、`data-*` 和不冲突的 `aria-*`;旧的 `width`、`vertical` 属性及未知 `on*` 监听器会被过滤。自定义模式只映射 `--el-scrollbar-bg-color` / `--el-scrollbar-hover-bg-color` 到 admin-theme 的 `--qy-scrollbar-thumb` / `--qy-scrollbar-thumb-hover`,不覆盖 Element Plus 滑块尺寸、定位、圆角、显隐或动画;原生模式继续使用 admin-theme 的全局原生滚动条规则。
189
+
190
+ ### `QyCascader`
191
+
192
+ `QyCascader` 是 Element Plus Cascader 的受控适配器,保留单值、路径值和多选值的原始形状,不自动改写业务 options。支持 `expandTrigger`、`multiple`、`checkStrictly`、`emitPath`、`lazyLoad`、过滤、折叠标签、浮层定位、虚拟滚动及键盘操作。
193
+
194
+ 节点默认插槽、`suggestion-item`、过滤、懒加载以及 `disabled` / `leaf` 回调接收只读的 `QyCascaderNodeSnapshot`,不会泄漏 Element Plus Node 或组件实例。组件仅暴露 `focus()`、`blur()`、`open()`、`close()` 四个方法。
195
+
196
+ ```vue
197
+ <QyCascader
198
+ v-model="value"
199
+ :options="options"
200
+ :props="{ emitPath: true, checkStrictly: true }"
201
+ filterable
202
+ placeholder="选择地区"
203
+ />
204
+ ```
205
+
206
+ 完整交互 playground 覆盖基础/路径、严格检查、多选折叠、过滤、懒加载、禁用、插槽、键盘、浮层和移动端 40px 触控目标。
207
+
208
+ ### `QyTree`
209
+
210
+ `QyTree` 以 Element Plus `ElTree` 作为唯一的树结构、勾选/半选、键盘、懒加载和拖拽实现。`data` 始终是业务唯一数据权威;节点回调、事件、默认插槽和 `QyTreeRef.getNode()` 都返回当前只读 Qy 快照,不泄漏 Element Node、Store、组件实例或私有 DOM。
211
+
212
+ ```vue
213
+ <QyTree
214
+ ref="treeRef"
215
+ :data="departments"
216
+ node-key="id"
217
+ show-checkbox
218
+ default-expand-all
219
+ :filter-node-method="(value, data, node) => node.label.includes(value)"
220
+ @check="(_, info) => console.log(info.checkedKeys, info.halfCheckedKeys)"
221
+ />
222
+ ```
223
+
224
+ 支持字段映射、展开/当前节点、联动和严格勾选、筛选、懒加载、拖拽、自定义节点插槽及本地键盘导航。公开引用仅包含筛选、当前节点、节点路径、勾选/半选读取与设置方法;不提供 `append`、`remove`、`insert` 或 `updateKeyChildren` 等内部数据修改方法。键值方法需要 `nodeKey`;未提供筛选函数时调用 `filter()` 会抛出 QyTree 自有错误。
225
+
126
226
  ### `QyFilePicker`
127
227
 
128
228
  单文件选择组件,支持点击选择、拖拽、替换、清空以及后缀和大小校验。
@@ -170,6 +270,23 @@ pnpm install --frozen-lockfile --ignore-scripts
170
270
 
171
271
  `disabled` 会设置 `aria-disabled="true"`、隐藏关闭按钮并抑制 `click` / `close`;非禁用状态下这两个事件各发出一次 `MouseEvent`。支持 `class`、`style`、`title`、`role`、`data-*`、`aria-*` 安全属性,不公开 `color`、`hit`、`disableTransitions` 或底层 Element Plus 实例。QyTag 不是按钮,不新增键盘按钮语义;需要动作语义时使用 `QyButton`。
172
272
 
273
+ ### `QyBadge`
274
+
275
+ `QyBadge` 基于 Element Plus `ElBadge` 渲染只读徽标,不管理未读状态、通知或点击逻辑。支持数字与文字、数字上限、圆点、隐藏、零值策略、五种语义类型、自定义颜色、偏移以及徽标内部样式和类名。
276
+
277
+ ```vue
278
+ <QyBadge :value="unreadCount" :max="99" type="danger">
279
+ <QyButton>消息</QyButton>
280
+ </QyBadge>
281
+
282
+ <QyBadge value="!" is-dot>
283
+ <span>待处理</span>
284
+ <template #content="{ value }">数量:{{ value }}</template>
285
+ </QyBadge>
286
+ ```
287
+
288
+ `value` 默认为空字符串,`max` 默认为 `99`,`type` 默认为 `danger`,`showZero` 默认为 `true`,`offset` 默认为 `[0, 0]`。上限只作用于数字,字符串原样显示;`content` 插槽收到经过圆点和上限规则处理后的只读 `{ value: string }`,组件公开的 `content` 也只有最终显示内容,不暴露 Element Plus 实例。根节点安全透传 `class`、`style`、`id`、`role`、`title`、`data-*` 和 `aria-*`,不声明事件、`v-model` 或尺寸参数。
289
+
173
290
  ### `QyTooltip`
174
291
 
175
292
  只读提示组件。默认插槽是唯一触发内容,不增加触发元素包装 DOM;`content` 插槽(content slot)优先于 `content` 属性。组件支持 hover / focus、完整 `placement`、`light` / `dark` effect、延迟、偏移和可收缩的 `maxWidth`。
@@ -205,6 +322,49 @@ pnpm install --frozen-lockfile --ignore-scripts
205
322
 
206
323
  默认值为 `trigger="click"`、`placement="bottom"`、`effect="light"`、`width=240`、`offset=12`、`showDelay=0`、`hideDelay=200`、`showArrow=true`、`disabled=false`。`open` 未传时组件内部管理状态,传入时通过 `v-model:open` 由父级回传决定状态;`update:open` 是状态意图,`open-change` / `open` / `close` 只在实际显隐转换时发出。唯一暴露的方法是 `close()`,不公开 Element Plus 实例、定位更新、`teleported`、`appendTo` 或 `popperOptions`。
207
324
 
325
+ ### `QySkeleton` 与 `QySkeletonItem`
326
+
327
+ 加载骨架组件基于 Element Plus 的 `ElSkeleton` / `ElSkeletonItem` 渲染。`loading` 由业务受控,加载期间使用 `template` 插槽,加载完成后使用默认插槽;支持 `animated`、`count`、`rows` 及数字或对象形式的 `throttle`。
328
+
329
+ ```vue
330
+ <QySkeleton :loading="loading" animated :count="2">
331
+ <template #template>
332
+ <QySkeletonItem variant="rect" style="height: 120px" />
333
+ </template>
334
+ <div>真实内容</div>
335
+ </QySkeleton>
336
+ ```
337
+
338
+ `QySkeletonItem` 的 `variant` 支持 `p`、`text`、`h1`、`h3`、`caption`、`button`、`image`、`circle`、`rect`,默认值为 `text`。两者均支持 `class`、`style`、`role`、`title`、`data-*` 和 `aria-*`,不公开 Element Plus 实例。
339
+
340
+ ### `QyTabs` 与 `QyTabPane`
341
+
342
+ `QyTabs` 使用 Element Plus 的 `ElTabs` / `ElTabPane` 处理渲染、焦点与键盘行为。`modelValue` 传入时保持受控;`defaultValue` 仅提供初始选择。`tab-change`、`tab-remove`、`tab-add` 与 `edit` 都是意图事件,不会改写业务页签数组、路由或 AdminShell 运行时。
343
+
344
+ ```vue
345
+ <QyTabs v-model="current" editable @tab-add="addTab" @tab-remove="removeTab">
346
+ <QyTabPane label="概览" name="overview">概览内容</QyTabPane>
347
+ <QyTabPane label="详情" :name="2" lazy closable>详情内容</QyTabPane>
348
+ </QyTabs>
349
+ ```
350
+
351
+ 支持 `type`(`'' | 'card' | 'border-card')、`tabPosition`、`stretch`、`closable`、`addable`、`editable`、`beforeLeave` 和 `tabindex`。`QyTabPane` 支持 `label`、字符串或数字 `name`、`closable`、`disabled`、`lazy` 与 `label` 插槽。`tab-click` 的首个参数是冻结的 `QyTabPaneSnapshot`,只包含 `name`、`label`、`disabled`、`closable`、`lazy`、`active`、`index`,不会泄漏 Element Plus 页签上下文或实例。
352
+
353
+ ### `QyDescriptions` 与 `QyDescriptionsItem`
354
+
355
+ `QyDescriptions` 使用 Element Plus 的 `ElDescriptions` / `ElDescriptionsItem` 处理描述列表的行列和单元格渲染。`QyDescriptionsItem` 是无 DOM 声明节点,父组件会递归处理直接子项、`v-if`、`v-for` 和 `template`/Fragment,再交给 Element Plus 完成 `span`、`rowspan`、宽度和对齐计算。
356
+
357
+ ```vue
358
+ <QyDescriptions border :column="3" title="订单详情">
359
+ <template #extra><QyLink href="/orders">查看全部</QyLink></template>
360
+ <QyDescriptionsItem label="编号">SO-2026-001</QyDescriptionsItem>
361
+ <QyDescriptionsItem label="摘要" :span="2" :rowspan="2">复杂内容也可放入默认插槽。</QyDescriptionsItem>
362
+ <QyDescriptionsItem label="金额" align="right">¥12,800.00</QyDescriptionsItem>
363
+ </QyDescriptions>
364
+ ```
365
+
366
+ 父级支持 `border`、`column`、`direction`、`size`(`'' | 'large' | 'default' | 'small'`)、`title`、`extra`、`labelWidth` 以及默认、`title`、`extra` 插槽;插槽优先于同名文本属性。描述项支持 `label`、`span`、`rowspan`、`width`、`minWidth`、`labelWidth`、`align`、`labelAlign`、`className`、`labelClassName` 以及默认和 `label` 插槽。组件只安全透传根节点的 `class`、`style`、`id`、`title`、`role`、`data-*`、`aria-*`,不公开事件、状态或 Element Plus 实例。
367
+
208
368
  ### `QyUpload`
209
369
 
210
370
  上传组件,支持:
@@ -677,18 +837,18 @@ options 模式物理复用 `QyCheckbox`;不提供 CheckboxButton、全选、in
677
837
 
678
838
  ### `QyTreeSelect`
679
839
 
680
- 树选择组件,第一版定位为 `ElTreeSelect` 的轻量包装层,重点支持:
840
+ 树选择组件以 `ElTreeSelect` 作为唯一树、勾选、过滤、键盘和浮层实现,重点支持:
681
841
 
682
- - `options` 树数据直出
683
- - 兼容 `ElTreeSelect` `data` 参数
684
- - `labelKey / valueKey / childrenKey / disabledKey` 字段映射
842
+ - `data` 树数据直出,`options` 作为兼容入口;同时传入时 `data` 优先,节点与数组保持原始引用
843
+ - `labelKey / valueKey / childrenKey / disabledKey` 快捷字段与 `props` 映射(显式 `props` 优先)
844
+ - string、number、boolean、对象和多选数组的受控值;对象值必须配置稳定的 `nodeKey`
685
845
  - 单选 / 多选
686
846
  - `check-strictly`
687
847
  - `collapse-tags`
688
848
  - 默认弹层挂载策略
689
849
  - 保留原始节点字段,便于业务 slot 和后续透传使用
690
850
 
691
- `QyTreeSelect` 只处理树选择器的通用 UI 协议,不内置远程请求、权限过滤或业务接口格式化。业务接口返回字段不一致时,优先通过字段映射解决,避免每个页面先手写一遍 tree map。
851
+ `QyTreeSelect` 只处理树选择器的通用 UI 协议,不内置远程请求、权限过滤或业务接口格式化。节点插槽、回调和事件只提供原始数据与安全快照;公开实例只有 `focus()` 和 `blur()`,不会暴露 Element Node、Store 或组件实例。
692
852
 
693
853
  为降低迁移成本,`QyTreeSelect` 的 `clearable`、`filterable`、`check-strictly`、`render-after-expand`、`fit-input-width` 等默认行为尽量跟随 `ElTreeSelect`。业务需要搜索、清空、父子不联动时应显式传参。
694
854
 
@@ -1222,6 +1382,114 @@ function handleSelect(item) {
1222
1382
  </template>
1223
1383
  ```
1224
1384
 
1385
+ ### QyCollapse
1386
+
1387
+ `QyCollapse` 与 `QyCollapseItem` 是 Element Plus 折叠面板的受控适配器。普通模式使用数组值,手风琴模式使用单个字符串或数字;`beforeCollapse` 同时拦截展开和收起。
1388
+
1389
+ ```vue
1390
+ <template>
1391
+ <QyCollapse v-model="activeNames" :before-collapse="beforeCollapse">
1392
+ <QyCollapseItem title="基本信息" name="base">内容</QyCollapseItem>
1393
+ <QyCollapseItem title="数字名称" :name="2" />
1394
+ </QyCollapse>
1395
+ </template>
1396
+
1397
+ <script setup>
1398
+ import { ref } from 'vue'
1399
+ import { QyCollapse, QyCollapseItem } from '@qynpm/ui'
1400
+
1401
+ const activeNames = ref(['base'])
1402
+ function beforeCollapse(name) {
1403
+ return name !== 'locked'
1404
+ }
1405
+ </script>
1406
+ ```
1407
+
1408
+ 通过 `ref` 可读取只读的 `activeNames`,并调用 `setActiveNames(value)` 设置完整公共值;标题和图标插槽都接收 `{ isActive }`。
1409
+
1410
+ ### QyLink
1411
+
1412
+ `QyLink` 基于 Element Plus `ElLink`,保留真实 `<a href>` 的浏览器焦点、Enter 激活和默认导航语义。支持六种语义类型、`always` / `never` / `hover` 下划线策略、禁用、原生链接地址和属性、图标属性及默认/图标插槽。
1413
+
1414
+ ```vue
1415
+ <QyLink
1416
+ href="https://example.com"
1417
+ target="_blank"
1418
+ rel="noopener noreferrer"
1419
+ type="primary"
1420
+ underline="hover"
1421
+ >
1422
+ 打开外部文档
1423
+ <template #icon>↗</template>
1424
+ </QyLink>
1425
+ ```
1426
+
1427
+ `disabled` 会移除有效 `href` 与 `target` 并抑制 `click`;非禁用点击只转发一次原生 `MouseEvent`。`type` 和 `underline` 未传时可继承 Element Plus ConfigProvider;布尔下划线仅作兼容,`true` 等同 `hover`、`false` 等同 `never`。不自动改写 `target` 或 `rel`,外部新窗口链接请显式提供 `rel="noopener noreferrer"`。无 href、只监听 `click` 的旧用法可以兼容,但新业务动作应使用 `QyButton`,路由导航应使用 RouterLink。
1428
+
1429
+ ### QyDivider
1430
+
1431
+ `QyDivider` 基于 Element Plus `ElDivider`,支持水平/垂直方向、左中右标题位置和标准 CSS `border-style` 值。水平模式渲染默认插槽,垂直模式即使传入插槽也保持 Element Plus 行为而不渲染;消费者传入的 `width`、`height`、`margin` 等根样式会与 Element Plus 的边框 CSS 变量合并。
1432
+
1433
+ ```vue
1434
+ <QyDivider content-position="left" border-style="dashed">
1435
+ 分组标题
1436
+ </QyDivider>
1437
+ <QyDivider direction="vertical" :style="{ height: '130px', margin: '0 8px' }" />
1438
+ ```
1439
+
1440
+ 根节点保留 `role="separator"`,只安全透传 `class`、`style`、`id`、`title`、`role`、`data-*` 和 `aria-*`;组件没有事件、尺寸参数、公开实例或额外布局规则。
1441
+
1442
+ ### QyProgress
1443
+
1444
+ `QyProgress` 基于 Element Plus `ElProgress`,用于文件上传、批处理和任务进度的受控展示。支持 line / circle / dashboard 三种形态、percentage、四种 status、显示/隐藏/内部/自定义文字、固定/分段/函数颜色、线宽、端点、圆形画布宽度、不确定动画、条纹、流动条纹和默认插槽;不接管上传、轮询、暂停、恢复、重试或任务状态映射。
1445
+
1446
+ ```vue
1447
+ <QyProgress :percentage="progress" status="success" />
1448
+ <QyProgress type="circle" :percentage="progress" :color="colorStops" />
1449
+ <QyProgress :percentage="progress" :style="{ width: '720px', margin: '8px auto' }">
1450
+ <template #default="{ percentage }">已完成 {{ percentage }}%</template>
1451
+ </QyProgress>
1452
+ ```
1453
+
1454
+ 颜色、文字优先级、合法 percentage、图形和动画全部沿用 Element Plus;根级只安全透传 `class`、`style`、`id`、`role`、`title`、`data-*` 和 `aria-*`,未知属性、事件监听器、实例、DOM ref 和方法不对外暴露。文档演示位于 `src/docs/QyProgressDoc.vue`,API 表使用局部横向滚动,不产生页面级横向溢出。
1455
+
1456
+ ### QyAvatar
1457
+
1458
+ `QyAvatar` 基于 Element Plus `ElAvatar`,用于用户头像及自定义头像内容展示。支持数字尺寸、`small` / `default` / `large` 命名尺寸、圆形和方形、图片 `src` / `srcSet` / `alt` / `fit`、图标、默认插槽和图片加载失败后的原生回退。
1459
+
1460
+ ```vue
1461
+ <QyAvatar :size="80" src="/avatar.png" alt="用户头像" />
1462
+ <QyAvatar size="large" shape="square" :icon="UserFilled" />
1463
+ <QyAvatar src="/missing.png" @error="handleAvatarError">
1464
+ 张三
1465
+ </QyAvatar>
1466
+ ```
1467
+
1468
+ 图片加载、失败回退、图标与默认插槽优先级全部沿用 Element Plus;`error` 只转发标准图片 `Event`。根级只安全透传 `class`、`style`、`id`、`role`、`title`、`tabindex`、`data-*` 和 `aria-*`,未知属性、未声明事件、实例、DOM ref 和方法不对外暴露。QyAvatar 不接管上传、裁剪、预览、缓存、用户资料保存或头像组;文档演示位于 `src/docs/QyAvatarDoc.vue`,API 表使用局部横向滚动。
1469
+
1470
+ ### QyAlert
1471
+
1472
+ `QyAlert` 基于 Element Plus `ElAlert`,用于页面模板中的常驻成功、警告、信息和错误提示。支持 `title`、`description`、五种 `type`、关闭入口、图标、居中和明暗效果,以及 `icon`、`title`、默认三个插槽;关闭时只触发无参数 `close` 事件,隐藏状态由 Element Plus 管理。
1473
+
1474
+ ```vue
1475
+ <QyAlert type="warning" title="请检查填写内容" description="修改后即可继续提交" @close="handleClose" />
1476
+ ```
1477
+
1478
+ 根级只安全透传 `class`、`style`、`id`、`role`、`data-*` 和 `aria-*`;不透传原生 `title`、未知属性、原始鼠标事件或 Element Plus 实例。`QyAlert` 只负责常驻提示,不替代 `@qynpm/hooks` feedback runtime,也不改动 `QyFormSection` 的现有 tip 协议。
1479
+
1480
+ ### QyCard
1481
+
1482
+ `QyCard` 基于 Element Plus `ElCard`,用于页面内部可独立识别的小型内容面板。支持 `header`、`footer`、`shadow`、`bodyStyle` 以及三个区域类名入口,原生转发 `header`、默认和 `footer` 插槽;插槽存在时由 Element Plus 优先于同名文本属性渲染。
1483
+
1484
+ ```vue
1485
+ <QyCard header="订单概览" shadow="hover" @click="handleCardClick">
1486
+ <template #footer>更新于刚刚</template>
1487
+ 面板正文
1488
+ </QyCard>
1489
+ ```
1490
+
1491
+ 根级只安全透传 `class`、`style`、`id`、`role`、`title`、`tabindex`、`data-*` 和 `aria-*`;`click` 只转发一次原生 `MouseEvent`,不把普通卡片自动改成按钮或链接。`QyCard` 不替代 `QyPage` 的页面语义根和页面节奏,也不替代 `QyFormSection` 的表单标题、说明、动作或折叠;标准列表页和完整页面不要再套一层卡片 workspace。
1492
+
1225
1493
  ## 说明
1226
1494
 
1227
1495
  - 当前版本更适合体系内拆包复用
@@ -1269,3 +1537,21 @@ const ENABLE_LOCAL_QIYIN_DEBUG = true
1269
1537
  2. 清理消费项目的 `node_modules/.vite`
1270
1538
  3. 重新启动
1271
1539
 
1540
+ ### QySteps 与 QyStep
1541
+
1542
+ `QySteps` 和 `QyStep` 是 Element Plus `ElSteps` / `ElStep` 的安全公共入口。布局、父子注册、排序、状态计算和过渡全部由 Element Plus 负责;Qy 层只隔离公共属性、插槽、根级安全属性和 `change(newValue, oldValue)` 事件。
1543
+
1544
+ ```vue
1545
+ <QySteps :active="active" direction="horizontal" @change="handleChange">
1546
+ <QyStep title="创建订单" description="填写订单信息" />
1547
+ <QyStep title="确认信息">
1548
+ <template #title><button type="button" @click="openOrder">查看订单</button></template>
1549
+ </QyStep>
1550
+ <QyStep title="完成" status="success" />
1551
+ </QySteps>
1552
+ ```
1553
+
1554
+ 支持自动、像素和百分比 `space`,横向/纵向、居中、简洁模式、五种步骤状态以及受控 `active`。`QyStep` 支持 `title`、`description`、`icon`、显式 `status` 和 `icon` / `title` / `description` 插槽;插槽内容优先于同名属性。组件不提供 `update:active`、自动导航或步骤点击事件,业务跳转应在插槽中放置真实按钮或链接并自行处理。
1555
+
1556
+ 两个入口分别为 `@qynpm/ui/qy-steps` 与 `@qynpm/ui/qy-step`;根入口也导出 `QySteps`、`QyStep` 及其 Qy 自有类型。根级只安全透传 `class`、`style`、`id`、`role`、`title`、`data-*` 和 `aria-*`,未知属性、未声明事件、Element Plus 实例、内部注册对象和 DOM 方法不对外暴露。文档演示位于 `src/docs/QyStepsDoc.vue`,宽步骤条和 API 表使用局部横向滚动。
1557
+