npmapps 1.0.25 → 1.0.27

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 (213) hide show
  1. package/PUBLISH.md +268 -0
  2. package/app/.codegraph/daemon.pid +6 -0
  3. package/app/.eslintrc.js +19 -0
  4. package/app/README.md +24 -0
  5. package/app/babel.config.js +5 -0
  6. package/app/devtool-windows-amd64.zip +0 -0
  7. package/app/docs/superpowers/plans/2026-05-29-quill-editor.md +836 -0
  8. package/app/docs/superpowers/specs/2026-05-29-quill-editor-design.md +210 -0
  9. package/app/docs/superpowers/specs/2026-06-06-lazy-cascader-design.md +400 -0
  10. package/app/jsconfig.json +19 -0
  11. package/app/package-lock.json +21347 -0
  12. package/app/package.json +63 -0
  13. package/app/postcss.config.js +10 -0
  14. package/app/public/favicon.ico +0 -0
  15. package/app/public/index.html +17 -0
  16. package/app/public//344/270/200/351/224/256/351/273/221/346/232/227.html +136 -0
  17. package/app/src/App.vue +110 -0
  18. package/app/src/assets/bpmn-camunda.jpg +0 -0
  19. package/app/src/assets/css/diagram.less +17 -0
  20. package/app/src/assets/icon/Icon.less +31 -0
  21. package/app/src/assets/icon/font/app-codes.css +26 -0
  22. package/app/src/assets/icon/font/app.eot +0 -0
  23. package/app/src/assets/icon/font/app.svg +60 -0
  24. package/app/src/assets/icon/font/app.ttf +0 -0
  25. package/app/src/assets/icon/font/app.woff +0 -0
  26. package/app/src/assets/icon/font/app.woff2 +0 -0
  27. package/app/src/assets/icon/font/config.json +248 -0
  28. package/app/src/assets/icon/font/source/raw/align-bottom-tool.svg +30 -0
  29. package/app/src/assets/icon/font/source/raw/align-horizontal-center-tool.svg +85 -0
  30. package/app/src/assets/icon/font/source/raw/align-left-tool.svg +84 -0
  31. package/app/src/assets/icon/font/source/raw/align-right-tool.svg +80 -0
  32. package/app/src/assets/icon/font/source/raw/align-top-tool.svg +84 -0
  33. package/app/src/assets/icon/font/source/raw/align-vertical-center-tool.svg +89 -0
  34. package/app/src/assets/icon/font/source/raw/distribute-horizontally-tool.svg +95 -0
  35. package/app/src/assets/icon/font/source/raw/distribute-vertically-tool.svg +99 -0
  36. package/app/src/assets/icon/font/source/raw/set-color-tool.svg +111 -0
  37. package/app/src/assets/icon/font/source/symbols/align-bottom-tool.svg +30 -0
  38. package/app/src/assets/icon/font/source/symbols/align-horizontal-center-tool.svg +30 -0
  39. package/app/src/assets/icon/font/source/symbols/align-left-tool.svg +30 -0
  40. package/app/src/assets/icon/font/source/symbols/align-right-tool.svg +30 -0
  41. package/app/src/assets/icon/font/source/symbols/align-top-tool.svg +30 -0
  42. package/app/src/assets/icon/font/source/symbols/align-vertical-center-tool.svg +30 -0
  43. package/app/src/assets/icon/font/source/symbols/distribute-horizontally-tool.svg +30 -0
  44. package/app/src/assets/icon/font/source/symbols/distribute-vertically-tool.svg +30 -0
  45. package/app/src/assets/icon/font/source/symbols/set-color-tool.svg +63 -0
  46. package/app/src/assets/logo.png +0 -0
  47. package/app/src/components/EllTable/README.md +70 -0
  48. package/app/src/components/EllTable/article.md +184 -0
  49. package/app/src/components/EllTable/index.js +213 -0
  50. package/app/src/components/FormulaEditor/FunctionSelector.vue +123 -0
  51. package/app/src/components/FormulaEditor/OperatorSelector.vue +184 -0
  52. package/app/src/components/FormulaEditor/ParameterSelector.vue +123 -0
  53. package/app/src/components/FormulaEditor/api.js +69 -0
  54. package/app/src/components/FormulaEditor/index.vue +435 -0
  55. package/app/src/components/HelloWorld.vue +58 -0
  56. package/app/src/components/PageHeader/index.vue +158 -0
  57. package/app/src/components/Splitter/README.md +144 -0
  58. package/app/src/components/Splitter/example.vue +88 -0
  59. package/app/src/components/Splitter/index.vue +203 -0
  60. package/app/src/components/diagram/ToolBar.vue +357 -0
  61. package/app/src/components/diagram/customTranslate/customTranslate.js +12 -0
  62. package/app/src/components/diagram/customTranslate/translationsGerman.js +241 -0
  63. package/app/src/components/diagram/index.vue +261 -0
  64. package/app/src/components/diagram/xmlData.js +29 -0
  65. package/app/src/directives/filldown.js +155 -0
  66. package/app/src/directives/filldownTable.js +291 -0
  67. package/app/src/main.js +40 -0
  68. package/app/src/router/index.js +63 -0
  69. package/app/src/store/index.js +23 -0
  70. package/app/src/utils/winBox.js +23 -0
  71. package/app/src/views/Extend/A.vue +12 -0
  72. package/app/src/views/Extend/B.vue +10 -0
  73. package/app/src/views/Extend/MagicalComponentsForELFormItem.vue +87 -0
  74. package/app/src/views/Extend/index.vue +59 -0
  75. package/app/src/views/Extend/tableMouseHorizontalWheel.vue +193 -0
  76. package/app/src/views/Home.vue +37 -0
  77. package/app/src/views/RouterJump.vue +155 -0
  78. package/app/src/views/css.vue +57 -0
  79. package/app/src/views/cssComponents/EllipsisText.vue +83 -0
  80. package/app/src/views/cssComponents/HoverCard.vue +79 -0
  81. package/app/src/views/cssComponents/TableHover.vue +140 -0
  82. package/app/src/views/cssComponents/inputSlo.vue +52 -0
  83. package/app/src/views/cssComponents/tableFixed.vue +158 -0
  84. package/app/src/views/echarts/echart-dome.vue +82 -0
  85. package/app/src/views/echarts/index.vue +118 -0
  86. package/app/src/views/echarts/pei3d.vue +667 -0
  87. package/app/src/views/element/bpmn/index.vue +18 -0
  88. package/app/src/views/element/components/attendanceCycle/index.vue +131 -0
  89. package/app/src/views/element/components/attendanceGroup/index.vue +147 -0
  90. package/app/src/views/element/components/attendancePersonnel/index.vue +158 -0
  91. package/app/src/views/element/components/companyCalendar/index.vue +147 -0
  92. package/app/src/views/element/components/shift/index.vue +147 -0
  93. package/app/src/views/element/components/shiftRotationSystem/index.vue +147 -0
  94. package/app/src/views/element/elTableJsx/columnManagement.vue +340 -0
  95. package/app/src/views/element/elTableJsx/dialogInput.vue +71 -0
  96. package/app/src/views/element/elTableJsx/elTableJsx.vue +1826 -0
  97. package/app/src/views/element/elTableJsx/formTable.vue +598 -0
  98. package/app/src/views/element/elTableJsx/index.vue +29 -0
  99. package/app/src/views/element/elTableJsx/simpleTable.vue +192 -0
  100. package/app/src/views/element/elTableJsx.zip +0 -0
  101. package/app/src/views/element/index.vue +44 -0
  102. package/app/src/views/element/lazyCascader/LazyCascader.vue +302 -0
  103. package/app/src/views/element/lazyCascader/data.js +205 -0
  104. package/app/src/views/element/lazyCascader/index.vue +315 -0
  105. package/app/src/views/element/quillEditor/README.md +163 -0
  106. package/app/src/views/element/quillEditor/example.vue +314 -0
  107. package/app/src/views/element/quillEditor/index.vue +409 -0
  108. package/app/src/views/element/quillEditor/toolbar.js +122 -0
  109. package/app/vue.config.js +15 -0
  110. package/package.json +1 -1
  111. package/app/wujie-vue3-child/.claude/settings.local.json +0 -8
  112. package/app/wujie-vue3-child/.vscode/extensions.json +0 -3
  113. package/app/wujie-vue3-child/PROJECT_MEMORY.md +0 -427
  114. package/app/wujie-vue3-child/README.md +0 -5
  115. package/app/wujie-vue3-child/index.html +0 -13
  116. package/app/wujie-vue3-child/package-lock.json +0 -5744
  117. package/app/wujie-vue3-child/package.json +0 -28
  118. package/app/wujie-vue3-child/public/vite.svg +0 -1
  119. package/app/wujie-vue3-child/src/App.vue +0 -130
  120. package/app/wujie-vue3-child/src/assets/vue.svg +0 -1
  121. package/app/wujie-vue3-child/src/components/HelloWorld.vue +0 -43
  122. package/app/wujie-vue3-child/src/components/SmartAnchorTabs/index.jsx +0 -224
  123. package/app/wujie-vue3-child/src/components/SmartAnchorTabs/style.css +0 -154
  124. package/app/wujie-vue3-child/src/components/tags-view.vue +0 -193
  125. package/app/wujie-vue3-child/src/components/tags-view1.vue +0 -131
  126. package/app/wujie-vue3-child/src/directives/aiLoading.js +0 -182
  127. package/app/wujie-vue3-child/src/hooks/useClickOutside.js +0 -11
  128. package/app/wujie-vue3-child/src/hooks/useTableDragSort.js +0 -28
  129. package/app/wujie-vue3-child/src/main.js +0 -18
  130. package/app/wujie-vue3-child/src/router/index.js +0 -104
  131. package/app/wujie-vue3-child/src/store/tagsViewStroe.js +0 -34
  132. package/app/wujie-vue3-child/src/style.css +0 -171
  133. package/app/wujie-vue3-child/src/views/aiCoach/collapseExpand/index.jsx +0 -108
  134. package/app/wujie-vue3-child/src/views/aiCoach/collapseExpand/index.module.scss +0 -97
  135. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/README.md +0 -836
  136. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/REFLEX_EXAMPLES.md +0 -728
  137. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/DepartmentPersonnelSelector.jsx +0 -687
  138. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/DepartmentPersonnelSelector.module.scss +0 -560
  139. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/DepartmentSelector.jsx +0 -570
  140. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/DepartmentSelector.module.scss +0 -330
  141. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/DepartmentSelectorV2.jsx +0 -378
  142. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/DepartmentSelectorV2.module.scss +0 -228
  143. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/OptionsSelector.jsx +0 -399
  144. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/OptionsSelector.module.scss +0 -252
  145. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/PersonnelSelector.jsx +0 -585
  146. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/PersonnelSelector.module.scss +0 -331
  147. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/PopoverSelector.jsx +0 -392
  148. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/PopoverSelector.module.scss +0 -39
  149. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/README.md +0 -248
  150. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/components/SelectorTrigger.jsx +0 -194
  151. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/index.jsx +0 -1459
  152. package/app/wujie-vue3-child/src/views/aiCoach/departmentPersonnel/mockData.js +0 -301
  153. package/app/wujie-vue3-child/src/views/aiCoach/dialogueSegment/index.jsx +0 -182
  154. package/app/wujie-vue3-child/src/views/aiCoach/dialogueSegment/index.module.scss +0 -28
  155. package/app/wujie-vue3-child/src/views/aiCoach/index.jsx +0 -375
  156. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/ChartsPanel/index.jsx +0 -121
  157. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/ChartsPanel/index.module.scss +0 -76
  158. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/DonutChart/index.jsx +0 -104
  159. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/PracticeTable/index.jsx +0 -75
  160. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/PracticeTable/index.module.scss +0 -12
  161. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/RankBarChart/index.jsx +0 -62
  162. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/RankBarChart/index.module.scss +0 -43
  163. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/RankingGroup/index.jsx +0 -29
  164. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/RankingGroup/index.module.scss +0 -5
  165. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/RankingList/index.jsx +0 -58
  166. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/RankingList/index.module.scss +0 -85
  167. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/ScriptStatsPanel/index.jsx +0 -92
  168. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/ScriptStatsPanel/index.module.scss +0 -56
  169. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/StatCardsRow/index.jsx +0 -40
  170. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/StatCardsRow/index.module.scss +0 -53
  171. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/echarts/EchartsDonut.jsx +0 -106
  172. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/components/echarts/EchartsRankBar.jsx +0 -132
  173. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/index.jsx +0 -176
  174. package/app/wujie-vue3-child/src/views/aiCoach/practiceStatus/index.module.scss +0 -96
  175. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/CoachReport/index.jsx +0 -162
  176. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/CoachReport/index.module.scss +0 -16
  177. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/ComprehensiveEvaluation/index.jsx +0 -29
  178. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/ComprehensiveEvaluation/index.module.scss +0 -25
  179. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/DialogueBubble/index.jsx +0 -106
  180. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/DialogueBubble/index.module.scss +0 -164
  181. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/DialogueRecord/index.jsx +0 -182
  182. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/DialogueRecord/index.module.scss +0 -203
  183. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/DimensionDetail/index.jsx +0 -145
  184. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/DimensionDetail/index.module.scss +0 -126
  185. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/DimensionScores/index.jsx +0 -67
  186. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/DimensionScores/index.module.scss +0 -105
  187. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/ReportHeader/index.jsx +0 -81
  188. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/ReportHeader/index.module.scss +0 -47
  189. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/RoleInfo/index.jsx +0 -64
  190. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/RoleInfo/index.module.scss +0 -85
  191. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/ScoreBadge/index.jsx +0 -39
  192. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/ScoreBadge/index.module.scss +0 -44
  193. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/SubDimensionItem/index.jsx +0 -83
  194. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/components/SubDimensionItem/index.module.scss +0 -101
  195. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/index.jsx +0 -50
  196. package/app/wujie-vue3-child/src/views/aiCoach/reportDetail/index.module.scss +0 -25
  197. package/app/wujie-vue3-child/src/views/aiCoach/scriptTable/index.jsx +0 -196
  198. package/app/wujie-vue3-child/src/views/aiCoach/scriptTable/index.module.scss +0 -41
  199. package/app/wujie-vue3-child/src/views/aiCoach/scriptTable/inputColumn/index.jsx +0 -183
  200. package/app/wujie-vue3-child/src/views/aiCoach/scriptTable/inputColumn/index.module.scss +0 -115
  201. package/app/wujie-vue3-child/src/views/child-to-parent.vue +0 -117
  202. package/app/wujie-vue3-child/src/views/home.vue +0 -53
  203. package/app/wujie-vue3-child/src/views/jsx/btnSelect/btnSelect.vue +0 -169
  204. package/app/wujie-vue3-child/src/views/jsx/btnSelect/index.vue +0 -69
  205. package/app/wujie-vue3-child/src/views/jsx/com.vue +0 -44
  206. package/app/wujie-vue3-child/src/views/jsx/dialog.jsx +0 -66
  207. package/app/wujie-vue3-child/src/views/jsx/index.vue +0 -72
  208. package/app/wujie-vue3-child/src/views/jsx/props.vue +0 -33
  209. package/app/wujie-vue3-child/src/views/parent-to-child.vue +0 -225
  210. package/app/wujie-vue3-child/src/views/phone-code.vue +0 -318
  211. package/app/wujie-vue3-child/src/views/router-jump.vue +0 -123
  212. package/app/wujie-vue3-child/src/views/test.vue +0 -192
  213. package/app/wujie-vue3-child/vite.config.js +0 -15
@@ -1,330 +0,0 @@
1
- // 部门选择器样式
2
- .departmentSelector {
3
- position: relative;
4
- width: 100%;
5
- }
6
-
7
- // 自定义输入框
8
- .customInput {
9
- display: flex;
10
- align-items: center;
11
- width: 100%;
12
- min-height: 32px;
13
- padding: 1px 11px;
14
- background: #fff;
15
- border: 1px solid #dcdfe6;
16
- border-radius: 4px;
17
- cursor: pointer;
18
- transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
19
- outline: none;
20
- box-sizing: border-box;
21
-
22
- &:hover {
23
- border-color: #c0c4cc;
24
- }
25
-
26
- &.focused {
27
- border-color: #409eff;
28
- }
29
-
30
- &.disabled {
31
- background-color: #f5f7fa;
32
- border-color: #e4e7ed;
33
- color: #c0c4cc;
34
- cursor: not-allowed;
35
- }
36
- }
37
-
38
- // 按钮模式包装器
39
- .buttonWrapper {
40
- // width: 100%;
41
- }
42
-
43
- // 按钮内部容器
44
- .buttonInner {
45
- display: flex;
46
- align-items: center;
47
- justify-content: space-between;
48
- width: 100%;
49
- gap: 8px;
50
- }
51
-
52
- // 按钮内容区域
53
- .buttonContent {
54
- flex: 1;
55
- display: flex;
56
- align-items: center;
57
- min-width: 0;
58
- text-align: left;
59
- overflow: hidden;
60
- }
61
-
62
- // 按钮文字包装器(用于显示文字+徽章)
63
- .buttonTextWrapper {
64
- display: flex;
65
- align-items: center;
66
- gap: 8px;
67
- }
68
-
69
- // 数量徽章(圆圈显示 +N)
70
- .countBadge {
71
- display: inline-flex;
72
- align-items: center;
73
- justify-content: center;
74
- min-width: 20px;
75
- height: 20px;
76
- padding: 0 4px;
77
- background-color: #ecf5ff;
78
- color: #409eff;
79
- font-size: 12px;
80
- font-weight: 500;
81
- border-radius: 10px;
82
- white-space: nowrap;
83
- flex-shrink: 0;
84
- }
85
-
86
- // 输入框内容区域
87
- .inputContent {
88
- flex: 1;
89
- display: flex;
90
- align-items: center;
91
- min-width: 0;
92
- min-height: 30px;
93
- padding: 2px 0;
94
- }
95
-
96
- // 占位符
97
- .placeholder {
98
- // color: #c0c4cc;
99
- font-size: 14px;
100
- }
101
-
102
- // 前置标签
103
- .label {
104
- color: #606266;
105
- font-size: 14px;
106
- margin-right: 4px;
107
- flex-shrink: 0;
108
- }
109
-
110
- // 单选文本
111
- .text {
112
- color: #606266;
113
- font-size: 14px;
114
- overflow: hidden;
115
- text-overflow: ellipsis;
116
- white-space: nowrap;
117
- }
118
-
119
- // 标签容器
120
- .tagsWrapper {
121
- display: flex;
122
- align-items: center;
123
- flex-wrap: wrap;
124
- gap: 4px;
125
- }
126
-
127
- // 标签
128
- .tag {
129
- margin: 0;
130
- max-width: 100%;
131
-
132
- :global(.el-tag__content) {
133
- overflow: hidden;
134
- text-overflow: ellipsis;
135
- white-space: nowrap;
136
- }
137
- }
138
-
139
- // 右侧图标区域
140
- .suffixIcons {
141
- display: flex;
142
- align-items: center;
143
- gap: 4px;
144
- margin-left: 8px;
145
- flex-shrink: 0;
146
- }
147
-
148
- // 清除图标
149
- .clearIcon {
150
- font-size: 14px;
151
- color: #c0c4cc;
152
- cursor: pointer;
153
- transition: color 0.2s;
154
-
155
- &:hover {
156
- color: #909399;
157
- }
158
- }
159
-
160
- // 下拉箭头图标
161
- .arrowIcon {
162
- font-size: 14px;
163
- color: #c0c4cc;
164
- transition: transform 0.3s;
165
-
166
- &.reverse {
167
- transform: rotate(180deg);
168
- }
169
- }
170
-
171
- .disabled {
172
- .clearIcon,
173
- .arrowIcon {
174
- cursor: not-allowed;
175
- }
176
- }
177
-
178
- // 下拉框容器
179
- .dropdown {
180
- position: fixed;
181
- background: #fff;
182
- border: 1px solid #e4e7ed;
183
- border-radius: 4px;
184
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
185
- z-index: 2000;
186
- display: flex;
187
- flex-direction: column;
188
- overflow: hidden;
189
-
190
- // 添加动画效果
191
- animation: dropdownSlideIn 0.2s ease-out;
192
- transform-origin: top;
193
- }
194
-
195
- // 悬浮窗内容
196
- .dropdownContent {
197
- display: flex;
198
- flex-direction: column;
199
- height: 100%;
200
- max-height: inherit; // 继承父容器的 maxHeight
201
- overflow: hidden; // 防止内容溢出到悬浮窗外
202
- }
203
-
204
- // 下拉框淡入动画
205
- @keyframes dropdownSlideIn {
206
- from {
207
- opacity: 0;
208
- transform: scaleY(0.8);
209
- }
210
- to {
211
- opacity: 1;
212
- transform: scaleY(1);
213
- }
214
- }
215
-
216
- // 搜索框区域
217
- .searchBox {
218
- padding: 8px;
219
- border-bottom: 1px solid #e4e7ed;
220
- background: #fff;
221
- }
222
-
223
- // 树形结构容器
224
- .treeWrapper {
225
- flex: 1;
226
- overflow-y: auto;
227
- padding: 8px 0;
228
-
229
- // 自定义滚动条样式
230
- &::-webkit-scrollbar {
231
- width: 6px;
232
- }
233
-
234
- &::-webkit-scrollbar-track {
235
- background: #f1f1f1;
236
- border-radius: 3px;
237
- }
238
-
239
- &::-webkit-scrollbar-thumb {
240
- background: #c1c1c1;
241
- border-radius: 3px;
242
-
243
- &:hover {
244
- background: #a8a8a8;
245
- }
246
- }
247
-
248
- // 树节点样式
249
- :global {
250
- .el-tree {
251
- background: transparent;
252
-
253
- .el-tree-node {
254
- &:focus > .el-tree-node__content {
255
- background-color: #f5f7fa;
256
- }
257
- }
258
-
259
- .el-tree-node__content {
260
- height: 32px;
261
- padding-right: 12px;
262
- transition: background-color 0.2s;
263
-
264
- &:hover {
265
- background-color: #f5f7fa;
266
- }
267
- }
268
-
269
- .el-tree-node__label {
270
- font-size: 14px;
271
- color: #606266;
272
- }
273
-
274
- // 高亮当前选中节点(单选)
275
- .el-tree-node.is-current > .el-tree-node__content {
276
- background-color: #ecf5ff;
277
- color: #409eff;
278
-
279
- .el-tree-node__label {
280
- color: #409eff;
281
- font-weight: 500;
282
- }
283
- }
284
-
285
- // 复选框样式
286
- .el-checkbox {
287
- margin-right: 8px;
288
- }
289
-
290
- // 展开/收起图标
291
- .el-tree-node__expand-icon {
292
- font-size: 12px;
293
- color: #c0c4cc;
294
-
295
- &.is-leaf {
296
- color: transparent;
297
- }
298
- }
299
- }
300
- }
301
- }
302
-
303
- // 空状态
304
- .empty {
305
- padding: 40px 16px;
306
- text-align: center;
307
- color: #909399;
308
- font-size: 14px;
309
- }
310
-
311
- // 加载状态
312
- .loading {
313
- display: flex;
314
- flex-direction: column;
315
- align-items: center;
316
- justify-content: center;
317
- padding: 60px 16px;
318
- color: #909399;
319
- font-size: 14px;
320
- gap: 12px;
321
-
322
- :global(.el-icon) {
323
- font-size: 24px;
324
- color: #409eff;
325
- }
326
-
327
- span {
328
- margin-top: 4px;
329
- }
330
- }
@@ -1,378 +0,0 @@
1
- import { defineComponent, ref } from 'vue'
2
- import { ArrowDown, CircleClose, Loading } from '@element-plus/icons-vue'
3
- import PopoverSelector from './PopoverSelector.jsx'
4
- import { fetchDepartments } from '../mockData.js'
5
- import styles from './DepartmentSelectorV2.module.scss'
6
-
7
- /**
8
- * 基于 PopoverSelector 的部门选择器示例
9
- * @component DepartmentSelectorV2
10
- * @description 使用通用 PopoverSelector 组件构建的部门选择器
11
- */
12
- export default defineComponent({
13
- name: 'DepartmentSelectorV2',
14
-
15
- props: {
16
- /**
17
- * 选中的部门(单选时为对象,多选时为数组)
18
- * @type {Object|Array<Object>}
19
- * @example 单选:{ id: 911, label: '前端开发组' }
20
- * @example 多选:[{ id: 910, label: '后端开发组' }, { id: 911, label: '前端开发组' }]
21
- */
22
- modelValue: {
23
- type: [Object, Array],
24
- default: null,
25
- },
26
- /**
27
- * 是否多选
28
- */
29
- multiple: {
30
- type: Boolean,
31
- default: false,
32
- },
33
- /**
34
- * 占位文本
35
- */
36
- placeholder: {
37
- type: String,
38
- default: '请选择部门',
39
- },
40
- /**
41
- * 前置标签
42
- */
43
- label: {
44
- type: String,
45
- default: '',
46
- },
47
- /**
48
- * 显示类型:input | button
49
- */
50
- displayType: {
51
- type: String,
52
- default: 'input',
53
- validator: (value) => ['input', 'button'].includes(value),
54
- },
55
- /**
56
- * 是否禁用
57
- */
58
- disabled: {
59
- type: Boolean,
60
- default: false,
61
- },
62
- /**
63
- * 是否可清空
64
- */
65
- clearable: {
66
- type: Boolean,
67
- default: false,
68
- },
69
- },
70
-
71
- emits: ['update:modelValue', 'change'],
72
-
73
- setup(props, { emit }) {
74
- // 部门树数据
75
- const departments = ref([])
76
- // 数据加载状态
77
- const loading = ref(false)
78
- // 是否 hover
79
- const isHovering = ref(false)
80
- // 树组件 ref
81
- const treeRef = ref(null)
82
- // 搜索关键词
83
- const searchKeyword = ref('')
84
-
85
- /**
86
- * 获取选中的部门信息
87
- */
88
- const selectedDepartments = (() => {
89
- if (!props.modelValue) return []
90
- // v-model 直接绑定对象,单选转数组,多选直接使用
91
- return Array.isArray(props.modelValue) ? props.modelValue : [props.modelValue]
92
- })
93
-
94
- /**
95
- * 显示文本
96
- */
97
- const displayText = (() => {
98
- const selected = selectedDepartments()
99
- if (selected.length === 0) return ''
100
- return selected.map(d => d.label).join(', ')
101
- })
102
-
103
- /**
104
- * 加载部门数据
105
- */
106
- const loadDepartments = async () => {
107
- loading.value = true
108
- try {
109
- departments.value = await fetchDepartments(2000)
110
- } catch (error) {
111
- console.error('加载部门数据失败:', error)
112
- } finally {
113
- loading.value = false
114
- }
115
- }
116
-
117
- /**
118
- * 树节点点击
119
- */
120
- const handleNodeClick = (data, node, close) => {
121
- if (!props.multiple) {
122
- // 单选:选中后关闭,emit 完整对象
123
- emit('update:modelValue', data)
124
- emit('change', data)
125
- close()
126
- } else {
127
- // 多选:点击展开/收起
128
- if (node.childNodes && node.childNodes.length > 0) {
129
- node.expanded = !node.expanded
130
- }
131
- }
132
- }
133
-
134
- /**
135
- * 树节点勾选
136
- */
137
- const handleCheck = (data, checkedInfo) => {
138
- if (props.multiple) {
139
- const checkedKeys = checkedInfo.checkedKeys
140
- // 找出所有选中的部门对象
141
- const findDepartment = (depts, id) => {
142
- for (const dept of depts) {
143
- if (dept.id === id) return dept
144
- if (dept.children) {
145
- const found = findDepartment(dept.children, id)
146
- if (found) return found
147
- }
148
- }
149
- return null
150
- }
151
- const selectedDepts = checkedKeys.map(id => findDepartment(departments.value, id)).filter(Boolean)
152
-
153
- emit('update:modelValue', selectedDepts) // emit 完整对象数组
154
- emit('change', selectedDepts)
155
- }
156
- }
157
-
158
- /**
159
- * 清空选择
160
- */
161
- const handleClear = (e) => {
162
- e.stopPropagation()
163
- emit('update:modelValue', props.multiple ? [] : null)
164
- emit('change', props.multiple ? [] : null)
165
- }
166
-
167
- /**
168
- * 过滤节点
169
- */
170
- const filterNode = (value, data) => {
171
- if (!value) return true
172
- return data.label.toLowerCase().includes(value.toLowerCase())
173
- }
174
-
175
- /**
176
- * 搜索变化
177
- */
178
- const handleSearchChange = (value) => {
179
- if (treeRef.value) {
180
- treeRef.value.filter(value)
181
- }
182
- }
183
-
184
- /**
185
- * 悬浮窗打开时
186
- */
187
- const handleOpen = async () => {
188
- // 如果数据未加载,加载数据
189
- if (departments.value.length === 0) {
190
- await loadDepartments()
191
- }
192
-
193
- // 设置树的选中状态
194
- setTimeout(() => {
195
- if (treeRef.value) {
196
- if (props.multiple) {
197
- // 多选:从对象数组中提取 id
198
- const ids = Array.isArray(props.modelValue)
199
- ? props.modelValue.map(item => item.id)
200
- : []
201
- treeRef.value.setCheckedKeys(ids)
202
- } else {
203
- // 单选:从对象中提取 id
204
- const id = props.modelValue?.id || null
205
- treeRef.value.setCurrentKey(id)
206
- }
207
- }
208
- }, 100)
209
- }
210
-
211
- return () => {
212
- // 渲染显示内容
213
- const renderContent = () => {
214
- let content = null
215
-
216
- if (props.multiple) {
217
- const selected = selectedDepartments()
218
- if (selected.length === 0) {
219
- content = <span class={styles.placeholder}>{props.placeholder}</span>
220
- } else if (props.displayType === 'button') {
221
- // 按钮模式:显示文字 + 徽章
222
- const first = selected[0]
223
- const restCount = selected.length - 1
224
- content = (
225
- <div class={styles.textWrapper}>
226
- <span class={styles.text}>{first.label}</span>
227
- {restCount > 0 && (
228
- <span class={styles.countBadge}>+{restCount}</span>
229
- )}
230
- </div>
231
- )
232
- } else {
233
- // 输入框模式:显示文本
234
- content = <span class={styles.text}>{displayText()}</span>
235
- }
236
- } else {
237
- content = displayText() ? (
238
- <span class={styles.text}>{displayText()}</span>
239
- ) : (
240
- <span class={styles.placeholder}>{props.placeholder}</span>
241
- )
242
- }
243
-
244
- if (props.label) {
245
- return (
246
- <>
247
- <span class={styles.label}>{props.label}</span>
248
- {content}
249
- </>
250
- )
251
- }
252
-
253
- return content
254
- }
255
-
256
- // 渲染图标
257
- const renderIcons = (visible) => {
258
- const hasValue = props.multiple
259
- ? selectedDepartments().length > 0
260
- : !!displayText()
261
-
262
- const showClearIcon = props.clearable && hasValue && isHovering.value
263
-
264
- return (
265
- <div class={styles.icons}>
266
- {showClearIcon && (
267
- <el-icon class={styles.clearIcon} onClick={handleClear}>
268
- <CircleClose />
269
- </el-icon>
270
- )}
271
- {!showClearIcon && (
272
- <el-icon class={[styles.arrowIcon, visible && styles.reverse]}>
273
- <ArrowDown />
274
- </el-icon>
275
- )}
276
- </div>
277
- )
278
- }
279
-
280
- return (
281
- <PopoverSelector
282
- width={400}
283
- maxHeight={400}
284
- disabled={props.disabled}
285
- onOpen={handleOpen}
286
- >
287
- {{
288
- // 触发器插槽
289
- trigger: ({ open, visible }) => {
290
- if (props.displayType === 'button') {
291
- return (
292
- <el-button
293
- disabled={props.disabled}
294
- onClick={open}
295
- onMouseenter={() => (isHovering.value = true)}
296
- onMouseleave={() => (isHovering.value = false)}
297
- class={styles.buttonTrigger}
298
- >
299
- {{
300
- default: () => (
301
- <div class={styles.buttonInner}>
302
- <div class={styles.content}>
303
- {renderContent()}
304
- </div>
305
- {renderIcons(visible)}
306
- </div>
307
- ),
308
- }}
309
- </el-button>
310
- )
311
- }
312
-
313
- return (
314
- <div
315
- class={[
316
- styles.inputTrigger,
317
- props.disabled && styles.disabled,
318
- visible && styles.focused,
319
- ]}
320
- onClick={open}
321
- onMouseenter={() => (isHovering.value = true)}
322
- onMouseleave={() => (isHovering.value = false)}
323
- >
324
- <div class={styles.content}>{renderContent()}</div>
325
- {renderIcons(visible)}
326
- </div>
327
- )
328
- },
329
-
330
- // 悬浮窗内容插槽
331
- default: ({ close }) => (
332
- <div class={styles.dropdownContent}>
333
- {/* 搜索框 */}
334
- <div class={styles.searchBox}>
335
- <el-input
336
- v-model={searchKeyword.value}
337
- placeholder="搜索部门"
338
- prefix-icon="Search"
339
- clearable
340
- size="small"
341
- onInput={handleSearchChange}
342
- />
343
- </div>
344
-
345
- {/* 树形结构 */}
346
- <div class={styles.treeWrapper}>
347
- {loading.value ? (
348
- <div class={styles.loading}>
349
- <el-icon class="is-loading">
350
- <Loading />
351
- </el-icon>
352
- <span>加载中...</span>
353
- </div>
354
- ) : (
355
- <el-tree
356
- ref={treeRef}
357
- data={departments.value}
358
- node-key="id"
359
- props={{ label: 'label', children: 'children' }}
360
- show-checkbox={props.multiple}
361
- check-strictly={true}
362
- default-expand-all={false}
363
- highlight-current={!props.multiple}
364
- expand-on-click-node={false}
365
- filter-node-method={filterNode}
366
- onNodeClick={(data, node) => handleNodeClick(data, node, close)}
367
- onCheck={handleCheck}
368
- />
369
- )}
370
- </div>
371
- </div>
372
- ),
373
- }}
374
- </PopoverSelector>
375
- )
376
- }
377
- },
378
- })