diff --git a/src/assets/css/pages/tools/edit.scss b/src/assets/css/pages/tools/edit.scss new file mode 100644 index 0000000..fb79eda --- /dev/null +++ b/src/assets/css/pages/tools/edit.scss @@ -0,0 +1,6 @@ +[data-component=tools-edit] { + .root-content { + width: 100%; + height: 100%; + } +} \ No newline at end of file diff --git a/src/components/Playground/Output/Preview/index.tsx b/src/components/Playground/Output/Preview/index.tsx index 93cedc3..d960c35 100644 --- a/src/components/Playground/Output/Preview/index.tsx +++ b/src/components/Playground/Output/Preview/index.tsx @@ -8,9 +8,18 @@ interface PreviewProps { files: IFiles importMap: IImportMap entryPoint: string + preExpansionCode?: string + postExpansionCode?: string } -const Preview = ({ iframeKey, files, importMap, entryPoint }: PreviewProps) => { +const Preview = ({ + iframeKey, + files, + importMap, + entryPoint, + preExpansionCode = '', + postExpansionCode = '' +}: PreviewProps) => { const [errorMsg, setErrorMsg] = useState('') const [compiledCode, setCompiledCode] = useState('') @@ -19,14 +28,19 @@ const Preview = ({ iframeKey, files, importMap, entryPoint }: PreviewProps) => { } useEffect(() => { + if (!Object.keys(files).length || !importMap || !entryPoint.length) { + return + } Compiler.compile(files, importMap, entryPoint) .then((result) => { - setCompiledCode(result.outputFiles[0].text) + setCompiledCode( + `${preExpansionCode}\n${result.outputFiles[0].text}\n${postExpansionCode}` + ) }) .catch((e: Error) => { setErrorMsg(`编译失败:${e.message}`) }) - }, [files, Compiler]) + }, [files, Compiler, importMap, entryPoint]) return (
diff --git a/src/components/Playground/Output/Preview/preview.scss b/src/components/Playground/Output/Preview/preview.scss index e69a5b6..f4a3b6e 100644 --- a/src/components/Playground/Output/Preview/preview.scss +++ b/src/components/Playground/Output/Preview/preview.scss @@ -3,4 +3,14 @@ position: relative; width: 100%; height: 100%; + + .playground-error-message { + position: absolute; + bottom: 0; + width: 100%; + color: white; + background-color: #FF4D4FAA; + padding: 5px 10px; + font-size: 1.2em; + } } \ No newline at end of file diff --git a/src/components/Playground/Output/index.tsx b/src/components/Playground/Output/index.tsx index bf729b7..b138375 100644 --- a/src/components/Playground/Output/index.tsx +++ b/src/components/Playground/Output/index.tsx @@ -9,9 +9,18 @@ interface OutputProps { selectedFileName: string importMap: IImportMap entryPoint: string + preExpansionCode?: string + postExpansionCode?: string } -const Output = ({ files, selectedFileName, importMap, entryPoint }: OutputProps) => { +const Output = ({ + files, + selectedFileName, + importMap, + entryPoint, + preExpansionCode, + postExpansionCode +}: OutputProps) => { const [selectedTab, setSelectedTab] = useState('Preview') return ( @@ -31,6 +40,8 @@ const Output = ({ files, selectedFileName, importMap, entryPoint }: OutputProps) files={files} importMap={importMap} entryPoint={entryPoint} + preExpansionCode={preExpansionCode} + postExpansionCode={postExpansionCode} /> )} {selectedTab === 'Transform' && } diff --git a/src/components/Playground/playground.scss b/src/components/Playground/playground.scss index 35c78d1..b4b927d 100644 --- a/src/components/Playground/playground.scss +++ b/src/components/Playground/playground.scss @@ -5,14 +5,4 @@ > * { width: 0 !important; } - - .playground-error-message { - position: absolute; - bottom: 0; - width: 100%; - color: white; - background-color: #FF4D4FAA; - padding: 5px 10px; - font-size: 1.2em; - } } \ No newline at end of file diff --git a/src/global.d.ts b/src/global.d.ts index 0a6942b..481d5f7 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -540,7 +540,7 @@ interface ToolVo { dist: ToolDataVo entryPoint: string publish: string - review: 'NONE' | 'PASS' | 'REJECT' + review: 'NONE' | 'PROCESSING' | 'PASS' | 'REJECT' createTime: string updateTime: string } diff --git a/src/pages/System/Tools/index.tsx b/src/pages/System/Tools/index.tsx index 170916e..44880c7 100644 --- a/src/pages/System/Tools/index.tsx +++ b/src/pages/System/Tools/index.tsx @@ -1,5 +1,15 @@ +import Playground from '@/components/Playground' +import templates from '@/components/Playground/templates' + const Tools = () => { - return <>1 + const template = templates['base'] + return ( + + ) } export default Tools diff --git a/src/pages/Tools/Edit.tsx b/src/pages/Tools/Edit.tsx new file mode 100644 index 0000000..63ef259 --- /dev/null +++ b/src/pages/Tools/Edit.tsx @@ -0,0 +1,168 @@ +import '@/assets/css/pages/tools/edit.scss' +import { r_tool_detail } from '@/services/tool.tsx' +import { DATABASE_NO_RECORD_FOUND, DATABASE_SELECT_SUCCESS } from '@/constants/common.constants.ts' +import { useEffect, useState } from 'react' +import Playground from '@/components/Playground' +import FitFullscreen from '@/components/common/FitFullscreen.tsx' +import FlexBox from '@/components/common/FlexBox.tsx' +import { IFiles, IImportMap, ITsconfig } from '@/components/Playground/shared.ts' +import { + base64ToFiles, + base64ToStr, + IMPORT_MAP_FILE_NAME, + TS_CONFIG_FILE_NAME +} from '@/components/Playground/files.ts' +import LoadingMask from '@/components/common/LoadingMask.tsx' + +const Edit = () => { + const navigate = useNavigate() + const { toolId } = useParams() + const [loading, setLoading] = useState(false) + const [toolData, setToolData] = useState() + const [files, setFiles] = useState({}) + const [selectedFileName, setSelectedFileName] = useState('') + const [importMapRaw, setImportMapRaw] = useState('') + const [importMap, setImportMap] = useState() + const [tsconfigRaw, setTsconfigRaw] = useState('') + const [tsconfig, setTsconfig] = useState() + const [entryPoint, setEntryPoint] = useState('') + const [baseDist, setBaseDist] = useState('') + + const handleOnChangeFileContent = (content: string, fileName: string, files: IFiles) => { + if (fileName === IMPORT_MAP_FILE_NAME) { + setImportMapRaw(content) + return + } + if (fileName === TS_CONFIG_FILE_NAME) { + setTsconfigRaw(content) + return + } + + delete files[IMPORT_MAP_FILE_NAME] + delete files[TS_CONFIG_FILE_NAME] + setFiles(files) + } + + const getTool = () => { + if (loading) { + return + } + setLoading(true) + void message.loading({ content: '加载中……', key: 'LOADING', duration: 0 }) + + void r_tool_detail('!', toolId!, 'latest') + .then((res) => { + const response = res.data + switch (response.code) { + case DATABASE_SELECT_SUCCESS: + switch (response.data!.review) { + case 'NONE': + case 'REJECT': + setToolData(response.data!) + break + case 'PROCESSING': + void message.warning('工具审核中,请勿修改') + navigate('/') + break + default: + void message.warning('请先创建新版本后编辑工具') + navigate('/') + } + break + case DATABASE_NO_RECORD_FOUND: + void message.error('未找到指定工具') + navigate('/') + break + default: + void message.error('获取工具信息失败,请稍后重试') + } + }) + .finally(() => { + setLoading(false) + message.destroy('LOADING') + }) + } + + useEffect(() => { + try { + setImportMap(JSON.parse(importMapRaw) as IImportMap) + } catch (e) { + /* empty */ + } + }, [importMapRaw]) + + useEffect(() => { + setTimeout(() => { + try { + setTsconfig(JSON.parse(tsconfigRaw) as ITsconfig) + } catch (e) { + /* empty */ + } + }, 1000) + }, [tsconfigRaw]) + + useEffect(() => { + if (!toolData) { + return + } + try { + setBaseDist(base64ToStr(toolData.base.dist.data!)) + const files = base64ToFiles(toolData.source.data!) + setFiles(files) + setImportMapRaw(files[IMPORT_MAP_FILE_NAME].value) + setTsconfigRaw(files[TS_CONFIG_FILE_NAME].value) + setEntryPoint(toolData.entryPoint) + setTimeout(() => { + setSelectedFileName(toolData.entryPoint) + }, 100) + } catch (e) { + console.error(e) + void message.error('载入工具失败') + } + }, [toolData]) + + useEffect(() => { + getTool() + }, []) + + return ( + + + + + + ) +} + +export default Edit diff --git a/src/pages/Tools/View.tsx b/src/pages/Tools/View.tsx index 459f750..7d1ae1e 100644 --- a/src/pages/Tools/View.tsx +++ b/src/pages/Tools/View.tsx @@ -11,8 +11,8 @@ import Card from '@/components/common/Card' const View = () => { const navigate = useNavigate() - const [loading, setLoading] = useState(false) const { username, toolId, ver } = useParams() + const [loading, setLoading] = useState(false) const [compiledCode, setCompiledCode] = useState('') const render = (toolVo: ToolVo) => { diff --git a/src/pages/Tools/index.tsx b/src/pages/Tools/index.tsx index 23632aa..b89ff28 100644 --- a/src/pages/Tools/index.tsx +++ b/src/pages/Tools/index.tsx @@ -25,6 +25,7 @@ interface CommonCardProps onOpen?: () => void onEdit?: () => void onPublish?: () => void + onCancelReview?: () => void onDelete?: () => void } @@ -46,6 +47,7 @@ const CommonCard = ({ onOpen, onEdit, onPublish, + onCancelReview, onDelete, children, ...props @@ -80,14 +82,19 @@ const CommonCard = ({ 打开 )} - {onEdit && ( + {onEdit && onPublish && (
编辑 - {onPublish && 发布} + 发布
)} + {onCancelReview && ( + + 取消审核 + + )} {onDelete && ( 删除 @@ -119,13 +126,21 @@ const ToolCard = ({ tools, onDelete, onUpgrade }: ToolCardProps) => { } const handleOnEditTool = () => { - if (selectedTool.publish === '0') { - return () => {} + if (selectedTool.publish === '0' && ['NONE', 'REJECT'].includes(selectedTool.review)) { + return () => { + navigate(`/edit/${tools[0].toolId}`) + } } } const handleOnPublishTool = () => { - if (selectedTool.publish === '0') { + if (selectedTool.publish === '0' && ['NONE', 'REJECT'].includes(selectedTool.review)) { + return () => {} + } + } + + const handleOnCancelReview = () => { + if (selectedTool.publish === '0' && selectedTool.review === 'PROCESSING') { return () => {} } } @@ -146,6 +161,7 @@ const ToolCard = ({ tools, onDelete, onUpgrade }: ToolCardProps) => { onOpen={handleOnOpenTool} onEdit={handleOnEditTool()} onPublish={handleOnPublishTool()} + onCancelReview={handleOnCancelReview()} onDelete={handleOnDeleteTool} > import('@/pages/Tools/View')), name: '查看' }, + { + path: 'edit/:toolId', + absolutePath: '/edit', + id: 'tools-edit', + component: lazy(() => import('@/pages/Tools/Edit')), + name: '查看' + }, { path: '*', absolutePath: '*',