feat(web): update document title
This commit is contained in:
@@ -16,7 +16,7 @@ import {
|
|||||||
ConfigProvider,
|
ConfigProvider,
|
||||||
App as AntdApp
|
App as AntdApp
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { useTranslation } from 'react-i18next';
|
import i18n from 'i18next';
|
||||||
|
|
||||||
import { lightTheme } from './styles/antdThemeConfig.ts'
|
import { lightTheme } from './styles/antdThemeConfig.ts'
|
||||||
import router from './routes';
|
import router from './routes';
|
||||||
@@ -29,11 +29,58 @@ import 'dayjs/plugin/utc'
|
|||||||
import { cookieUtils } from './utils/request';
|
import { cookieUtils } from './utils/request';
|
||||||
import { useUser } from '@/store/user';
|
import { useUser } from '@/store/user';
|
||||||
|
|
||||||
|
import menuJson from '@/store/menu.json';
|
||||||
|
|
||||||
|
type MenuEntry = { path: string; i18nKey: string };
|
||||||
|
|
||||||
|
function flattenMenuEntries(list: any[]): MenuEntry[] {
|
||||||
|
const result: MenuEntry[] = [];
|
||||||
|
for (const item of list) {
|
||||||
|
if (item.path && item.i18nKey && item.type !== 'group') result.push({ path: item.path, i18nKey: item.i18nKey });
|
||||||
|
if (item.subs?.length) result.push(...flattenMenuEntries(item.subs));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const menuEntries: MenuEntry[] = flattenMenuEntries([...menuJson.manage, ...menuJson.space]);
|
||||||
|
|
||||||
|
function pathMatches(pattern: string, path: string): boolean {
|
||||||
|
if (pattern === path) return true;
|
||||||
|
if (pattern.includes(':')) {
|
||||||
|
return new RegExp('^' + pattern.replace(/:[\w-]+/g, '[^/]+') + '$').test(path);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPageTitle(pathname: string): string {
|
||||||
|
const appName = i18n.t('memoryBear');
|
||||||
|
const entry = menuEntries.find(e => pathMatches(e.path, pathname));
|
||||||
|
if (!entry) return appName;
|
||||||
|
return `${i18n.t(entry.i18nKey)} - ${appName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SKIP_TITLE_PATTERNS = [
|
||||||
|
'/user-memory/detail/:id/:type',
|
||||||
|
'/forgetting-engine/:id',
|
||||||
|
'/memory-extraction-engine/:id',
|
||||||
|
'/emotion-engine/:id',
|
||||||
|
'/reflection-engine/:id',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const { t } = useTranslation();
|
|
||||||
const { locale, language, timeZone } = useI18n()
|
const { locale, language, timeZone } = useI18n()
|
||||||
const { checkJump } = useUser();
|
const { checkJump } = useUser();
|
||||||
|
useEffect(() => {
|
||||||
|
const unsubscribe = router.subscribe(({ location }) => {
|
||||||
|
if (SKIP_TITLE_PATTERNS.some(p => pathMatches(p, location.pathname))) return;
|
||||||
|
document.title = getPageTitle(location.pathname);
|
||||||
|
});
|
||||||
|
return () => unsubscribe();
|
||||||
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const authToken = cookieUtils.get('authToken')
|
const authToken = cookieUtils.get('authToken')
|
||||||
if (!authToken && !window.location.hash.includes('#/login') && !window.location.hash.includes('#/conversation/') && !window.location.hash.includes('#/jump') && !window.location.hash.includes('#/invite-register')) {
|
if (!authToken && !window.location.hash.includes('#/login') && !window.location.hash.includes('#/conversation/') && !window.location.hash.includes('#/jump') && !window.location.hash.includes('#/invite-register')) {
|
||||||
@@ -44,7 +91,9 @@ function App() {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = t('memoryBear')
|
if (!SKIP_TITLE_PATTERNS.some(p => pathMatches(p, router.state.location.pathname))) {
|
||||||
|
document.title = getPageTitle(router.state.location.pathname)
|
||||||
|
}
|
||||||
dayjs.locale(language)
|
dayjs.locale(language)
|
||||||
localStorage.setItem('language', language)
|
localStorage.setItem('language', language)
|
||||||
}, [language])
|
}, [language])
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-02 16:24:44
|
* @Date: 2026-02-02 16:24:44
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-02-02 16:24:44
|
* @Last Modified time: 2026-04-14 15:52:57
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* useBreadcrumbManager Hook
|
* useBreadcrumbManager Hook
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useMenu } from '@/store/menu';
|
import { useMenu } from '@/store/menu';
|
||||||
import type { MenuItem } from '@/store/menu';
|
import type { MenuItem } from '@/store/menu';
|
||||||
|
|
||||||
@@ -53,6 +54,7 @@ export interface BreadcrumbOptions {
|
|||||||
export const useBreadcrumbManager = (options?: BreadcrumbOptions) => {
|
export const useBreadcrumbManager = (options?: BreadcrumbOptions) => {
|
||||||
const { allBreadcrumbs, setCustomBreadcrumbs } = useMenu();
|
const { allBreadcrumbs, setCustomBreadcrumbs } = useMenu();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
/** Update breadcrumbs based on current path and type */
|
/** Update breadcrumbs based on current path and type */
|
||||||
const updateBreadcrumbs = useCallback((breadcrumbPath: BreadcrumbPath) => {
|
const updateBreadcrumbs = useCallback((breadcrumbPath: BreadcrumbPath) => {
|
||||||
@@ -336,8 +338,8 @@ export const useBreadcrumbManager = (options?: BreadcrumbOptions) => {
|
|||||||
/** Use different keys based on breadcrumb type to implement independent breadcrumb paths */
|
/** Use different keys based on breadcrumb type to implement independent breadcrumb paths */
|
||||||
const breadcrumbKey = breadcrumbType === 'list' ? 'space' : 'space-detail';
|
const breadcrumbKey = breadcrumbType === 'list' ? 'space' : 'space-detail';
|
||||||
|
|
||||||
|
const lastMenu = customBreadcrumbs[customBreadcrumbs.length - 1]
|
||||||
|
document.title = `${lastMenu.i18nKey ? t(lastMenu.i18nKey) : lastMenu.label} - ${t('memoryBear') }`;
|
||||||
setCustomBreadcrumbs(customBreadcrumbs, breadcrumbKey);
|
setCustomBreadcrumbs(customBreadcrumbs, breadcrumbKey);
|
||||||
}, [setCustomBreadcrumbs, navigate, options?.breadcrumbType, options?.onKnowledgeBaseMenuClick, options?.onKnowledgeBaseFolderClick]);
|
}, [setCustomBreadcrumbs, navigate, options?.breadcrumbType, options?.onKnowledgeBaseMenuClick, options?.onKnowledgeBaseFolderClick]);
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
{ "path": "/application/config/:id", "element": "ApplicationConfig" },
|
{ "path": "/application/config/:id", "element": "ApplicationConfig" },
|
||||||
{ "path": "/application/config/:id/:source", "element": "ApplicationConfig" },
|
{ "path": "/application/config/:id/:source", "element": "ApplicationConfig" },
|
||||||
{ "path": "/user-memory/neo4j/:id", "element": "Neo4jUserMemoryDetail" },
|
{ "path": "/user-memory/neo4j/:id", "element": "Neo4jUserMemoryDetail" },
|
||||||
{ "path": "/statement/:id", "element": "StatementDetail" },
|
|
||||||
{ "path": "/user-memory/detail/:id/:type", "element": "MemoryNodeDetail" },
|
{ "path": "/user-memory/detail/:id/:type", "element": "MemoryNodeDetail" },
|
||||||
{ "path": "/ontology/:id", "element": "OntologyDetail" }
|
{ "path": "/ontology/:id", "element": "OntologyDetail" }
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"code": "workbench",
|
"code": "workbench",
|
||||||
"label": "workbench",
|
"label": "workbench",
|
||||||
"i18nKey": "menu.workbench",
|
"i18nKey": "menu.workbench",
|
||||||
"path": "/",
|
"path": null,
|
||||||
"enable": true,
|
"enable": true,
|
||||||
"display": true,
|
"display": true,
|
||||||
"level": 1,
|
"level": 1,
|
||||||
@@ -174,7 +174,7 @@
|
|||||||
"code": "workbench",
|
"code": "workbench",
|
||||||
"label": "workbench",
|
"label": "workbench",
|
||||||
"i18nKey": "menu.workbench",
|
"i18nKey": "menu.workbench",
|
||||||
"path": "/",
|
"path": null,
|
||||||
"enable": true,
|
"enable": true,
|
||||||
"display": true,
|
"display": true,
|
||||||
"level": 1,
|
"level": 1,
|
||||||
@@ -425,15 +425,14 @@
|
|||||||
{
|
{
|
||||||
"id": 2211,
|
"id": 2211,
|
||||||
"parent": 221,
|
"parent": 221,
|
||||||
"code": "statementDetail",
|
"code": "userMemoryDetail",
|
||||||
"label": "记忆详情",
|
"label": "记忆详情",
|
||||||
"i18nKey": "menu.statementDetail",
|
"i18nKey": "menu.userMemoryDetail",
|
||||||
"path": "/statement/:id",
|
"path": "/user-memory/detail/:id/:type",
|
||||||
"enable": true,
|
"enable": true,
|
||||||
"display": false,
|
"display": false,
|
||||||
"level": 4,
|
"level": 3,
|
||||||
"sort": 0,
|
"sort": 0
|
||||||
"subs": null
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 16:29:37
|
* @Date: 2026-02-03 16:29:37
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-26 15:37:18
|
* @Last Modified time: 2026-04-14 10:01:05
|
||||||
*/
|
*/
|
||||||
import React, { useEffect, useState, useRef } from 'react';
|
import React, { useEffect, useState, useRef } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { Flex } from 'antd'
|
import { Flex } from 'antd'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import ConfigHeader from './components/ConfigHeader'
|
import ConfigHeader from './components/ConfigHeader'
|
||||||
import type { AgentRef, ClusterRef, WorkflowRef, Config } from './types'
|
import type { AgentRef, ClusterRef, WorkflowRef, Config } from './types'
|
||||||
@@ -30,6 +31,7 @@ import Logs from './Logs';
|
|||||||
const ApplicationConfig: React.FC = () => {
|
const ApplicationConfig: React.FC = () => {
|
||||||
// Hooks
|
// Hooks
|
||||||
const { id, source } = useParams();
|
const { id, source } = useParams();
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
// Refs for different application types
|
// Refs for different application types
|
||||||
const agentRef = useRef<AgentRef>(null)
|
const agentRef = useRef<AgentRef>(null)
|
||||||
@@ -95,6 +97,13 @@ const ApplicationConfig: React.FC = () => {
|
|||||||
getApplicationInfo()
|
getApplicationInfo()
|
||||||
}, [id])
|
}, [id])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (application?.name) {
|
||||||
|
const appName = t('memoryBear');
|
||||||
|
document.title = `${application.name} - ${appName}`;
|
||||||
|
}
|
||||||
|
}, [application?.name])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch application information
|
* Fetch application information
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 17:33:15
|
* @Date: 2026-02-03 17:33:15
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-26 14:56:00
|
* @Last Modified time: 2026-04-14 16:17:29
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Memory Management Page
|
* Memory Management Page
|
||||||
@@ -74,7 +74,8 @@ const MemoryManagement: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Navigate to engine configuration page */
|
/** Navigate to engine configuration page */
|
||||||
const handleClick = (id: number, type: string) => {
|
const handleClick = (id: number, type: string, config_name: string) => {
|
||||||
|
document.title = `${config_name} - ${t('memoryBear')}`;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'memoryExtractionEngine':
|
case 'memoryExtractionEngine':
|
||||||
navigate(`/memory-extraction-engine/${id}`)
|
navigate(`/memory-extraction-engine/${id}`)
|
||||||
@@ -130,7 +131,7 @@ const MemoryManagement: React.FC = () => {
|
|||||||
align="center"
|
align="center"
|
||||||
justify="space-between"
|
justify="space-between"
|
||||||
className="rb:cursor-pointer rb:bg-[#F6F6F6] rb:h-8 rb:rounded-lg rb:font-medium rb:leading-5 rb:pl-2! rb:pr-1! rb:hover:shadow-[0px_2px_8px_0px_rgba(23,23,25,0.16)]"
|
className="rb:cursor-pointer rb:bg-[#F6F6F6] rb:h-8 rb:rounded-lg rb:font-medium rb:leading-5 rb:pl-2! rb:pr-1! rb:hover:shadow-[0px_2px_8px_0px_rgba(23,23,25,0.16)]"
|
||||||
onClick={() => handleClick(item.config_id, key)}
|
onClick={() => handleClick(item.config_id, key, item.config_name)}
|
||||||
>
|
>
|
||||||
{t(`memory.${key}`)}
|
{t(`memory.${key}`)}
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 14:10:20
|
* @Date: 2026-02-03 14:10:20
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-26 18:55:37
|
* @Last Modified time: 2026-04-14 15:54:05
|
||||||
*/
|
*/
|
||||||
import { type FC, useEffect, useState, useRef } from 'react'
|
import { type FC, useEffect, useState, useRef } from 'react'
|
||||||
import { useParams, useNavigate } from 'react-router-dom';
|
import { useParams, useNavigate } from 'react-router-dom';
|
||||||
@@ -46,6 +46,10 @@ const Detail: FC = () => {
|
|||||||
getData()
|
getData()
|
||||||
}, [id, query])
|
}, [id, query])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.title = `${data.scene_name} - ${t('memoryBear')}`;
|
||||||
|
}, [data.scene_name])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch ontology class list data
|
* Fetch ontology class list data
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-05 10:44:08
|
* @Date: 2026-02-05 10:44:08
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-02-05 10:56:28
|
* @Last Modified time: 2026-04-14 16:27:08
|
||||||
*/
|
*/
|
||||||
import { type FC, useEffect, useRef, useState } from "react";
|
import { type FC, useEffect, useRef, useState } from "react";
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@@ -71,6 +71,7 @@ const SkillConfig: FC = () => {
|
|||||||
.then(res => {
|
.then(res => {
|
||||||
form.setFieldsValue(res as SkillFormData)
|
form.setFieldsValue(res as SkillFormData)
|
||||||
setData(res as SkillFormData)
|
setData(res as SkillFormData)
|
||||||
|
document.title = `${(res as SkillFormData).name} - ${t('memoryBear')}`;
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 17:57:26
|
* @Date: 2026-02-03 17:57:26
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-26 18:59:53
|
* @Last Modified time: 2026-04-14 16:38:21
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Neo4j User Memory Detail View
|
* Neo4j User Memory Detail View
|
||||||
@@ -22,7 +22,7 @@ import InterestDistribution from './components/InterestDistribution'
|
|||||||
import NodeStatistics from './components/NodeStatistics'
|
import NodeStatistics from './components/NodeStatistics'
|
||||||
import RelationshipNetwork from './components/RelationshipNetwork'
|
import RelationshipNetwork from './components/RelationshipNetwork'
|
||||||
import MemoryInsight from './components/MemoryInsight'
|
import MemoryInsight from './components/MemoryInsight'
|
||||||
import type { EndUserProfileRef, MemoryInsightRef, AboutMeRef } from './types'
|
import type { EndUserProfileRef, MemoryInsightRef, AboutMeRef, EndUser } from './types'
|
||||||
import {
|
import {
|
||||||
analyticsRefresh,
|
analyticsRefresh,
|
||||||
} from '@/api/memory'
|
} from '@/api/memory'
|
||||||
@@ -39,8 +39,11 @@ const Neo4j: FC = () => {
|
|||||||
const [selectedKey, setSelectedKey] = useState<string | null>(null)
|
const [selectedKey, setSelectedKey] = useState<string | null>(null)
|
||||||
|
|
||||||
/** Update displayed name */
|
/** Update displayed name */
|
||||||
const handleNameUpdate = (data: { other_name?: string; id: string }) => {
|
const handleNameUpdate = (data?: EndUser) => {
|
||||||
setName(data.other_name && data.other_name !== '' ? data.other_name : data.id)
|
if (!data) return
|
||||||
|
let name = data.other_name && data.other_name !== '' ? data.other_name : data.id || data.end_user_id
|
||||||
|
setName(name)
|
||||||
|
document.title = `${name} - ${t('memoryBear')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Navigate back */
|
/** Navigate back */
|
||||||
@@ -78,7 +81,7 @@ const Neo4j: FC = () => {
|
|||||||
<Flex className="rb:h-full!" gap={12}>
|
<Flex className="rb:h-full!" gap={12}>
|
||||||
<Flex gap={15} vertical justify="space-between" align="center" className="rb:h-full! rb:px-4! rb:pt-6! rb:pb-5! rb:bg-white rb:w-20 rb:rounded-xl">
|
<Flex gap={15} vertical justify="space-between" align="center" className="rb:h-full! rb:px-4! rb:pt-6! rb:pb-5! rb:bg-white rb:w-20 rb:rounded-xl">
|
||||||
<Flex gap={15} vertical>
|
<Flex gap={15} vertical>
|
||||||
<Popover
|
<Popover
|
||||||
content={t('userMemory.memoryWindow', { name: name })}
|
content={t('userMemory.memoryWindow', { name: name })}
|
||||||
placement="right"
|
placement="right"
|
||||||
arrow={false}
|
arrow={false}
|
||||||
@@ -87,7 +90,7 @@ const Neo4j: FC = () => {
|
|||||||
<div className="rb:mb-4.25! rb:size-12 rb:rounded-xl rb:bg-cover rb:bg-[url('@/assets/images/userMemory/logo.png')]"></div>
|
<div className="rb:mb-4.25! rb:size-12 rb:rounded-xl rb:bg-cover rb:bg-[url('@/assets/images/userMemory/logo.png')]"></div>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
<Flex
|
<Flex
|
||||||
align="center"
|
align="center"
|
||||||
justify="center"
|
justify="center"
|
||||||
className={clsx("rb:cursor-pointer rb:size-12 rb:rounded-xl rb:group", {
|
className={clsx("rb:cursor-pointer rb:size-12 rb:rounded-xl rb:group", {
|
||||||
@@ -155,7 +158,7 @@ const Neo4j: FC = () => {
|
|||||||
<div className="rb:cursor-pointer rb:size-6 rb:bg-cover rb:bg-[url('@/assets/images/userMemory/logout.svg')]" onClick={goBack}></div>
|
<div className="rb:cursor-pointer rb:size-6 rb:bg-cover rb:bg-[url('@/assets/images/userMemory/logout.svg')]" onClick={goBack}></div>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Flex vertical className="rb:flex-1">
|
<Flex vertical className="rb:flex-1">
|
||||||
<NodeStatistics />
|
<NodeStatistics />
|
||||||
<RelationshipNetwork />
|
<RelationshipNetwork />
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 17:57:11
|
* @Date: 2026-02-03 17:57:11
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-31 15:29:45
|
* @Last Modified time: 2026-04-14 15:56:15
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* RAG User Memory Detail View
|
* RAG User Memory Detail View
|
||||||
@@ -97,6 +97,10 @@ const Rag: FC = () => {
|
|||||||
}
|
}
|
||||||
const name = loading.detail ? '' : data?.name && data?.name !== '' ? data.name : id
|
const name = loading.detail ? '' : data?.name && data?.name !== '' ? data.name : id
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.title = `${name} - ${t('memoryBear')}`;
|
||||||
|
}, [name])
|
||||||
|
|
||||||
const [refreshLoading, setRefreshLoading] = useState(false)
|
const [refreshLoading, setRefreshLoading] = useState(false)
|
||||||
const handleRefresh = () => {
|
const handleRefresh = () => {
|
||||||
if (refreshLoading || !id) return
|
if (refreshLoading || !id) return
|
||||||
|
|||||||
Reference in New Issue
Block a user