@@ -187,9 +121,48 @@ const ComponentCoding = () => {
size={50}
style={{ marginTop: '20px', marginBottom: '30px' }}
>
-
-
组件筛选:
- {componentScreening()}
+
+
+
+ 组件名称:
+ {componentCoding.name || '未选择组件'}
+
+
+ 组件标识:
+ {componentCoding.projectId || '未选择组件'}
+
+
+ 组件选择:
+
+
+
@@ -200,17 +173,35 @@ const ComponentCoding = () => {
>
启动项设置
-
}
- placeholder={'搜索组件关键词'}
- style={{ width: 236 }}
- />
-
+
+
+
+
+ 同步代码
+
+
+
+ 复制git地址
+
+
+
+ 提交代码
+
+
+
+ {isFullscreen ? (
+
+ ) : (
+
+ )}
+
+
+
);
diff --git a/src/pages/componentDevelopment/componentCoding/style/index.module.less b/src/pages/componentDevelopment/componentCoding/style/index.module.less
index f776b4d..1bcbe04 100644
--- a/src/pages/componentDevelopment/componentCoding/style/index.module.less
+++ b/src/pages/componentDevelopment/componentCoding/style/index.module.less
@@ -6,9 +6,51 @@
.header {
display: flex;
justify-content: space-between;
+
+ .handle-row {
+ .handle-row-item {
+ display: flex;
+ align-items: center;
+ }
+ }
}
.code-iframe {
height: 90%;
+
+ .code-iframe-handle {
+ display: flex;
+ justify-content: space-between;
+ padding: 0 10px;
+ background-color: #2c2c2c;
+ border-top-left-radius: 7px;
+ border-top-right-radius: 7px;
+
+ .code-iframe-handle-left {
+ color: #ffffff;
+
+ .align {
+ display: flex;
+ align-items: center;
+ padding: 5px 8px;
+
+ &:hover {
+ cursor: pointer;
+ background-color: #474748;
+ }
+ }
+ }
+
+ .code-iframe-handle-right {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ &:hover {
+ cursor: pointer;
+ background-color: #474748;
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/pages/componentDevelopment/componentList/addApiModal.tsx b/src/pages/componentDevelopment/componentList/addApiModal.tsx
new file mode 100644
index 0000000..7ad81bc
--- /dev/null
+++ b/src/pages/componentDevelopment/componentList/addApiModal.tsx
@@ -0,0 +1,172 @@
+import React, { useState, useEffect } from 'react';
+import { Modal, Form, Input, Message } from '@arco-design/web-react';
+import EditableTable from '@/pages/componentDevelopment/componentList/editableTable';
+import { updateComponentDesign } from '@/api/componentDevelopProcess';
+
+const FormItem = Form.Item;
+const TextArea = Input.TextArea;
+
+const AddApiModal = ({
+ visible,
+ baseInfo,
+ componentDesignProgress,
+ componentDesignData,
+ onUpdateComponentDesign,
+ onCancel,
+ onOk
+ }) => {
+ const [form] = Form.useForm();
+ const [parametersData, setParametersData] = useState([]);
+ const [responsesData, setResponsesData] = useState([]);
+
+ // 当 visible 或 componentDesignProgress 变化时,设置表单初始值
+ useEffect(() => {
+ if (visible && componentDesignProgress) {
+ // 设置表单字段值
+ form.setFieldsValue({
+ ident: componentDesignProgress.ident || '',
+ desc: componentDesignProgress.desc || ''
+ });
+
+ // 设置参数表格数据
+ if (componentDesignProgress.parameters && Array.isArray(componentDesignProgress.parameters)) {
+ setParametersData(componentDesignProgress.parameters.map((param, index) => ({
+ key: param.id || index,
+ ...param
+ })));
+ }
+ else {
+ setParametersData([]);
+ }
+
+ // 设置响应表格数据
+ if (componentDesignProgress.responses && Array.isArray(componentDesignProgress.responses)) {
+ setResponsesData(componentDesignProgress.responses.map((response, index) => ({
+ key: response.id || index,
+ ...response
+ })));
+ }
+ else {
+ setResponsesData([]);
+ }
+ }
+ else if (visible) {
+ // 重置表单和表格数据
+ form.resetFields();
+ setParametersData([]);
+ setResponsesData([]);
+ }
+ }, [visible, componentDesignProgress, form]);
+
+ const submit = async () => {
+ try {
+ await form.validate();
+ const formData = form.getFields();
+
+ // 构造要提交的数据
+ const params = {
+ baseInfo
+ };
+
+ // 如果是编辑模式且有完整的组件设计数据,需要更新对应的记录
+ if (componentDesignProgress && componentDesignData && Array.isArray(componentDesignData)) {
+ // 更新对应的记录
+ const updatedOperates = componentDesignData.map(item => {
+ if (item.ident === componentDesignProgress.ident) {
+ // 更新记录
+ return {
+ ...formData,
+ type: 'EVENT',
+ parameters: parametersData,
+ responses: responsesData
+ };
+ }
+ return item;
+ });
+
+ params['operates'] = updatedOperates;
+ }
+ else if (componentDesignData && Array.isArray(componentDesignData)) {
+ // 新增模式,将新记录添加到现有数据中
+ const newOperate = {
+ ...formData,
+ type: 'EVENT',
+ parameters: parametersData,
+ responses: responsesData
+ };
+
+ params['operates'] = [...componentDesignData, newOperate];
+ }
+ else {
+ // 没有现有数据时,创建包含单个元素的数组
+ params['operates'] = [{
+ ...formData,
+ type: 'EVENT',
+ parameters: parametersData,
+ responses: responsesData
+ }];
+ }
+
+ const res: any = await updateComponentDesign(params);
+
+ if (res.code === 200) {
+ Message.success(componentDesignProgress ? '更新成功' : '新增成功');
+ // 调用父组件传递的 onUpdateComponentDesign 回调,用于更新父组件中的数据
+ onUpdateComponentDesign && onUpdateComponentDesign(params);
+ }
+ else {
+ Message.error(res.message);
+ }
+
+ // 调用父组件传递的 onOk 回调,并传递数据
+ onOk && onOk(params);
+ } catch (error) {
+ console.error('表单验证失败:', error);
+ Message.error('请检查表单填写是否正确');
+ }
+ };
+
+ return (
+
+
+
+ );
+};
+
+export default AddApiModal;
\ No newline at end of file
diff --git a/src/pages/componentDevelopment/componentList/addComponentModal.tsx b/src/pages/componentDevelopment/componentList/addComponentModal.tsx
new file mode 100644
index 0000000..eb869b5
--- /dev/null
+++ b/src/pages/componentDevelopment/componentList/addComponentModal.tsx
@@ -0,0 +1,760 @@
+import React, { useEffect, useState } from 'react';
+import {
+ Modal,
+ Form,
+ Input,
+ Grid,
+ Space,
+ Divider,
+ Button,
+ Table,
+ TableColumnProps,
+ Select,
+ Message,
+ Upload,
+ Progress
+} from '@arco-design/web-react';
+import { IconPlus, IconEdit } from '@arco-design/web-react/icon';
+import styles from './style/addComponentModal.module.less';
+import EditorSection from '@/components/EditorSection';
+import AddApiModal from '@/pages/componentDevelopment/componentList/addApiModal';
+import CompReview from '@/pages/componentDevelopment/componentList/compReview';
+import { getComponentClassify } from '@/api/componentClassify';
+import {
+ compProjectValidate,
+ compSubmit,
+ getTagList,
+ copyAll,
+ getMyComponentList,
+ getCooperationComponentList
+} from '@/api/componentBase';
+import { copyDesign } from '@/api/componentMarket';
+import { codeInit, getComponentDesign, updateComponentDesign } from '@/api/componentDevelopProcess';
+
+const FormItem = Form.Item;
+const Option = Select.Option;
+
+// 定义组件模式类型
+type ComponentMode = 'create' | 'edit' | 'copy';
+
+const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'create' }) => {
+ const [selectedImage, setSelectedImage] = useState('');
+ const [description, setDescription] = useState('');
+ const [classifyList, setClassifyList] = useState([]);
+ const [showSaveBtn, setShowSaveBtn] = useState(false);
+ const [tagsList, setTagsList] = useState([]);
+ const [componentInfo, setComponentInfo] = useState(null); // 合并后的组件信息状态
+ const [componentDesignData, setComponentDesignData] = useState([]); // 新增状态用于存储接口设计数据
+ const [selectedApiData, setSelectedApiData] = useState(null); // 新增状态用于存储选中的API数据
+ const [showApiModal, setShowApiModal] = useState(false);
+ const [created, setCreated] = useState(false); // 是否提交了组件信息
+ const [codeInitLoading, setCodeInitLoading] = useState(false); // 代码初始化按钮 loading
+ const [file, setFile] = useState(null);
+ const [form] = Form.useForm();
+
+ // 组件语言选项
+ const codeLanguageOptions = [
+ { label: 'Java:8', value: 'Java' },
+ { label: 'Python:3.10.12', value: 'Python' }
+ ];
+
+ // 组件类型选项
+ const componentTypeOptions = [
+ { label: '普通组件', value: 'normal' },
+ { label: '监听组件', value: 'loop' }
+ ];
+
+ const cs = `arco-upload-list-item${file && file.status === 'error' ? ' is-error' : ''}`;
+
+ // 判断是否为复制模式
+ const isCopyMode = mode === 'copy';
+ // 判断是否为编辑模式
+ const isEditMode = mode === 'edit';
+ // 判断是否为创建模式
+ const isCreateMode = mode === 'create';
+
+ const columns: TableColumnProps[] = [
+ {
+ title: '接口名称',
+ dataIndex: 'ident'
+ },
+ {
+ title: '输入参数',
+ dataIndex: 'parameters',
+ render: (_, record) => {
+ if (!record.parameters || record.parameters.length === 0) {
+ return '-';
+ }
+ return record.parameters.map(param => param.ident).join(', ');
+ }
+ },
+ {
+ title: '输出参数',
+ dataIndex: 'responses',
+ render: (_, record) => {
+ if (!record.responses || record.responses.length === 0) {
+ return '-';
+ }
+ return record.responses.map(response => response.ident).join(', ');
+ }
+ },
+ {
+ title: '操作',
+ dataIndex: 'op',
+ width: 240,
+ render: (_, record) => (
+ <>
+
+
+ >
+ )
+ }
+ ];
+
+ const getComponentClassifyList = async () => {
+ const res: any = await getComponentClassify('component');
+ if (res.code === 200) {
+ const data = [];
+ res.data.forEach((item) => {
+ data.push({
+ label: item.classifyName,
+ value: item.id
+ });
+ });
+ setClassifyList(data);
+ }
+ };
+
+ const getTageList = async () => {
+ const res: any = await getTagList();
+ if (res.code === 200) setTagsList(res.data);
+ };
+
+ const validateProjectId = async (projectId: string) => {
+ if (!projectId) return;
+
+ try {
+ const res = await compProjectValidate(projectId);
+ if (res.data === false) {
+ // 项目标识已存在,设置表单字段错误
+ form.setFields({
+ projectId: {
+ value: projectId,
+ error: {
+ message: '项目标识已存在'
+ }
+ }
+ });
+ }
+ else {
+ // 项目标识可用,清除错误
+ form.setFields({
+ projectId: {
+ value: projectId,
+ error: null
+ }
+ });
+ }
+ } catch (error) {
+ // API调用出错
+ form.setFields({
+ projectId: {
+ value: projectId,
+ error: {
+ message: '验证项目标识时发生错误'
+ }
+ }
+ });
+ }
+ };
+
+ const onSubmit = async (showMessage = true) => {
+ try {
+ await form.validate();
+ const formData = form.getFields();
+ const params: any = {
+ ...componentInfo,
+ name: formData.name,
+ projectId: formData.projectId,
+ logoUrl: selectedImage,
+ desc: description,
+ componentClassify: formData.componentClassify,
+ codeLanguage: formData.codeLanguage, // 直接使用value值
+ type: formData.type, // 直接使用value值
+ tags: formData.tags
+ };
+
+ // 如果是编辑模式(componentInfo存在),则传递id
+ if (componentInfo && componentInfo.id) {
+ params.id = componentInfo.id;
+ }
+
+ const res: any = await compSubmit(params);
+ if (res.code === 200) {
+ setComponentInfo(res.data);
+ setShowSaveBtn(true);
+ showMessage && Message.success(isEditMode ? '组件信息更新成功' : isCopyMode ? '组件复制成功' : '组件信息提交完成,可继续组件接口设计');
+ onReFresh();
+
+ // 最终保存成功后关闭弹窗
+ if (showSaveBtn && showMessage) {
+ setVisible(false);
+ return;
+ }
+
+ // 提交成功后获取组件设计数据
+ if (res.data && res.data.id) {
+ setCreated(true);
+ getComponentDesignData(res.data.id);
+ }
+
+ }
+ else {
+ showMessage && Message.error(isEditMode ? '组件信息更新失败' : isCopyMode ? '组件复制失败' : '组件信息提交失败');
+ }
+ } catch (error) {
+ console.error('提交/更新失败:', error);
+ }
+ };
+
+ const fetchComponentData = async (extraParams: any = {}) => {
+ try {
+ const params = {
+ currPage: 1,
+ pageSize: 99,
+ ...extraParams
+ };
+
+ const res: any = await getMyComponentList(params);
+ if (res.code === 200 && res.data.list.length > 0) {
+ setComponentInfo(res.data.list[0]);
+ getComponentDesignData(res.data.list[0].id);
+ }
+ } catch (error) {
+ console.error('获取组件列表失败:', error);
+ Message.error('获取组件列表失败');
+ }
+ };
+
+ const getComponentDesignData = async (componentBaseId) => {
+ try {
+ const res = await getComponentDesign(componentBaseId);
+ if (res.data) {
+ // 处理返回的数据,使其符合表格显示格式
+ const processedData = res.data.operates.map(item => ({
+ ...item,
+ key: item.ident,
+ name: item.ident // 使用ident作为名称显示
+ }));
+ setComponentDesignData(processedData);
+ }
+ } catch (error) {
+ console.error('获取组件设计数据失败:', error);
+ Message.error('获取组件设计数据失败');
+ }
+ };
+
+
+ // 仅复制设计
+ const handleCopyDesign = async () => {
+ try {
+ await form.validate();
+ const formData = form.getFields();
+
+ // 构造要提交的数据
+ const params = {
+ ...componentInfo,
+ name: formData.name,
+ projectId: formData.projectId,
+ logoUrl: selectedImage,
+ desc: description,
+ componentClassify: formData.componentClassify,
+ codeLanguage: formData.codeLanguage, // 直接使用value值
+ type: formData.type, // 直例使用value值
+ tags: formData.tags
+ };
+
+ const res: any = await copyDesign(params);
+
+ if (res.code === 200) {
+ Message.success('仅复制设计成功');
+ onReFresh && onReFresh();
+ setVisible(false);
+ }
+ else {
+ Message.error(res.message || '复制失败');
+ }
+ } catch (error) {
+ console.error('复制失败:', error);
+ }
+ };
+
+ // 复制设计和代码
+ const handleCopyAll = async () => {
+ try {
+ await form.validate();
+ const formData = form.getFields();
+
+ // 构造要提交的数据
+ const params = {
+ ...componentInfo,
+ name: formData.name,
+ projectId: formData.projectId,
+ logoUrl: selectedImage,
+ desc: description,
+ componentClassify: formData.componentClassify,
+ codeLanguage: formData.codeLanguage, // 直接使用value值
+ type: formData.type, // 直接使用value값
+ tags: formData.tags
+ };
+
+ const res: any = await copyAll(params);
+
+ if (res.code === 200) {
+ Message.success('复制设计和代码成功');
+ onReFresh && onReFresh();
+ setVisible(false);
+ }
+ else {
+ Message.error(res.message || '复制失败');
+ }
+ } catch (error) {
+ console.error('复制失败:', error);
+ }
+ };
+
+ const handleCodeInit = async () => {
+ setCodeInitLoading(true);
+ Message.warning('代码初始化中');
+ const res: any = await codeInit(componentInfo?.id);
+ setCodeInitLoading(false);
+ if (res.code === 200) {
+ Message.success('代码初始化完成');
+ fetchComponentData({ id: componentInfo?.id });
+ }
+ else Message.error(res.message || '代码初始化失败');
+ };
+
+ useEffect(() => {
+ getComponentClassifyList();
+ getTageList();
+ }, []);
+
+ // 当baseInfo或visible变化时,设置表单初始值
+ useEffect(() => {
+ if (visible && (isEditMode || isCopyMode)) {
+ // 设置表单字段值
+ form.setFieldsValue({
+ name: baseInfo.name || '',
+ projectId: (isCopyMode ? '' : baseInfo.projectId) || '',
+ componentClassify: baseInfo.componentClassify || '',
+ codeLanguage: baseInfo.codeLanguage || '',
+ tags: baseInfo.tags || [],
+ type: baseInfo.type || ''
+ });
+
+ // 设置其他状态
+ setSelectedImage(baseInfo.logoUrl || '');
+ setDescription(baseInfo.desc || '');
+ setShowSaveBtn(true);
+ setComponentInfo(baseInfo);
+
+ // 获取组件设计数据
+ if (isEditMode || isCopyMode) {
+ getComponentDesignData(baseInfo.id);
+ }
+ // else {
+ // // 复制模式下清空接口设计数据
+ // setComponentDesignData([]);
+ // }
+ }
+ else if (visible && isCreateMode) {
+ // 重置表单
+ form.resetFields();
+ setSelectedImage('');
+ setDescription('');
+ setShowSaveBtn(false);
+ setComponentDesignData([]); // 清空接口设计数据
+ setComponentInfo(null);
+ }
+ }, [baseInfo, visible, form, isEditMode, isCopyMode, isCreateMode]);
+
+ const modalFooter = () => {
+ return (
+
+
+ {isCopyMode ? (
+ <>
+
+
+ >
+ ) : showSaveBtn ? (
+
+ ) : (
+
+ )}
+
+ );
+ };
+
+ const UploadImage = () => {
+ // 如果是编辑模式且有componentInfo.logoUrl,则使用componentInfo中的logoUrl
+ const initialImageUrl = componentInfo && componentInfo.logoUrl ? componentInfo.logoUrl : null;
+
+ return (
+
{
+ setFile({
+ ...currentFile,
+ url: URL.createObjectURL(currentFile.originFile)
+ });
+ if (currentFile.status === 'done') setSelectedImage(currentFile.response.data.link);
+ }}
+ onProgress={(currentFile) => {
+ setFile(currentFile);
+ }}
+ >
+
+ {(file && file.url) || initialImageUrl ? (
+
+

+
+
+
+ {file && file.status === 'uploading' && file.percent < 100 && (
+
+ )}
+
+ ) : (
+
+ )}
+
+
+ );
+ };
+
+ return (
+
setVisible(false)}
+ afterClose={() => {
+ // 关闭模态框后重置表单
+ form.resetFields();
+ setSelectedImage('');
+ setDescription('');
+ setShowSaveBtn(false);
+ setFile(null);
+ setCreated(false);
+ }}
+ >
+
+
+ );
+};
+
+export default AddComponentModal;
\ No newline at end of file
diff --git a/src/pages/componentDevelopment/componentList/compReview.tsx b/src/pages/componentDevelopment/componentList/compReview.tsx
new file mode 100644
index 0000000..cbef0d8
--- /dev/null
+++ b/src/pages/componentDevelopment/componentList/compReview.tsx
@@ -0,0 +1,90 @@
+import React from 'react';
+import styles from './style/compReview.module.less';
+
+const CompReview = ({ componentDesignData }) => {
+
+ // 确保数据是数组格式
+ const dataArray = Array.isArray(componentDesignData) ? componentDesignData :
+ componentDesignData ? [componentDesignData] : [];
+
+ return (
+
+
+
+
+ {/* 上方内容 - 根据数组长度渲染 */}
+
+ {dataArray.map((data, index) => (
+
+ ))}
+
+
+ {/* 输入输出部分 - 根据数组长度渲染 */}
+
+ {/* 输入部分 */}
+
+
input
+
+ {dataArray.map((data, index) => {
+ // 确保参数始终是数组格式
+ const parameters = Array.isArray(data.parameters) ? data.parameters :
+ (data.parameters ? [data.parameters] : []);
+
+ return (
+
+ {parameters.length > 0 ? (
+ parameters.map((param, paramIndex) => (
+
+ {param.ident} {param.type}
+
+ ))
+ ) : (
+
+ 无输入参数
+
+ )}
+
+ );
+ })}
+
+
+
+ {/* 输出部分 */}
+
+
output
+
+ {dataArray.map((data, index) => {
+ // 确保响应始终是数组格式
+ const responses = Array.isArray(data.responses) ? data.responses :
+ (data.responses ? [data.responses] : []);
+
+ return (
+
+ {responses.length > 0 ? (
+ responses.map((response, responseIndex) => (
+
+ {response.type} {response.ident}
+
+ ))
+ ) : (
+
+ 无输出参数
+
+ )}
+
+ );
+ })}
+
+
+
+
+
+
+ );
+};
+
+export default CompReview;
\ No newline at end of file
diff --git a/src/pages/componentDevelopment/componentList/editableTable.tsx b/src/pages/componentDevelopment/componentList/editableTable.tsx
new file mode 100644
index 0000000..e50093a
--- /dev/null
+++ b/src/pages/componentDevelopment/componentList/editableTable.tsx
@@ -0,0 +1,209 @@
+import React, { useState, useEffect } from 'react';
+import { Button, Table, Input, Select, Modal, Message } from '@arco-design/web-react';
+
+// 定义数据类型选项
+const dataTypeOptions = [
+ { label: 'STRING', value: 'STRING' },
+ { label: 'INTEGER', value: 'INTEGER' },
+ { label: 'BOOLEAN', value: 'BOOLEAN' },
+ { label: 'ARRAY', value: 'ARRAY' },
+ { label: 'OBJECT', value: 'OBJECT' },
+ { label: 'JSON', value: 'JSON' },
+ { label: 'DOUBLE', value: 'DOUBLE' }
+];
+
+// 定义数组类型选项
+const arrayTypeOptions = [
+ { label: 'STRING', value: 'STRING' },
+ { label: 'INTEGER', value: 'INTEGER' },
+ { label: 'DOUBLE', value: 'DOUBLE' },
+ { label: 'BOOLEAN', value: 'BOOLEAN' },
+ { label: 'JSON', value: 'JSON' },
+ { label: 'OBJECT', value: 'OBJECT' }
+];
+
+function EditableCell({ value, onChange, columnType, record, dataIndex }) {
+ // 对于数组类型字段的特殊处理
+ if (dataIndex === 'generic') {
+ // 仅当数据类型为 ARRAY 时才可编辑
+ if (record.type === 'ARRAY') {
+ return (
+
+ );
+ }
+ else {
+ // 非 ARRAY 类型显示横杠
+ return
-;
+ }
+ }
+
+ if (columnType === 'input') {
+ return (
+
+ );
+ }
+
+ if (columnType === 'select') {
+ return (
+
+ );
+ }
+
+ return
{value};
+}
+
+function EditableTable({ onDataUpdate, initialData = [] }) {
+ const [data, setData] = useState([]);
+
+ // 当初始数据变化时,更新表格数据
+ useEffect(() => {
+ if (initialData && Array.isArray(initialData) && initialData.length > 0) {
+ // 为每个数据项添加唯一的 key
+ const dataWithKeys = initialData.map((item, index) => ({
+ key: item.key || item.id || `key_${index}`,
+ ...item
+ }));
+ setData(dataWithKeys);
+ }
+ }, [initialData]);
+
+ const handleValueChange = (key, dataIndex, value) => {
+ const newData = data.map(item => {
+ if (item.key === key) {
+ const updatedItem = { ...item, [dataIndex]: value };
+
+ // 如果更改的是 type 字段且不是 ARRAY,则清空 generic 字段
+ if (dataIndex === 'type' && value !== 'ARRAY') {
+ updatedItem.generic = '';
+ }
+
+ return updatedItem;
+ }
+ return item;
+ });
+
+ setData(newData);
+ onDataUpdate && onDataUpdate(newData);
+ };
+
+ const columns = [
+ {
+ title: '名称',
+ dataIndex: 'ident',
+ render: (_, record) => (
+
handleValueChange(record.key, 'ident', value)}
+ columnType="input"
+ record={record}
+ dataIndex="ident"
+ />
+ )
+ },
+ {
+ title: '数据类型',
+ dataIndex: 'type',
+ render: (_, record) => (
+ handleValueChange(record.key, 'type', value)}
+ columnType="select"
+ record={record}
+ dataIndex="type"
+ />
+ )
+ },
+ {
+ title: '数组类型',
+ dataIndex: 'generic',
+ render: (_, record) => (
+ handleValueChange(record.key, 'generic', value)}
+ columnType="select"
+ record={record}
+ dataIndex="generic"
+ />
+ )
+ },
+ {
+ title: '参数描述',
+ dataIndex: 'desc',
+ render: (_, record) => (
+ handleValueChange(record.key, 'desc', value)}
+ columnType="input"
+ record={record}
+ dataIndex="desc"
+ />
+ )
+ },
+ {
+ title: '操作',
+ dataIndex: 'op',
+ render: (_, record) => (
+
+ )
+ }
+ ];
+
+ const removeRow = (key) => {
+ const newData = data.filter(item => item.key !== key);
+ setData(newData);
+ onDataUpdate && onDataUpdate(newData);
+ };
+
+ const addRow = () => {
+ const newRow = {
+ key: `${Date.now()}`,
+ ident: '',
+ type: '',
+ generic: '',
+ desc: ''
+ };
+ const newData = [...data, newRow];
+ setData(newData);
+ onDataUpdate && onDataUpdate(newData);
+ };
+
+ return (
+ <>
+
+
+ >
+ );
+}
+
+export default EditableTable;
\ No newline at end of file
diff --git a/src/pages/componentDevelopment/componentList/handleButtonGroup.tsx b/src/pages/componentDevelopment/componentList/handleButtonGroup.tsx
new file mode 100644
index 0000000..f3c8650
--- /dev/null
+++ b/src/pages/componentDevelopment/componentList/handleButtonGroup.tsx
@@ -0,0 +1,166 @@
+import React from 'react';
+import { Button, Dropdown, Menu, Message } from '@arco-design/web-react';
+import { ComponentItem } from '@/api/interface';
+import {
+ componentStatusConstant,
+ publicStatus,
+ publishStatusConstant
+} from '@/const/isdp/componentBase';
+
+interface HandleButtonGroupProps {
+ row: ComponentItem;
+ index: number;
+ onHandlePublishComponent: (row: ComponentItem) => void;
+ onGoToReview: (row: ComponentItem) => void;
+ onPublishOrRevokeComponent: (action: 'publish' | 'revoke', identifier: string, version: string) => void;
+ onNavTo: (id: number, type: string) => void;
+ onSourceCodeView: (row: ComponentItem) => void;
+ onShowEdit: (row: ComponentItem, index: number) => void;
+ onCopyHandler: (row: ComponentItem) => void;
+ onShareCollaboration: (row: ComponentItem) => void;
+ onExportComponent: (id: number) => void;
+ onStopComponentShow: (row: ComponentItem) => void;
+ onRowDel: (row: ComponentItem) => void;
+}
+
+const HandleButtonGroup: React.FC = ({
+ row,
+ index,
+ onHandlePublishComponent,
+ onGoToReview,
+ onPublishOrRevokeComponent,
+ onNavTo,
+ onSourceCodeView,
+ onShowEdit,
+ onCopyHandler,
+ onShareCollaboration,
+ onExportComponent,
+ onStopComponentShow,
+ onRowDel
+ }) => {
+
+ // 检查组件状态是否符合条件
+ const isEligible = (eligibleStatuses: string[], currentStatus: string) => {
+ return eligibleStatuses.includes(currentStatus.toLowerCase());
+ };
+
+ // 构建更多操作菜单
+ const renderDropdownMenu = () => {
+ const items = [];
+
+ // 组件复制
+ if (!isEligible([componentStatusConstant.DEFAULT, componentStatusConstant.DESIGN], row.componentStatus)) {
+ items.push(
+
+
+
+ );
+ }
+
+ // 分享协作
+ if (!isEligible([componentStatusConstant.DESIGN, componentStatusConstant.DEFAULT], row.componentStatus)) {
+ items.push(
+
+
+
+ );
+ }
+
+ // 导出组件
+ items.push(
+
+
+
+ );
+
+ // 下架组件
+ if (isEligible([componentStatusConstant.DEPLOYED], row.componentStatus)) {
+ items.push(
+
+
+
+ );
+ }
+
+ // 删除组件
+ if (!isEligible([componentStatusConstant.DEPLOYED, componentStatusConstant.PUBLISHED], row.componentStatus)) {
+ items.push(
+
+
+
+ );
+ }
+
+ return ;
+ };
+
+ return (
+ <>
+ {/* 发布组件/更新版本*/}
+ {row.publicStatus !== publicStatus.REVIEW && isEligible([componentStatusConstant.CODING, componentStatusConstant.DEPLOYED, componentStatusConstant.PUBLISHED], row.componentStatus) && (
+
+ )}
+
+ {(row.publicStatus === publicStatus.REVIEW || row.publicStatus === publicStatus.REJECTED) && (
+
+ )}
+
+ {/* 公开组件/取消公开 */}
+ {row.publishStatus !== publishStatusConstant.PUBLISHED ? (
+
+ ) : (
+
+ )}
+
+ {/* 查看源码 */}
+ {isEligible(
+ [componentStatusConstant.CODING, componentStatusConstant.DEPLOYED, componentStatusConstant.PUBLISHED],
+ row.componentStatus
+ ) ? (
+
+ ) : null}
+
+ {/* 编辑组件 */}
+
+
+ {/* 更多操作 */}
+
+
+
+ >
+ );
+};
+
+export default HandleButtonGroup;
\ No newline at end of file
diff --git a/src/pages/componentDevelopment/componentList/index.tsx b/src/pages/componentDevelopment/componentList/index.tsx
index a3289a0..3013f69 100644
--- a/src/pages/componentDevelopment/componentList/index.tsx
+++ b/src/pages/componentDevelopment/componentList/index.tsx
@@ -1,12 +1,41 @@
-import React, { useState } from 'react';
+import React, { useState, useEffect } from 'react';
import styles from './style/index.module.less';
-import { Button, Divider, Input, Space, Table, Radio } from '@arco-design/web-react';
+import { Button, Divider, Input, Space, Table, Radio, Pagination, Modal, Message } from '@arco-design/web-react';
import { IconSearch } from '@arco-design/web-react/icon';
+import { getMyComponentList, getCooperationComponentList, remove, exportComponent } from '@/api/componentBase';
+import { getReviewGroupByNew } from '@/api/componentMarket';
+import { componentRelease, componentRevoke } from '@/api/componentRelease';
+import { ComponentItem } from '@/api/interface';
+import AddComponentModal from '@/pages/componentDevelopment/componentList/addComponentModal';
+import HandleButtonGroup from '@/pages/componentDevelopment/componentList/handleButtonGroup';
+import {
+ componentStatusConstant,
+ componentStatusDict,
+ publicStatusDict,
+ publishStatusDict
+} from '@/const/isdp/componentBase';
+import dayjs from 'dayjs';
+import { updateComponentCodingPath } from '@/store/ideContainer';
+import { useDispatch } from 'react-redux';
const Group = Radio.Group;
const GlobalVarContainer = () => {
- const [selectedItem, setSelectedItem] = useState('数字类型');
+ const [selectedItem, setSelectedItem] = useState('我的组件');
+ const [selectComponent, setSelectComponent] = useState(null);
+ const [componentData, setComponentData] = useState([]);
+ const [pagination, setPagination] = useState({
+ totalCount: 0,
+ pageSize: 10,
+ totalPage: 0,
+ currPage: 1
+ });
+ const [loading, setLoading] = useState(false);
+ const [visible, setVisible] = useState(false);
+ const [mode, setMode] = useState<'create' | 'edit' | 'copy'>('create'); // 添加模式状态
+ const [searchValue, setSearchValue] = useState(''); // 添加搜索状态
+ const [componentStatus, setComponentStatus] = useState(''); // 添加组件状态筛选
+ const dispatch = useDispatch();
const menuItems = [
{
@@ -29,70 +58,414 @@ const GlobalVarContainer = () => {
}
];
+ const columns = [
+ {
+ title: '组件名称',
+ dataIndex: 'name'
+ },
+ {
+ title: '组件标识',
+ dataIndex: 'projectId'
+ },
+ {
+ title: '分类',
+ dataIndex: 'componentClassify'
+ },
+ {
+ title: '创建人',
+ dataIndex: 'createUserName'
+ },
+ {
+ title: '代码语言',
+ dataIndex: 'codeLanguage'
+ },
+ {
+ title: '组件类型',
+ dataIndex: 'type',
+ render: (_, record) => {
+ return (
+ {record.type === 'normal' ? '普通组件' : '监听组件'}
+ );
+ }
+ },
+ {
+ title: '组件状态',
+ dataIndex: 'componentStatus',
+ render: (_, record) => {
+ const formattedData = componentStatusDict.find(item => item.value === componentStatusConstant[record.componentStatus]) || { label: '' };
+ return (
+ {formattedData.label}
+ );
+ }
+ },
+ {
+ title: '发布状态',
+ dataIndex: 'publicStatus',
+ render: (_, record) => {
+ const formattedData = publicStatusDict.find(item => item.value === record.publicStatus) || { label: '' };
+ return (
+ {formattedData.label}
+ );
+ }
+ },
+ {
+ title: '公开状态',
+ dataIndex: 'publishStatus',
+ render: (_, record) => {
+ const formattedData = publishStatusDict.find(item => item.value === record.publishStatus) || { label: '' };
+ return (
+ {formattedData.label}
+ );
+ }
+ },
+ {
+ title: '修改时间',
+ dataIndex: 'updateTime',
+ render: (_, record) => {
+ return (
+ {dayjs(record.updateTime).format('YYYY-MM-DD HH:mm:ss')}
+ );
+ }
+ },
+ {
+ title: '操作',
+ dataIndex: 'operations',
+ render: (_, record, index) => (
+ {
+ // TODO: 实现发布组件逻辑
+ console.log('Handle publish component', row);
+ }}
+ onGoToReview={(row) => {
+ // TODO: 实现查看审核逻辑
+ console.log('Go to review', row);
+ }}
+ onPublishOrRevokeComponent={async (action, identifier, version) => {
+ try {
+ if (action === 'publish') {
+ await componentRelease({ identifier, version });
+ Message.success('组件公开成功');
+ }
+ else if (action === 'revoke') {
+ await componentRevoke({ identifier, version });
+ Message.success('组件撤销成功');
+ }
+ // 重新获取数据以更新状态
+ fetchComponentData();
+ } catch (error) {
+ console.error('操作失败:', error);
+ Message.error(`组件${action === 'publish' ? '公开' : '撤销'}失败: ${error.message || ''}`);
+ }
+ }}
+ onNavTo={(id, type) => {
+ // TODO: 实现导航逻辑
+ console.log('Nav to', id, type);
+ }}
+ onSourceCodeView={(row) => {
+ dispatch(updateComponentCodingPath({
+ localProjectPath: row.localProjectPath,
+ name: row.name,
+ projectId: row.projectId,
+ id: row.id
+ }));
+ const event = new CustomEvent('navigateToTab', {
+ detail: {
+ path: 'componentCoding'
+ }
+ });
+
+ document.dispatchEvent(event);
+ }}
+ onShowEdit={(row, index) => {
+ setSelectComponent(row);
+ setVisible(true);
+ setMode('edit'); // 设置模式为复制
+ }}
+ onCopyHandler={(row) => {
+ setSelectComponent(row);
+ setVisible(true);
+ setMode('copy'); // 设置模式为复制
+ }}
+ onShareCollaboration={(row) => {
+ // TODO: 实现分享协作逻辑
+ console.log('Share collaboration', row);
+ }}
+ onExportComponent={(id) => {
+ // 实现导出组件逻辑
+ onExportComponent(id);
+ }}
+ onStopComponentShow={(row) => {
+ // TODO: 实现下架组件逻辑
+ console.log('Stop component show', row);
+ }}
+ onRowDel={(row) => {
+ // 显示确认框
+ Modal.confirm({
+ title: '确认删除',
+ content: `确定要删除组件 "${row.name}" 吗?此操作不可恢复。`,
+ okButtonProps: { status: 'danger' },
+ onOk: async () => {
+ try {
+ const res = await remove(row.id);
+ console.log('res:', res);
+ Message.success('组件删除成功');
+ // 重新获取数据
+ fetchComponentData();
+ } catch (error) {
+ console.error('删除组件失败:', error);
+ Message.error('组件删除失败');
+ }
+ }
+ });
+ }}
+ />
+ )
+ }
+ ];
+
+ useEffect(() => {
+ if (selectedItem === '我的组件' || selectedItem === '协同组件') {
+ // 当切换菜单或搜索条件变化时,重置到第一页
+ setPagination({
+ ...pagination,
+ currPage: 1
+ });
+ // 延迟执行搜索,确保分页参数已更新
+ setTimeout(() => {
+ fetchComponentData();
+ }, 0);
+ }
+ else if (selectedItem === '组件审核') {
+ fetchComponentReview();
+ }
+ }, [selectedItem, searchValue]);
+
+ // 获取组件列表数据,支持传入额外参数
+ const fetchComponentData = async (extraParams: any = {}) => {
+ setLoading(true);
+ const apiMap = {
+ '我的组件': getMyComponentList,
+ '协同组件': getCooperationComponentList
+ };
+ try {
+ const params = {
+ currPage: pagination.currPage,
+ pageSize: pagination.pageSize,
+ ...extraParams
+ };
+
+ // 如果有搜索关键词,则添加到参数中
+ if (searchValue.trim()) {
+ params.name = searchValue.trim();
+ }
+
+ // 如果选择了组件状态,则添加到参数中
+ if (componentStatus) {
+ params.componentStatus = componentStatus.toUpperCase();
+ }
+
+ const res: any = await apiMap[selectedItem](params);
+
+ setComponentData(res.data.list);
+ setPagination({
+ totalCount: res.data.totalCount,
+ pageSize: res.data.pageSize,
+ totalPage: res.data.totalPage,
+ currPage: res.data.currPage
+ });
+ } catch (error) {
+ console.error('获取组件列表失败:', error);
+ Message.error('获取组件列表失败');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ // 获取组件审核列表数据
+ const fetchComponentReview = async () => {
+ const res: any = await getReviewGroupByNew({
+ queryType: 'create',
+ current: pagination.currPage,
+ size: pagination.pageSize
+ });
+
+ console.log('组件审核列表:', res);
+ };
+
+ const handlePageChange = (page: number, pageSize?: number) => {
+ setPagination({
+ ...pagination,
+ currPage: page,
+ pageSize: pageSize || pagination.pageSize
+ });
+ };
+
+ // 修改分页变化处理函数
+ useEffect(() => {
+ if (selectedItem === '我的组件' || selectedItem === '协同组件') {
+ fetchComponentData();
+ }
+ }, [pagination.currPage, pagination.pageSize, componentStatus]);
+
+ // 搜索处理函数
+ const searchHandle = () => {
+ // 重置到第一页并触发搜索
+ setPagination({
+ ...pagination,
+ currPage: 1
+ });
+ fetchComponentData();
+ };
+
+ // 重置搜索
+ const resetSearch = () => {
+ setSearchValue('');
+ setComponentStatus(''); // 同时重置组件状态筛选
+ setPagination({
+ ...pagination,
+ currPage: 1
+ });
+ fetchComponentData();
+ };
+
+ // 修改导出组件的回调函数
+ const onExportComponent = async (id) => {
+ try {
+ await exportComponent(id);
+ Message.success('组件导出成功');
+ } catch (error) {
+ console.error('导出组件失败:', error);
+ Message.error('组件导出失败');
+ }
+ };
+
+ // 组件状态筛选处理函数
+ const handleStatusChange = (value) => {
+ setComponentStatus(value);
+ };
+
return (
-
- {/*左侧菜单*/}
-
- {menuItems.map((item, index) => (
-
setSelectedItem(item.label)}
- >
-

-
{item.label}
-
- ))}
-
-
- {/*头部*/}
-
-
-
- }
- placeholder={'搜索'}
- style={{ width: 236 }}
- />
-