refactor: Webhook 移入系统设置「消息通知」Tab,取消独立菜单

- WebhookConfig 页面转为可嵌入卡片组件 WebhookManager
  (标准设置卡样式,逻辑不变),渲染于飞书通知卡下方
- 移除侧边栏「Webhook」菜单项、/webhooks 路由与页面文件
  (旧地址自动回退流水线页)
- 使用指南/接口文档同步更新 Webhook 配置入口描述
This commit is contained in:
Logan.Li committed 2026-10-27 14:53:00 +08:00
1 parent ed88a18e03
commit 695c1c2357
6 files changed
+22 -23

No files matched your search

+1 -6
View File
@@ -17,7 +17,6 @@ import ToolConfig from '@/pages/ToolConfig';
import JenkinsImport from '@/pages/JenkinsImport';
import BatchRelease from '@/pages/BatchRelease';
import ReleaseRecords from '@/pages/ReleaseRecords';
import WebhookConfig from '@/pages/WebhookConfig';
import GitOpsDeploy from '@/pages/GitOpsDeploy';
import PluginManager from '@/pages/PluginManager';
import SystemSettings from '@/pages/SystemSettings';
@@ -27,7 +26,7 @@ import UserManage from '@/pages/UserManage';
import Docs from '@/pages/Docs';
import { apiClient, auth } from '@/lib/api';
export type ModuleType = 'pipelines' | 'gitops' | 'batch-release' | 'release-records' | 'environments' | 'credentials' | 'build-nodes' | 'tools' | 'jenkins-import' | 'webhooks' | 'plugins' | 'users' | 'docs' | 'settings';
export type ModuleType = 'pipelines' | 'gitops' | 'batch-release' | 'release-records' | 'environments' | 'credentials' | 'build-nodes' | 'tools' | 'jenkins-import' | 'plugins' | 'users' | 'docs' | 'settings';
export type EditorTab = '基本信息' | '流程配置' | '触发设置' | '变量和缓存' | '发布';
// 路由 ↔ 模块映射(用户可直接访问 /release、/pipelines/1 等)
@@ -42,7 +41,6 @@ const ROUTE_TO_MODULE: Record<string, ModuleType> = {
'/build-nodes': 'build-nodes',
'/tools': 'tools',
'/jenkins-import': 'jenkins-import',
'/webhooks': 'webhooks',
'/plugins': 'plugins',
'/users': 'users',
'/docs': 'docs',
@@ -59,7 +57,6 @@ const MODULE_TO_ROUTE: Record<ModuleType, string> = {
'build-nodes': '/build-nodes',
tools: '/tools',
'jenkins-import': '/jenkins-import',
webhooks: '/webhooks',
plugins: '/plugins',
users: '/users',
docs: '/docs',
@@ -230,8 +227,6 @@ export default function App() {
return <BatchRelease onViewRecords={() => goToModule('release-records')} />;
case 'release-records':
return <ReleaseRecords />;
case 'webhooks':
return <WebhookConfig />;
case 'gitops':
return <GitOpsDeploy />;
case 'plugins':
+1 -3
View File
@@ -10,7 +10,6 @@ import {
Rocket,
Zap,
History,
Webhook,
CloudSync,
Puzzle,
Settings,
@@ -24,7 +23,7 @@ import { useQuery } from '@tanstack/react-query';
import { apiClient } from '@/lib/api';
import { useTheme } from '@/providers/theme';
type ModuleType = 'pipelines' | 'gitops' | 'batch-release' | 'release-records' | 'environments' | 'credentials' | 'build-nodes' | 'tools' | 'jenkins-import' | 'webhooks' | 'plugins' | 'users' | 'docs' | 'settings';
type ModuleType = 'pipelines' | 'gitops' | 'batch-release' | 'release-records' | 'environments' | 'credentials' | 'build-nodes' | 'tools' | 'jenkins-import' | 'plugins' | 'users' | 'docs' | 'settings';
interface SidebarProps {
activeModule: ModuleType;
@@ -56,7 +55,6 @@ const menuGroups: { label: string; items: { id: ModuleType; label: string; icon:
label: '集成',
items: [
{ id: 'jenkins-import', label: 'Jenkins导入', icon: Download, badge: null },
{ id: 'webhooks', label: 'Webhook', icon: Webhook, badge: null },
{ id: 'tools', label: '工具配置', icon: Wrench, badge: null },
],
},
@@ -49,7 +49,7 @@ const formatTime = (v: string | null | undefined) => {
const emptyForm = { name: '', url: '', secret: '', events: [] as string[] };
export default function WebhookConfig() {
export default function WebhookManager() {
const queryClient = useQueryClient();
const [showForm, setShowForm] = useState(false);
const [editingId, setEditingId] = useState<number | null>(null);
@@ -137,14 +137,13 @@ export default function WebhookConfig() {
};
return (
<div className="h-full flex flex-col" style={{ background: 'var(--canvas-bg)' }}>
{/* Header */}
<div className="px-5 py-3 border-b flex items-center justify-between flex-shrink-0" style={{ background: 'var(--panel-bg)', borderColor: 'var(--border-color)' }}>
<div className="flex items-center gap-3">
<h1 className="text-[15px] font-semibold" style={{ color: 'var(--text-primary)' }}>Webhook 配置</h1>
<span className="text-[11px] px-2 py-[2px] rounded-full font-medium" style={{ background: 'var(--panel-bg-secondary)', color: 'var(--text-tertiary)' }}>
{webhooks.length}
</span>
<div className="rounded-lg border overflow-hidden" style={{ background: 'var(--panel-bg)', borderColor: 'var(--border-color)' }}>
{/* Card Header */}
<div className="px-5 py-3 border-b flex items-center justify-between" style={{ borderColor: 'var(--border-color)', background: 'var(--panel-bg-secondary)' }}>
<div className="flex items-center gap-2">
<Webhook className="w-4 h-4" style={{ color: 'var(--accent-blue)' }} />
<span className="text-[13px] font-semibold" style={{ color: 'var(--text-primary)' }}>Webhook 通知</span>
<span className="text-[10px]" style={{ color: 'var(--text-tertiary)' }}>发布事件回调第三方(HMAC-SHA256 签名)</span>
</div>
<button
onClick={() => { setShowForm(true); setEditingId(null); setEditingSecretSet(false); setForm(emptyForm); }}
@@ -155,8 +154,8 @@ export default function WebhookConfig() {
</button>
</div>
{/* Content */}
<div className="flex-1 overflow-y-auto custom-scrollbar p-5">
{/* Body */}
<div className="p-5">
{showForm && (
<div className="rounded-lg border p-4 mb-4" style={{ background: 'var(--panel-bg)', borderColor: 'var(--border-color)' }}>
<h3 className="text-[14px] font-semibold mb-3" style={{ color: 'var(--text-primary)' }}>{editingId != null ? '编辑 Webhook' : '新建 Webhook'}</h3>
+5
View File
@@ -7,6 +7,7 @@ import { toast } from 'sonner';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '@/lib/api';
import { useTheme, type ThemeMode } from '@/providers/theme';
import WebhookManager from '@/components/settings/WebhookManager';
interface ThemeConfig {
mode: 'light' | 'dark' | 'system';
@@ -638,6 +639,10 @@ export default function SystemSettings() {
</div>
</div>
</div>
<div className="mt-4">
<WebhookManager />
</div>
</>
)}