You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

305 lines
10 KiB
TypeScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;