diff --git a/CHANGELOG.md b/CHANGELOG.md index ab3f424e..86752ce7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ ### 变更 +- 组织页改为应用内多标签浏览器(标签栏 + 地址栏 + iframe),进入时打开本机 openXYOS。`target=_blank` / `window.open` 收入应用内标签,不再弹出系统新窗口;去掉「在新窗口打开」。 - 组织页顶部蓝色状态栏增加「下载最新源码」主按钮:点击后先打开系统文件夹选择器,再下载最新 openXYOS 主分支源码。不必先打开「组织OS管理」。成功提示保存路径;管理抽屉仍保留同一操作作为次要入口。 - 对话与工作区共用一份列表:侧栏「对话」进入工作区「对话」标签;点开一条才进入聊天画布。工作区侧栏默认打开「项目」标签。 - 用户可见用词对齐:员工 = 已入编部门;同事 = 同一组织里一起聊的人;专家 / 智能助手 = 尚未入编的帮手。个性化「子智能体」改为「专项助手」。群聊选择「同事或智能助手」。 diff --git a/dashboard/src/locales/en.json b/dashboard/src/locales/en.json index bb0a03fa..bc760a37 100644 --- a/dashboard/src/locales/en.json +++ b/dashboard/src/locales/en.json @@ -97,6 +97,10 @@ "optional": "Optional", "embedTitle": "Organization console", "openSidecar": "Open in new tab", + "browserNewTab": "New tab", + "addressPlaceholder": "Enter a URL", + "addressGo": "Go", + "homeTabTitle": "openXYOS", "loadFailed": "Could not load organization module status", "saveFailed": "Could not update organization module", "actionFailed": "Action failed", diff --git a/dashboard/src/locales/zh.json b/dashboard/src/locales/zh.json index 7f626bc4..49547e91 100644 --- a/dashboard/src/locales/zh.json +++ b/dashboard/src/locales/zh.json @@ -97,6 +97,10 @@ "optional": "可选", "embedTitle": "组织控制台", "openSidecar": "新窗口打开", + "browserNewTab": "新标签", + "addressPlaceholder": "输入网址", + "addressGo": "前往", + "homeTabTitle": "openXYOS", "loadFailed": "无法加载组织模块状态", "saveFailed": "无法更新组织模块", "actionFailed": "操作失败", diff --git a/dashboard/src/pages/Organization/OrgMiniBrowser.tsx b/dashboard/src/pages/Organization/OrgMiniBrowser.tsx new file mode 100644 index 00000000..1f7e97af --- /dev/null +++ b/dashboard/src/pages/Organization/OrgMiniBrowser.tsx @@ -0,0 +1,131 @@ +import { useMemo, type MutableRefObject } from "react"; +import { Button, Input } from "antd"; +import { useTranslation } from "react-i18next"; +import { ChromeTabBar } from "../../components/ChromeTabBar"; +import { + buildEmbedSrc, + iframeSandboxFor, + type OrgBrowserTab, +} from "./orgBrowser"; +import styles from "./Organization.module.less"; + +type OrgMiniBrowserProps = { + tabs: OrgBrowserTab[]; + activeId: string; + addressValue: string; + sidecarOrigin: string; + disabledKeys: string[]; + previewNonce: string; + sidecarUp: boolean; + previewBlank: boolean; + iframeRefs: MutableRefObject>; + onAddressChange: (value: string) => void; + onAddressSubmit: () => void; + onSelectTab: (id: string) => void; + onCloseTab: (id: string) => void; + onNewTab: () => void; + onFrameLoad: () => void; +}; + +export default function OrgMiniBrowser({ + tabs, + activeId, + addressValue, + sidecarOrigin, + disabledKeys, + previewNonce, + sidecarUp, + previewBlank, + iframeRefs, + onAddressChange, + onAddressSubmit, + onSelectTab, + onCloseTab, + onNewTab, + onFrameLoad, +}: OrgMiniBrowserProps) { + const { t } = useTranslation(); + const chromeTabs = useMemo( + () => + tabs.map((tab) => ({ + key: tab.id, + label: tab.title, + tooltip: tab.url, + closable: tabs.length > 1, + })), + [tabs], + ); + + return ( +
+ { + event.preventDefault(); + onCloseTab(key); + }} + onNewTab={onNewTab} + newTabTitle={t("organization.browserNewTab")} + /> +
{ + event.preventDefault(); + onAddressSubmit(); + }} + > + onAddressChange(event.target.value)} + placeholder={t("organization.addressPlaceholder")} + aria-label={t("organization.addressPlaceholder")} + /> + +
+
+ {!sidecarUp && ( +
+ {t("organization.previewOffline")} +
+ )} + {previewBlank && ( +
+ {t("organization.previewBlank")} +
+ )} + {tabs.map((tab) => { + const src = buildEmbedSrc(tab.srcUrl, { + sidecarOrigin, + disabledKeys, + nonce: previewNonce, + }); + const active = tab.id === activeId; + return ( +