diff --git a/src/components/CompanySearch.jsx b/src/components/CompanySearch.jsx
new file mode 100644
index 0000000..9da1f51
--- /dev/null
+++ b/src/components/CompanySearch.jsx
@@ -0,0 +1,102 @@
+import { useState } from 'react';
+import {
+ Autocomplete,
+ AutocompleteInput,
+ AutocompleteContent,
+ AutocompleteEmpty,
+ AutocompleteList,
+ AutocompleteItem,
+} from '@appica/ui-react/autocomplete';
+import { BuildingSkyscraper, BuildingCommunity, UsersGroup, Rocket, Search } from '@appica/icons-react';
+
+/* =========================================================
+ 入驻企业搜索(Appica Autocomplete)
+ 按名称搜索企业,显示区域/行业/所在房间
+ ========================================================= */
+
+const ZONE_META = {
+ '加速区': { icon: Rocket, color: '#4c8dff' },
+ '国际区': { icon: BuildingCommunity, color: '#22d3ee' },
+ '成长区': { icon: UsersGroup, color: '#34d399' },
+ 'OPC 空间': { icon: BuildingSkyscraper, color: '#fbbf24' },
+ '孵化加速区': { icon: Rocket, color: '#4c8dff' },
+ '国际创客区': { icon: BuildingCommunity, color: '#22d3ee' },
+ '成长苗圃区': { icon: UsersGroup, color: '#34d399' },
+};
+
+export default function CompanySearch({ companies }) {
+ // value 存字符串(企业名),onValueChange 收到的是 item 对象 → 取 name
+ const [value, setValue] = useState('');
+ const selected = companies.find((c) => c.name === value);
+
+ return (
+
+
setValue(typeof v === 'string' ? v : (v && v.name) || '')}
+ itemToStringValue={(item) => (item && item.name) || ''}
+ clearable
+ icon
+ size="md"
+ >
+ {
+ const meta = ZONE_META[selected.zone];
+ const Ico = meta ? meta.icon : BuildingSkyscraper;
+ return ;
+ })()
+ : }
+ />
+
+ 未找到匹配企业
+
+ {(item) => {
+ const meta = ZONE_META[item.zone];
+ const ZoneIco = meta ? meta.icon : BuildingSkyscraper;
+ return (
+
+
+
+
+
+
+ {item.name}
+ {item.zone} · {item.industry}
+
+ {item.room}
+
+
+ );
+ }}
+
+
+
+
+ {selected && (
+
+
+ {selected.name}
+
+ {selected.zone}
+
+
+
+ 行业 {selected.industry}
+ 房间 {selected.room}
+ 状态 在驻
+
+
+ )}
+
+ );
+}
diff --git a/src/components/Icons.jsx b/src/components/Icons.jsx
new file mode 100644
index 0000000..13a8fc9
--- /dev/null
+++ b/src/components/Icons.jsx
@@ -0,0 +1,98 @@
+/* =========================================================
+ 图标库:Appica Icons(@appica/icons-react)
+ 禁止使用表情图标,统一从这里引用 SVG 图标
+ ========================================================= */
+import {
+ Bolt, Wrench, BuildingSkyscraper, Users, UsersGroup, Coin, Radio, Trophy,
+ Flask, BuildingFactory, Diamond, GraduationCap, ChartLine, ChartArea,
+ Clock, Robot, Broadcast, Message, Briefcase, Flame, Leaf, Star,
+ Check, Gauge, Cpu, Server, Database, Sparkles, Bulb, Settings,
+ Heart, Pill, Dna, Microscope, Atom, MapPin, Flag, Award, Medal,
+ History, Drone, Plane, Rocket, Satellite, Wallet, UserPlus, Activity,
+} from '@appica/icons-react';
+
+/* 名称 → 图标组件映射(推荐的调用方式:icon="bolt") */
+const NAME_MAP = {
+ bolt: Bolt,
+ wrench: Wrench,
+ building: BuildingSkyscraper,
+ 'building-skyscraper': BuildingSkyscraper,
+ 'building-community': UsersGroup,
+ users: Users,
+ 'users-group': UsersGroup,
+ coin: Coin,
+ radio: Radio,
+ trophy: Trophy,
+ flask: Flask,
+ factory: BuildingFactory,
+ 'building-factory': BuildingFactory,
+ diamond: Diamond,
+ graduation: GraduationCap,
+ 'graduation-cap': GraduationCap,
+ 'chart-line': ChartLine,
+ 'chart-area': ChartArea,
+ clock: Clock,
+ robot: Robot,
+ broadcast: Broadcast,
+ message: Message,
+ briefcase: Briefcase,
+ flame: Flame,
+ leaf: Leaf,
+ star: Star,
+ check: Check,
+ gauge: Gauge,
+ cpu: Cpu,
+ server: Server,
+ database: Database,
+ sparkles: Sparkles,
+ bulb: Bulb,
+ settings: Settings,
+ heart: Heart,
+ pill: Pill,
+ dna: Dna,
+ microscope: Microscope,
+ atom: Atom,
+ 'map-pin': MapPin,
+ flag: Flag,
+ award: Award,
+ medal: Medal,
+ history: History,
+ drone: Drone,
+ plane: Plane,
+ rocket: Rocket,
+ satellite: Satellite,
+ wallet: Wallet,
+ 'user-plus': UserPlus,
+ activity: Activity,
+};
+
+/**
+ * Icon —— 统一图标组件
+ * @param {string} name 图标标识(emoji 兼容 或 名称,如 "bolt" / "chart-line")
+ * @param {number|string} size
+ * @param {number} strokeWidth
+ * @param {string} className
+ */
+export default function Icon({ name, size = 18, strokeWidth = 1.6, className = '', ...rest }) {
+ const Comp = NAME_MAP[name] || null;
+ if (!Comp) return null;
+ return (
+
+ );
+}
+
+/* 独立导出的常用图标(组件内直接引用) */
+export {
+ Bolt, Wrench, BuildingSkyscraper, Users, Coin, Radio, Trophy,
+ Flask, BuildingFactory, Diamond, GraduationCap, ChartLine, ChartArea,
+ Clock, Robot, Broadcast, Message, Briefcase, Flame, Leaf, Star,
+ Check, Gauge, Cpu, Server, Database, Sparkles, Bulb, Settings,
+ Heart, Pill, Dna, Microscope, Atom, MapPin, Flag, Award, Medal,
+ History, Drone, Plane, Rocket, Satellite, Wallet, UserPlus, Activity,
+};
diff --git a/src/components/PageHeader.jsx b/src/components/PageHeader.jsx
new file mode 100644
index 0000000..c2f754c
--- /dev/null
+++ b/src/components/PageHeader.jsx
@@ -0,0 +1,60 @@
+import { useEffect, useState } from 'react';
+import { useNavigate } from 'react-router-dom';
+import Icon from './Icons';
+
+/* =========================================================
+ 共享页眉 —— 两个大屏页面(数据大屏 / 数字孪生)统一风格
+ 仅通过 props 区分:导航目标、状态文案
+ ========================================================= */
+
+export default function PageHeader({ nav, status = '数据实时' }) {
+ const navigate = useNavigate();
+ const [now, setNow] = useState(new Date());
+
+ useEffect(() => {
+ const iv = setInterval(() => setNow(new Date()), 1000);
+ return () => clearInterval(iv);
+ }, []);
+
+ const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
+ const week = ['日', '一', '二', '三', '四', '五', '六'][now.getDay()];
+ const timeStr = now.toLocaleTimeString('zh-CN', { hour12: false });
+
+ return (
+
+
+
+
+
+
+
昆明市大学生创业园 · OPC 智能园区数字运营中心
+
云南省首家政府主办大学生创业孵化园区 · 空间+孵化+融资+政策+资源+AI赋能+综合服务 七位一体
+
+
+
+ {nav && (
+
+ )}
+
+
+ {status}
+
+
+
{timeStr}
+
{dateStr} 周{week}
+
+
+
+ );
+}