@agile-team/wl-skills-ui 1.9.16 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +4 -0
- package/es/{chunk-53TF2NQQ.js → chunk-FB4NHDR3.js} +67 -1
- package/es/common-preset.d.ts +1 -1
- package/es/common-preset.js +2 -2
- package/es/index.d.ts +21 -2
- package/es/index.js +2 -2
- package/es/presets/security.js +1 -1
- package/es/{renderers-DlFRBX9K.d.ts → renderers-DKcXOFnF.d.ts} +24 -1
- package/package.json +1 -1
- package/standards/ui/06-legacy-migration-lessons.md +149 -0
- package/styles/vendors/_ag-grid.scss +55 -18
- package/styles/vendors/_base-components.scss +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,23 @@ All notable changes to **@agile-team/wl-skills-ui** will be documented in this f
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
6
|
|
|
7
|
+
## [1.10.0] - 2026-08-15
|
|
8
|
+
|
|
9
|
+
> 来源:wl-ui-ep(危废/环保子系统)存量改造实战沉淀,全部经过"线上翻车 → 定位 → 修复 → 验证"闭环。
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- 新增 `renderAutoTag(value, dictKey, fieldName?)` / `renderAutoTagByLabel(label, fieldName?)` 文案语义自动判色 Tag:按字典渲染出的文案关键词判色(状态词实心 Tag、分类/形态词镂空 Tag、中性词原样纯文本兜底),零配色表覆盖存量项目上百字典列;规则表 `AUTO_STATUS_RULES` / `AUTO_CLASSIFY_RULES` / `autoTagTypeByLabel` 同步导出可扩展。
|
|
14
|
+
- 新增 `ensureDefaultAlignment` / `normalizeColumnAlignmentsWith(cols, { defaultAlign: "center" })` 默认对齐补齐:无显式 `align/cellStyle/headerClass` 的列补默认居中(含表头 class 桥接,兼容共享 AG 适配层只认 class 的场景),递归分组 children;不传 options 保持原有"仅桥接显式声明"行为,向后兼容。
|
|
15
|
+
- 新增规范文档 `standards/ui/06-legacy-migration-lessons.md`:二级表头、滚动条双轨、默认居中、状态 Tag、操作图标配色、禁用按钮可辨识、搜索区间距、分页位置、联邦门户样式污染规避、字典列审计机制十条实战沉淀。
|
|
16
|
+
- `check:scss` 新增反模式守门:包内出现 `.ag-header-row` 强制 height 直接报错(防二级表头破坏模式回流)。
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- AG Grid 二级(分组)表头不渲染:移除 `.ag-header-row { height: 36px !important }` 强制行高,改由 `--ag-header-height` / 新增 `--ag-group-header-height` 变量驱动;并增加 `:has(.ag-header-row-column-group)` 两行兜底(真实存在分组行时强制两行各 36px),兼容共享 AG 适配层不透传 `groupHeaderHeight` 的存量场景。
|
|
21
|
+
- 表格滚动条改为"默认隐藏 → 悬停显示主题色(单档)"双轨实现:Chrome 121+ / Firefox 走标准 `scrollbar-color`,旧 Chromium 走 webkit 伪元素 + CSS 变量继承(`--wk-sb-thumb`),根治"容器:hover 直选伪元素在部分 Chromium 不触发重绘导致悬停不显示"的缺陷;横向条悬停展开 8px 主题色。
|
|
22
|
+
- 操作列编辑图标 hover 由绿改警示黄:与查看蓝/删除红拉开三色区分,绿留给成功/审核语义(业务定案)。
|
|
23
|
+
|
|
7
24
|
## [1.9.16] - 2026-08-11
|
|
8
25
|
|
|
9
26
|
### Fixed
|
package/README.md
CHANGED
|
@@ -730,9 +730,13 @@ export const myRules = [
|
|
|
730
730
|
| ------------------------------------------------ | -------------------------------------------------- |
|
|
731
731
|
| `defineColumns(cols)` | 列定义,应用自动映射并桥接显式列对齐 |
|
|
732
732
|
| `normalizeColumnAlignments(cols)` | 仅桥接显式 `align/headerAlign`,不设置默认对齐 |
|
|
733
|
+
| `normalizeColumnAlignmentsWith(cols, opts)` | 桥接 + 默认对齐补齐(`{ defaultAlign: "center" }`,属性可退出) |
|
|
734
|
+
| `ensureDefaultAlignment(col, align)` | 单列默认对齐补齐(递归分组 children,尊重显式声明) |
|
|
733
735
|
| `renderOps(items)` | 操作列图标按钮组(view/edit/del/log/ok/send 预设) |
|
|
734
736
|
| `renderTagNode(v, map)` | 状态 Tag 渲染 |
|
|
735
737
|
| `renderClassifyTag(v, map)` | 分类 Tag 渲染 |
|
|
738
|
+
| `renderAutoTag(v, dictKey, fieldName?)` | 字典列文案语义自动判色 Tag(状态实心/分类镂空/中性纯文本兜底,存量改造验证) |
|
|
739
|
+
| `renderAutoTagByLabel(label, fieldName?)` | 同上,已解析文案直调版 |
|
|
736
740
|
| `renderBadge(v)` / `renderCountBadge(v)` | 编号 / 计数徽标 |
|
|
737
741
|
| `renderRatingLevel(v)` | 评级颜色 |
|
|
738
742
|
| `registerColumnAutoMap(field, config)` | 注册新字段自动渲染 |
|
|
@@ -29,6 +29,26 @@ function normalizeColumnAlignment(column) {
|
|
|
29
29
|
function normalizeColumnAlignments(columns) {
|
|
30
30
|
return columns.map((column) => normalizeColumnAlignment(column));
|
|
31
31
|
}
|
|
32
|
+
function ensureDefaultAlignment(column, defaultAlign) {
|
|
33
|
+
const normalizedChildren = Array.isArray(column.children) ? column.children.map((child) => ensureDefaultAlignment(child, defaultAlign)) : column.children;
|
|
34
|
+
const hasExplicit = column.align !== void 0 || column.cellStyle !== void 0 || column.headerClass !== void 0;
|
|
35
|
+
if (hasExplicit) {
|
|
36
|
+
return normalizedChildren === column.children ? column : { ...column, children: normalizedChildren };
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
...column,
|
|
40
|
+
align: defaultAlign,
|
|
41
|
+
headerAlign: defaultAlign,
|
|
42
|
+
children: normalizedChildren
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function normalizeColumnAlignmentsWith(columns, options = {}) {
|
|
46
|
+
const { defaultAlign = null } = options;
|
|
47
|
+
return columns.map((column) => {
|
|
48
|
+
const withDefault = defaultAlign == null ? column : ensureDefaultAlignment(column, defaultAlign);
|
|
49
|
+
return normalizeColumnAlignment(withDefault);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
32
52
|
var ENABLE_STATUS_MAP = {
|
|
33
53
|
0: { label: "\u505C\u7528", type: "danger" },
|
|
34
54
|
1: { label: "\u542F\u7528", type: "success" }
|
|
@@ -145,6 +165,52 @@ function renderDictClassifyTag(value, dictKey, typeColorMap) {
|
|
|
145
165
|
() => label
|
|
146
166
|
);
|
|
147
167
|
}
|
|
168
|
+
var AUTO_STATUS_RULES = [
|
|
169
|
+
[/驳回|拒绝|停用|作废|报废|超标|异常|超期|逾期|不合格|失效|无效|惩罚|隐患/, "danger"],
|
|
170
|
+
[/已完成|已结束|完成|正常|有效|启用|合格|达标|通过|已处置|已确认|已审批|在用|使用中|奖励/, "success"],
|
|
171
|
+
[/待|进行中|审批中|整改中|处置中|评估中|调查|预警|管控|注意/, "warning"],
|
|
172
|
+
[/新建|未开始|草稿|暂存|历史|撤回|无|否|未/, "info"]
|
|
173
|
+
];
|
|
174
|
+
var AUTO_CLASSIFY_RULES = [
|
|
175
|
+
[/危废|危险|惩罚|事故|气态/, "danger"],
|
|
176
|
+
[/奖励|安全/, "success"],
|
|
177
|
+
[/一般|普通|计划外/, "warning"],
|
|
178
|
+
[/液态|固态|半固态/, "info"]
|
|
179
|
+
];
|
|
180
|
+
var CLASSIFY_HINT = /类型|类别|级别|维度|形态|相态|气态|液态|固态/;
|
|
181
|
+
function matchRules(label, rules) {
|
|
182
|
+
for (const [re, type] of rules) {
|
|
183
|
+
if (re.test(label)) return type;
|
|
184
|
+
}
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
function autoTagTypeByLabel(label, fieldName) {
|
|
188
|
+
const statusType = matchRules(label, AUTO_STATUS_RULES);
|
|
189
|
+
if (statusType !== null) return { type: statusType, plain: false };
|
|
190
|
+
const isClassify = CLASSIFY_HINT.test(label) || /type|level|category|class/i.test(fieldName ?? "");
|
|
191
|
+
if (isClassify) {
|
|
192
|
+
return { type: matchRules(label, AUTO_CLASSIFY_RULES) ?? "", plain: true };
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
function renderAutoTagByLabel(label, fieldName) {
|
|
197
|
+
const tag = autoTagTypeByLabel(label, fieldName);
|
|
198
|
+
if (tag === null) return label;
|
|
199
|
+
return h(
|
|
200
|
+
ElTag,
|
|
201
|
+
{ type: tag.type, size: "small", effect: tag.plain ? "plain" : "light" },
|
|
202
|
+
() => label
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
function renderAutoTag(value, dictKey, fieldName) {
|
|
206
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
207
|
+
let label = String(value);
|
|
208
|
+
if (dictResolver) {
|
|
209
|
+
const resolved = dictResolver(dictKey, value);
|
|
210
|
+
if (resolved) label = resolved;
|
|
211
|
+
}
|
|
212
|
+
return renderAutoTagByLabel(label, fieldName ?? dictKey);
|
|
213
|
+
}
|
|
148
214
|
function renderBadge(value) {
|
|
149
215
|
if (value === null || value === void 0 || value === "") return null;
|
|
150
216
|
return h("span", { class: "jh-riskno-badge" }, String(value));
|
|
@@ -356,4 +422,4 @@ registerColumnAutoMaps({
|
|
|
356
422
|
}
|
|
357
423
|
});
|
|
358
424
|
|
|
359
|
-
export { AUDIT_STATUS_MAP, ENABLE_STATUS_MAP, RATING_LEVEL_COLORS, VERIFY_STATUS_MAP, clearColumnAutoMap, defineColumns, getColumnAutoMap, normalizeColumnAlignment, normalizeColumnAlignments, registerColumnAutoMap, registerColumnAutoMaps, registerDictColorMap, registerDictColorMaps, renderAuditStatus, renderBadge, renderClassifyTag, renderCountBadge, renderDangerText, renderDictClassifyTag, renderEnableStatus, renderOps, renderRatingLevel, renderTagNode, renderTagSlot, renderVerifyStatus, setDictResolver };
|
|
425
|
+
export { AUDIT_STATUS_MAP, AUTO_CLASSIFY_RULES, AUTO_STATUS_RULES, ENABLE_STATUS_MAP, RATING_LEVEL_COLORS, VERIFY_STATUS_MAP, autoTagTypeByLabel, clearColumnAutoMap, defineColumns, ensureDefaultAlignment, getColumnAutoMap, normalizeColumnAlignment, normalizeColumnAlignments, normalizeColumnAlignmentsWith, registerColumnAutoMap, registerColumnAutoMaps, registerDictColorMap, registerDictColorMaps, renderAuditStatus, renderAutoTag, renderAutoTagByLabel, renderBadge, renderClassifyTag, renderCountBadge, renderDangerText, renderDictClassifyTag, renderEnableStatus, renderOps, renderRatingLevel, renderTagNode, renderTagSlot, renderVerifyStatus, setDictResolver };
|
package/es/common-preset.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
2
|
import { VNode } from 'vue';
|
|
3
3
|
import { T as TagMapItem, J as JhTagNode } from './types-DtmxwMWV.js';
|
|
4
|
-
export { r as registerDictColorMap, a as registerDictColorMaps, b as renderDictClassifyTag, s as setDictResolver } from './renderers-
|
|
4
|
+
export { r as registerDictColorMap, a as registerDictColorMaps, b as renderDictClassifyTag, s as setDictResolver } from './renderers-DKcXOFnF.js';
|
|
5
5
|
|
|
6
6
|
declare const RISK_LEVEL_MAP: Record<string | number, TagMapItem>;
|
|
7
7
|
declare const renderRiskLevel: (v: string | number | null | undefined) => JhTagNode | null;
|
package/es/common-preset.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { installUiRuntimeGuards } from './chunk-QLPJLXY6.js';
|
|
2
|
-
import { renderTagNode, renderClassifyTag, registerColumnAutoMaps, renderRatingLevel, renderBadge } from './chunk-
|
|
3
|
-
export { registerDictColorMap, registerDictColorMaps, renderDictClassifyTag, setDictResolver } from './chunk-
|
|
2
|
+
import { renderTagNode, renderClassifyTag, registerColumnAutoMaps, renderRatingLevel, renderBadge } from './chunk-FB4NHDR3.js';
|
|
3
|
+
export { registerDictColorMap, registerDictColorMaps, renderDictClassifyTag, setDictResolver } from './chunk-FB4NHDR3.js';
|
|
4
4
|
import './chunk-Q3N5QNRZ.js';
|
|
5
5
|
|
|
6
6
|
// runtime/presets/common.ts
|
package/es/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { C as ColumnLike } from './types-DtmxwMWV.js';
|
|
2
2
|
export { E as ElTagType, J as JhTagNode, a as OpChip, O as OpItem, b as OpLink, c as OpPreset, T as TagMapItem } from './types-DtmxwMWV.js';
|
|
3
|
-
export { A as AUDIT_STATUS_MAP, E as ENABLE_STATUS_MAP, R as RATING_LEVEL_COLORS, V as VERIFY_STATUS_MAP, r as registerDictColorMap, a as registerDictColorMaps,
|
|
3
|
+
export { A as AUDIT_STATUS_MAP, c as AUTO_CLASSIFY_RULES, d as AUTO_STATUS_RULES, E as ENABLE_STATUS_MAP, R as RATING_LEVEL_COLORS, V as VERIFY_STATUS_MAP, e as autoTagTypeByLabel, r as registerDictColorMap, a as registerDictColorMaps, f as renderAuditStatus, g as renderAutoTag, h as renderAutoTagByLabel, i as renderBadge, j as renderClassifyTag, k as renderCountBadge, l as renderDangerText, b as renderDictClassifyTag, m as renderEnableStatus, n as renderOps, o as renderRatingLevel, p as renderTagNode, q as renderTagSlot, t as renderVerifyStatus, s as setDictResolver } from './renderers-DKcXOFnF.js';
|
|
4
4
|
import 'vue';
|
|
5
5
|
|
|
6
6
|
type ColumnAlignment = "left" | "center" | "right";
|
|
@@ -15,6 +15,25 @@ type ColumnAlignment = "left" | "center" | "right";
|
|
|
15
15
|
declare function normalizeColumnAlignment<T extends ColumnLike>(column: T): T;
|
|
16
16
|
/** 批量规范化列定义;只桥接显式对齐意图,不设置全局默认对齐。 */
|
|
17
17
|
declare function normalizeColumnAlignments<T extends ColumnLike>(columns: T[]): T[];
|
|
18
|
+
interface DefaultAlignmentOptions {
|
|
19
|
+
/**
|
|
20
|
+
* 无显式 align 时补齐的默认对齐。
|
|
21
|
+
* - "center"(推荐)表头/内容默认居中
|
|
22
|
+
* - "left" / "right" 其他默认
|
|
23
|
+
* - 不传或 null 不补齐,保持调用方现状(向后兼容)
|
|
24
|
+
*/
|
|
25
|
+
defaultAlign?: ColumnAlignment | null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 为无显式对齐声明的列补齐默认对齐(含表头)。
|
|
29
|
+
*
|
|
30
|
+
* - 列已有 align / cellStyle / headerClass 时一律不动(业务意图优先);
|
|
31
|
+
* - 递归处理分组列 children;
|
|
32
|
+
* - 与 normalizeColumnAlignment 兼容:补齐产物仍可被桥接函数消费。
|
|
33
|
+
*/
|
|
34
|
+
declare function ensureDefaultAlignment<T extends ColumnLike>(column: T, defaultAlign: ColumnAlignment): T;
|
|
35
|
+
/** 桥接 + 可选默认对齐的统一入口(推荐列定义管线使用)。 */
|
|
36
|
+
declare function normalizeColumnAlignmentsWith<T extends ColumnLike>(columns: T[], options?: DefaultAlignmentOptions): T[];
|
|
18
37
|
|
|
19
38
|
/**
|
|
20
39
|
* runtime/core/registry.ts — COLUMN_AUTO_MAP 注册中心 + defineColumns
|
|
@@ -209,4 +228,4 @@ declare function uninstallSplitGridResizeGuard(): void;
|
|
|
209
228
|
*/
|
|
210
229
|
declare function installUiRuntimeGuards(): void;
|
|
211
230
|
|
|
212
|
-
export { BRAND_THEME_TOKENS, type ColumnAlignment, ColumnLike, type OverflowTooltipGuardOptions, type PresetConfig, SPLIT_GRID_RESIZE_EVENT, type SplitGridResizeDetail, clearColumnAutoMap, createPreset, defineColumns, getColumnAutoMap, getInstalledPresets, installBrandThemeLock, installOverflowTooltipGuard, installPreset, installSplitGridResizeGuard, installUiRuntimeGuards, normalizeColumnAlignment, normalizeColumnAlignments, registerColumnAutoMap, registerColumnAutoMaps, uninstallOverflowTooltipGuard, uninstallSplitGridResizeGuard };
|
|
231
|
+
export { BRAND_THEME_TOKENS, type ColumnAlignment, ColumnLike, type DefaultAlignmentOptions, type OverflowTooltipGuardOptions, type PresetConfig, SPLIT_GRID_RESIZE_EVENT, type SplitGridResizeDetail, clearColumnAutoMap, createPreset, defineColumns, ensureDefaultAlignment, getColumnAutoMap, getInstalledPresets, installBrandThemeLock, installOverflowTooltipGuard, installPreset, installSplitGridResizeGuard, installUiRuntimeGuards, normalizeColumnAlignment, normalizeColumnAlignments, normalizeColumnAlignmentsWith, registerColumnAutoMap, registerColumnAutoMaps, uninstallOverflowTooltipGuard, uninstallSplitGridResizeGuard };
|
package/es/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { SPLIT_GRID_RESIZE_EVENT, installOverflowTooltipGuard, installSplitGridResizeGuard, installUiRuntimeGuards, uninstallOverflowTooltipGuard, uninstallSplitGridResizeGuard } from './chunk-QLPJLXY6.js';
|
|
2
|
-
import { registerColumnAutoMaps } from './chunk-
|
|
3
|
-
export { AUDIT_STATUS_MAP, ENABLE_STATUS_MAP, RATING_LEVEL_COLORS, VERIFY_STATUS_MAP, clearColumnAutoMap, defineColumns, getColumnAutoMap, normalizeColumnAlignment, normalizeColumnAlignments, registerColumnAutoMap, registerColumnAutoMaps, registerDictColorMap, registerDictColorMaps, renderAuditStatus, renderBadge, renderClassifyTag, renderCountBadge, renderDangerText, renderDictClassifyTag, renderEnableStatus, renderOps, renderRatingLevel, renderTagNode, renderTagSlot, renderVerifyStatus, setDictResolver } from './chunk-
|
|
2
|
+
import { registerColumnAutoMaps } from './chunk-FB4NHDR3.js';
|
|
3
|
+
export { AUDIT_STATUS_MAP, AUTO_CLASSIFY_RULES, AUTO_STATUS_RULES, ENABLE_STATUS_MAP, RATING_LEVEL_COLORS, VERIFY_STATUS_MAP, autoTagTypeByLabel, clearColumnAutoMap, defineColumns, ensureDefaultAlignment, getColumnAutoMap, normalizeColumnAlignment, normalizeColumnAlignments, normalizeColumnAlignmentsWith, registerColumnAutoMap, registerColumnAutoMaps, registerDictColorMap, registerDictColorMaps, renderAuditStatus, renderAutoTag, renderAutoTagByLabel, renderBadge, renderClassifyTag, renderCountBadge, renderDangerText, renderDictClassifyTag, renderEnableStatus, renderOps, renderRatingLevel, renderTagNode, renderTagSlot, renderVerifyStatus, setDictResolver } from './chunk-FB4NHDR3.js';
|
|
4
4
|
export { BRAND_THEME_TOKENS, installBrandThemeLock } from './chunk-Q3N5QNRZ.js';
|
|
5
5
|
|
|
6
6
|
// runtime/presets/registry.ts
|
package/es/presets/security.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { renderTagNode, registerDictColorMaps, registerColumnAutoMaps } from '../chunk-
|
|
1
|
+
import { renderTagNode, registerDictColorMaps, registerColumnAutoMaps } from '../chunk-FB4NHDR3.js';
|
|
2
2
|
import { installBrandThemeLock } from '../chunk-Q3N5QNRZ.js';
|
|
3
3
|
|
|
4
4
|
// runtime/presets/security.ts
|
|
@@ -34,6 +34,29 @@ declare function registerDictColorMap(dictKey: string, colorMap: Record<string,
|
|
|
34
34
|
declare function registerDictColorMaps(maps: Record<string, Record<string, string>>): void;
|
|
35
35
|
/** 渲染动态字典分类 Tag,适用于 logicType=dict 的类型/来源/方式/规则类型等列 */
|
|
36
36
|
declare function renderDictClassifyTag(value: string | number | null | undefined, dictKey: string, typeColorMap?: Record<string, string>): VNode | null;
|
|
37
|
+
/** 状态类关键词 → 实心 Tag 颜色(顺序即优先级:危险 > 成功 > 警示 > 中性) */
|
|
38
|
+
declare const AUTO_STATUS_RULES: Array<[RegExp, string]>;
|
|
39
|
+
/** 分类/级别/形态类关键词 → 镂空 Tag 颜色 */
|
|
40
|
+
declare const AUTO_CLASSIFY_RULES: Array<[RegExp, string]>;
|
|
41
|
+
/**
|
|
42
|
+
* 按已解析文案判语义 Tag 类型;中性文案返回 null(调用方保持纯文本)。
|
|
43
|
+
* 返回 { type, plain }:plain=true 表示分类/级别类(镂空 outline,低视觉权重)。
|
|
44
|
+
*/
|
|
45
|
+
declare function autoTagTypeByLabel(label: string, fieldName?: string): {
|
|
46
|
+
type: string;
|
|
47
|
+
plain: boolean;
|
|
48
|
+
} | null;
|
|
49
|
+
/**
|
|
50
|
+
* 文案语义 Tag(label 版):已拿到展示文案时直接调用。
|
|
51
|
+
* 状态类 → 浅色实心 Tag;分类/级别/形态类 → 镂空 Tag;
|
|
52
|
+
* 中性文案原样返回字符串(defaultSlot 直接可用,零视觉变化兜底)。
|
|
53
|
+
*/
|
|
54
|
+
declare function renderAutoTagByLabel(label: string, fieldName?: string): VNode | string;
|
|
55
|
+
/**
|
|
56
|
+
* 文案语义 Tag(字典版):传字典 key,内部经 setDictResolver 解析文案后判色。
|
|
57
|
+
* 未注入 resolver 时按 value 原文判色(多数字典 value 即文案的存量场景可用)。
|
|
58
|
+
*/
|
|
59
|
+
declare function renderAutoTag(value: string | number | null | undefined, dictKey: string, fieldName?: string): VNode | string | null;
|
|
37
60
|
/** 蓝色圆角徽标(编号类) */
|
|
38
61
|
declare function renderBadge(value: string | number | null | undefined): VNode | null;
|
|
39
62
|
/** 绿色圆角徽标(数值类) */
|
|
@@ -48,4 +71,4 @@ declare const renderVerifyStatus: (v: string | number | null | undefined) => JhT
|
|
|
48
71
|
/** 渲染操作列按钮组(图标 + 胶囊 + 文字链接,自动 stopPropagation) */
|
|
49
72
|
declare function renderOps(items: OpItem[]): VNode;
|
|
50
73
|
|
|
51
|
-
export { AUDIT_STATUS_MAP as A, ENABLE_STATUS_MAP as E, RATING_LEVEL_COLORS as R, VERIFY_STATUS_MAP as V, registerDictColorMaps as a, renderDictClassifyTag as b,
|
|
74
|
+
export { AUDIT_STATUS_MAP as A, ENABLE_STATUS_MAP as E, RATING_LEVEL_COLORS as R, VERIFY_STATUS_MAP as V, registerDictColorMaps as a, renderDictClassifyTag as b, AUTO_CLASSIFY_RULES as c, AUTO_STATUS_RULES as d, autoTagTypeByLabel as e, renderAuditStatus as f, renderAutoTag as g, renderAutoTagByLabel as h, renderBadge as i, renderClassifyTag as j, renderCountBadge as k, renderDangerText as l, renderEnableStatus as m, renderOps as n, renderRatingLevel as o, renderTagNode as p, renderTagSlot as q, registerDictColorMap as r, setDictResolver as s, renderVerifyStatus as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agile-team/wl-skills-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "企业级 UI 风格对齐框架 — Vue + Element Plus 项目通用化妆/原生双模式(tokens / element / vendors / layouts / runtime / scanner / fixer / skills)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./es/index.js",
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# 规范 06:存量改造踩坑沉淀(Legacy Migration Lessons)
|
|
2
|
+
|
|
3
|
+
> 来源:wl-ui-ep(危废/环保子系统)存量改造实战验证,2026-08。
|
|
4
|
+
> 每条都经历过"线上翻车 → 定位 → 修复 → 验证"闭环,新项目直接受益,不再重踩。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. AG Grid 二级(分组)表头不渲染
|
|
9
|
+
|
|
10
|
+
**症状**:列定义带 `children` 的分组列,渲染出来"扁平成一级",分组行消失。
|
|
11
|
+
|
|
12
|
+
**根因**:全局样式对 `.ag-header-row` 强制了 `height: auto !important`(或任意强制行高)。
|
|
13
|
+
ag-grid 内部按变量计算分组行高与各行 `top` 定位,强制 height 让分组行高度算成 0。
|
|
14
|
+
|
|
15
|
+
**正确姿势**(已固化到 `vendors/_ag-grid.scss`):
|
|
16
|
+
|
|
17
|
+
```scss
|
|
18
|
+
// 变量驱动,行高交给 ag-grid
|
|
19
|
+
.ag-root-wrapper {
|
|
20
|
+
--ag-header-height: 36px;
|
|
21
|
+
--ag-group-header-height: 36px;
|
|
22
|
+
}
|
|
23
|
+
// 分组兜底:真实存在分组行时强制两行各 36px(:has 只在分组时命中)
|
|
24
|
+
.ag-header:has(.ag-header-row-column-group) { /* height: 2×36 */ }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**守门**:`npm run check:scss` 含反模式扫描,包内出现 `.ag-header-row` 强制 height 直接报错。
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 2. 滚动条悬停不显示 / 灰色不主题色
|
|
32
|
+
|
|
33
|
+
**症状**:容器 hover 时滚动条不出现;或滚动条是灰的、与品牌色无关。
|
|
34
|
+
|
|
35
|
+
**根因**:
|
|
36
|
+
- 「容器:hover 直选 `::-webkit-scrollbar-thumb`」在部分 Chromium 版本**不触发滚动条重绘**;
|
|
37
|
+
- 灰色系配色没接品牌 token。
|
|
38
|
+
|
|
39
|
+
**正确姿势**(已固化,双轨):
|
|
40
|
+
|
|
41
|
+
```scss
|
|
42
|
+
// a) Chrome 121+ / Firefox:标准属性,容器 hover 换值必定生效
|
|
43
|
+
.box { scrollbar-width: thin; scrollbar-color: transparent transparent; }
|
|
44
|
+
.box:hover { scrollbar-color: var(--el-color-primary) transparent; }
|
|
45
|
+
// b) 旧 Chromium:webkit 伪元素 + CSS 变量继承(继承链更新可靠触发重绘)
|
|
46
|
+
.box { --wk-sb-thumb: transparent; }
|
|
47
|
+
.box:hover { --wk-sb-thumb: var(--el-color-primary); }
|
|
48
|
+
.box::-webkit-scrollbar-thumb { background-color: var(--wk-sb-thumb); }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
交互标准:**默认隐藏 → 悬停容器显示主题色(单档)→ 离开即隐藏**。不做深浅两档。
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 3. 表头/内容默认居中,属性可退出
|
|
56
|
+
|
|
57
|
+
**约定**:列定义不写 `align` 时默认表头+内容居中;显式声明 `align: "left"` 等以列为准。
|
|
58
|
+
|
|
59
|
+
**固化**:`runtime` 的 `normalizeColumnAlignmentsWith(cols, { defaultAlign: "center" })`:
|
|
60
|
+
无显式 align/cellStyle/headerClass 的列补齐默认居中(含表头 class 桥接,兼容共享
|
|
61
|
+
AG 适配层只认 class 的场景),递归分组 children;存量项目保持
|
|
62
|
+
`normalizeColumnAlignments(cols)` 不传 options 即不补齐,向后兼容。
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 4. 状态列 Tag:文案语义自动判色
|
|
67
|
+
|
|
68
|
+
**场景**:存量项目几十个列表页、上百个字典列,逐字段配颜色表不现实。
|
|
69
|
+
|
|
70
|
+
**固化**:`renderAutoTag(value, dictKey, fieldName?)` / `renderAutoTagByLabel(label, fieldName?)`
|
|
71
|
+
按字典渲染出的**文案关键词**判色,零配色表:
|
|
72
|
+
|
|
73
|
+
| 文案关键词 | 效果 |
|
|
74
|
+
|---|---|
|
|
75
|
+
| 驳回/停用/作废/超标/逾期/异常… | 实心 danger |
|
|
76
|
+
| 已完成/正常/合格/已审批/启用… | 实心 success |
|
|
77
|
+
| 待/进行中/审批中/整改中/预警… | 实心 warning |
|
|
78
|
+
| 新建/草稿/未开始/历史… | 实心 info |
|
|
79
|
+
| XX类型/形态(气态/液态/固态…) | 镂空 Tag(视觉权重低于状态) |
|
|
80
|
+
| 单位/职务/周期等中性词 | **原样纯文本**(零视觉变化兜底) |
|
|
81
|
+
|
|
82
|
+
规则表 `AUTO_STATUS_RULES` / `AUTO_CLASSIFY_RULES` 已导出,可按项目扩展。
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 5. 操作列图标:默认统一浅主题蓝,悬停出语义色
|
|
87
|
+
|
|
88
|
+
**定案**:查看/编辑/删除图标**默认一律浅主题蓝**(整列安静不花哨),**悬停**才显示
|
|
89
|
+
各自语义色——查看蓝、编辑黄、删除红。三类图标静态各涂一色被业务明确否决(太花)。
|
|
90
|
+
|
|
91
|
+
编辑 hover 用警示黄而非绿:与查看蓝/删除红拉开三色区分,绿留给成功/审核语义。
|
|
92
|
+
(已固化到 `vendors/_base-components.scss` 的 `jh-op-*`。)
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 6. 禁用按钮可辨识
|
|
97
|
+
|
|
98
|
+
**坑**:「语义按钮统一白字」规则若不带 `:not(.is-disabled)`,禁用态白字叠灰底文字消失。
|
|
99
|
+
|
|
100
|
+
**正确姿势**:白字规则排除 `.is-disabled`;禁用态用**语义淡色**——语义 light-8 浅底 +
|
|
101
|
+
light-5 文字(各语义色按钮禁用后仍可辨识"这是哪类按钮")。已固化到 `element/_button.scss`。
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 7. 搜索区间距标准
|
|
106
|
+
|
|
107
|
+
| 位置 | 标准值 |
|
|
108
|
+
|---|---|
|
|
109
|
+
| 搜索项之间(横向) | 16px |
|
|
110
|
+
| 搜索区容器左右 padding | 12px |
|
|
111
|
+
| label ↔ 控件 | 10px |
|
|
112
|
+
| 行间(纵向) | 6px |
|
|
113
|
+
|
|
114
|
+
(`vendors/_base-query-toolbar.scss` 已按此标准实现。)
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 8. 分页器位置
|
|
119
|
+
|
|
120
|
+
表格**右侧下方**:`.list-page__pager { display:flex; justify-content:flex-end }`
|
|
121
|
+
(`layouts/_list-page.scss` 已固化)。不允许分页器贴着表格左缘或顶在表格正下方左侧。
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 9. 样式污染规避(联邦门户共存场景)
|
|
126
|
+
|
|
127
|
+
**教训**(多子系统经门户联邦挂载、共享同一 document):
|
|
128
|
+
|
|
129
|
+
1. **`:root` / `body` / `#app` 是全体共享锚点**——在多子系统门户里 `#app` 是门户的容器,
|
|
130
|
+
不是自己子系统的。写在这三类锚点上的规则等于泼向所有子系统。
|
|
131
|
+
2. **token 互相剥除**:两个子系统都往 `:root body` 写 `--el-color-*` 且带 `!important`
|
|
132
|
+
时,后加载者胜——先进入的子系统皮肤被剥(真实事故:删除按钮红底被剥成白字白底)。
|
|
133
|
+
3. **防外溢固化**:怕被外来样式污染的自身组件,锚定**项目独有类名** + `!important`
|
|
134
|
+
(如 divider 间距、图标字号),别人命中不了、自己稳定。
|
|
135
|
+
|
|
136
|
+
**正确姿势**:规则尽量落在**项目/组件独有类**或本包 `managed-scope`(含
|
|
137
|
+
`data-wl-ui-skin="off"` 豁免)内;需要全局 token 时只写一遍且接受统一皮肤源。
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 10. 字典列扫描审计机制
|
|
142
|
+
|
|
143
|
+
存量项目"哪些列该上 Tag 而没上"靠肉眼不可维护。配套审计脚本思路(wl-skills-kit
|
|
144
|
+
提供 `audit-status-columns.mjs`):
|
|
145
|
+
|
|
146
|
+
- 扫描列定义中 `formatter: (row) => xDict.fmt(row.field)` 写法;
|
|
147
|
+
- 按列 label 语义分级:状态/类型类 → 建议转 `renderAutoTag`;中性(单位/职务)→ 保持;
|
|
148
|
+
- `--fix` 自动转换 + 补 import + 清理无引用 formatter;转换的 dict/字段取自 const 定义
|
|
149
|
+
(无歧义源),最坏情况走中性纯文本兜底,零风险。
|
|
@@ -42,6 +42,10 @@
|
|
|
42
42
|
--ag-font-family: var(--wk-font-family-sans);
|
|
43
43
|
--ag-row-height: 26px;
|
|
44
44
|
--ag-header-height: 36px;
|
|
45
|
+
// 分组表头(二级表头)行高:单列声明,ag-grid 内部按层级定位各行 top。
|
|
46
|
+
// 教训(wl-ui-ep ea6ab20):不要用 .ag-header-row { height:auto !important }
|
|
47
|
+
// 之类的强制行高——会破坏分组行高内部计算,分组行算成 0 → 二级表头不渲染。
|
|
48
|
+
--ag-group-header-height: 36px;
|
|
45
49
|
--ag-cell-horizontal-padding: 8px;
|
|
46
50
|
--ag-checkbox-checked-color: var(--el-color-primary);
|
|
47
51
|
--ag-input-focus-border-color: var(--el-color-primary);
|
|
@@ -59,8 +63,21 @@
|
|
|
59
63
|
min-height: 36px !important;
|
|
60
64
|
}
|
|
61
65
|
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
// 行高由上方 --ag-header-height / --ag-group-header-height 变量驱动,
|
|
67
|
+
// 不再强制 .ag-header-row 的 height(强制行高与 ag-grid 分组行定位冲突)。
|
|
68
|
+
// 分组表头兜底(wl-ui-ep 76f9dfa 验证):真实存在分组行时强制两行各 36px,
|
|
69
|
+
// 兼容共享 AG 适配层不透传 groupHeaderHeight 的存量场景;:has 只在分组时命中。
|
|
70
|
+
.ag-header:has(.ag-header-row-column-group) {
|
|
71
|
+
height: calc(var(--ag-header-height, 36px) * 2) !important;
|
|
72
|
+
min-height: calc(var(--ag-header-height, 36px) * 2) !important;
|
|
73
|
+
}
|
|
74
|
+
.ag-header:has(.ag-header-row-column-group) .ag-header-row-column-group {
|
|
75
|
+
top: 0 !important;
|
|
76
|
+
height: var(--ag-header-height, 36px) !important;
|
|
77
|
+
}
|
|
78
|
+
.ag-header:has(.ag-header-row-column-group) .ag-header-row-column {
|
|
79
|
+
top: var(--ag-header-height, 36px) !important;
|
|
80
|
+
height: var(--ag-header-height, 36px) !important;
|
|
64
81
|
}
|
|
65
82
|
|
|
66
83
|
.ag-header-cell {
|
|
@@ -289,36 +306,56 @@
|
|
|
289
306
|
letter-spacing: 0.02em;
|
|
290
307
|
}
|
|
291
308
|
|
|
292
|
-
// ──
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
309
|
+
// ── 滚动条:默认隐藏,悬停显示主题色(双轨实现) ────────────────────────────
|
|
310
|
+
// 教训(wl-ui-ep 695d664):灰色系/「容器:hover 直选伪元素」在部分 Chromium
|
|
311
|
+
// 不触发滚动条重绘,导致悬停不显示。双轨:
|
|
312
|
+
// a) Chrome 121+ / Firefox 走标准 scrollbar-color(容器 hover 换值必定生效);
|
|
313
|
+
// b) 旧 Chromium 走 webkit 伪元素 + CSS 变量继承(--wk-sb-thumb 从容器继承,
|
|
314
|
+
// 继承链更新可靠触发重绘)。
|
|
315
|
+
.ag-body-viewport {
|
|
316
|
+
scrollbar-width: thin;
|
|
317
|
+
scrollbar-color: transparent transparent;
|
|
318
|
+
--wk-sb-thumb: transparent;
|
|
319
|
+
&:hover {
|
|
320
|
+
scrollbar-color: var(--el-color-primary) transparent;
|
|
321
|
+
--wk-sb-thumb: var(--el-color-primary);
|
|
322
|
+
}
|
|
299
323
|
}
|
|
300
|
-
.ag-body-viewport::-webkit-scrollbar
|
|
301
|
-
|
|
324
|
+
.ag-body-viewport::-webkit-scrollbar {
|
|
325
|
+
width: 6px;
|
|
302
326
|
}
|
|
303
327
|
.ag-body-viewport::-webkit-scrollbar-track {
|
|
304
328
|
background: transparent;
|
|
305
329
|
}
|
|
330
|
+
.ag-body-viewport::-webkit-scrollbar-thumb {
|
|
331
|
+
background-color: var(--wk-sb-thumb);
|
|
332
|
+
border-radius: 6px;
|
|
333
|
+
}
|
|
306
334
|
|
|
335
|
+
// 横向滚动条:静默 4px → 悬停展开 8px 主题色
|
|
336
|
+
.ag-body-horizontal-scroll-viewport {
|
|
337
|
+
--wk-sbh-thumb: transparent;
|
|
338
|
+
&:hover {
|
|
339
|
+
--wk-sbh-thumb: var(--el-color-primary);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
307
342
|
.ag-body-horizontal-scroll-viewport::-webkit-scrollbar {
|
|
308
343
|
height: 4px;
|
|
309
344
|
}
|
|
310
345
|
.ag-body-horizontal-scroll-viewport::-webkit-scrollbar-track {
|
|
311
|
-
background:
|
|
346
|
+
background: rgba(0, 0, 0, 0.04);
|
|
347
|
+
border-radius: 4px;
|
|
312
348
|
}
|
|
313
349
|
.ag-body-horizontal-scroll-viewport::-webkit-scrollbar-thumb {
|
|
314
|
-
background-color:
|
|
315
|
-
border-radius:
|
|
350
|
+
background-color: var(--wk-sbh-thumb);
|
|
351
|
+
border-radius: 4px;
|
|
316
352
|
}
|
|
317
|
-
.ag-body-horizontal-scroll-viewport:hover::-webkit-scrollbar
|
|
318
|
-
|
|
353
|
+
.ag-body-horizontal-scroll-viewport:hover::-webkit-scrollbar {
|
|
354
|
+
height: 8px;
|
|
319
355
|
}
|
|
320
|
-
.ag-body-horizontal-scroll-viewport:hover::-webkit-scrollbar-
|
|
321
|
-
background
|
|
356
|
+
.ag-body-horizontal-scroll-viewport:hover::-webkit-scrollbar-track {
|
|
357
|
+
background: rgba(var(--el-color-primary-rgb), 0.08);
|
|
358
|
+
border-radius: 4px;
|
|
322
359
|
}
|
|
323
360
|
|
|
324
361
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
@@ -54,11 +54,11 @@
|
|
|
54
54
|
background: rgba(var(--el-color-primary-rgb), 0.09);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
// 编辑 — hover
|
|
57
|
+
// 编辑 — hover 警示黄(wl-ui-ep 定案:查看蓝/编辑黄/删除红三色区分,原绿与成功语义撞色)
|
|
58
58
|
&.jh-op-edit {
|
|
59
59
|
&:hover:not(:disabled) {
|
|
60
|
-
color: var(--el-color-
|
|
61
|
-
background: rgba(
|
|
60
|
+
color: var(--el-color-warning);
|
|
61
|
+
background: rgba(234, 154, 19, 0.12);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
// 删除/作废 — hover 红
|