|
|
import React, { useEffect, useState, useRef } from 'react';
|
|
|
import styles from './style/index.module.less';
|
|
|
import { Button, Select, Space, Message, Modal, Input, Empty } from '@arco-design/web-react';
|
|
|
import { IconFullscreen, IconFullscreenExit } from '@arco-design/web-react/icon';
|
|
|
import { useSelector, useDispatch } from 'react-redux';
|
|
|
import { getMyComponentList } from '@/api/componentBase';
|
|
|
import { updateComponentCodingPath } from '@/store/ideContainer';
|
|
|
import { getComponentBaseInfo } from '@/api/componentDevelopProcess';
|
|
|
import { gitCommit, gitPull } from '@/api/componentGitea';
|
|
|
import copy from 'copy-to-clipboard';
|
|
|
|
|
|
const Option = Select.Option;
|
|
|
|
|
|
const ComponentCoding = () => {
|
|
|
const [serverUrl, setServerUrl] = useState(''); // code-server 地址
|
|
|
const [optionsList, setOptionsList] = useState([]); // 下拉选择菜单
|
|
|
const [originList, setOriginList] = useState([]); // 原始数据-组件列表
|
|
|
const [currentComponent, setCurrentComponent] = useState<any>({}); // 当前组件信息
|
|
|
const [isFullscreen, setIsFullscreen] = useState(false); // 全屏状态
|
|
|
const [commitMessage, setCommitMessage] = useState(''); // 提交信息
|
|
|
const [commitModal, setCommitModal] = useState(false); // 提交信息弹窗
|
|
|
const iframeRef = useRef(null);
|
|
|
const { componentCoding } = useSelector((state: any) => state.ideContainer);
|
|
|
const dispatch = useDispatch();
|
|
|
|
|
|
const getOptionsList = async () => {
|
|
|
const res: any = await getMyComponentList({
|
|
|
currPage: 1,
|
|
|
pageSize: 999
|
|
|
});
|
|
|
if (res.code === 200) {
|
|
|
setOriginList(res.data.list);
|
|
|
setOptionsList(res.data.list.map(item => {
|
|
|
return { label: item.name, value: item.localProjectPath, ...item };
|
|
|
}));
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const getComponentInfo = async () => {
|
|
|
const res: any = await getComponentBaseInfo(componentCoding.id);
|
|
|
if (res.code === 200) {
|
|
|
setCurrentComponent(res.data);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
|
|
|
// 切换全屏状态
|
|
|
const toggleFullscreen = () => {
|
|
|
const iframeContainer = document.querySelector(`.${styles['code-iframe']}`) as HTMLElement;
|
|
|
|
|
|
if (!isFullscreen) {
|
|
|
// 进入全屏
|
|
|
if (iframeContainer.requestFullscreen) {
|
|
|
iframeContainer.requestFullscreen();
|
|
|
}
|
|
|
else if ((iframeContainer as any).webkitRequestFullscreen) {
|
|
|
(iframeContainer as any).webkitRequestFullscreen();
|
|
|
}
|
|
|
else if ((iframeContainer as any).mozRequestFullScreen) {
|
|
|
(iframeContainer as any).mozRequestFullScreen();
|
|
|
}
|
|
|
else if ((iframeContainer as any).msRequestFullscreen) {
|
|
|
(iframeContainer as any).msRequestFullscreen();
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
// 退出全屏
|
|
|
if (document.exitFullscreen) {
|
|
|
document.exitFullscreen();
|
|
|
}
|
|
|
else if ((document as any).webkitExitFullscreen) {
|
|
|
(document as any).webkitExitFullscreen();
|
|
|
}
|
|
|
else if ((document as any).mozCancelFullScreen) {
|
|
|
(document as any).mozCancelFullScreen();
|
|
|
}
|
|
|
else if ((document as any).msExitFullscreen) {
|
|
|
(document as any).msExitFullscreen();
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const gitPullHandler = async () => {
|
|
|
const res: any = await gitPull(componentCoding.id);
|
|
|
if (res.code === 200) {
|
|
|
Message.success('代码拉取成功');
|
|
|
}
|
|
|
else {
|
|
|
Message.error('代码拉取失败');
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const gitCommitHandler = async () => {
|
|
|
const res: any = await gitCommit(componentCoding.id, { commit: commitMessage });
|
|
|
if (res.code === 200) {
|
|
|
Message.success('代码提交成功');
|
|
|
setCommitModal(false);
|
|
|
setCommitMessage('');
|
|
|
}
|
|
|
else {
|
|
|
Message.error('代码提交失败');
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const copyGitUrlHandler = () => {
|
|
|
if (!currentComponent.repoHtmlUrl) {
|
|
|
Message.error('当前组件没有Git仓库,请选择组件!');
|
|
|
return;
|
|
|
}
|
|
|
const textToCopy = currentComponent.repoHtmlUrl;
|
|
|
|
|
|
const success = copy(textToCopy);
|
|
|
|
|
|
if (success) {
|
|
|
Message.success('复制成功');
|
|
|
}
|
|
|
else {
|
|
|
Message.error('复制失败');
|
|
|
}
|
|
|
};
|
|
|
|
|
|
useEffect(() => {
|
|
|
getOptionsList();
|
|
|
}, []);
|
|
|
|
|
|
useEffect(() => {
|
|
|
componentCoding.id && getComponentInfo();
|
|
|
const codeServerFolderPre = '/app/data';
|
|
|
|
|
|
// 根据当前域名决定使用的URL
|
|
|
const getCodeServerUri = () => {
|
|
|
const hostname = window.location.hostname;
|
|
|
const protocol = window.location.protocol;
|
|
|
|
|
|
// localhost 使用环境变量配置
|
|
|
if (hostname === 'localhost' || hostname === '127.0.0.1') {
|
|
|
return process.env.NEXT_PUBLIC_DEV_CODE_SERVER_HOST;
|
|
|
}
|
|
|
|
|
|
// IP地址使用当前IP拼接端口8443
|
|
|
const ipRegex = /^(\d{1,3}\.){3}\d{1,3}$/;
|
|
|
if (ipRegex.test(hostname)) {
|
|
|
return `${protocol}//${hostname}:8443`;
|
|
|
}
|
|
|
|
|
|
// 域名直接使用当前域名
|
|
|
return `${protocol}//${hostname}/code-server/`;
|
|
|
};
|
|
|
|
|
|
const uri = getCodeServerUri();
|
|
|
// 使用传入的localProjectPath或默认值
|
|
|
const path = componentCoding.localProjectPath;
|
|
|
if (!path) return;
|
|
|
setServerUrl(`${uri}?folder=${codeServerFolderPre}${path}`);
|
|
|
}, [componentCoding]);
|
|
|
|
|
|
// 监听全屏状态变化
|
|
|
useEffect(() => {
|
|
|
const handleFullscreenChange = () => {
|
|
|
const isCurrentlyFullscreen =
|
|
|
document.fullscreenElement ||
|
|
|
(document as any).webkitFullscreenElement ||
|
|
|
(document as any).mozFullScreenElement ||
|
|
|
(document as any).msFullscreenElement;
|
|
|
|
|
|
setIsFullscreen(!!isCurrentlyFullscreen);
|
|
|
};
|
|
|
|
|
|
document.addEventListener('fullscreenchange', handleFullscreenChange);
|
|
|
document.addEventListener('webkitfullscreenchange', handleFullscreenChange);
|
|
|
document.addEventListener('mozfullscreenchange', handleFullscreenChange);
|
|
|
document.addEventListener('MSFullscreenChange', handleFullscreenChange);
|
|
|
|
|
|
return () => {
|
|
|
document.removeEventListener('fullscreenchange', handleFullscreenChange);
|
|
|
document.removeEventListener('webkitfullscreenchange', handleFullscreenChange);
|
|
|
document.removeEventListener('mozfullscreenchange', handleFullscreenChange);
|
|
|
document.removeEventListener('MSFullscreenChange', handleFullscreenChange);
|
|
|
};
|
|
|
}, []);
|
|
|
|
|
|
return (
|
|
|
<div className={styles['component-coding']}>
|
|
|
<div className={styles['header']}>
|
|
|
<Space
|
|
|
size={50}
|
|
|
style={{ marginTop: '20px', marginBottom: '30px' }}
|
|
|
>
|
|
|
<div className={styles['handle-row']}>
|
|
|
<Space size={40}>
|
|
|
<div className={styles['handle-row-item']}>
|
|
|
<span>组件名称:</span>
|
|
|
<span>{componentCoding.name || '未选择组件'}</span>
|
|
|
</div>
|
|
|
<div className={styles['handle-row-item']}>
|
|
|
<span>组件标识:</span>
|
|
|
<span>{componentCoding.projectId || '未选择组件'}</span>
|
|
|
</div>
|
|
|
<div className={styles['handle-row-item']}>
|
|
|
<span>组件选择:</span>
|
|
|
<Select
|
|
|
placeholder="选择组件"
|
|
|
style={{ width: 250 }}
|
|
|
showSearch
|
|
|
filterOption={(inputValue, option) => {
|
|
|
return option.props.children.toLowerCase().indexOf(inputValue.toLowerCase()) >= 0;
|
|
|
}}
|
|
|
onChange={(value) => {
|
|
|
// 查找选中项的完整信息
|
|
|
const selectedComponent = originList.find(item => item.localProjectPath === value);
|
|
|
if (selectedComponent) {
|
|
|
// 更新Redux状态
|
|
|
dispatch(updateComponentCodingPath({
|
|
|
localProjectPath: selectedComponent.localProjectPath,
|
|
|
name: selectedComponent.name,
|
|
|
projectId: selectedComponent.projectId,
|
|
|
id: selectedComponent.id
|
|
|
}));
|
|
|
}
|
|
|
}}
|
|
|
value={componentCoding.localProjectPath || undefined}
|
|
|
>
|
|
|
{optionsList.map((option, index) => (
|
|
|
<Option key={option.value} value={option.value}>
|
|
|
{option.label}
|
|
|
</Option>
|
|
|
))}
|
|
|
</Select>
|
|
|
</div>
|
|
|
</Space>
|
|
|
</div>
|
|
|
</Space>
|
|
|
|
|
|
<Space>
|
|
|
<Button
|
|
|
type="primary"
|
|
|
style={{ marginLeft: 5, borderRadius: 4 }}
|
|
|
>
|
|
|
启动项设置
|
|
|
</Button>
|
|
|
</Space>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className={styles['code-iframe']}>
|
|
|
<div className={styles['code-iframe-handle']}>
|
|
|
<Space size={10} className={styles['code-iframe-handle-left']}>
|
|
|
<span className={styles['align']} onClick={gitPullHandler}>
|
|
|
<img src={'/ideContainer/imgs/tongbu.svg'} style={{ width: 16, height: 16, marginRight: 5 }}
|
|
|
/>
|
|
|
同步代码
|
|
|
</span>
|
|
|
<span className={styles['align']} onClick={copyGitUrlHandler}>
|
|
|
<img src={'/ideContainer/imgs/git.svg'} style={{ width: 16, height: 16, marginRight: 5 }} />
|
|
|
复制git地址
|
|
|
</span>
|
|
|
<span className={styles['align']} onClick={() => setCommitModal(true)}>
|
|
|
<img src={'/ideContainer/imgs/tijiao.svg'} style={{ width: 16, height: 16, marginRight: 5 }}
|
|
|
/>
|
|
|
提交代码
|
|
|
</span>
|
|
|
</Space>
|
|
|
<div className={styles['code-iframe-handle-right']} onClick={toggleFullscreen}>
|
|
|
{isFullscreen ? (
|
|
|
<IconFullscreenExit style={{ width: 18, height: 18, marginRight: 5, marginLeft: 5, color: '#ffffff' }} />
|
|
|
) : (
|
|
|
<IconFullscreen style={{ width: 18, height: 18, marginRight: 5, marginLeft: 5, color: '#ffffff' }} />
|
|
|
)}
|
|
|
</div>
|
|
|
</div>
|
|
|
{serverUrl ?
|
|
|
(
|
|
|
<iframe width="100%" height="100%" frameBorder={0} src={serverUrl} ref={iframeRef} />
|
|
|
)
|
|
|
:
|
|
|
(
|
|
|
<div className={styles['empty-container']}>
|
|
|
<Empty
|
|
|
description="暂无组件编码,请选择需要编码的组件"
|
|
|
></Empty>
|
|
|
</div>
|
|
|
)}
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<Modal
|
|
|
title="Git提交信息"
|
|
|
visible={commitModal}
|
|
|
onOk={() => gitCommitHandler()}
|
|
|
onCancel={() => {
|
|
|
setCommitMessage('');
|
|
|
setCommitModal(false);
|
|
|
}}
|
|
|
autoFocus={false}
|
|
|
focusLock={true}
|
|
|
>
|
|
|
<div style={{ marginBottom: 5 }}>请输入提交信息:</div>
|
|
|
<Input value={commitMessage} onChange={(e: any) => setCommitMessage(e)}></Input>
|
|
|
</Modal>
|
|
|
|
|
|
</div>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
export default ComponentCoding; |