diff --git a/frontend/src/domain/dataSource/DataSourceRegistry.ts b/frontend/src/domain/dataSource/DataSourceRegistry.ts index 114d9204..c69df3a3 100644 --- a/frontend/src/domain/dataSource/DataSourceRegistry.ts +++ b/frontend/src/domain/dataSource/DataSourceRegistry.ts @@ -9,6 +9,7 @@ import { gitRepositoriesConfig } from './presets/git'; import { dockerRegistriesConfig } from './presets/docker'; import { notificationChannelTypesConfig, notificationChannelsConfig } from './presets/notification'; import { usersConfig, rolesConfig, departmentsConfig } from './presets/user'; +import { environmentsConfig, projectGroupsConfig, applicationsConfig } from './presets/deploy'; /** * 数据源配置注册表 @@ -22,7 +23,10 @@ export const DATA_SOURCE_REGISTRY: DataSourceRegistry = { [DataSourceType.NOTIFICATION_CHANNELS]: notificationChannelsConfig, [DataSourceType.USERS]: usersConfig, [DataSourceType.ROLES]: rolesConfig, - [DataSourceType.DEPARTMENTS]: departmentsConfig + [DataSourceType.DEPARTMENTS]: departmentsConfig, + [DataSourceType.ENVIRONMENTS]: environmentsConfig, + [DataSourceType.PROJECT_GROUPS]: projectGroupsConfig, + [DataSourceType.APPLICATIONS]: applicationsConfig }; /** diff --git a/frontend/src/domain/dataSource/presets/deploy.ts b/frontend/src/domain/dataSource/presets/deploy.ts new file mode 100644 index 00000000..8d716ff7 --- /dev/null +++ b/frontend/src/domain/dataSource/presets/deploy.ts @@ -0,0 +1,55 @@ +/** + * 部署相关数据源 + */ +import type { DataSourceConfig } from '../types'; + +/** + * 环境列表数据源 + */ +export const environmentsConfig: DataSourceConfig = { + url: '/api/v1/environments/list', + params: { enabled: true }, + transform: (data: any[]) => { + return data.map((item: any) => ({ + label: item.name, + value: item.id, + code: item.code, + type: item.type, + description: item.description + })); + } +}; + +/** + * 项目组列表数据源 + */ +export const projectGroupsConfig: DataSourceConfig = { + url: '/api/v1/project-groups/list', + params: { enabled: true }, + transform: (data: any[]) => { + return data.map((item: any) => ({ + label: item.name, + value: item.id, + code: item.code, + description: item.description + })); + } +}; + +/** + * 应用列表数据源 + */ +export const applicationsConfig: DataSourceConfig = { + url: '/api/v1/applications/list', + params: { enabled: true }, + transform: (data: any[]) => { + return data.map((item: any) => ({ + label: item.name, + value: item.id, + code: item.code, + projectGroupId: item.projectGroupId, + description: item.description + })); + } +}; + diff --git a/frontend/src/domain/dataSource/types.ts b/frontend/src/domain/dataSource/types.ts index e01af7fe..0ae5cd37 100644 --- a/frontend/src/domain/dataSource/types.ts +++ b/frontend/src/domain/dataSource/types.ts @@ -14,7 +14,10 @@ export enum DataSourceType { NOTIFICATION_CHANNELS = 'NOTIFICATION_CHANNELS', USERS = 'USERS', ROLES = 'ROLES', - DEPARTMENTS = 'DEPARTMENTS' + DEPARTMENTS = 'DEPARTMENTS', + ENVIRONMENTS = 'ENVIRONMENTS', + PROJECT_GROUPS = 'PROJECT_GROUPS', + APPLICATIONS = 'APPLICATIONS' } /** diff --git a/frontend/src/pages/Form/Definition/Designer.tsx b/frontend/src/pages/Form/Definition/Designer.tsx index 1835e590..bb8ac3d7 100644 --- a/frontend/src/pages/Form/Definition/Designer.tsx +++ b/frontend/src/pages/Form/Definition/Designer.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; +import { useToast } from '@/components/ui/use-toast'; import { FormDesigner } from '@/components/FormDesigner'; import type { FormSchema } from '@/components/FormDesigner'; import { ArrowLeft, Workflow } from 'lucide-react'; @@ -14,6 +15,7 @@ import type { FormDefinitionRequest } from './types'; const FormDesignerPage: React.FC = () => { const navigate = useNavigate(); const { id } = useParams<{ id: string }>(); + const { toast } = useToast(); const [formSchema, setFormSchema] = useState(null); const [formDefinition, setFormDefinition] = useState(null); @@ -37,7 +39,11 @@ const FormDesignerPage: React.FC = () => { // 保存表单(只更新 schema,不修改基本信息) const handleSave = async (schema: FormSchema) => { if (!id || !formDefinition) { - alert('表单信息加载失败'); + toast({ + variant: "destructive", + title: "保存失败", + description: "表单信息加载失败,请刷新页面后重试", + }); return; } @@ -49,14 +55,22 @@ const FormDesignerPage: React.FC = () => { isTemplate: formDefinition.isTemplate, schema, status: formDefinition.status || 'DRAFT', + version: formDefinition.version, // 乐观锁版本号 }; try { await updateDefinition(Number(id), request); - alert('保存成功'); + toast({ + title: "保存成功", + description: `表单 "${formDefinition.name}" 已保存`, + }); } catch (error) { console.error('保存表单失败:', error); - alert('保存失败'); + toast({ + variant: "destructive", + title: "保存失败", + description: error instanceof Error ? error.message : '未知错误,请稍后重试', + }); } }; diff --git a/frontend/src/pages/Form/Definition/components/EditBasicInfoModal.tsx b/frontend/src/pages/Form/Definition/components/EditBasicInfoModal.tsx index f20c8980..b92102a6 100644 --- a/frontend/src/pages/Form/Definition/components/EditBasicInfoModal.tsx +++ b/frontend/src/pages/Form/Definition/components/EditBasicInfoModal.tsx @@ -13,6 +13,7 @@ import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Switch } from '@/components/ui/switch'; +import { useToast } from '@/components/ui/use-toast'; import { Loader2, FileText, Tag, Folder, AlignLeft, Copy } from 'lucide-react'; import { getEnabledCategories } from '../../Category/service'; import { updateDefinition } from '../service'; @@ -27,6 +28,7 @@ interface EditBasicInfoModalProps { } const EditBasicInfoModal: React.FC = ({ visible, record, onClose, onSuccess }) => { + const { toast } = useToast(); const [submitting, setSubmitting] = useState(false); const [categories, setCategories] = useState([]); const [formData, setFormData] = useState({ @@ -70,15 +72,27 @@ const EditBasicInfoModal: React.FC = ({ visible, record if (!record) return; if (!formData.name.trim()) { - alert('请输入表单名称'); + toast({ + variant: "destructive", + title: "验证失败", + description: "请输入表单名称", + }); return; } if (!formData.key.trim()) { - alert('请输入表单标识'); + toast({ + variant: "destructive", + title: "验证失败", + description: "请输入表单标识", + }); return; } if (!/^[a-zA-Z0-9-]+$/.test(formData.key)) { - alert('表单标识只能包含英文字母、数字和中划线'); + toast({ + variant: "destructive", + title: "验证失败", + description: "表单标识只能包含英文字母、数字和中划线", + }); return; } @@ -92,15 +106,23 @@ const EditBasicInfoModal: React.FC = ({ visible, record schema: record.schema, status: record.status, isTemplate: formData.isTemplate, + version: record.version, // 乐观锁版本号 }; await updateDefinition(record.id, request); - alert('更新成功'); + toast({ + title: "更新成功", + description: `表单 "${formData.name}" 的基本信息已更新`, + }); onSuccess(); onClose(); } catch (error) { console.error('更新表单失败:', error); - alert('更新表单失败: ' + (error as Error).message); + toast({ + variant: "destructive", + title: "更新失败", + description: error instanceof Error ? error.message : '未知错误,请稍后重试', + }); } finally { setSubmitting(false); } diff --git a/frontend/src/pages/Form/Definition/types.ts b/frontend/src/pages/Form/Definition/types.ts index fcf8f3ca..832525c6 100644 --- a/frontend/src/pages/Form/Definition/types.ts +++ b/frontend/src/pages/Form/Definition/types.ts @@ -1,4 +1,4 @@ -import { BaseQuery } from '@/types/base'; +import { BaseQuery, BaseResponse } from '@/types/base'; import type { FormSchema } from '@/components/FormDesigner'; /** @@ -19,8 +19,7 @@ export interface FormDefinitionQuery extends BaseQuery { /** * 表单定义响应 */ -export interface FormDefinitionResponse { - id: number; +export interface FormDefinitionResponse extends BaseResponse { name: string; key: string; formVersion: number; @@ -30,10 +29,6 @@ export interface FormDefinitionResponse { tags?: string[]; status: FormDefinitionStatus; isTemplate: boolean; - createBy?: string; - createTime?: string; - updateBy?: string; - updateTime?: string; } /** @@ -48,5 +43,6 @@ export interface FormDefinitionRequest { tags?: string[]; status?: FormDefinitionStatus; isTemplate?: boolean; + version?: number; // 乐观锁版本号(更新时必传) }