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.

260 lines
9.4 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 } 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';
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 = () => {
navigator.clipboard.writeText(currentComponent.repoHtmlUrl);
Message.success('复制成功');
};
useEffect(() => {
getOptionsList();
}, []);
useEffect(() => {
componentCoding.id && getComponentInfo();
const uri = process.env.NEXT_PUBLIC_DEV_CODE_SERVER_HOST;
const codeServerFolderPre = '/app/data';
// 使用传入的localProjectPath或默认值
const path = componentCoding.localProjectPath || '/000000/admin_testcode1/master';
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>
<iframe width="100%" height="100%" frameBorder={0} src={serverUrl} ref={iframeRef} />
</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;