mirror of
https://github.com/whyour/qinglong.git
synced 2026-10-18 18:33:06 +08:00
fix: synchronize runtime locales and harden online updates
Translate UI, scheduler, validation, preload and maintenance messages dynamically, and propagate locale changes between workers. Harden update checks, downloads and terminal states, verify Debian pnpm, and ignore generated test artifacts.
This commit is contained in:
@@ -364,13 +364,10 @@ const CronDetailModal = ({
|
||||
|
||||
const enabledOrDisabledCron = () => {
|
||||
Modal.confirm({
|
||||
title: `确认${currentCron.isDisabled === 1 ? intl.get('启用') : intl.get('禁用')
|
||||
}`,
|
||||
title: intl.get('确认操作', { operation: currentCron.isDisabled === 1 ? intl.get('启用') : intl.get('禁用') }),
|
||||
content: (
|
||||
<>
|
||||
{intl.get('确认')}
|
||||
{currentCron.isDisabled === 1 ? intl.get('启用') : intl.get('禁用')}
|
||||
{intl.get('定时任务')}{' '}
|
||||
{intl.get('确认操作对象', { operation: currentCron.isDisabled === 1 ? intl.get('启用') : intl.get('禁用'), object: intl.get('定时任务') })}{' '}
|
||||
<Text style={{ wordBreak: 'break-all' }} type="warning">
|
||||
{currentCron.name}
|
||||
</Text>{' '}
|
||||
@@ -398,13 +395,10 @@ const CronDetailModal = ({
|
||||
|
||||
const pinOrUnPinCron = () => {
|
||||
Modal.confirm({
|
||||
title: `确认${currentCron.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶')
|
||||
}`,
|
||||
title: intl.get('确认操作', { operation: currentCron.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶') }),
|
||||
content: (
|
||||
<>
|
||||
{intl.get('确认')}
|
||||
{currentCron.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶')}
|
||||
{intl.get('定时任务')}{' '}
|
||||
{intl.get('确认操作对象', { operation: currentCron.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶'), object: intl.get('定时任务') })}{' '}
|
||||
<Text style={{ wordBreak: 'break-all' }} type="warning">
|
||||
{currentCron.name}
|
||||
</Text>{' '}
|
||||
|
||||
+16
-18
@@ -544,13 +544,13 @@ const Crontab = () => {
|
||||
|
||||
const enabledOrDisabledCron = (record: any, index: number) => {
|
||||
Modal.confirm({
|
||||
title: `确认${record.isDisabled === 1 ? intl.get('启用') : intl.get('禁用')
|
||||
}`,
|
||||
title: intl.get('确认操作', {
|
||||
operation:
|
||||
record.isDisabled === 1 ? intl.get('启用') : intl.get('禁用'),
|
||||
}),
|
||||
content: (
|
||||
<>
|
||||
{intl.get('确认')}
|
||||
{record.isDisabled === 1 ? intl.get('启用') : intl.get('禁用')}
|
||||
{intl.get('定时任务')}{' '}
|
||||
{intl.get('确认操作对象', { operation: record.isDisabled === 1 ? intl.get('启用') : intl.get('禁用'), object: intl.get('定时任务') })}{' '}
|
||||
<Text style={{ wordBreak: 'break-all' }} type="warning">
|
||||
{record.name}
|
||||
</Text>{' '}
|
||||
@@ -584,13 +584,13 @@ const Crontab = () => {
|
||||
|
||||
const pinOrUnPinCron = (record: any, index: number) => {
|
||||
Modal.confirm({
|
||||
title: `确认${record.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶')
|
||||
}`,
|
||||
title: intl.get('确认操作', {
|
||||
operation:
|
||||
record.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶'),
|
||||
}),
|
||||
content: (
|
||||
<>
|
||||
{intl.get('确认')}
|
||||
{record.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶')}
|
||||
{intl.get('定时任务')}{' '}
|
||||
{intl.get('确认操作对象', { operation: record.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶'), object: intl.get('定时任务') })}{' '}
|
||||
<Text style={{ wordBreak: 'break-all' }} type="warning">
|
||||
{record.name}
|
||||
</Text>{' '}
|
||||
@@ -745,12 +745,12 @@ const Crontab = () => {
|
||||
|
||||
const operateCrons = (operationStatus: number) => {
|
||||
Modal.confirm({
|
||||
title: `确认${OperationName[operationStatus]}`,
|
||||
title: intl.get('确认操作', {
|
||||
operation: intl.get(OperationName[operationStatus]),
|
||||
}),
|
||||
content: (
|
||||
<>
|
||||
{intl.get('确认')}
|
||||
{OperationName[operationStatus]}
|
||||
{intl.get('选中的定时任务吗')}
|
||||
{intl.get('确认批量操作', { operation: intl.get(OperationName[operationStatus]), object: intl.get('定时任务') })}
|
||||
</>
|
||||
),
|
||||
onOk() {
|
||||
@@ -1035,9 +1035,7 @@ const Crontab = () => {
|
||||
{intl.get('批量修改标签')}
|
||||
</Button>
|
||||
<span style={{ marginLeft: 8 }}>
|
||||
{intl.get('已选择')}
|
||||
<a>{selectedRowIds?.length}</a>
|
||||
{intl.get('项')}
|
||||
{intl.get('选中条数', { count: selectedRowIds.length })}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -1051,7 +1049,7 @@ const Crontab = () => {
|
||||
simple: isPhone,
|
||||
total,
|
||||
showTotal: (total: number, range: number[]) =>
|
||||
`第 ${range[0]}-${range[1]} 条/总共 ${total} 条`,
|
||||
intl.get('分页总数', { start: range[0], end: range[1], total }),
|
||||
pageSizeOptions: [10, 20, 50, 100, 200, 500, total || 10000].sort(
|
||||
(a, b) => a - b,
|
||||
),
|
||||
|
||||
@@ -167,7 +167,7 @@ const Dashboard = () => {
|
||||
const runtimePagination = {
|
||||
pageSize: 5,
|
||||
showSizeChanger: false,
|
||||
showTotal: (total: number) => `共 ${total} 个`,
|
||||
showTotal: (total: number) => intl.get('总条数', { total }),
|
||||
};
|
||||
|
||||
if (loading) return <Spin size="large" style={{ display: 'block', marginTop: 100 }} />;
|
||||
@@ -348,7 +348,7 @@ const Dashboard = () => {
|
||||
data={{
|
||||
target: Number(system.memUsagePercent),
|
||||
total: 100,
|
||||
name: '内存使用率',
|
||||
name: intl.get('内存使用'),
|
||||
}}
|
||||
style={{
|
||||
textY: '70%',
|
||||
|
||||
@@ -536,9 +536,7 @@ const Dependence = () => {
|
||||
{intl.get('批量强制删除')}
|
||||
</Button>
|
||||
<span style={{ marginLeft: 8 }}>
|
||||
{intl.get('已选择')}
|
||||
<a>{selectedRowIds?.length}</a>
|
||||
{intl.get('项')}
|
||||
{intl.get('选中条数', { count: selectedRowIds.length })}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Vendored
+18
-22
@@ -279,16 +279,13 @@ const Env = () => {
|
||||
|
||||
const enabledOrDisabledEnv = (record: any, index: number) => {
|
||||
Modal.confirm({
|
||||
title: `确认${
|
||||
record.status === Status.已禁用 ? intl.get('启用') : intl.get('禁用')
|
||||
}`,
|
||||
title: intl.get('确认操作', {
|
||||
operation:
|
||||
record.status === Status.已禁用 ? intl.get('启用') : intl.get('禁用'),
|
||||
}),
|
||||
content: (
|
||||
<>
|
||||
{intl.get('确认')}
|
||||
{record.status === Status.已禁用
|
||||
? intl.get('启用')
|
||||
: intl.get('禁用')}
|
||||
Env{' '}
|
||||
{intl.get('确认操作对象', { operation: record.status === Status.已禁用 ? intl.get('启用') : intl.get('禁用'), object: 'Env' })}{' '}
|
||||
<Paragraph
|
||||
style={{ wordBreak: 'break-all', display: 'inline' }}
|
||||
ellipsis={{ rows: 6, expandable: true }}
|
||||
@@ -343,14 +340,13 @@ const Env = () => {
|
||||
|
||||
const pinOrUnpinEnv = (record: any, index: number) => {
|
||||
Modal.confirm({
|
||||
title: `确认${
|
||||
record.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶')
|
||||
}`,
|
||||
title: intl.get('确认操作', {
|
||||
operation:
|
||||
record.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶'),
|
||||
}),
|
||||
content: (
|
||||
<>
|
||||
{intl.get('确认')}
|
||||
{record.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶')}
|
||||
Env{' '}
|
||||
{intl.get('确认操作对象', { operation: record.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶'), object: 'Env' })}{' '}
|
||||
<Paragraph
|
||||
style={{ wordBreak: 'break-all', display: 'inline' }}
|
||||
ellipsis={{ rows: 6, expandable: true }}
|
||||
@@ -543,12 +539,12 @@ const Env = () => {
|
||||
|
||||
const operateEnvs = (operationStatus: number) => {
|
||||
Modal.confirm({
|
||||
title: `确认${OperationName[operationStatus]}`,
|
||||
title: intl.get('确认操作', {
|
||||
operation: intl.get(OperationName[operationStatus]),
|
||||
}),
|
||||
content: (
|
||||
<>
|
||||
{intl.get('确认')}
|
||||
{OperationName[operationStatus]}
|
||||
{intl.get('选中的变量吗')}
|
||||
{intl.get('确认批量操作', { operation: intl.get(OperationName[operationStatus]), object: intl.get('环境变量') })}
|
||||
</>
|
||||
),
|
||||
onOk() {
|
||||
@@ -603,7 +599,9 @@ const Env = () => {
|
||||
);
|
||||
|
||||
if (code === 200) {
|
||||
message.success(`${intl.get('成功上传')}${data.length}${intl.get('个环境变量')}`);
|
||||
message.success(
|
||||
`${intl.get('成功上传')}${data.length}${intl.get('个环境变量')}`,
|
||||
);
|
||||
getEnvs();
|
||||
}
|
||||
setImportLoading(false);
|
||||
@@ -708,9 +706,7 @@ const Env = () => {
|
||||
{intl.get('批量取消置顶')}
|
||||
</Button>
|
||||
<span style={{ marginLeft: 8 }}>
|
||||
{intl.get('已选择')}
|
||||
<a>{selectedRowIds?.length}</a>
|
||||
{intl.get('项')}
|
||||
{intl.get('选中条数', { count: selectedRowIds.length })}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -79,16 +79,10 @@ const Error = () => {
|
||||
description={
|
||||
<Typography.Text type="danger">
|
||||
<div>{intl.get('请先按如下方式修复:')}</div>
|
||||
<div>
|
||||
1. 宿主机执行 docker run --rm -v
|
||||
/var/run/docker.sock:/var/run/docker.sock
|
||||
containrrr/watchtower -cR <容器名>
|
||||
</div>
|
||||
<div>{intl.get('容器更新修复命令')}</div>
|
||||
<div>{intl.get('2. 容器内执行 ql check、ql update')}</div>
|
||||
<div>
|
||||
{intl.get(
|
||||
'3. 如果无法解决,容器内执行 ql log,拷贝执行结果',
|
||||
)}
|
||||
{intl.get('3. 如果无法解决,容器内执行 ql log,拷贝执行结果')}
|
||||
<Typography.Link href="https://github.com/whyour/qinglong/issues/new?assignees=&labels=&template=bug_report.yml">
|
||||
{intl.get('提交 issue')}
|
||||
</Typography.Link>
|
||||
|
||||
@@ -129,7 +129,7 @@ const Initialization = () => {
|
||||
>
|
||||
<Input.TextArea
|
||||
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||
placeholder={`请输入${x.label}`}
|
||||
placeholder={`${intl.get('请输入')} ${x.label}`}
|
||||
/>
|
||||
</Form.Item>
|
||||
))}
|
||||
|
||||
@@ -91,7 +91,7 @@ const Login = () => {
|
||||
</div>
|
||||
<div>
|
||||
{intl.get('上次登录地点:')}
|
||||
{lastaddr || '-'}
|
||||
{lastaddr === '内网IP' ? intl.get('内网IP') : lastaddr || '-'}
|
||||
</div>
|
||||
<div>
|
||||
{intl.get('上次登录IP:')}
|
||||
@@ -103,7 +103,7 @@ const Login = () => {
|
||||
</div>
|
||||
<div>
|
||||
{intl.get('上次登录状态:')}
|
||||
{retries > 0 ? `失败${retries}次` : intl.get('成功')}
|
||||
{retries > 0 ? intl.get('登录失败次数', { count: retries }) : intl.get('成功')}
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
import { disableBody } from "@/utils";
|
||||
import config from "@/utils/config";
|
||||
import { request } from "@/utils/http";
|
||||
import WebSocketManager from "@/utils/websocket";
|
||||
import Ansi from "ansi-to-react";
|
||||
import { Button, Modal, Statistic, message } from "antd";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import intl from "react-intl-universal";
|
||||
import { disableBody } from '@/utils';
|
||||
import config from '@/utils/config';
|
||||
import { request } from '@/utils/http';
|
||||
import WebSocketManager from '@/utils/websocket';
|
||||
import Ansi from 'ansi-to-react';
|
||||
import { Button, Modal, Statistic, message } from 'antd';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
|
||||
const { Countdown } = Statistic;
|
||||
|
||||
const CheckUpdate = ({ systemInfo }: any) => {
|
||||
const [updateLoading, setUpdateLoading] = useState(false);
|
||||
const [value, setValue] = useState("");
|
||||
const [value, setValue] = useState('');
|
||||
const modalRef = useRef<any>();
|
||||
const lastStatusRef = useRef<string | undefined>();
|
||||
const [updateStatus, setUpdateStatus] = useState<string>();
|
||||
|
||||
const checkUpgrade = () => {
|
||||
if (updateLoading) return;
|
||||
if (updateLoading || modalRef.current) return;
|
||||
setUpdateLoading(true);
|
||||
message.loading(intl.get("检查更新中..."), 0);
|
||||
message.loading(intl.get('检查更新中...'), 0);
|
||||
request
|
||||
.put(`${config.apiPrefix}system/update-check`)
|
||||
.then(({ code, data }) => {
|
||||
@@ -33,7 +34,7 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||
})
|
||||
.catch((error: any) => {
|
||||
message.destroy();
|
||||
console.log(error);
|
||||
message.error(intl.get('检查更新失败,请检查网络后重试'));
|
||||
})
|
||||
.finally(() => {
|
||||
setUpdateLoading(false);
|
||||
@@ -43,25 +44,19 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||
const showForceUpdateModal = (data: any) => {
|
||||
Modal.confirm({
|
||||
width: 500,
|
||||
title: intl.get("更新"),
|
||||
title: intl.get('更新'),
|
||||
content: (
|
||||
<>
|
||||
<div>{intl.get("已经是最新版了!")}</div>
|
||||
<div>{intl.get('已经是最新版了!')}</div>
|
||||
<div style={{ fontSize: 12, fontWeight: 400, marginTop: 5 }}>
|
||||
{intl.get("青龙")} {data.lastVersion}{" "}
|
||||
{intl.get("是目前检测到的最新可用版本了。")}
|
||||
{intl.get('青龙')} {data.lastVersion}{' '}
|
||||
{intl.get('是目前检测到的最新可用版本了。')}
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
okText: intl.get("重新下载"),
|
||||
okText: intl.get('重新下载'),
|
||||
onOk() {
|
||||
showUpdatingModal();
|
||||
request
|
||||
.put(`${config.apiPrefix}system/update`)
|
||||
.then((_data: any) => { })
|
||||
.catch((error: any) => {
|
||||
console.log(error);
|
||||
});
|
||||
startUpdate();
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -72,10 +67,12 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||
width: 500,
|
||||
title: (
|
||||
<>
|
||||
<div>{intl.get("更新可用")}</div>
|
||||
<div>{intl.get('更新可用')}</div>
|
||||
<div style={{ fontSize: 12, fontWeight: 400, marginTop: 5 }}>
|
||||
{intl.get("新版本")} {lastVersion}{" "}
|
||||
{intl.get("可用,你使用的版本为")} {systemInfo.version}。
|
||||
{intl.get('新版本可用,当前版本', {
|
||||
version: lastVersion,
|
||||
current: systemInfo.version,
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
@@ -84,52 +81,60 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||
<Ansi>{lastLog}</Ansi>
|
||||
</pre>
|
||||
),
|
||||
okText: intl.get("下载更新"),
|
||||
cancelText: intl.get("以后再说"),
|
||||
okText: intl.get('下载更新'),
|
||||
cancelText: intl.get('以后再说'),
|
||||
onOk() {
|
||||
showUpdatingModal();
|
||||
request
|
||||
.put(`${config.apiPrefix}system/update`)
|
||||
.then((_data: any) => { })
|
||||
.catch((error: any) => {
|
||||
console.log(error);
|
||||
});
|
||||
startUpdate();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const showUpdatingModal = () => {
|
||||
setValue("");
|
||||
setValue('');
|
||||
lastStatusRef.current = 'running';
|
||||
setUpdateStatus('running');
|
||||
modalRef.current = Modal.info({
|
||||
width: 600,
|
||||
maskClosable: false,
|
||||
closable: false,
|
||||
keyboard: false,
|
||||
okButtonProps: { disabled: true },
|
||||
title: intl.get("下载更新中..."),
|
||||
title: intl.get('下载更新中...'),
|
||||
centered: true,
|
||||
content: (
|
||||
<pre>
|
||||
<Ansi>{value}</Ansi>
|
||||
</pre>
|
||||
),
|
||||
afterClose: () => {
|
||||
modalRef.current = undefined;
|
||||
},
|
||||
content: <pre />,
|
||||
});
|
||||
};
|
||||
|
||||
const startUpdate = async () => {
|
||||
showUpdatingModal();
|
||||
try {
|
||||
const response = await request.put(`${config.apiPrefix}system/update`);
|
||||
if (response.code !== 200) throw new Error(response.message);
|
||||
} catch {
|
||||
lastStatusRef.current = 'failed';
|
||||
setUpdateStatus('failed');
|
||||
message.error(intl.get('更新失败,请检查网络及日志或稍后再试'));
|
||||
}
|
||||
};
|
||||
|
||||
const reloadSystem = (type?: string) => {
|
||||
request
|
||||
.put(`${config.apiPrefix}update/${type}`)
|
||||
.then((_data: any) => {
|
||||
.then(({ code }: any) => {
|
||||
if (code !== 200) return;
|
||||
message.success({
|
||||
content: (
|
||||
<span>
|
||||
{intl.get("系统将在")}
|
||||
{intl.get('系统将在')}
|
||||
<Countdown
|
||||
className="inline-countdown"
|
||||
format="ss"
|
||||
value={Date.now() + 1000 * 30}
|
||||
/>
|
||||
{intl.get("秒后自动刷新")}
|
||||
{intl.get('秒后自动刷新')}
|
||||
</span>
|
||||
),
|
||||
duration: 30,
|
||||
@@ -148,15 +153,15 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||
Modal.confirm({
|
||||
width: 600,
|
||||
maskClosable: false,
|
||||
title: intl.get("确认重启"),
|
||||
title: intl.get('确认重启'),
|
||||
centered: true,
|
||||
content: intl.get("系统安装包下载成功,确认重启"),
|
||||
okText: intl.get("重启"),
|
||||
content: intl.get('系统安装包下载成功,确认重启'),
|
||||
okText: intl.get('重启'),
|
||||
onOk() {
|
||||
reloadSystem("system");
|
||||
reloadSystem('system');
|
||||
},
|
||||
onCancel() {
|
||||
modalRef.current.update({
|
||||
modalRef.current?.update({
|
||||
maskClosable: true,
|
||||
closable: true,
|
||||
okButtonProps: { disabled: false },
|
||||
@@ -166,8 +171,8 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!value) return;
|
||||
const updateFailed = lastStatusRef.current === 'failed';
|
||||
if (!modalRef.current) return;
|
||||
const updateFailed = updateStatus === 'failed';
|
||||
|
||||
modalRef.current.update({
|
||||
maskClosable: updateFailed,
|
||||
@@ -182,27 +187,32 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||
</>
|
||||
),
|
||||
});
|
||||
}, [value]);
|
||||
}, [value, updateStatus]);
|
||||
|
||||
const handleMessage = useCallback((payload: any) => {
|
||||
if (!modalRef.current || lastStatusRef.current !== 'running') return;
|
||||
const { message: _message, status } = payload;
|
||||
|
||||
if (status === 'failed') {
|
||||
lastStatusRef.current = 'failed';
|
||||
message.error(intl.get("更新失败,请检查网络及日志或稍后再试"));
|
||||
setUpdateStatus('failed');
|
||||
message.error(intl.get('更新失败,请检查网络及日志或稍后再试'));
|
||||
}
|
||||
|
||||
if (status === 'success') {
|
||||
lastStatusRef.current = 'success';
|
||||
setUpdateStatus('success');
|
||||
setTimeout(() => {
|
||||
showReloadModal();
|
||||
if (modalRef.current && lastStatusRef.current === 'success') {
|
||||
showReloadModal();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
document
|
||||
.querySelector("#log-identifier")
|
||||
?.scrollIntoView({ behavior: "smooth" });
|
||||
.querySelector('#log-identifier')
|
||||
?.scrollIntoView({ behavior: 'smooth' });
|
||||
}, 600);
|
||||
|
||||
if (_message) {
|
||||
@@ -212,24 +222,26 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||
|
||||
useEffect(() => {
|
||||
const ws = WebSocketManager.getInstance();
|
||||
ws.subscribe("updateSystemVersion", handleMessage);
|
||||
ws.subscribe('updateSystemVersion', handleMessage);
|
||||
|
||||
return () => {
|
||||
ws.unsubscribe("updateSystemVersion", handleMessage);
|
||||
ws.unsubscribe('updateSystemVersion', handleMessage);
|
||||
modalRef.current?.destroy();
|
||||
modalRef.current = undefined;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button type="primary" onClick={checkUpgrade}>
|
||||
{intl.get("检查更新")}
|
||||
{intl.get('检查更新')}
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => reloadSystem("reload")}
|
||||
onClick={() => reloadSystem('reload')}
|
||||
style={{ marginLeft: 8 }}
|
||||
>
|
||||
{intl.get("重新启动")}
|
||||
{intl.get('重新启动')}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -33,6 +33,11 @@
|
||||
gap: 40px;
|
||||
}
|
||||
|
||||
.notify-log-table .ant-table-thead > tr > th,
|
||||
.login-log-table .ant-table-thead > tr > th {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ql-container-wrapper.ql-setting-container {
|
||||
.ant-tabs-tabpane > div {
|
||||
padding-left: 2px;
|
||||
|
||||
@@ -47,7 +47,7 @@ const LoginLog = ({ data, height }: { data: Array<any>; height: number }) => {
|
||||
const columns = [
|
||||
{
|
||||
title: intl.get('序号'),
|
||||
width: 50,
|
||||
width: 90,
|
||||
render: (text: string, record: any, index: number) => index + 1,
|
||||
},
|
||||
{
|
||||
@@ -63,6 +63,7 @@ const LoginLog = ({ data, height }: { data: Array<any>; height: number }) => {
|
||||
dataIndex: 'address',
|
||||
width: 120,
|
||||
key: 'address',
|
||||
render: (text: string) => (text === '内网IP' ? intl.get('内网IP') : text),
|
||||
},
|
||||
{
|
||||
title: intl.get('登录IP'),
|
||||
@@ -74,13 +75,13 @@ const LoginLog = ({ data, height }: { data: Array<any>; height: number }) => {
|
||||
title: intl.get('登录设备'),
|
||||
dataIndex: 'platform',
|
||||
key: 'platform',
|
||||
width: 80,
|
||||
width: 140,
|
||||
},
|
||||
{
|
||||
title: intl.get('登录状态'),
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
width: 80,
|
||||
width: 140,
|
||||
render: (text: string, record: any) => (
|
||||
<Tag color={LoginStatusColor[record.status]} style={{ marginRight: 0 }}>
|
||||
{intl.get(LoginStatus[record.status])}
|
||||
@@ -116,12 +117,13 @@ const LoginLog = ({ data, height }: { data: Array<any>; height: number }) => {
|
||||
return (
|
||||
<>
|
||||
<Table
|
||||
className="login-log-table"
|
||||
columns={columns}
|
||||
pagination={false}
|
||||
dataSource={data}
|
||||
rowKey={(record) => `${record.ip}-${record.timestamp}`}
|
||||
size="middle"
|
||||
scroll={{ x: 1000, y: height }}
|
||||
scroll={{ x: 1120, y: height }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@ import intl from 'react-intl-universal';
|
||||
import React from 'react';
|
||||
import { Table, Tag } from 'antd';
|
||||
import dayjs from 'dayjs';
|
||||
import './index.less';
|
||||
|
||||
interface NotifyLogItem {
|
||||
id?: number;
|
||||
@@ -40,7 +41,7 @@ const columns = [
|
||||
},
|
||||
{
|
||||
title: intl.get('序号'),
|
||||
width: 50,
|
||||
width: 90,
|
||||
render: (text: string, record: any, index: number) => {
|
||||
return index + 1;
|
||||
},
|
||||
@@ -79,7 +80,7 @@ const columns = [
|
||||
title: intl.get('发送状态'),
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
width: 90,
|
||||
width: 140,
|
||||
render: (text: string, record: NotifyLogItem) => {
|
||||
const statusKey = record.status ?? 1;
|
||||
return (
|
||||
@@ -101,12 +102,13 @@ const NotifyLog = ({
|
||||
return (
|
||||
<>
|
||||
<Table
|
||||
className="notify-log-table"
|
||||
columns={columns}
|
||||
pagination={false}
|
||||
dataSource={data}
|
||||
rowKey="id"
|
||||
size="middle"
|
||||
scroll={{ x: 1000, y: height }}
|
||||
scroll={{ x: 1240, y: height }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -103,7 +103,7 @@ const Subscription = () => {
|
||||
key: 'type',
|
||||
width: 130,
|
||||
render: (text: string, record: any) => {
|
||||
return (SubscriptionType as any)[record.type];
|
||||
return intl.get((SubscriptionType as any)[record.type]);
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -121,7 +121,7 @@ const Subscription = () => {
|
||||
render: (text: string, record: any) => {
|
||||
if (record.schedule_type === 'interval') {
|
||||
const { type, value } = record.interval_schedule;
|
||||
return `每${value}${(IntervalSchedule as any)[type]}`;
|
||||
return intl.get('间隔定时规则', { value, unit: intl.get((IntervalSchedule as any)[type]) });
|
||||
}
|
||||
return record.schedule;
|
||||
},
|
||||
@@ -369,14 +369,13 @@ const Subscription = () => {
|
||||
|
||||
const enabledOrDisabledSubscription = (record: any, index: number) => {
|
||||
Modal.confirm({
|
||||
title: `确认${
|
||||
record.is_disabled === 1 ? intl.get('启用') : intl.get('禁用')
|
||||
}`,
|
||||
title: intl.get('确认操作', {
|
||||
operation:
|
||||
record.is_disabled === 1 ? intl.get('启用') : intl.get('禁用'),
|
||||
}),
|
||||
content: (
|
||||
<>
|
||||
{intl.get('确认')}
|
||||
{record.is_disabled === 1 ? intl.get('启用') : intl.get('禁用')}
|
||||
{intl.get('定时订阅')}{' '}
|
||||
{intl.get('确认操作对象', { operation: record.is_disabled === 1 ? intl.get('启用') : intl.get('禁用'), object: intl.get('定时订阅') })}{' '}
|
||||
<Text style={{ wordBreak: 'break-all' }} type="warning">
|
||||
{record.name}
|
||||
</Text>{' '}
|
||||
@@ -569,7 +568,7 @@ const Subscription = () => {
|
||||
simple: isPhone,
|
||||
defaultPageSize: 20,
|
||||
showTotal: (total: number, range: number[]) =>
|
||||
`第 ${range[0]}-${range[1]} 条/总共 ${total} 条`,
|
||||
intl.get('分页总数', { start: range[0], end: range[1], total }),
|
||||
pageSizeOptions: [20, 100, 500, 1000] as any,
|
||||
}}
|
||||
dataSource={value}
|
||||
|
||||
@@ -150,10 +150,10 @@ const SubscriptionModal = ({
|
||||
precision={0}
|
||||
min={1}
|
||||
value={intervalNumber}
|
||||
style={{ width: 'calc(100% - 58px)' }}
|
||||
style={{ width: 'calc(100% - 100px)' }}
|
||||
onChange={numberChange}
|
||||
/>
|
||||
<Select value={intervalType} onChange={intervalTypeChange}>
|
||||
<Select value={intervalType} onChange={intervalTypeChange} style={{ width: 100 }}>
|
||||
<Option value="days">{intl.get('天')}</Option>
|
||||
<Option value="hours">{intl.get('时')}</Option>
|
||||
<Option value="minutes">{intl.get('分')}</Option>
|
||||
@@ -527,8 +527,8 @@ const SubscriptionModal = ({
|
||||
onPaste={onNamePaste}
|
||||
placeholder={
|
||||
type === 'private-repo'
|
||||
? 'SOCK5代理,例如 IP:PORT'
|
||||
: 'HTTP/SOCK5代理,例如 http://127.0.0.1:1080'
|
||||
? intl.get('SOCK5代理,例如 IP:PORT')
|
||||
: intl.get('HTTP/SOCK5代理,例如 http://127.0.0.1:1080')
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
Reference in New Issue
Block a user