@agile-team/wl-skills-ui 1.6.2

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 (150) hide show
  1. package/CHANGELOG.md +207 -0
  2. package/README.md +623 -0
  3. package/SKILL.md +632 -0
  4. package/bin/wl-ui.js +794 -0
  5. package/design/spec/color.md +41 -0
  6. package/design/spec/spacing.md +28 -0
  7. package/design/spec/typography.md +29 -0
  8. package/design/tokens/base.css +144 -0
  9. package/design/tokens/index.css +8 -0
  10. package/dist/ag-grid-override.scss +1 -0
  11. package/dist/element.scss +1 -0
  12. package/dist/index.scss +1 -0
  13. package/dist/portal.scss +1 -0
  14. package/dist/style-override.scss +1 -0
  15. package/dist/tokens.css +144 -0
  16. package/es/chunk-GBB7LDKQ.js +261 -0
  17. package/es/chunk-MDI2SCUP.js +281 -0
  18. package/es/chunk-QDTNMM7W.js +286 -0
  19. package/es/chunk-YLNAFAWE.js +233 -0
  20. package/es/common-preset.d.ts +38 -0
  21. package/es/common-preset.js +157 -0
  22. package/es/index.d.ts +32 -0
  23. package/es/index.js +1 -0
  24. package/es/presets/security.d.ts +16 -0
  25. package/es/presets/security.js +99 -0
  26. package/es/renderers-BFRSp2BH.d.ts +51 -0
  27. package/es/renderers-DMZbi_Gs.d.ts +51 -0
  28. package/es/renderers-DWhUlI2y.d.ts +47 -0
  29. package/es/types-04qLKHMt.d.ts +62 -0
  30. package/es/types-BrCPjAH6.d.ts +62 -0
  31. package/es/types-QZ1gy9KX.d.ts +63 -0
  32. package/examples/migration-operations-to-renderOps.md +107 -0
  33. package/examples/wk-exempt.example.json +30 -0
  34. package/mcp/server.js +394 -0
  35. package/package.json +130 -0
  36. package/reference/SelectPopupCom.vue +634 -0
  37. package/reference/ag-cell-renders.ts +644 -0
  38. package/reference/define-columns.ts +185 -0
  39. package/reference/jhlc.d.ts +1 -0
  40. package/scanner/coverage.mjs +287 -0
  41. package/scanner/exempt.mjs +127 -0
  42. package/scanner/fix.mjs +216 -0
  43. package/scanner/index.mjs +403 -0
  44. package/scanner/integration.mjs +155 -0
  45. package/scanner/report.mjs +459 -0
  46. package/scanner/rules/_shared.mjs +134 -0
  47. package/scanner/rules/button.mjs +97 -0
  48. package/scanner/rules/color.mjs +118 -0
  49. package/scanner/rules/componentFamily.mjs +184 -0
  50. package/scanner/rules/dialog.mjs +42 -0
  51. package/scanner/rules/form.mjs +86 -0
  52. package/scanner/rules/index.mjs +58 -0
  53. package/scanner/rules/table.mjs +170 -0
  54. package/scanner/rules/tag.mjs +245 -0
  55. package/scanner/snapshot.mjs +198 -0
  56. package/skills/_flows/full-audit.md +65 -0
  57. package/skills/_flows/legacy-skin-align.md +71 -0
  58. package/skills/_flows/new-project-init.md +80 -0
  59. package/skills/_flows/progressive-migrate.md +49 -0
  60. package/skills/_meta/_compat/README.md +47 -0
  61. package/skills/_meta/_compat/editors.json +76 -0
  62. package/skills/_meta/_compat/headers/agents.txt +7 -0
  63. package/skills/_meta/_compat/headers/claude-code.txt +7 -0
  64. package/skills/_meta/_compat/headers/cline.txt +7 -0
  65. package/skills/_meta/_compat/headers/cursor-mdc.txt +5 -0
  66. package/skills/_meta/_compat/headers/github-copilot.txt +5 -0
  67. package/skills/_meta/_compat/headers/kiro.txt +4 -0
  68. package/skills/_meta/_compat/headers/qoder.txt +4 -0
  69. package/skills/_meta/_compat/headers/trae.txt +3 -0
  70. package/skills/_meta/_compat/headers/windsurf.txt +5 -0
  71. package/skills/_meta/_detection.md +81 -0
  72. package/skills/_meta/_registry.md +96 -0
  73. package/skills/element/component-family/SKILL.md +71 -0
  74. package/skills/element/el-dialog/SKILL.md +124 -0
  75. package/skills/element/el-form/SKILL.md +84 -0
  76. package/skills/element/el-table/SKILL.md +86 -0
  77. package/skills/element/el-tag/SKILL.md +127 -0
  78. package/skills/layouts/detail-page/SKILL.md +99 -0
  79. package/skills/layouts/form-dialog/SKILL.md +128 -0
  80. package/skills/layouts/list-page/SKILL.md +111 -0
  81. package/skills/layouts/tree-list/SKILL.md +108 -0
  82. package/skills/ops/audit/SKILL.md +109 -0
  83. package/skills/ops/fix/SKILL.md +52 -0
  84. package/skills/ops/fix/USAGE.md +24 -0
  85. package/skills/ops/migrate/SKILL.md +157 -0
  86. package/skills/ops/scan/SKILL.md +71 -0
  87. package/skills/ops/scan/USAGE.md +16 -0
  88. package/skills/runtime/design-tokens/SKILL.md +88 -0
  89. package/skills/runtime/design-tokens/USAGE.md +19 -0
  90. package/skills/runtime/migration/SKILL.md +106 -0
  91. package/skills/runtime/migration/USAGE.md +34 -0
  92. package/skills/runtime/style-align/SKILL.md +124 -0
  93. package/skills/runtime/style-align/USAGE.md +52 -0
  94. package/skills/vendors/ag-grid/SKILL.md +94 -0
  95. package/skills/vendors/base-table/SKILL.md +57 -0
  96. package/skills/vendors/c-components/SKILL.md +36 -0
  97. package/skills/vendors/custom-wrappers/SKILL.md +45 -0
  98. package/skills/vendors/jh-components/SKILL.md +42 -0
  99. package/skills/vendors/unknown-wrapper/SKILL.md +44 -0
  100. package/standards/engineering/01-import-order.md +46 -0
  101. package/standards/engineering/02-naming.md +54 -0
  102. package/standards/engineering/03-scss-structure.md +59 -0
  103. package/standards/ui/01-table.md +111 -0
  104. package/standards/ui/02-button.md +83 -0
  105. package/standards/ui/03-form.md +118 -0
  106. package/standards/ui/04-tag-status.md +110 -0
  107. package/standards/ui/05-dialog-pagination.md +118 -0
  108. package/styles/element/_card.scss +26 -0
  109. package/styles/element/_descriptions.scss +22 -0
  110. package/styles/element/_dialog.scss +43 -0
  111. package/styles/element/_drawer.scss +22 -0
  112. package/styles/element/_feedback.scss +52 -0
  113. package/styles/element/_form.scss +22 -0
  114. package/styles/element/_navigation.scss +36 -0
  115. package/styles/element/_overlay.scss +32 -0
  116. package/styles/element/_pagination.scss +16 -0
  117. package/styles/element/_steps.scss +32 -0
  118. package/styles/element/_table.scss +13 -0
  119. package/styles/element/_tabs.scss +40 -0
  120. package/styles/element/_tree.scss +27 -0
  121. package/styles/element/_upload.scss +34 -0
  122. package/styles/element/index.scss +17 -0
  123. package/styles/index.scss +21 -0
  124. package/styles/layouts/_detail-page.scss +27 -0
  125. package/styles/layouts/_form-dialog.scss +19 -0
  126. package/styles/layouts/_list-page.scss +47 -0
  127. package/styles/layouts/_tree-list.scss +33 -0
  128. package/styles/layouts/index.scss +6 -0
  129. package/styles/presets/element-only.scss +6 -0
  130. package/styles/presets/full.scss +12 -0
  131. package/styles/presets/security.scss +37 -0
  132. package/styles/presets/skin.scss +14 -0
  133. package/styles/presets/tokens-only.scss +7 -0
  134. package/styles/tokens/index.scss +79 -0
  135. package/styles/vendors/_ag-grid.scss +273 -0
  136. package/styles/vendors/_base-components.scss +480 -0
  137. package/styles/vendors/_base-query-toolbar.scss +253 -0
  138. package/styles/vendors/_base-table.scss +41 -0
  139. package/styles/vendors/_c-components.scss +34 -0
  140. package/styles/vendors/_custom-wrappers.scss +30 -0
  141. package/styles/vendors/_jh-drag-col.scss +63 -0
  142. package/styles/vendors/_jh-pagination.scss +81 -0
  143. package/styles/vendors/_jh-tree.scss +196 -0
  144. package/styles/vendors/_portal.scss +114 -0
  145. package/styles/vendors/index.scss +17 -0
  146. package/templates/ag-grid-page/TPL-AG-GRID.md +76 -0
  147. package/templates/form-dialog/TPL-FORM-DIALOG.md +165 -0
  148. package/templates/list-page/TPL-LIST.md +139 -0
  149. package/templates/tree-list/TPL-TREE-LIST.md +176 -0
  150. package/templates/ui-optimization-report/TPL-UI-OPTIM-REPORT.md +343 -0
@@ -0,0 +1,196 @@
1
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2
+ // el-tree / jh-tree 全局样式 — wl-ui-safe 统一设计规范
3
+ //
4
+ // 【根因确认】
5
+ // jh-drag-col 渲染出 .drag-left(来源确认:common-core drag-col.vue)
6
+ // BaseTree 渲染 .base-tree,内部经过 el-scrollbar 多层后才是 jh-tree
7
+ // 中间层 class 名称(.left-tree-box 等)在运行时版本中可能不存在
8
+ // → 选择器只依赖 .drag-left 这一个确定父级,不写任何中间 class
9
+ //
10
+ // 【策略:最短可靠路径 + 通配覆盖】
11
+ // .drag-left .el-tree-node__content:hover → 背景色
12
+ // .drag-left .el-tree-node__content:hover * → 文字色(通配,覆盖所有子元素)
13
+ // .drag-left .el-tree-node.is-current > .el-tree-node__content → 选中
14
+ // !important 确保胜过 jh-tree scoped 规则(后者不用 !important)
15
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
16
+
17
+ // ── 面板容器 ──────────────────────────────────────────────────────────────────
18
+ .drag-left > div {
19
+ background-color: #f7f8fb;
20
+ padding: 10px 0;
21
+ border-radius: 4px 0 0 4px;
22
+ border-right: 1px solid rgba(0, 0, 0, 0.07);
23
+ }
24
+
25
+ // ── 搜索框(BaseTree 内置搜索)───────────────────────────────────────────────
26
+ .drag-left .base-tree-search-box {
27
+ padding: 0 10px 8px;
28
+
29
+ .el-input__wrapper {
30
+ border-radius: 6px;
31
+ background: #ffffff;
32
+ box-shadow: 0 0 0 1px var(--el-border-color) inset;
33
+ transition: box-shadow 0.18s;
34
+ &:hover { box-shadow: 0 0 0 1px var(--el-border-color-darker) inset; }
35
+ &.is-focus { box-shadow: 0 0 0 1.5px var(--el-color-primary) inset !important; }
36
+ }
37
+
38
+ .el-input__inner {
39
+ font-size: 13px;
40
+ color: var(--el-text-color-regular);
41
+ &::placeholder { color: var(--el-text-color-placeholder); }
42
+ }
43
+
44
+ .el-input__prefix-inner .el-icon { color: var(--el-text-color-placeholder); }
45
+ }
46
+
47
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
48
+ // jh-tree 核心颜色覆盖(已修正:不依赖 .left-tree-box 等中间层 class)
49
+ // 直接使用 .drag-left 作为唯一父级锚点
50
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
51
+ // ── 树节点宽度 ────────────────────────────────────────────────────────────────
52
+ .drag-left .el-tree-node {
53
+ white-space: normal !important;
54
+ overflow: visible !important;
55
+ width: 100%;
56
+ }
57
+ .drag-left .el-tree-node__children { width: 100%; }
58
+ .drag-left .el-tree { background: transparent; width: 100%; }
59
+
60
+ // ── 行基础 ────────────────────────────────────────────────────────────────────
61
+ .drag-left .el-tree-node__content {
62
+ position: relative;
63
+ width: 100% !important;
64
+ height: 32px;
65
+ line-height: 32px;
66
+ font-size: 13px;
67
+ box-sizing: border-box !important;
68
+ padding-right: 12px;
69
+ transition: background-color 0.12s ease, color 0.12s ease;
70
+ user-select: none;
71
+ background-color: transparent !important;
72
+
73
+ // ── 左侧圆点装饰(仅 hover 时显示,选中时隐藏)────────────────────────────
74
+ &::before {
75
+ content: '';
76
+ position: absolute;
77
+ left: 4px;
78
+ top: 50%;
79
+ width: 5px;
80
+ height: 5px;
81
+ border-radius: 50%;
82
+ background: var(--el-color-primary);
83
+ transform: translateY(-50%) scale(0);
84
+ opacity: 0;
85
+ pointer-events: none;
86
+ z-index: 2;
87
+ transition: transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.15s ease;
88
+ }
89
+
90
+ // ── Hover(非选中行)──────────────────────────────────────────────────────
91
+ &:hover {
92
+ background-color: rgba(34, 84, 244, 0.07) !important;
93
+
94
+ &::before { transform: translateY(-50%) scale(1); opacity: 0.55; }
95
+
96
+ // 通配覆盖所有子元素(包括 menu-tree-node background:#f0f3ff)
97
+ * {
98
+ color: var(--el-color-primary) !important;
99
+ background-color: transparent !important;
100
+ background: transparent !important;
101
+ }
102
+
103
+ // 叶子展开图标保持透明
104
+ > .el-tree-node__expand-icon.is-leaf { color: transparent !important; }
105
+ }
106
+ }
107
+
108
+ // 键盘 focus → 去除 jh-tree 的 background:#addaff
109
+ .drag-left .el-tree-node:focus > .el-tree-node__content {
110
+ background-color: transparent !important;
111
+ outline: none;
112
+ }
113
+
114
+ // ── 选中状态 ──────────────────────────────────────────────────────────────────
115
+ .drag-left .el-tree-node.is-current > .el-tree-node__content {
116
+ background-color: rgba(34, 84, 244, 0.10) !important;
117
+ box-shadow: inset 3px 0 0 var(--el-color-primary) !important;
118
+ font-weight: 500;
119
+ color: var(--el-color-primary) !important;
120
+
121
+ // 选中时圆点不显示
122
+ &::before {
123
+ transform: translateY(-50%) scale(0) !important;
124
+ opacity: 0 !important;
125
+ }
126
+
127
+ // ① 通配覆盖 — 确保所有子孙文字同色(左右一致)
128
+ // background/background-color 同时清除,防止 jh-tree scoped 的 background: #f0f3ff 残留
129
+ * {
130
+ color: var(--el-color-primary) !important;
131
+ background-color: transparent !important;
132
+ background: transparent !important;
133
+ }
134
+
135
+ // ② 精确覆盖 jh-tree scoped 选中态规则
136
+ .menu-tree-node,
137
+ .menu-title,
138
+ .el-tree-node__label,
139
+ span,
140
+ div {
141
+ color: var(--el-color-primary) !important;
142
+ background: transparent !important;
143
+ background-color: transparent !important;
144
+ }
145
+
146
+ > .el-tree-node__expand-icon.is-leaf { color: transparent !important; }
147
+
148
+ // hover 时加深一点
149
+ &:hover {
150
+ background-color: rgba(34, 84, 244, 0.15) !important;
151
+ }
152
+ }
153
+
154
+ // ── 展开/折叠图标 ─────────────────────────────────────────────────────────────
155
+ .drag-left .el-tree-node__expand-icon {
156
+ font-size: 11px;
157
+ padding: 9px 7px;
158
+ flex-shrink: 0;
159
+ transition: color 0.12s, transform 0.18s ease;
160
+
161
+ &.is-leaf { color: transparent !important; pointer-events: none; cursor: default; }
162
+ }
163
+
164
+ // ── 树滚动条 ──────────────────────────────────────────────────────────────────
165
+ .drag-left .base-tree .el-scrollbar__wrap {
166
+ overflow-y: auto !important;
167
+ overflow-x: auto !important;
168
+ padding-right: 0 !important;
169
+
170
+ &::-webkit-scrollbar { width: 4px; height: 4px; }
171
+ &::-webkit-scrollbar-corner { background: transparent; }
172
+ &::-webkit-scrollbar-track { background: transparent; }
173
+ &::-webkit-scrollbar-thumb { background: transparent; border-radius: 2px; }
174
+ }
175
+
176
+ .drag-left .base-tree:hover .el-scrollbar__wrap::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.12); }
177
+ .drag-left .base-tree:hover .el-scrollbar__wrap::-webkit-scrollbar-thumb:hover { background: rgba(0, 0, 0, 0.25); }
178
+
179
+ // ── 兜底:当 BaseTree 内部不是 el-scrollbar 而是直接出现原生滚动条时 ─────
180
+ // 覆盖范围:.drag-left 内所有可能的滚动容器(.base-tree、.jh-tree、.el-tree、
181
+ // 以及 .left-tree-box / .left-content 等任意中间层),统一为 4px 极细滚动条,
182
+ // 颜色与表格保持一致(rgba 0.12 / hover 0.25)。
183
+ // 仅 hover 容器时才显示 thumb,避免静态视觉噪声。
184
+ .drag-left {
185
+ // 所有子级滚动容器(包含 :hover 子树)都统一为 4px、透明轨道
186
+ *::-webkit-scrollbar { width: 4px !important; height: 4px !important; }
187
+ *::-webkit-scrollbar-track { background: transparent !important; }
188
+ *::-webkit-scrollbar-corner { background: transparent !important; }
189
+ *::-webkit-scrollbar-thumb {
190
+ background: transparent !important;
191
+ border-radius: 2px !important;
192
+ }
193
+
194
+ &:hover *::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.12) !important; }
195
+ &:hover *::-webkit-scrollbar-thumb:hover { background: rgba(0, 0, 0, 0.25) !important; }
196
+ }
@@ -0,0 +1,114 @@
1
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2
+ // @agile-team/wk-skills-ui — Portal / 远程 public 模块视觉增强(可选模块)
3
+ // 来源:wl-safe src/assets/style/element.scss 中 .portal-* 段落
4
+ // 仅当业务系统嵌入了相同的 jh4j-cloud-ui-public Portal 模块时引入
5
+ // 用法: @use '@agile-team/wk-skills-ui/dist/portal.scss';
6
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
7
+
8
+ // 主背景:双径向渐变替换纯灰
9
+ html body .portal-main {
10
+ background:
11
+ radial-gradient(ellipse at 15% 0%, rgba(34, 84, 244, 0.09) 0%, transparent 45%),
12
+ radial-gradient(ellipse at 85% 85%, rgba(122, 152, 248, 0.07) 0%, transparent 45%),
13
+ #eef0f8 !important;
14
+ }
15
+
16
+ // 顶栏:毛玻璃效果
17
+ html body .portal-header {
18
+ background: rgba(255, 255, 255, 0.88) !important;
19
+ backdrop-filter: blur(12px) !important;
20
+ -webkit-backdrop-filter: blur(12px) !important;
21
+ box-shadow: 0 1px 16px rgba(34, 84, 244, 0.08) !important;
22
+ border-bottom: 1px solid rgba(34, 84, 244, 0.07) !important;
23
+ }
24
+
25
+ // 平台标题:蓝紫渐变文字
26
+ html body .portal-text {
27
+ background: linear-gradient(135deg, #2254f4 0%, #7a98f8 100%) !important;
28
+ -webkit-background-clip: text !important;
29
+ -webkit-text-fill-color: transparent !important;
30
+ background-clip: text !important;
31
+ font-weight: 700 !important;
32
+ }
33
+
34
+ // 左侧 banner 图:加圆角+阴影
35
+ html body .portal-bg {
36
+ border-radius: 14px !important;
37
+ overflow: hidden !important;
38
+ box-shadow: 0 8px 32px rgba(34, 84, 244, 0.12) !important;
39
+ }
40
+
41
+ // 综合待办卡片:玻璃质感
42
+ html body .portal-zh {
43
+ background: rgba(255, 255, 255, 0.82) !important;
44
+ backdrop-filter: blur(20px) !important;
45
+ -webkit-backdrop-filter: blur(20px) !important;
46
+ border-radius: 14px !important;
47
+ border: 1px solid rgba(34, 84, 244, 0.12) !important;
48
+ box-shadow: 0 8px 32px rgba(34, 84, 244, 0.1) !important;
49
+ overflow: hidden !important;
50
+ }
51
+
52
+ // 通知待办 Tab 激活下划线
53
+ html body .portal-tabs .el-tabs__active-bar {
54
+ background: linear-gradient(90deg, #2254f4 0%, #7a98f8 100%) !important;
55
+ }
56
+ html body .portal-tabs .el-tabs__item.is-active {
57
+ color: #2254f4 !important;
58
+ font-weight: 600 !important;
59
+ }
60
+ html body .portal-tabs .el-tabs__item:hover {
61
+ color: #2254f4 !important;
62
+ }
63
+
64
+ // 子系统区域卡片:玻璃质感
65
+ html body .portal-mainBottom .portal-content,
66
+ html body .portal-mainMiddle {
67
+ background: rgba(255, 255, 255, 0.82) !important;
68
+ backdrop-filter: blur(20px) !important;
69
+ -webkit-backdrop-filter: blur(20px) !important;
70
+ border-radius: 14px !important;
71
+ border: 1px solid rgba(34, 84, 244, 0.12) !important;
72
+ box-shadow: 0 8px 32px rgba(34, 84, 244, 0.1) !important;
73
+ overflow: hidden !important;
74
+ }
75
+
76
+ // 子系统图标卡:悬停上浮动效
77
+ html body .portal-childrenSystem {
78
+ transition: transform 0.28s cubic-bezier(0.34, 1.56, 0.64, 1) !important;
79
+ cursor: pointer !important;
80
+
81
+ &:hover {
82
+ transform: translateY(-8px) scale(1.08) !important;
83
+ }
84
+
85
+ &:hover .children-name {
86
+ color: var(--el-color-primary, #2254f4) !important;
87
+ font-weight: 600 !important;
88
+ }
89
+ }
90
+
91
+ // 区块标题左竖线:蓝紫渐变
92
+ html body .portal-line {
93
+ background: linear-gradient(180deg, #2254f4 0%, #7a98f8 100%) !important;
94
+ border-radius: 2px !important;
95
+ }
96
+
97
+ // 区块标题文字
98
+ html body .portal-font {
99
+ color: var(--el-text-color-primary, #303133) !important;
100
+ font-weight: 600 !important;
101
+ }
102
+
103
+ // 消息数量角标:主色背景
104
+ html body .portal-tabs-label .num {
105
+ background: var(--el-color-primary, #2254f4) !important;
106
+ color: #fff !important;
107
+ border-radius: 10px !important;
108
+ font-weight: 600 !important;
109
+ }
110
+
111
+ // 消息行 hover
112
+ html body .portal-tabs-row:hover {
113
+ color: var(--el-color-primary, #2254f4) !important;
114
+ }
@@ -0,0 +1,17 @@
1
+ // styles/vendors/index.scss — Vendors 层(L2 化妆层)汇总
2
+ //
3
+ // 加载顺序:从最高优先级到兜底(同选择器特异性下,后加载会覆盖前面)
4
+ // 优先级约定(v3 团队规范):
5
+ // Base* > jh-* > C_*/c_* > custom wrappers
6
+ // → 但 SCSS 加载顺序里我们反过来:兜底先加载,让高优先级覆盖
7
+
8
+ @forward './_portal'; // 弹层/popper 通用(基础设施层)
9
+ @forward './_ag-grid'; // AG Grid 完整主题
10
+ @forward './_custom-wrappers'; // 兜底:野路子自封装
11
+ @forward './_c-components'; // C_/c_ 前缀
12
+ @forward './_jh-tree'; // jh-tree
13
+ @forward './_jh-pagination'; // jh-pagination
14
+ @forward './_jh-drag-col'; // jh-drag-col(含左树右表骨架)
15
+ @forward './_base-query-toolbar';// BaseQuery / BaseToolbar
16
+ @forward './_base-components'; // Base* 通用(操作按钮组、徽标、tag)
17
+ @forward './_base-table'; // BaseTable(最高优先级)
@@ -0,0 +1,76 @@
1
+ # TPL-AG-GRID — AG Grid 列表页模板
2
+
3
+ > 适用:使用 AG Grid 作为表格组件的高性能列表页(大数据量、复杂列操作)。
4
+
5
+ ## 模板代码(TypeScript 类风格)
6
+
7
+ ```typescript
8
+ // [Module]List.ts — 页面逻辑
9
+ import { defineColumns, renderOps, renderTagNode } from '@agile-team/wk-skills-ui/runtime';
10
+ import type { TableColumnDesc } from '@/types/table';
11
+
12
+ columnsDef(): TableColumnDesc<any>[] {
13
+ return defineColumns([
14
+ // ── 选择/序号 ──
15
+ {
16
+ type: 'selection',
17
+ label: '',
18
+ width: 55,
19
+ fixed: 'left',
20
+ align: 'center',
21
+ headerAlign: 'center',
22
+ },
23
+ { type: 'index', label: '序号', width: 60, align: 'center' },
24
+
25
+ // ── 数据列(已注册字段自动映射,无需 defaultNode)──
26
+ { name: 'riskNo', label: '编号', width: 100 }, // → renderBadge
27
+ { name: 'name', label: '名称', minWidth: 150 },
28
+ { name: 'riskLevel', label: '风险分级', width: 90 }, // → renderRiskLevel Tag
29
+ { name: 'riskStatus', label: '状态', width: 90 }, // → renderRiskStatus Tag
30
+
31
+ // ── 自定义渲染列 ──
32
+ { name: 'checkLevel', label: '检查层级', width: 90,
33
+ defaultSlot: ({ row }) => renderCheckLevel(row.checkLevel) },
34
+
35
+ // ── 操作列 ──
36
+ {
37
+ label: '操作',
38
+ width: 120,
39
+ fixed: 'right',
40
+ align: 'center',
41
+ defaultSlot: ({ row }) => renderOps([
42
+ { type: 'view', onClick: () => this.modal.view(row.id) },
43
+ { type: 'edit', show: !this.isReadonly, onClick: () => this.modal.edit(row.id) },
44
+ { type: 'del', show: !this.isReadonly, onClick: () => this.handleDel(row.id) },
45
+ ]),
46
+ },
47
+ ]);
48
+ }
49
+ ```
50
+
51
+ ## 工具栏定义
52
+
53
+ ```typescript
54
+ toolbarDef() {
55
+ return [
56
+ {
57
+ label: '新增',
58
+ icon: 'Plus',
59
+ type: 'primary',
60
+ onClick: () => this.modal.add(),
61
+ },
62
+ {
63
+ label: '导出',
64
+ icon: 'Download',
65
+ onClick: () => this.handleExport(),
66
+ },
67
+ ];
68
+ }
69
+ ```
70
+
71
+ ## 注意事项
72
+
73
+ 1. 所有列用 `defineColumns()` 包裹 — 已注册字段自动应用渲染器
74
+ 2. 操作列用 `renderOps([...])` — 图标按钮 + 自动 stopPropagation
75
+ 3. selection 列必须同时设置 `align: 'center'` + `headerAlign: 'center'`(R014)
76
+ 4. 分类字段(type/level)用 `renderClassifyTag`,状态字段用 `renderTagNode`
@@ -0,0 +1,165 @@
1
+ # TPL-FORM-DIALOG — 标准表单弹窗模板
2
+
3
+ > 适用:新增/编辑弹窗,含表单验证、查看模式(只读)、成功回调。
4
+
5
+ ## 模板代码
6
+
7
+ ```vue
8
+ <template>
9
+ <el-dialog
10
+ v-model="visible"
11
+ :title="title"
12
+ width="700px"
13
+ :close-on-click-modal="false"
14
+ @closed="handleClosed"
15
+ >
16
+ <el-form
17
+ ref="formRef"
18
+ :model="form"
19
+ :rules="rules"
20
+ label-width="150px"
21
+ :disabled="optr === 'view'"
22
+ >
23
+ <el-row :gutter="20">
24
+ <el-col :span="12">
25
+ <el-form-item label="名称" prop="name">
26
+ <el-input
27
+ size="small"
28
+ v-model="form.name"
29
+ placeholder="请输入名称"
30
+ maxlength="50"
31
+ show-word-limit
32
+ />
33
+ </el-form-item>
34
+ </el-col>
35
+ <el-col :span="12">
36
+ <el-form-item label="所属部门" prop="deptId">
37
+ <el-select
38
+ size="small"
39
+ v-model="form.deptId"
40
+ placeholder="请选择"
41
+ style="width:100%"
42
+ >
43
+ <el-option
44
+ v-for="o in deptOptions"
45
+ :key="o.value"
46
+ :label="o.label"
47
+ :value="o.value"
48
+ />
49
+ </el-select>
50
+ </el-form-item>
51
+ </el-col>
52
+ <el-col :span="12">
53
+ <el-form-item label="开始日期" prop="startDate">
54
+ <el-date-picker
55
+ style="width:100%"
56
+ size="small"
57
+ v-model="form.startDate"
58
+ type="date"
59
+ placeholder="请选择日期"
60
+ value-format="YYYY-MM-DD"
61
+ />
62
+ </el-form-item>
63
+ </el-col>
64
+ <el-col :span="24">
65
+ <el-form-item label="备注" prop="remark">
66
+ <el-input
67
+ size="small"
68
+ v-model="form.remark"
69
+ type="textarea"
70
+ :rows="3"
71
+ placeholder="请输入备注"
72
+ />
73
+ </el-form-item>
74
+ </el-col>
75
+ </el-row>
76
+ </el-form>
77
+
78
+ <template #footer>
79
+ <el-button @click="visible = false">取消</el-button>
80
+ <el-button
81
+ v-if="optr !== 'view'"
82
+ type="primary"
83
+ :loading="saving"
84
+ @click="handleSubmit"
85
+ >
86
+ 确定
87
+ </el-button>
88
+ </template>
89
+ </el-dialog>
90
+ </template>
91
+
92
+ <script setup lang="ts">
93
+ import { ref, reactive } from 'vue';
94
+ import { ElMessage } from 'element-plus';
95
+ // import { addModule, updateModule, getModuleDetail } from '@/api/module';
96
+
97
+ const emit = defineEmits(['success']);
98
+
99
+ // ── 状态 ────────────────────────────────────────────────────────────────────
100
+ const visible = ref(false);
101
+ const optr = ref<'add' | 'edit' | 'view'>('add');
102
+ const saving = ref(false);
103
+ const formRef = ref();
104
+
105
+ // ── 表单数据 ──────────────────────────────────────────────────────────────────
106
+ const EMPTY_FORM = { name: '', deptId: undefined, startDate: '', remark: '' };
107
+ const form = reactive({ ...EMPTY_FORM });
108
+
109
+ // ── 验证规则 ──────────────────────────────────────────────────────────────────
110
+ const rules = {
111
+ name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
112
+ deptId: [{ required: true, message: '请选择部门', trigger: 'change' }],
113
+ };
114
+
115
+ // ── 计算标题 ──────────────────────────────────────────────────────────────────
116
+ const title = computed(() => ({ add: '新增', edit: '编辑', view: '查看' }[optr.value] || '');
117
+
118
+ // ── 打开弹窗 ──────────────────────────────────────────────────────────────────
119
+ async function add() {
120
+ optr.value = 'add';
121
+ Object.assign(form, EMPTY_FORM);
122
+ visible.value = true;
123
+ }
124
+ async function edit(id: string) {
125
+ optr.value = 'edit';
126
+ // const data = await getModuleDetail(id);
127
+ // Object.assign(form, data);
128
+ visible.value = true;
129
+ }
130
+ async function view(id: string) {
131
+ optr.value = 'view';
132
+ // const data = await getModuleDetail(id);
133
+ // Object.assign(form, data);
134
+ visible.value = true;
135
+ }
136
+ defineExpose({ add, edit, view });
137
+
138
+ // ── 提交 ──────────────────────────────────────────────────────────────────────
139
+ async function handleSubmit() {
140
+ await formRef.value?.validate();
141
+ saving.value = true;
142
+ try {
143
+ // if (optr.value === 'add') await addModule(form);
144
+ // else await updateModule(form);
145
+ ElMessage.success('操作成功');
146
+ visible.value = false;
147
+ emit('success');
148
+ } finally {
149
+ saving.value = false;
150
+ }
151
+ }
152
+
153
+ function handleClosed() {
154
+ formRef.value?.resetFields();
155
+ }
156
+ </script>
157
+ ```
158
+
159
+ ## 注意事项
160
+
161
+ 1. `label-width="150px"` — 统一标准(R008)
162
+ 2. `el-input` / `el-select` 必须 `size="small"`(R006)
163
+ 3. `el-date-picker` 必须 `style="width:100%"`(R007)
164
+ 4. 查看模式用 `:disabled="optr === 'view'"`,不重复渲染
165
+ 5. `<template #footer>` 只放操作按钮,不放分页(R011)