npmapps 1.0.24 → 1.0.26

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