Compare commits

..

No commits in common. '4599b3d39bda419d3e966ef72144c82d15bb338a' and 'ded88c7721a86db4a2f0e266b6ca706ce8fe3962' have entirely different histories.

@ -1,24 +1,20 @@
import React, { useState, useRef, useEffect } from 'react'; import React, { useState, useRef, useEffect } from 'react';
import { Modal, Button, Message, Tabs } from '@arco-design/web-react'; import { Modal, Button, Message, Divider, Tabs, Checkbox } from '@arco-design/web-react';
import { IconUpload, IconDelete, IconFile } from '@arco-design/web-react/icon'; import { IconUpload, IconDelete, IconFile } from '@arco-design/web-react/icon';
import styles from './style/importComponentModal.module.less'; import styles from './style/importComponentModal.module.less';
interface ParsedComponentInfo {
baseInfo?: any;
operates?: any[];
}
interface ImportComponentModalProps { interface ImportComponentModalProps {
visible: boolean; visible: boolean;
onCancel: () => void; onCancel: () => void;
onOk: (files: FileItem[]) => void; onOk: (files: FileItem[]) => void;
onFileSelect: (file: File) => Promise<ParsedComponentInfo[] | ParsedComponentInfo | null>; onFileSelect: (file: File) => void;
componentInfo: any; // 单次文件解析的结果
loading: boolean; loading: boolean;
} }
interface FileItem { interface FileItem {
file: File; file: File;
componentInfo: ParsedComponentInfo[]; // 该文件包含的组件列表 componentInfo: any[]; // 该文件包含的组件列表
} }
const ImportComponentModal: React.FC<ImportComponentModalProps> = ({ const ImportComponentModal: React.FC<ImportComponentModalProps> = ({
@ -26,10 +22,12 @@ const ImportComponentModal: React.FC<ImportComponentModalProps> = ({
onCancel, onCancel,
onOk, onOk,
onFileSelect, onFileSelect,
componentInfo,
loading loading
}) => { }) => {
const [fileItems, setFileItems] = useState<FileItem[]>([]); const [fileItems, setFileItems] = useState<FileItem[]>([]);
const [activeTabKey, setActiveTabKey] = useState<string>('0'); const [activeTabKey, setActiveTabKey] = useState<string>('0');
const [pendingFile, setPendingFile] = useState<File | null>(null); // 等待解析的文件
const fileInputRef = useRef<HTMLInputElement>(null); const fileInputRef = useRef<HTMLInputElement>(null);
// 当弹窗关闭时清空所有状态 // 当弹窗关闭时清空所有状态
@ -37,60 +35,56 @@ const ImportComponentModal: React.FC<ImportComponentModalProps> = ({
if (!visible) { if (!visible) {
setFileItems([]); setFileItems([]);
setActiveTabKey('0'); setActiveTabKey('0');
setPendingFile(null);
} }
}, [visible]); }, [visible]);
const updateFileItem = (file: File, componentInfo: ParsedComponentInfo[] | ParsedComponentInfo) => { // 当 componentInfo 更新时,添加到 fileItems`
const componentList = Array.isArray(componentInfo) ? componentInfo : [componentInfo]; useEffect(() => {
let nextActiveKey = '0'; if (pendingFile && componentInfo) {
const componentList = Array.isArray(componentInfo) ? componentInfo : [componentInfo];
setFileItems((prev) => { // 检查文件是否已存在
const existingIndex = prev.findIndex((item) => item.file.name === file.name); const existingIndex = fileItems.findIndex(item => item.file.name === pendingFile.name);
if (existingIndex >= 0) { if (existingIndex >= 0) {
nextActiveKey = String(existingIndex); // 更新现有文件
const nextItems = [...prev]; const newFileItems = [...fileItems];
nextItems[existingIndex] = { newFileItems[existingIndex] = {
file, file: pendingFile,
componentInfo: componentList componentInfo: componentList
}; };
return nextItems; setFileItems(newFileItems);
} }
else {
nextActiveKey = String(prev.length); // 添加新文件
return [ const newFileItem: FileItem = {
...prev, file: pendingFile,
{
file,
componentInfo: componentList componentInfo: componentList
} };
]; const updatedFileItems = [...fileItems, newFileItem];
}); setFileItems(updatedFileItems);
setActiveTabKey(String(fileItems.length)); // 切换到新添加的标签页
setActiveTabKey(nextActiveKey); }
};
const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
const selectedFiles = Array.from(event.target.files ?? []);
if (selectedFiles.length === 0) return;
const validFiles = selectedFiles.filter((file) => file.name.match(/\.zip$/i));
const invalidFileCount = selectedFiles.length - validFiles.length;
if (invalidFileCount > 0) { setPendingFile(null);
Message.error('请选择 ZIP 压缩包文件');
} }
}, [componentInfo]);
for (const file of validFiles) { const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const parsedComponentInfo = await onFileSelect(file); const files = event.target.files;
if (!files || files.length === 0) return;
if (!parsedComponentInfo) { // 验证文件类型 (.zip)
continue; const file = files[0];
} if (!file.name.match(/\.zip$/i)) {
Message.error('请选择ZIP压缩包文件');
updateFileItem(file, parsedComponentInfo); event.target.value = '';
return;
} }
setPendingFile(file);
onFileSelect(file);
event.target.value = ''; event.target.value = '';
}; };
@ -122,6 +116,7 @@ const ImportComponentModal: React.FC<ImportComponentModalProps> = ({
const handleClose = () => { const handleClose = () => {
setFileItems([]); setFileItems([]);
setActiveTabKey('0'); setActiveTabKey('0');
setPendingFile(null);
onCancel(); onCancel();
}; };
@ -156,7 +151,6 @@ const ImportComponentModal: React.FC<ImportComponentModalProps> = ({
> >
<input <input
ref={fileInputRef} ref={fileInputRef}
multiple
type="file" type="file"
accept=".zip" accept=".zip"
style={{ display: 'none' }} style={{ display: 'none' }}
@ -164,7 +158,7 @@ const ImportComponentModal: React.FC<ImportComponentModalProps> = ({
/> />
<div className={styles['import-modal-content']}> <div className={styles['import-modal-content']}>
{fileItems.length === 0 && ( {fileItems.length === 0 && !pendingFile && (
<div className={styles['empty-state']}> <div className={styles['empty-state']}>
<p className={styles['empty-text']}>&#34;&#34;</p> <p className={styles['empty-text']}>&#34;&#34;</p>
<p className={styles['empty-hint']}> .zip </p> <p className={styles['empty-hint']}> .zip </p>
@ -178,9 +172,9 @@ const ImportComponentModal: React.FC<ImportComponentModalProps> = ({
type="card" type="card"
> >
{fileItems.map((fileItem, fileIndex) => { {fileItems.map((fileItem, fileIndex) => {
const currentComponent = fileItem.componentInfo[0]; const current = fileItems[activeTabKey];
const baseInfo = currentComponent?.baseInfo || {}; const baseInfo = current.componentInfo[0].baseInfo;
const operates = currentComponent?.operates || []; const operates = current.componentInfo[0].operates;
return ( return (
<Tabs.TabPane <Tabs.TabPane
key={String(fileIndex)} key={String(fileIndex)}

@ -84,6 +84,7 @@ const GlobalVarContainer = () => {
{ label: 'Python', value: 'Python' } { label: 'Python', value: 'Python' }
]; ];
const [importModalVisible, setImportModalVisible] = useState(false); // 导入弹窗 const [importModalVisible, setImportModalVisible] = useState(false); // 导入弹窗
const [importComponentInfo, setImportComponentInfo] = useState(null); // 导入组件信息
const [importLoading, setImportLoading] = useState(false); // 导入加载状态 const [importLoading, setImportLoading] = useState(false); // 导入加载状态
const [showOffSaleModal, setShowOffSaleModal] = useState(false); const [showOffSaleModal, setShowOffSaleModal] = useState(false);
const [offSaleComponent, setOffSaleComponent] = useState(null); const [offSaleComponent, setOffSaleComponent] = useState(null);
@ -422,16 +423,16 @@ const GlobalVarContainer = () => {
const res: any = await getImportComponentInfo({ file }); const res: any = await getImportComponentInfo({ file });
if (res.code === 200) { if (res.code === 200) {
setImportComponentInfo(res.data);
Message.success('组件信息解析成功'); Message.success('组件信息解析成功');
return res.data;
} }
else { else {
Message.error(res.msg || '解析组件信息失败'); Message.error(res.msg || '解析组件信息失败');
return null; setImportComponentInfo(null);
} }
} catch (error) { } catch (error) {
Message.error('解析组件信息失败'); Message.error('解析组件信息失败');
return null; setImportComponentInfo(null);
} finally { } finally {
setImportLoading(false); setImportLoading(false);
} }
@ -452,6 +453,7 @@ const GlobalVarContainer = () => {
if (res.code === 200) { if (res.code === 200) {
Message.success('组件导入成功'); Message.success('组件导入成功');
setImportModalVisible(false); setImportModalVisible(false);
setImportComponentInfo(null);
fetchComponentData(); // 刷新列表 fetchComponentData(); // 刷新列表
} }
else { else {
@ -469,6 +471,7 @@ const GlobalVarContainer = () => {
// 关闭导入弹窗 // 关闭导入弹窗
const handleImportCancel = () => { const handleImportCancel = () => {
setImportModalVisible(false); setImportModalVisible(false);
setImportComponentInfo(null);
}; };
// 查看审核历史 // 查看审核历史
@ -887,6 +890,7 @@ const GlobalVarContainer = () => {
onCancel={handleImportCancel} onCancel={handleImportCancel}
onOk={handleImportConfirm} onOk={handleImportConfirm}
onFileSelect={handleImportFileSelect} onFileSelect={handleImportFileSelect}
componentInfo={importComponentInfo}
loading={importLoading} loading={importLoading}
/> />

Loading…
Cancel
Save