feat(web): app import and Overwrite
This commit is contained in:
@@ -1522,6 +1522,8 @@ export const en = {
|
|||||||
"version":"app_release_id"
|
"version":"app_release_id"
|
||||||
// string, optional, application version ID; specify a historical release version ID, or omit to use the currently active version;
|
// string, optional, application version ID; specify a historical release version ID, or omit to use the currently active version;
|
||||||
}`,
|
}`,
|
||||||
|
uploadCover: 'Import and Overwrite',
|
||||||
|
refresh: 'Refresh Current Page',
|
||||||
},
|
},
|
||||||
userMemory: {
|
userMemory: {
|
||||||
userMemory: 'User Memory',
|
userMemory: 'User Memory',
|
||||||
|
|||||||
@@ -857,6 +857,8 @@ export const zh = {
|
|||||||
"version":"app_release_id"
|
"version":"app_release_id"
|
||||||
//string,可选,应用版本ID;指定历史发布版本ID,不传则使用当前生效版本;
|
//string,可选,应用版本ID;指定历史发布版本ID,不传则使用当前生效版本;
|
||||||
}`,
|
}`,
|
||||||
|
uploadCover: '导入并覆盖',
|
||||||
|
refresh: '刷新当前页',
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
totalRecords: '共 {{total}} 条记录'
|
totalRecords: '共 {{total}} 条记录'
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 16:27:52
|
* @Date: 2026-02-03 16:27:52
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-04-07 16:28:33
|
* @Last Modified time: 2026-04-13 18:19:27
|
||||||
*/
|
*/
|
||||||
import { type FC, useRef, useMemo } from 'react';
|
import { type FC, useRef, useMemo } from 'react';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
@@ -12,13 +12,14 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import styles from '../index.module.css'
|
import styles from '../index.module.css'
|
||||||
import type { Application, ApplicationModalRef } from '@/views/ApplicationManagement/types';
|
import type { Application, ApplicationModalRef, UploadWorkflowModalRef } from '@/views/ApplicationManagement/types';
|
||||||
import ApplicationModal from '@/views/ApplicationManagement/components/ApplicationModal'
|
import ApplicationModal from '@/views/ApplicationManagement/components/ApplicationModal'
|
||||||
import type { CopyModalRef, AgentRef, ClusterRef, WorkflowRef, FeaturesConfigForm } from '../types'
|
import type { CopyModalRef, AgentRef, ClusterRef, WorkflowRef, FeaturesConfigForm } from '../types'
|
||||||
import { deleteApplication, appExport } from '@/api/application'
|
import { deleteApplication, appExport } from '@/api/application'
|
||||||
import CopyModal from './CopyModal'
|
import CopyModal from './CopyModal'
|
||||||
import PageHeader from '@/components/Layout/PageHeader'
|
import PageHeader from '@/components/Layout/PageHeader'
|
||||||
import CheckList from '@/views/Workflow/components/CheckList'
|
import CheckList from '@/views/Workflow/components/CheckList'
|
||||||
|
import UploadModal from '@/views/ApplicationManagement/components/UploadModal'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tab keys for application configuration
|
* Tab keys for application configuration
|
||||||
@@ -77,6 +78,7 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
|
|||||||
const { id, source } = useParams();
|
const { id, source } = useParams();
|
||||||
const applicationModalRef = useRef<ApplicationModalRef>(null);
|
const applicationModalRef = useRef<ApplicationModalRef>(null);
|
||||||
const copyModalRef = useRef<CopyModalRef>(null);
|
const copyModalRef = useRef<CopyModalRef>(null);
|
||||||
|
const uploadModalRef = useRef<UploadWorkflowModalRef>(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format tab items for display
|
* Format tab items for display
|
||||||
@@ -111,6 +113,9 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
|
|||||||
case 'delete':
|
case 'delete':
|
||||||
handleDelete()
|
handleDelete()
|
||||||
break;
|
break;
|
||||||
|
case 'uploadCover':
|
||||||
|
uploadModalRef.current?.handleOpen()
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -165,11 +170,11 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
|
|||||||
* Format dropdown menu items
|
* Format dropdown menu items
|
||||||
*/
|
*/
|
||||||
const formatMenuItems = useMemo(() => {
|
const formatMenuItems = useMemo(() => {
|
||||||
const items = (application?.type !== 'multi_agent' ? ['edit', 'copy', 'export', 'delete'] : ['edit', 'copy', 'delete']).map(key => ({
|
const items = (application?.type !== 'multi_agent' ? ['edit', 'copy', 'export', 'uploadCover', 'delete'] : ['edit', 'copy', 'delete']).map(key => ({
|
||||||
key,
|
key,
|
||||||
icon: <div className={`rb:size-4 rb:mr-2 ${menuIcons[key]}`} />,
|
icon: <div className={`rb:size-4 rb:mr-2 ${menuIcons[key]}`} />,
|
||||||
danger: key === 'delete',
|
danger: key === 'delete',
|
||||||
label: t(`common.${key}`),
|
label: key === 'uploadCover' ? t('application.uploadCover') : t(`common.${key}`),
|
||||||
}))
|
}))
|
||||||
return items
|
return items
|
||||||
}, [t, handleClick, application])
|
}, [t, handleClick, application])
|
||||||
@@ -261,6 +266,11 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
|
|||||||
refresh={refresh}
|
refresh={refresh}
|
||||||
/>
|
/>
|
||||||
<CopyModal ref={copyModalRef} data={application as Application} />
|
<CopyModal ref={copyModalRef} data={application as Application} />
|
||||||
|
<UploadModal
|
||||||
|
ref={uploadModalRef}
|
||||||
|
refresh={refresh}
|
||||||
|
id={id as string}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-28 14:08:14
|
* @Date: 2026-02-28 14:08:14
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-12 17:19:46
|
* @Last Modified time: 2026-04-13 18:17:32
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* UploadModal Component
|
* UploadModal Component
|
||||||
@@ -28,6 +28,7 @@ import { appImport } from '@/api/application'
|
|||||||
interface UploadModalProps {
|
interface UploadModalProps {
|
||||||
/** Function to refresh the parent component after workflow import */
|
/** Function to refresh the parent component after workflow import */
|
||||||
refresh: () => void;
|
refresh: () => void;
|
||||||
|
id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -46,10 +47,11 @@ const steps = [
|
|||||||
* @param {React.Ref<UploadModalRef>} ref - Ref for imperative methods
|
* @param {React.Ref<UploadModalRef>} ref - Ref for imperative methods
|
||||||
*/
|
*/
|
||||||
const UploadModal = forwardRef<UploadModalRef, UploadModalProps>(({
|
const UploadModal = forwardRef<UploadModalRef, UploadModalProps>(({
|
||||||
refresh
|
refresh,
|
||||||
|
id
|
||||||
}, ref) => {
|
}, ref) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
// State management
|
// State management
|
||||||
const [visible, setVisible] = useState(false); // Modal visibility
|
const [visible, setVisible] = useState(false); // Modal visibility
|
||||||
const [form] = Form.useForm<{ file: File[] }>(); // Form instance
|
const [form] = Form.useForm<{ file: File[] }>(); // Form instance
|
||||||
@@ -87,8 +89,8 @@ const UploadModal = forwardRef<UploadModalRef, UploadModalProps>(({
|
|||||||
*/
|
*/
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
const values = form.getFieldsValue();
|
const values = form.getFieldsValue();
|
||||||
|
|
||||||
switch(current) {
|
switch (current) {
|
||||||
case 0: // Step 1: Upload file
|
case 0: // Step 1: Upload file
|
||||||
if (!values.file || values.file.length === 0) {
|
if (!values.file || values.file.length === 0) {
|
||||||
message.warning(t('application.pleaseUploadFile'));
|
message.warning(t('application.pleaseUploadFile'));
|
||||||
@@ -96,6 +98,9 @@ const UploadModal = forwardRef<UploadModalRef, UploadModalProps>(({
|
|||||||
}
|
}
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', values.file[0]);
|
formData.append('file', values.file[0]);
|
||||||
|
if (id) {
|
||||||
|
formData.append('app_id', id)
|
||||||
|
}
|
||||||
|
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
// Call import API
|
// Call import API
|
||||||
@@ -134,8 +139,12 @@ const UploadModal = forwardRef<UploadModalRef, UploadModalProps>(({
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'detail':
|
case 'detail':
|
||||||
// Open application detail page in new tab
|
if (id) {
|
||||||
window.open(`/#/application/config/${appId}`, '_blank');
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
// Open application detail page in new tab
|
||||||
|
window.open(`/#/application/config/${appId}`, '_blank');
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}, 100)
|
}, 100)
|
||||||
@@ -171,7 +180,7 @@ const UploadModal = forwardRef<UploadModalRef, UploadModalProps>(({
|
|||||||
loading={loading}
|
loading={loading}
|
||||||
onClick={() => handleJump('detail')}
|
onClick={() => handleJump('detail')}
|
||||||
>
|
>
|
||||||
{t('application.gotoDetail')}
|
{id ? t('application.refresh') : t('application.gotoDetail')}
|
||||||
</Button>
|
</Button>
|
||||||
]
|
]
|
||||||
default:
|
default:
|
||||||
@@ -244,7 +253,7 @@ const UploadModal = forwardRef<UploadModalRef, UploadModalProps>(({
|
|||||||
loading={loading}
|
loading={loading}
|
||||||
onClick={() => handleJump('detail')}
|
onClick={() => handleJump('detail')}
|
||||||
>
|
>
|
||||||
{t('application.gotoDetail')}
|
{id ? t('application.refresh') : t('application.gotoDetail')}
|
||||||
</Button>
|
</Button>
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user