diff --git a/apps/web/src/features/gov-archive/internal/panel.tsx b/apps/web/src/features/gov-archive/internal/panel.tsx
index 5201024..fc58e42 100644
--- a/apps/web/src/features/gov-archive/internal/panel.tsx
+++ b/apps/web/src/features/gov-archive/internal/panel.tsx
@@ -4,18 +4,25 @@
* 占位页只做一件事:**如实说它还没有**。不摆假数据、不摆点不动的按钮 ——
* 空着比装着强(与死信卡、沟通记录同一条规矩)。
*/
-import { Card, Clear } from '@web-shared/gov/primitives.tsx';
+import { Card, Note, Rows } from '@web-shared/gov/primitives.tsx';
import type { Nav } from '@web-shared/gov/gov-route.ts';
export function ArchiveHome({ nav }: { tab: string; nav: Nav }) {
void nav;
return (
-
- 这里将放企业的资料与文档 —— 规范、图纸、样例、外部材料,供活动按需引用。
-
- 目前还没有建:没有存储、没有检索、没有引用机制。等要用到的第一条流出现时再动手。
-
+ {/* 中性口吻,不是绿对勾 —— 「还没建」不是一件办妥了的事 */}
+
+ 这里将放企业的资料与文档:规范、图纸、样例、外部材料,供活动按需引用。
+ 等第一条真要用到资料的流出现时再动手 —— 那时才知道它该按什么检索、被谁引用。
+
+
);
}
diff --git a/apps/web/src/shared/gov/__tests__/zone-icons.test.ts b/apps/web/src/shared/gov/__tests__/zone-icons.test.ts
new file mode 100644
index 0000000..59d67ca
--- /dev/null
+++ b/apps/web/src/shared/gov/__tests__/zone-icons.test.ts
@@ -0,0 +1,40 @@
+/**
+ * 导航表里的图标名**必须在册** —— 这条实测抓出来的洞(2026-07-29)。
+ *
+ * `Ico` 从前查不到名字就返回一个**空 svg**:左轨那一格什么都不画,
+ * 而周围八格都有图标,看上去像布局塌了。知识库区就这么空着上了一版,
+ * 是用户指出来的(「知识库至少做个图标啊」)。
+ *
+ * 图标名是**手写的字符串**,没有类型能拦住笔误;那就用一条测试逐格对表。
+ */
+import { describe, expect, it } from 'vitest';
+import { hasIco } from '@ui';
+import { TABS, ZM, ZONES } from '../gov-route.ts';
+
+describe('导航图标名在册', () => {
+ it('左轨每一区的图标都画得出来', () => {
+ const missing = ZONES.filter((z) => !hasIco(z.icon)).map((z) => `${z.label}(${z.icon})`);
+ expect(missing, '左轨缺图标的区').toEqual([]);
+ });
+
+ it('区头每一区的图标都画得出来', () => {
+ const missing = Object.entries(ZM)
+ .filter(([, m]) => !hasIco(m.icon))
+ .map(([k, m]) => `${k}(${m.icon})`);
+ expect(missing, '区头缺图标的区').toEqual([]);
+ });
+
+ it('区内页签的图标都画得出来', () => {
+ const missing = Object.entries(TABS).flatMap(([zone, tabs]) =>
+ tabs.filter((t) => !hasIco(t.ico)).map((t) => `${zone}/${t.key}(${t.ico})`),
+ );
+ expect(missing, '页签缺图标的格').toEqual([]);
+ });
+});
+
+describe('查名本身管用', () => {
+ it('在册的答在、不在册的答不在 —— 否则上面三条测试是空转的', () => {
+ expect(hasIco('library'), '知识库那格的图标').toBe(true);
+ expect(hasIco('这个名字不存在')).toBe(false);
+ });
+});
diff --git a/packages/ui-kit/src/Ico.tsx b/packages/ui-kit/src/Ico.tsx
index 37a44a4..330bcfd 100644
--- a/packages/ui-kit/src/Ico.tsx
+++ b/packages/ui-kit/src/Ico.tsx
@@ -1,6 +1,5 @@
// 共享内联 lucide 图标(会话面板 / 工作区驾驶舱 / 设置等共用)。
-export function Ico({ name, s = 18 }: { name: string; s?: number }) {
- const p: Record = {
+const GLYPHS: Record = {
"chevron-right": (),
"chevron-down": (),
check: (),
@@ -125,11 +124,31 @@ export function Ico({ name, s = 18 }: { name: string; s?: number }) {
"redo-2": (<>>),
"maximize-2": (<>>),
x: (<>>),
+ library: (<>>),
"log-out": (<>>),
- };
+};
+
+/**
+ * 名字在不在册 —— 给守闸的测试用。
+ * 导航表里写错一个名字,从前只会在界面上留一格**看不见的空白**(知识库那格就这么空了一版);
+ * 现在有测试逐个对表,写错当场红。
+ */
+export function hasIco(name: string): boolean {
+ return Object.hasOwn(GLYPHS, name);
+}
+
+/**
+ * 查无此名时画一枚**虚线空框**(字体界的「豆腐块」),不画空气 ——
+ * 缺图标得看得见才修得掉。
+ */
+const MISSING = (
+
+);
+
+export function Ico({ name, s = 18 }: { name: string; s?: number }) {
return (
);
}
diff --git a/packages/ui-kit/src/index.ts b/packages/ui-kit/src/index.ts
index 87c7f75..ad67fa2 100644
--- a/packages/ui-kit/src/index.ts
+++ b/packages/ui-kit/src/index.ts
@@ -4,6 +4,6 @@
export type { ViewContainerProps } from './ViewContainer.tsx';
export { ViewContainer } from './ViewContainer.tsx';
export { ViewBlocks } from './ViewBlocks.tsx';
-export { Ico } from './Ico.tsx';
+export { Ico, hasIco } from './Ico.tsx';
export const UI_KIT_VERSION = '0.1.0-m6';