diff --git a/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx b/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx index d5bcaa05..5bf074d5 100644 --- a/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx +++ b/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx @@ -36,7 +36,7 @@ function BasicLayout({ project = 'core' }: { project: string }) { const { state, accessData, checkPermission, accessInit, dispatch, resetAccess, getGlobalAccessData, menuList } = useGlobalContext() const [pathname, setPathname] = useState(currentUrl) - const mainPage = project === 'core' ? '/service/list' : '/serviceHub/list' + const mainPage = project === 'core' ? '/service/list' : '/portal/list' const [menuItems, setMenuItems] = useState() const pluginSlotHub = usePluginSlotHub() diff --git a/frontend/packages/common/src/components/aoplatform/UnUsedWordForTranslate.tsx b/frontend/packages/common/src/components/aoplatform/UnUsedWordForTranslate.tsx index 7298d6cb..c38d7e0e 100644 --- a/frontend/packages/common/src/components/aoplatform/UnUsedWordForTranslate.tsx +++ b/frontend/packages/common/src/components/aoplatform/UnUsedWordForTranslate.tsx @@ -187,6 +187,7 @@ export const TranslateWord = () => { {$t('调用地址')} {$t('消费者 IP')} {$t('鉴权名称')} + {$t('日志输出')} ) } diff --git a/frontend/packages/common/src/components/aoplatform/serviceInfoCard.tsx b/frontend/packages/common/src/components/aoplatform/serviceInfoCard.tsx index 4fede82b..d592b8b9 100644 --- a/frontend/packages/common/src/components/aoplatform/serviceInfoCard.tsx +++ b/frontend/packages/common/src/components/aoplatform/serviceInfoCard.tsx @@ -106,7 +106,7 @@ const ServiceInfoCard = ({ * 打开服务详情页面 */ const openInPortal = () => { - window.open(`/serviceHub/detail/${serviceOverview?.id}`, '_blank') + window.open(`/portal/detail/${serviceOverview?.id}`, '_blank') } // 格式化调用次数,添加K和M单位 diff --git a/frontend/packages/common/src/contexts/GlobalStateContext.tsx b/frontend/packages/common/src/contexts/GlobalStateContext.tsx index 16246a22..ced39d41 100644 --- a/frontend/packages/common/src/contexts/GlobalStateContext.tsx +++ b/frontend/packages/common/src/contexts/GlobalStateContext.tsx @@ -87,8 +87,8 @@ const mockData = [ }, { name: 'API 市场', - key: 'serviceHub', - path: '/serviceHub', + key: 'portal', + path: '/portal', icon: 'ic:baseline-hub', access: 'system.api_portal.api_portal.view' }, @@ -107,15 +107,15 @@ const mockData = [ }, { name: '服务', - key: 'analyticsSubscriber', - path: '/analytics/subscriber/list', + key: 'analyticsService', + path: '/analytics/service/list', icon: 'ic:baseline-blinds-closed', access: 'system.analysis.run_view.view' }, { name: '消费者', - key: 'analyticsProvider', - path: '/analytics/provider/list', + key: 'analyticsConsumer', + path: '/analytics/consumer/list', icon: 'ic:baseline-apps', access: 'system.analysis.run_view.view' }, @@ -253,7 +253,7 @@ const mockData = [ access: 'system.settings.ssl_certificate.view' }, { - name: '日志', + name: '日志输出', key: 'logsettings', path: '/logsettings', icon: 'ic:baseline-sticky-note-2', diff --git a/frontend/packages/common/src/hooks/pluginLoader.ts b/frontend/packages/common/src/hooks/pluginLoader.ts index f9ae66b1..ccdbc4c2 100644 --- a/frontend/packages/common/src/hooks/pluginLoader.ts +++ b/frontend/packages/common/src/hooks/pluginLoader.ts @@ -112,10 +112,10 @@ const mockData = { }, { driver: 'apipark.builtIn.component', - name: 'serviceHub', + name: 'portal', router: [ { - path: 'serviceHub', + path: 'portal', type: 'normal' } ] diff --git a/frontend/packages/common/src/locales/scan/en-US.json b/frontend/packages/common/src/locales/scan/en-US.json index 5e9e24ee..2ff874a1 100644 --- a/frontend/packages/common/src/locales/scan/en-US.json +++ b/frontend/packages/common/src/locales/scan/en-US.json @@ -4,7 +4,7 @@ "Kb58e0c3f": "Service", "Kc9e489f5": "Team", "K61c89f5f": "API Portal", - "K16d71239": "Analysis", + "K16d71239": "Analytics", "K714c192d": "Call Statistics", "Kd57dfe97": "Topology", "K3fe97dcc": "System Settings", diff --git a/frontend/packages/core/src/const/const.tsx b/frontend/packages/core/src/const/const.tsx index f4cf1da3..2a7fc46d 100644 --- a/frontend/packages/core/src/const/const.tsx +++ b/frontend/packages/core/src/const/const.tsx @@ -535,7 +535,7 @@ export const routerMap: Map = new Map([ ], [ - 'serviceHub', + 'portal', { type: 'module', component: , @@ -702,12 +702,12 @@ export const routerMap: Map = new Map([ children: [ { path: 'total', - key: 'analytics2', + key: 'analyticsTotal', lazy: lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/DashboardTotal.tsx')) }, { path: ':dashboardType', - key: 'analytics3', + key: 'analyticsOther', component: , children: [ { diff --git a/frontend/packages/core/src/const/partitions/types.ts b/frontend/packages/core/src/const/partitions/types.ts index 99d9d507..ec998209 100644 --- a/frontend/packages/core/src/const/partitions/types.ts +++ b/frontend/packages/core/src/const/partitions/types.ts @@ -123,6 +123,7 @@ export type PartitionDataLogHeaderListFieldType = { export type PartitionDataLogConfigFieldType = { headers: PartitionDataLogHeaderListFieldType[] url: string + driver?: string } export const PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS: PageProColumns[] = [ diff --git a/frontend/packages/core/src/pages/logsettings/LogSettings.tsx b/frontend/packages/core/src/pages/logsettings/LogSettings.tsx index 124ee8d3..21488dad 100644 --- a/frontend/packages/core/src/pages/logsettings/LogSettings.tsx +++ b/frontend/packages/core/src/pages/logsettings/LogSettings.tsx @@ -68,7 +68,7 @@ const LogSettings = () => { <>
diff --git a/frontend/packages/core/src/pages/partitions/DataLogSettingEdit.tsx b/frontend/packages/core/src/pages/partitions/DataLogSettingEdit.tsx index 7dafa743..189c6993 100644 --- a/frontend/packages/core/src/pages/partitions/DataLogSettingEdit.tsx +++ b/frontend/packages/core/src/pages/partitions/DataLogSettingEdit.tsx @@ -1,11 +1,15 @@ -import EditableTable from "@common/components/aoplatform/EditableTable" -import WithPermission from "@common/components/aoplatform/WithPermission" -import { BasicResponse, PLACEHOLDER, STATUS_CODE } from "@common/const/const" -import { useFetch } from "@common/hooks/http" -import { $t } from "@common/locales" -import { PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS, PartitionDataLogConfigFieldType, PartitionDataLogHeaderListFieldType } from "@core/const/partitions/types" -import { Button, Form, Input, message } from "antd" -import { useEffect } from "react" +import EditableTable from '@common/components/aoplatform/EditableTable' +import WithPermission from '@common/components/aoplatform/WithPermission' +import { BasicResponse, PLACEHOLDER, STATUS_CODE } from '@common/const/const' +import { useFetch } from '@common/hooks/http' +import { $t } from '@common/locales' +import { + PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS, + PartitionDataLogConfigFieldType, + PartitionDataLogHeaderListFieldType +} from '@core/const/partitions/types' +import { Button, Form, Input, message, Select } from 'antd' +import { useEffect } from 'react' export type DashboardPageShowStatus = 'view' | 'edit' export type DashboardSettingEditProps = { @@ -15,7 +19,7 @@ export type DashboardSettingEditProps = { } const DataLogSettingEdit = (props: DashboardSettingEditProps) => { const { changeStatus, refreshData, data } = props - const [form] = Form.useForm(); + const [form] = Form.useForm() const { fetchData } = useFetch() const onFinish = () => { @@ -23,10 +27,16 @@ const DataLogSettingEdit = (props: DashboardSettingEditProps) => { const formData = { config: { url: value.url, - headers: value.headers.filter((item: PartitionDataLogHeaderListFieldType) => item.key).map((item: PartitionDataLogHeaderListFieldType) => ({key:item.key, value:item.value || ''})) + headers: value.headers + .filter((item: PartitionDataLogHeaderListFieldType) => item.key) + .map((item: PartitionDataLogHeaderListFieldType) => ({ key: item.key, value: item.value || '' })) } } - fetchData>('log/loki', { method: 'POST', body: JSON.stringify(formData), eoParams: {} }).then(response => { + fetchData>('log/loki', { + method: 'POST', + body: JSON.stringify(formData), + eoParams: {} + }).then((response) => { const { code, msg } = response if (code === STATUS_CODE.SUCCESS) { message.success(msg || $t('操作成功,即将刷新页面')) @@ -38,15 +48,26 @@ const DataLogSettingEdit = (props: DashboardSettingEditProps) => { }) } - useEffect(() => { form.setFieldsValue(data) }, [data]) + useEffect(() => { + form.setFieldsValue({ + ...data, + headers: data?.headers?.length ? data.headers : [ + { + key: '', + value: '' + } + ], + driver: 'loki' + }) + }, [data]) useEffect(() => { - return (form.setFieldsValue({})) - }, []); + return form.setFieldsValue({}) + }, []) return ( <>
- +
{ autoComplete="off" > - label={$t("请求前缀")} - name="url" + label={$t('数据源类型')} + name="driver" rules={[{ required: true }]} > + + + label={$t('请求前缀')} name="url" rules={[{ required: true }]}> - - label={$t("HTTP 头部")} - name="headers" - > + label={$t('HTTP 头部')} name="headers"> configFields={PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS} />
- + @@ -84,7 +111,7 @@ const DataLogSettingEdit = (props: DashboardSettingEditProps) => {
- ); + ) } -export default DataLogSettingEdit; \ No newline at end of file +export default DataLogSettingEdit diff --git a/frontend/packages/core/src/pages/partitions/PartitionInsideDashboardSetting.tsx b/frontend/packages/core/src/pages/partitions/PartitionInsideDashboardSetting.tsx index 6e243094..b732c6ab 100644 --- a/frontend/packages/core/src/pages/partitions/PartitionInsideDashboardSetting.tsx +++ b/frontend/packages/core/src/pages/partitions/PartitionInsideDashboardSetting.tsx @@ -161,7 +161,7 @@ const PartitionInsideDashboardSetting: FC = () => { className="overflow-hidden mt-[30px] w-full max-h-full flex flex-col justify-between" title={
- {$t('数据日志')} + {$t('请求日志')} {!dataLogLoading && !dataLogData && {$t('未配置')}}
} @@ -220,6 +220,11 @@ export function DataLogConfigPreview(x: PartitionDataLogConfigFieldType) { return (
+ + {$t('数据源')}: + {/* 先写死,或许会有选择列表,但现在可以不用 */} + Loki + {$t('请求前缀')}: {x?.url} diff --git a/frontend/packages/core/src/pages/serviceOverview/charts/ServiceAreaChart.tsx b/frontend/packages/core/src/pages/serviceOverview/charts/ServiceAreaChart.tsx index bfe7a00b..f9d82b56 100644 --- a/frontend/packages/core/src/pages/serviceOverview/charts/ServiceAreaChart.tsx +++ b/frontend/packages/core/src/pages/serviceOverview/charts/ServiceAreaChart.tsx @@ -9,6 +9,7 @@ type AreaChartInfo = { data: number[] max: string min: string + showXAxis?: boolean } type ServiceAreaCharProps = { @@ -24,27 +25,65 @@ const ServiceAreaChart = ({ customClassNames, dataInfo, height }: ServiceAreaCha const option = { tooltip: { trigger: 'axis', - position: function (pt) { - return [pt[0], '10%'] + formatter: function (value: any) { + // 如果是数组,取第一个参数的name + const param = Array.isArray(value) ? value[0] : value + console.log('params==', param) + let tooltipContent = `
` + const marker = `` + tooltipContent += `
+
${marker}
${param.name}
${param.value}
+
` + tooltipContent += '
' + return tooltipContent } }, - title: { - show: false - }, + title: [ + { + text: '{titleStyle|' + $t(dataInfo.title) + '}\n\n{valueStyle|' + dataInfo.value + '}', + left: '2%', + top: '0', + textStyle: { + rich: { + titleStyle: { + fontSize: 14, + color: '#999', + fontWeight: 'normal', + lineHeight: 20 + }, + valueStyle: { + fontSize: 32, + color: '#101010', + fontWeight: 500, + lineHeight: 40 + } + } + } + } + ], toolbox: { show: false }, grid: { - left: '5%', + left: '3%', right: '3%', - bottom: '5%', - top: '100px', + bottom: '0%', + top: '110px', containLabel: true }, xAxis: { type: 'category', boundaryGap: false, - data: dataInfo.date + data: dataInfo.date, + axisTick: { + show: false + }, + axisLine: { + lineStyle: { + color: '#ccc' + } + }, + show: false }, yAxis: { type: 'value', @@ -59,7 +98,51 @@ const ServiceAreaChart = ({ customClassNames, dataInfo, height }: ServiceAreaCha show: false } }, - dataZoom: [], + // 添加数据缩放组件,实现鼠标放大缩小,后续可能需要 + // dataZoom: [ + // { + // type: 'inside', // 内置的数据区域缩放组件(使用鼠标滚轮缩放) + // xAxisIndex: 0, // 设置缩放作用在第一个x轴 + // filterMode: 'filter', + // start: 0, + // end: 100 + // }, + // { + // type: 'slider', // 滑动条型数据区域缩放组件 + // xAxisIndex: 0, + // filterMode: 'filter', + // height: 20, + // bottom: 0, + // start: 0, + // end: 100, + // handleIcon: + // 'path://M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z', + // handleSize: '80%', + // handleStyle: { + // color: '#fff', + // shadowBlur: 3, + // shadowColor: 'rgba(0, 0, 0, 0.6)', + // shadowOffsetX: 2, + // shadowOffsetY: 2 + // }, + // show: false // 默认隐藏底部的滑动条,可以改为 true 显示 + // } + // ], + // 添加空状态提示 + graphic: !dataInfo.data.length + ? [ + { + type: 'text', + left: 'center', + top: 'middle', + style: { + text: $t('暂无数据'), + fontSize: 14, + fill: '#999' + } + } + ] + : [], series: [ { name: dataInfo.title, @@ -94,23 +177,30 @@ const ServiceAreaChart = ({ customClassNames, dataInfo, height }: ServiceAreaCha } setOption(option) } + // 使用深度监听来确保图表数据更新 useEffect(() => { if (!dataInfo) return - setChartOption(dataInfo) - }, [dataInfo]) + + // 直接获取 ECharts 实例并设置选项 + const echartsInstance = chartRef.current?.getEchartsInstance() + if (echartsInstance) { + // 清除已有的图表 + echartsInstance.clear() + // 重新设置选项 + setChartOption(dataInfo) + } + }, [dataInfo, JSON.stringify(dataInfo)]) return (
-
{$t(dataInfo?.title || '')}
-
- {dataInfo?.value} -
+
+
- +
{dataInfo?.max}
- +
{dataInfo?.min}
diff --git a/frontend/packages/core/src/pages/serviceOverview/charts/ServiceBarChar.tsx b/frontend/packages/core/src/pages/serviceOverview/charts/ServiceBarChar.tsx index d7ce6294..4b1b4226 100644 --- a/frontend/packages/core/src/pages/serviceOverview/charts/ServiceBarChar.tsx +++ b/frontend/packages/core/src/pages/serviceOverview/charts/ServiceBarChar.tsx @@ -12,6 +12,7 @@ export type BarChartInfo = { color: string value: number[] }[] + showXAxis?: boolean } type ServiceBarCharProps = { @@ -20,7 +21,6 @@ type ServiceBarCharProps = { height?: number } - const ServiceBarChar = ({ customClassNames, dataInfo, height }: ServiceBarCharProps) => { const chartRef = useRef(null) const [option, setOption] = useState({}) @@ -33,6 +33,7 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height }: ServiceBarCharPr const setChartOption = (dataInfo: BarChartInfo) => { const isNumberArray = typeof dataInfo.data[0] !== 'object' const legendData = isNumberArray ? [dataInfo.title] : dataInfo.data.map((item) => item.name) + const hasData = dataInfo.data && dataInfo.data.length > 0 const tooltipFormatter = (params: { name: string; color: string; seriesIndex?: number }) => { let tooltipContent = `
${isNumberArray ? '' : params.name}
` @@ -63,8 +64,8 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height }: ServiceBarCharPr const option: EChartsOption = { title: [ { - text: '{titleStyle|' + $t(dataInfo.title) + '}\n{valueStyle|' + dataInfo.value + '}', - left: '4%', + text: '{titleStyle|' + $t(dataInfo.title) + '}\n\n{valueStyle|' + dataInfo.value + '}', + left: '2%', top: '0', textStyle: { rich: { @@ -75,8 +76,8 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height }: ServiceBarCharPr lineHeight: 20 }, valueStyle: { - fontSize: 25, - color: '#000', + fontSize: 32, + color: '#101010', fontWeight: 500, lineHeight: 40 } @@ -85,10 +86,10 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height }: ServiceBarCharPr } ], grid: { - left: '5%', + left: '3%', right: '3%', - bottom: '5%', - top: '100px', + bottom: '0%', + top: '110px', containLabel: true }, tooltip: { @@ -124,12 +125,14 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height }: ServiceBarCharPr lineStyle: { color: '#ccc' } - } + }, + show: false }, yAxis: { type: 'value', name: '', min: 0, + minInterval: 1, splitLine: { lineStyle: { type: 'dashed', @@ -140,6 +143,50 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height }: ServiceBarCharPr formatter: '{value}' } }, + // 添加数据缩放组件,实现鼠标放大缩小,后续可能需要 + // dataZoom: [ + // { + // type: 'inside', // 内置的数据区域缩放组件(使用鼠标滚轮缩放) + // xAxisIndex: 0, // 设置缩放作用在第一个x轴 + // filterMode: 'filter', + // start: 0, + // end: 100 + // }, + // { + // type: 'slider', // 滑动条型数据区域缩放组件 + // xAxisIndex: 0, + // filterMode: 'filter', + // height: 20, + // bottom: 0, + // start: 0, + // end: 100, + // handleIcon: 'path://M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z', + // handleSize: '80%', + // handleStyle: { + // color: '#fff', + // shadowBlur: 3, + // shadowColor: 'rgba(0, 0, 0, 0.6)', + // shadowOffsetX: 2, + // shadowOffsetY: 2 + // }, + // show: false // 默认隐藏底部的滑动条,可以改为 true 显示 + // } + // ], + // 添加空状态提示 + graphic: !hasData + ? [ + { + type: 'text', + left: 'center', + top: 'middle', + style: { + text: $t('暂无数据'), + fontSize: 14, + fill: '#999' + } + } + ] + : [], series: isNumberArray ? [ { @@ -171,10 +218,19 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height }: ServiceBarCharPr setOption(option) } + // 使用深度监听来确保图表数据更新 useEffect(() => { if (!dataInfo) return - setChartOption(dataInfo) - }, [dataInfo]) + + // 直接获取 ECharts 实例并设置选项 + const echartsInstance = chartRef.current?.getEchartsInstance() + if (echartsInstance) { + // 清除已有的图表 + echartsInstance.clear() + // 重新设置选项 + setChartOption(dataInfo) + } + }, [dataInfo, JSON.stringify(dataInfo)]) return (
diff --git a/frontend/packages/core/src/pages/serviceOverview/indicator/Indicator.tsx b/frontend/packages/core/src/pages/serviceOverview/indicator/Indicator.tsx index 9f4454a2..d51f4de9 100644 --- a/frontend/packages/core/src/pages/serviceOverview/indicator/Indicator.tsx +++ b/frontend/packages/core/src/pages/serviceOverview/indicator/Indicator.tsx @@ -18,33 +18,30 @@ const Indicator = ({ indicatorInfo }: { indicatorInfo: any }) => { /** 设置服务指标 */ const setIndicatorList = () => { + const side = indicatorInfo?.serviceKind === 'ai' ? 'aiInside' : 'inside' setIndicator([ { title: indicatorInfo?.enableMcp ? 'APIs / Tools' : 'APIs', - link: `/serviceHub/detail/${indicatorInfo?.serviceId}`, + link: `/service/${indicatorInfo?.teamId}/${side}/${indicatorInfo?.serviceId}/route`, content: indicatorInfo?.apiNum ?? 0 }, { title: $t('订阅数量'), - link: `/consumer/list/${indicatorInfo?.teamId}`, + link: `/service/${indicatorInfo?.teamId}/${side}/${indicatorInfo?.serviceId}/subscriber`, content: indicatorInfo?.subscriberNum ?? 0 }, { title: 'MCP', + link: `/service/${indicatorInfo?.teamId}/${side}/${indicatorInfo?.serviceId}/setting`, content: ( <> - {/* green */}