From d6ff952596db97ebc8f991a456486f56527daa4c Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Tue, 30 Jan 2024 19:24:37 +0800 Subject: [PATCH] Add tool view page --- src/assets/css/pages/tools/index.scss | 10 +- src/assets/css/pages/tools/view.scss | 8 ++ src/assets/svg/upgrade.svg | 1 + src/constants/common.constants.ts | 2 + src/global.d.ts | 10 +- src/pages/Tools/Create.tsx | 6 +- src/pages/Tools/View.tsx | 47 ++++++-- src/pages/Tools/index.tsx | 166 +++++++++++++++++++++++--- src/services/tool.tsx | 4 + 9 files changed, 227 insertions(+), 27 deletions(-) create mode 100644 src/assets/css/pages/tools/view.scss create mode 100644 src/assets/svg/upgrade.svg diff --git a/src/assets/css/pages/tools/index.scss b/src/assets/css/pages/tools/index.scss index bb85d5a..8f0bcab 100644 --- a/src/assets/css/pages/tools/index.scss +++ b/src/assets/css/pages/tools/index.scss @@ -28,6 +28,14 @@ position: absolute; top: 10px; left: 10px; + width: 6em; + } + + .upgrade-bt { + position: absolute; + top: 10px; + right: 10px; + font-size: 1.8em; } .icon { @@ -61,7 +69,7 @@ & > :not(:first-child) { .info { - transform: translateY(20px); + transform: translateY(40px); transition: all 0.1s ease; } diff --git a/src/assets/css/pages/tools/view.scss b/src/assets/css/pages/tools/view.scss new file mode 100644 index 0000000..df4f6a6 --- /dev/null +++ b/src/assets/css/pages/tools/view.scss @@ -0,0 +1,8 @@ +[data-component=tools-view] { + padding: 30px; + + .card-box { + height: 100%; + width: 100%; + } +} \ No newline at end of file diff --git a/src/assets/svg/upgrade.svg b/src/assets/svg/upgrade.svg new file mode 100644 index 0000000..aa55d78 --- /dev/null +++ b/src/assets/svg/upgrade.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/constants/common.constants.ts b/src/constants/common.constants.ts index be6a3e7..12cc77e 100644 --- a/src/constants/common.constants.ts +++ b/src/constants/common.constants.ts @@ -74,6 +74,8 @@ export const DATABASE_EXECUTE_ERROR = 30050 export const DATABASE_DUPLICATE_KEY = 30051 export const DATABASE_NO_RECORD_FOUND = 30052 +export const TOOL_ILLEGAL_VERSION = 40050 + export const API_AVATAR_SUCCESS = 50100 export const API_AVATAR_ERROR = 50150 diff --git a/src/global.d.ts b/src/global.d.ts index 1c55dee..0a6942b 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -531,15 +531,16 @@ interface ToolVo { toolId: string icon: string description: string - baseId: string + base: ToolBaseVo author: UserInfoVo ver: string keywords: string[] categories: ToolCategoryVo[] source: ToolDataVo dist: ToolDataVo + entryPoint: string publish: string - review: number + review: 'NONE' | 'PASS' | 'REJECT' createTime: string updateTime: string } @@ -554,3 +555,8 @@ interface ToolCreateParam { keywords: string[] categories: string[] } + +interface ToolUpgradeParam { + toolId: string + ver: string +} diff --git a/src/pages/Tools/Create.tsx b/src/pages/Tools/Create.tsx index b6f6acb..746eaca 100644 --- a/src/pages/Tools/Create.tsx +++ b/src/pages/Tools/Create.tsx @@ -11,9 +11,9 @@ import { r_tool_template_get, r_tool_template_get_one } from '@/services/tool' +import compiler from '@/components/Playground/compiler' import { IImportMap } from '@/components/Playground/shared' import { base64ToFiles, base64ToStr, IMPORT_MAP_FILE_NAME } from '@/components/Playground/files' -import compiler from '@/components/Playground/compiler' import FlexBox from '@/components/common/FlexBox' import Card from '@/components/common/Card' import FitFullscreen from '@/components/common/FitFullscreen' @@ -21,6 +21,7 @@ import HideScrollbar from '@/components/common/HideScrollbar' import Playground from '@/components/Playground' const Create = () => { + const navigate = useNavigate() const [form] = AntdForm.useForm() const formValues = AntdForm.useWatch([], form) const [templateData, setTemplateData] = useState() @@ -43,9 +44,10 @@ const Create = () => { void message.success( `创建工具 ${response.data!.name}<${response.data!.toolId}>:${response.data!.ver} 成功` ) + navigate(`/view/!/${response.data!.toolId}/${response.data!.ver}`) break case DATABASE_DUPLICATE_KEY: - void message.warning('已存在相同 ID 相同版本或未发布版本的应用') + void message.warning('已存在相同 ID 的应用') setCreating(false) break default: diff --git a/src/pages/Tools/View.tsx b/src/pages/Tools/View.tsx index f20e37e..459f750 100644 --- a/src/pages/Tools/View.tsx +++ b/src/pages/Tools/View.tsx @@ -1,11 +1,39 @@ -import { r_tool_detail } from '@/services/tool.tsx' -import { DATABASE_NO_RECORD_FOUND, DATABASE_SELECT_SUCCESS } from '@/constants/common.constants.ts' -import { getLoginStatus } from '@/util/auth.tsx' +import '@/assets/css/pages/tools/view.scss' +import { DATABASE_NO_RECORD_FOUND, DATABASE_SELECT_SUCCESS } from '@/constants/common.constants' +import { getLoginStatus } from '@/util/auth' +import { r_tool_detail } from '@/services/tool' +import compiler from '@/components/Playground/compiler' +import { IImportMap } from '@/components/Playground/shared' +import { base64ToFiles, base64ToStr, IMPORT_MAP_FILE_NAME } from '@/components/Playground/files' +import FitFullscreen from '@/components/common/FitFullscreen' +import Playground from '@/components/Playground' +import Card from '@/components/common/Card' const View = () => { const navigate = useNavigate() const [loading, setLoading] = useState(false) const { username, toolId, ver } = useParams() + const [compiledCode, setCompiledCode] = useState('') + + const render = (toolVo: ToolVo) => { + try { + const baseDist = base64ToStr(toolVo.base.dist.data!) + const files = base64ToFiles(toolVo.source.data!) + const importMap = JSON.parse(files[IMPORT_MAP_FILE_NAME].value) as IImportMap + + void compiler + .compile(files, importMap, toolVo.entryPoint) + .then((result) => { + const output = result.outputFiles[0].text + setCompiledCode(`${output}\n${baseDist}`) + }) + .catch((reason) => { + void message.error(`编译失败:${reason}`) + }) + } catch (e) { + void message.error('载入工具失败') + } + } const getTool = () => { if (loading) { @@ -19,7 +47,7 @@ const View = () => { const response = res.data switch (response.code) { case DATABASE_SELECT_SUCCESS: - console.log(response.data) + render(response.data!) break case DATABASE_NO_RECORD_FOUND: void message.error('未找到指定工具') @@ -52,9 +80,14 @@ const View = () => { }, []) return ( - <> - {username}:{toolId}:{ver} - + + + + + ) } diff --git a/src/pages/Tools/index.tsx b/src/pages/Tools/index.tsx index 256313f..23632aa 100644 --- a/src/pages/Tools/index.tsx +++ b/src/pages/Tools/index.tsx @@ -1,15 +1,19 @@ -import { DetailedHTMLProps, HTMLAttributes, ReactNode, useState } from 'react' +import { DetailedHTMLProps, HTMLAttributes, ReactNode } from 'react' import Icon from '@ant-design/icons' import VanillaTilt, { TiltOptions } from 'vanilla-tilt' import '@/assets/css/pages/tools/index.scss' +import { + DATABASE_DELETE_SUCCESS, + DATABASE_SELECT_SUCCESS, + DATABASE_UPDATE_SUCCESS, + TOOL_ILLEGAL_VERSION +} from '@/constants/common.constants' +import { getLoginStatus } from '@/util/auth' +import { r_tool_delete, r_tool_get, r_tool_upgrade } from '@/services/tool' import FitFullscreen from '@/components/common/FitFullscreen' import HideScrollbar from '@/components/common/HideScrollbar' import FlexBox from '@/components/common/FlexBox' import Card from '@/components/common/Card' -import { r_tool_get } from '@/services/tool.tsx' -import { DATABASE_SELECT_SUCCESS } from '@/constants/common.constants.ts' -import { getLoginStatus } from '@/util/auth.tsx' -import { useNavigate } from 'react-router' interface CommonCardProps extends DetailedHTMLProps, HTMLDivElement> { @@ -79,13 +83,13 @@ const CommonCard = ({ {onEdit && (
- 编辑 - {onPublish && 发布} + 编辑 + {onPublish && 发布}
)} {onDelete && ( - + 删除 )} @@ -98,9 +102,11 @@ const CommonCard = ({ interface ToolCardProps { tools: ToolVo[] + onDelete?: (tool: ToolVo) => void + onUpgrade?: (tool: ToolVo) => void } -const ToolCard = ({ tools }: ToolCardProps) => { +const ToolCard = ({ tools, onDelete, onUpgrade }: ToolCardProps) => { const navigate = useNavigate() const [selectedTool, setSelectedTool] = useState(tools[0]) @@ -112,11 +118,25 @@ const ToolCard = ({ tools }: ToolCardProps) => { navigate(`/view/!/${selectedTool.toolId}/${selectedTool.ver}`) } - const handleOnEditTool = () => {} + const handleOnEditTool = () => { + if (selectedTool.publish === '0') { + return () => {} + } + } - const handleOnPublishTool = () => {} + const handleOnPublishTool = () => { + if (selectedTool.publish === '0') { + return () => {} + } + } - const handleOnDeleteTool = () => {} + const handleOnDeleteTool = () => { + onDelete?.(selectedTool) + } + + const handleOnUpgradeTool = () => { + onUpgrade?.(selectedTool) + } return ( { toolName={selectedTool.name} toolId={selectedTool.toolId} onOpen={handleOnOpenTool} - onEdit={handleOnEditTool} - onPublish={handleOnPublishTool} + onEdit={handleOnEditTool()} + onPublish={handleOnPublishTool()} onDelete={handleOnDeleteTool} > { label: `${value.ver}${value.publish === '0' ? '*' : ''}` }))} /> + {tools.every((value) => value.publish !== '0') && ( + + + + )} ) } const Tools = () => { + const navigate = useNavigate() + const [modal, contextHolder] = AntdModal.useModal() const [loading, setLoading] = useState(false) const [toolData, setToolData] = useState() + const [upgradeForm] = AntdForm.useForm() + + const handleOnDeleteTool = (tool: ToolVo) => { + modal + .confirm({ + title: '确定删除', + content: `确定删除工具 ${tool.name}:${tool.ver} 吗?` + }) + .then( + (confirmed) => { + if (confirmed) { + setLoading(true) + + void r_tool_delete(tool.id) + .then((res) => { + const response = res.data + if (response.code === DATABASE_DELETE_SUCCESS) { + void message.success('删除成功') + getTool() + } else { + void message.error('删除失败,请稍后重试') + } + }) + .finally(() => { + setLoading(false) + }) + } + }, + () => {} + ) + } + + const handleOnUpgradeTool = (tool: ToolVo) => { + void modal.confirm({ + title: '更新应用', + content: ( + <> + + + + + .<数字>.<数字>', eg. 1.0.3` + } + ]} + > + + + + + ), + onOk: () => + upgradeForm.validateFields().then( + () => { + return new Promise((resolve, reject) => { + void r_tool_upgrade({ + toolId: upgradeForm.getFieldValue('toolId') as string, + ver: upgradeForm.getFieldValue('ver') as string + }).then((res) => { + const response = res.data + switch (response.code) { + case DATABASE_UPDATE_SUCCESS: + void message.success('创建新版本成功') + const toolVo = response.data! + navigate(`/view/!/${toolVo.toolId}/${toolVo.ver}`) + resolve() + break + case TOOL_ILLEGAL_VERSION: + void message.error('版本有误,请重新输入') + reject() + break + default: + void message.error('更新失败,请稍后重试') + reject() + } + }) + }) + }, + () => { + return new Promise((_, reject) => { + reject('未输入版本') + }) + } + ) + }) + } const getTool = () => { if (loading) { @@ -195,10 +323,18 @@ const Tools = () => { result[item.toolId].push(item) return result }, {}) - ).map((value, index) => )} + ).map((value) => ( + + ))} + {contextHolder} ) } diff --git a/src/services/tool.tsx b/src/services/tool.tsx index 705fd7c..7339843 100644 --- a/src/services/tool.tsx +++ b/src/services/tool.tsx @@ -15,7 +15,11 @@ export const r_tool_category_get = () => request.get(URL_TOOL_ export const r_tool_create = (param: ToolCreateParam) => request.post(URL_TOOL, param) +export const r_tool_upgrade = (param: ToolUpgradeParam) => request.patch(URL_TOOL, param) + export const r_tool_get = () => request.get(URL_TOOL) export const r_tool_detail = (username: string, toolId: string, ver: string) => request.get(`${URL_TOOL_DETAIL}/${username}/${toolId}/${ver}`) + +export const r_tool_delete = (id: string) => request.delete(`${URL_TOOL}/${id}`)