diff --git a/web/hwlab-cloud-web/scripts/r6-architecture-parity.test.ts b/web/hwlab-cloud-web/scripts/r6-architecture-parity.test.ts
index 50ba2681..cfef3323 100644
--- a/web/hwlab-cloud-web/scripts/r6-architecture-parity.test.ts
+++ b/web/hwlab-cloud-web/scripts/r6-architecture-parity.test.ts
@@ -35,11 +35,14 @@ test("R6 useForm normalizes nested API errors for toast/error surfaces", () => {
assert.equal(messageFromError({ reason: "blocked_by_gate" }), "blocked_by_gate");
});
-test("R6 common module map keeps HWLAB views on shared table/dialog/form primitives", () => {
+test("R6 common module map keeps HWLAB views on shared console primitives", () => {
assert.equal(fs.existsSync(path.join(rootDir, "src/components/common/DataTable.vue")), false, "legacy DataTable should stay removed after DataGrid migration");
const expectations: Array<[string, string[]]> = [
["src/views/admin/ProviderProfilesView.vue", ["AsyncBoundary", "DataGrid", "ResourceCollection", "BaseDialog", "ConfirmDialog", "TablePageLayout", "useTableLoader", "useForm"]],
- ["src/components/access/AccessMatrixPanel.vue", ["AsyncBoundary", "DataGrid", "ResourceCollection", "BoundedWorkspace", "TablePageLayout"]],
+ ["src/components/access/AccessMatrixPanel.vue", ["AsyncBoundary", "OperationsWorkspace", "EntityIndex", "InspectorPanel", "ViewModeSwitch"]],
+ ["src/views/admin/SecretsView.vue", ["AsyncBoundary", "OperationsWorkspace", "EntityIndex", "FactPath", "ViewModeSwitch"]],
+ ["src/views/admin/UsersView.vue", ["AsyncBoundary", "OperationsWorkspace", "EntityIndex", "InspectorPanel", "ViewModeSwitch"]],
+ ["src/views/admin/BillingView.vue", ["AsyncBoundary", "OperationsWorkspace", "EntityIndex", "InspectorPanel", "ViewModeSwitch"]],
["src/views/GateView.vue", ["AsyncBoundary", "DataGrid", "Pagination", "BaseDialog", "TablePageLayout", "useTableLoader"]],
["src/views/PerformanceView.vue", ["AsyncBoundary", "DataGrid", "TablePageLayout", "useTableLoader"]],
["src/views/SkillsView.vue", ["AsyncBoundary", "DataGrid", "ResourceCollection", "VirtualList", "BaseDialog", "TablePageLayout", "useTableLoader", "useForm"]]
@@ -49,9 +52,23 @@ test("R6 common module map keeps HWLAB views on shared table/dialog/form primiti
const source = read(relativePath);
for (const term of terms) assert.match(source, new RegExp(`\\b${term}\\b`, "u"), `${relativePath} should use ${term}`);
assert.doesNotMatch(source, /
{
+ const iconSource = read("src/components/console/ConsoleIcon.vue");
+ for (const icon of ["list", "grid", "matrix", "flow", "queue", "report"]) assert.match(iconSource, new RegExp(`\\b${icon}:`, "u"), `ConsoleIcon should define ${icon}`);
+ assert.doesNotMatch(iconSource, /paths\[props\.name\]\s*\|\|\s*paths\.overview/u, "unknown icons must not silently masquerade as overview");
+ const entityIndexSource = read("src/components/console/EntityIndex.vue");
+ assert.match(entityIndexSource, / {
const issueBody = readIssueBodyFixture();
assert.match(issueBody, /Wei-Shaw\/sub2api@v0\.1\.136=a2f76e4/u);
diff --git a/web/hwlab-cloud-web/src/components/access/AccessMatrixPanel.vue b/web/hwlab-cloud-web/src/components/access/AccessMatrixPanel.vue
index 2503ba04..58fc4002 100644
--- a/web/hwlab-cloud-web/src/components/access/AccessMatrixPanel.vue
+++ b/web/hwlab-cloud-web/src/components/access/AccessMatrixPanel.vue
@@ -83,8 +83,8 @@ function valueText(value: unknown): string { return typeof value === "string" &&
-
-
+
+
用户{{ tool.label }}