Merge remote-tracking branch 'origin/main'

# Conflicts:
#	AGENTS.md
#	backend/docs/docs.go
#	backend/docs/swagger.json
#	backend/docs/swagger.yaml
#	frontend/components/providers/title-updater.tsx
#	frontend/messages/fragments/admin.en.json
#	frontend/messages/fragments/admin.zh-CN.json
#	frontend/proxy.ts
This commit is contained in:
ryan
2026-09-03 09:16:22 +08:00
1065 changed files with 271858 additions and 9600 deletions
@@ -4,6 +4,7 @@
'use client';
import * as React from 'react';
import { useTranslations } from 'next-intl';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import {
@@ -67,8 +68,6 @@ import {
PopoverTrigger,
} from '@/components/ui/popover';
import { useTranslations } from 'next-intl';
import { ErrorInline } from '@/components/layout/error';
import { LoadingStateWithBorder } from '@/components/layout/loading';
import { EmptyStateWithBorder } from '@/components/layout/empty';
@@ -263,8 +262,8 @@ export function EventsTab() {
);
if (taskMeta) {
const defaultTemplate = {
title: `任务完成: ${taskMeta.name}`,
content: `异步任务 {{task_name}} 已完成。状态: {{task_status}},耗时: {{task_duration}} ms。`,
title: t('taskCompleteTitle', { name: taskMeta.name }),
content: t('taskCompleteContent'),
level: 'INFO',
};
setNewEventTemplate(JSON.stringify(defaultTemplate, null, 2));
@@ -650,11 +649,11 @@ export function EventsTab() {
{newEventChannels.length > 0
? newEventChannels
.map((ch) => {
if (ch === 'email') return '邮件';
if (ch === 'email') return t('emailChannel');
return ch;
})
.join(', ')
: '选择已配置推送渠道'}
: t('selectConfiguredChannels')}
<ChevronDown className='ml-2 size-4 shrink-0 opacity-50' />
</Button>
</PopoverTrigger>
@@ -680,7 +679,7 @@ export function EventsTab() {
}
}}
/>
<span>{ch === 'email' ? '邮件推送' : ch}</span>
<span>{ch === 'email' ? t('emailPush') : ch}</span>
</label>
))}
{availableChannels.length === 0 && (
@@ -699,7 +698,7 @@ export function EventsTab() {
</Label>
<Input
type='text'
placeholder='多个目标用英文逗号分隔,例如:user1@test.com, user2@test.com'
placeholder={t('pushTargetsPlaceholder')}
value={newEventTargets}
onChange={(e) => setNewEventTargets(e.target.value)}
className='text-xs h-9'
@@ -4,6 +4,7 @@
'use client';
import * as React from 'react';
import { useTranslations } from 'next-intl';
import { useQuery } from '@tanstack/react-query';
import {
ChevronLeft,
@@ -35,7 +36,6 @@ import {
import { ErrorInline } from '@/components/layout/error';
import { LoadingStateWithBorder } from '@/components/layout/loading';
import { cn } from '@/lib/utils';
import { useTranslations } from 'next-intl';
import {
Dialog,
@@ -4,11 +4,11 @@
'use client';
import * as React from 'react';
import { useTranslations } from 'next-intl';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import { Edit2, Loader2, Play, Plus, Settings, Trash2 } from 'lucide-react';
import { useTranslations } from 'next-intl';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
@@ -219,7 +219,7 @@ export function SettingsTab() {
? channelToken
: channelOther;
if (field.required && !value.trim()) {
toast.error(`${field.label}不能为空`);
toast.error(t('fieldRequired', { label: field.label }));
return;
}
}
@@ -516,7 +516,7 @@ export function SettingsTab() {
<>
<div className='p-3.5 border rounded-lg bg-muted/20 space-y-1.5'>
<div className='text-xs font-semibold'>
{activeDef.name}配置说明
{t('configHelp', { name: activeDef.name })}
</div>
<p className='text-[11px] text-muted-foreground leading-relaxed'>
{activeDef.description}