diff --git a/dinky-web/src/locales/en-US/pages.ts b/dinky-web/src/locales/en-US/pages.ts index e7b626bd82..4da5c2ee80 100644 --- a/dinky-web/src/locales/en-US/pages.ts +++ b/dinky-web/src/locales/en-US/pages.ts @@ -618,6 +618,12 @@ export default { 'pages.datastudio.label.history.clusterInstance': 'Cluster Instance', 'pages.datastudio.label.history.clusterConfig': 'Cluster Config', 'pages.datastudio.label.history.local': 'Local (Built-in MiniCluster)', + + 'pages.datastudio.label.lastUpdateDes': 'Recently saved', + 'pages.datastudio.label.lastUpdateJust': 'Newly', + 'pages.datastudio.label.lastUpdateMinutesAgo': 'Minutes Ago', + 'pages.datastudio.label.lastUpdateHoursAgo': 'Hours Ago', + /** * * rc diff --git a/dinky-web/src/locales/zh-CN/pages.ts b/dinky-web/src/locales/zh-CN/pages.ts index 11c8ca2472..861ff37bcc 100644 --- a/dinky-web/src/locales/zh-CN/pages.ts +++ b/dinky-web/src/locales/zh-CN/pages.ts @@ -517,6 +517,11 @@ export default { 'pages.datastudio.label.version.rollback.flinksqlConfirm': '确定回滚Flink SQL版本至【{versionId}】吗?', + 'pages.datastudio.label.lastUpdateDes': '最近保存', + 'pages.datastudio.label.lastUpdateJust': '刚刚', + 'pages.datastudio.label.lastUpdateMinutesAgo': '分钟前', + 'pages.datastudio.label.lastUpdateHoursAgo': '小时前', + 'pages.datastudio.catalog.catalogSelect': '请选择 catalog & database', 'pages.datastudio.catalog.tableInfo': '表信息', 'pages.datastudio.catalog.fieldInformation': '字段信息', diff --git a/dinky-web/src/pages/DataStudio/FooterContainer/function.ts b/dinky-web/src/pages/DataStudio/FooterContainer/function.ts new file mode 100644 index 0000000000..658654a878 --- /dev/null +++ b/dinky-web/src/pages/DataStudio/FooterContainer/function.ts @@ -0,0 +1,50 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { l } from '@/utils/intl'; + +export function formatDate(inputDate: string) { + const now = new Date(); + const then = new Date(inputDate); + + // 计算时间差 + const diff = (now - then) / 1000; // 转换为秒 + const diffMinutes = Math.floor(diff / 60); // 转换为分钟 + const diffHours = Math.floor(diff / 3600); // 转换为小时 + + if (diff < 60) { + // 如果小于1分钟,显示“刚刚” + return l('pages.datastudio.label.lastUpdateJust'); + } else if (diff < 3600 && now.toDateString() === then.toDateString()) { + // 如果小于1小时且是同一天,显示几分钟前 + return `${diffMinutes}${l('pages.datastudio.label.lastUpdateMinutesAgo')}`; + } else if (diff < 86400 && now.toDateString() === then.toDateString()) { + // 如果小于1天且是同一天,显示几小时前 + return `${diffHours}${l('pages.datastudio.label.lastUpdateHoursAgo')}`; + } else { + // 否则显示日期和时间 + const options = { + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + } as Intl.DateTimeFormatOptions; + return then.toLocaleString('zh-CN', options).replace(/\//g, '-').slice(0, -3); + } +} diff --git a/dinky-web/src/pages/DataStudio/FooterContainer/index.tsx b/dinky-web/src/pages/DataStudio/FooterContainer/index.tsx index 8e8775134b..7117e981ce 100644 --- a/dinky-web/src/pages/DataStudio/FooterContainer/index.tsx +++ b/dinky-web/src/pages/DataStudio/FooterContainer/index.tsx @@ -18,10 +18,13 @@ */ import { l } from '@/utils/intl'; -import { useModel } from '@@/exports'; +import { connect, useModel } from '@@/exports'; import { Button, GlobalToken, Space } from 'antd'; import React, { useEffect, useState } from 'react'; import { SseData, Topic } from '@/models/UseWebSocketModel'; +import { CenterTab, DataStudioState } from '@/pages/DataStudio/model'; +import { mapDispatchToProps } from '@/pages/DataStudio/DvaFunction'; +import { formatDate } from '@/pages/DataStudio/FooterContainer/function'; type ButtonRoute = { text: React.ReactNode; @@ -29,8 +32,11 @@ type ButtonRoute = { onClick?: () => void; }; -export default (props: { token: GlobalToken }) => { - const { token } = props; +const FooterContainer = (props: { + token: GlobalToken; + centerContent?: DataStudioState['centerContent']; +}) => { + const { token, centerContent } = props; const [memDetailInfo, setMemDetailInfo] = useState('0/0M'); const { subscribeTopic } = useModel('UseWebSocketModel', (model: any) => ({ subscribeTopic: model.subscribeTopic @@ -91,6 +97,18 @@ export default (props: { token: GlobalToken }) => { )); }; + const renderFooterLastUpdate = () => { + const currentTab = centerContent?.tabs.find( + (item, index) => item.id === centerContent?.activeTab + ); + if (currentTab && currentTab.tabType === 'task') { + return ( +