diff --git a/src/cool/hooks/index.ts b/src/cool/hooks/index.ts index 166f5c4..ff551a7 100644 --- a/src/cool/hooks/index.ts +++ b/src/cool/hooks/index.ts @@ -55,3 +55,4 @@ export function useCool() { // 导出其他模块的功能 export * from './browser'; export * from './hmr'; +export * from './mitt'; diff --git a/src/cool/hooks/mitt.ts b/src/cool/hooks/mitt.ts index 4574435..a530ac0 100644 --- a/src/cool/hooks/mitt.ts +++ b/src/cool/hooks/mitt.ts @@ -1,7 +1,7 @@ import Mitt, { type Emitter } from 'mitt'; import { hmr } from './hmr'; -const mitt: Emitter = hmr.getData('mitt', Mitt()); +export const mitt: Emitter = hmr.getData('mitt', Mitt()); // 返回 mitt 实例,用于在应用中进行事件的发布和订阅 export function useMitt() { diff --git a/src/modules/helper/components/ai-code/btn.vue b/src/modules/helper/components/ai-code/btn.vue index 592f211..b40449c 100644 --- a/src/modules/helper/components/ai-code/btn.vue +++ b/src/modules/helper/components/ai-code/btn.vue @@ -42,6 +42,7 @@ function toCode() { animation-fill-mode: forwards; -webkit-text-size-adjust: none; font-size: 12px; + text-align: center; } .t2 { diff --git a/src/modules/helper/config.ts b/src/modules/helper/config.ts index 50264b7..504d8f2 100644 --- a/src/modules/helper/config.ts +++ b/src/modules/helper/config.ts @@ -1,3 +1,4 @@ +import { usePlugin } from './hooks'; import { type ModuleConfig } from '/@/cool'; export default (): ModuleConfig => { @@ -20,6 +21,10 @@ export default (): ModuleConfig => { }, component: () => import('./views/ai-code.vue') } - ] + ], + onLoad() { + const { register } = usePlugin(); + register(); + } }; }; diff --git a/src/modules/helper/hooks/index.ts b/src/modules/helper/hooks/index.ts index 8267df7..83c9777 100644 --- a/src/modules/helper/hooks/index.ts +++ b/src/modules/helper/hooks/index.ts @@ -1 +1,2 @@ export * from './menu'; +export * from './plugin'; diff --git a/src/modules/helper/hooks/plugin.ts b/src/modules/helper/hooks/plugin.ts new file mode 100644 index 0000000..25e271b --- /dev/null +++ b/src/modules/helper/hooks/plugin.ts @@ -0,0 +1,118 @@ +import { ElMessage, ElMessageBox } from 'element-plus'; +import { mitt, router, service } from '/@/cool'; +import { t } from '/@/plugins/i18n'; + +export const usePlugin = () => { + function getName(file: File) { + return file.name.replace('.cool', ''); + } + + // 注册 + function register() { + document.body.addEventListener('dragover', e => { + e.preventDefault(); + }); + document.body.addEventListener('drop', e => { + e.preventDefault(); + + if (e.dataTransfer) { + const file = e.dataTransfer.files[0]; + + ElMessageBox.confirm( + t('检测到插件「{name}」,是否安装?', { name: getName(file) }), + t('提示'), + { + type: 'warning', + confirmButtonText: t('安装') + } + ) + .then(() => { + install(file); + }) + .catch(() => null); + } + }); + } + + // 安装 + function install(file: File) { + const next = (force: boolean) => { + const data = new FormData(); + + data.append('files', file); + data.append('force', String(force)); + + service.plugin.info + .request({ + url: '/install', + method: 'POST', + data, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) + .then(res => { + if (!res) { + // 发送事件 + mitt.emit('plugin.refresh'); + + // 标题 + const title = t('插件「{name}」安装成功', { name: getName(file) }); + + // 是否插件页面 + if (router.currentRoute.value.path == '/helper/plugins') { + ElMessage.success(title); + } else { + ElMessageBox.alert(title, t('提示'), { + type: 'success', + confirmButtonText: t('点击查看'), + showCancelButton: true + }) + .then(() => { + router.push('/helper/plugins'); + }) + .catch(() => null); + } + + return; + } + + if (res.type == 0) { + ElMessageBox.confirm(res.message, t('提示'), { + type: 'error', + showConfirmButton: false + }) + .then(() => { + next(true); + }) + .catch(() => null); + } + + if (res.type == 1 || res.type == 2) { + ElMessageBox.confirm(res.message, t('提示'), { + type: 'warning', + confirmButtonText: t('继续') + }) + .then(() => { + next(true); + }) + .catch(() => null); + } + + if (res.type == 3) { + next(true); + } + }) + .catch(err => { + ElMessage.error(err.message); + }); + }; + + next(false); + } + + return { + register, + install + }; +}; diff --git a/src/modules/helper/locales/en.json b/src/modules/helper/locales/en.json index fe8da7c..a226dab 100644 --- a/src/modules/helper/locales/en.json +++ b/src/modules/helper/locales/en.json @@ -1,64 +1,66 @@ { - "搜索插件名称": "Search Plugin Name", - "后端": "Backend", - "未知": "Unknown", - "暂无描述": "No description yet", - "示例": "Example", - "预览": "Preview", - "文档": "Documentation", - "图片预览": "Image Preview", - "说明文档": "Instruction Document", - "作者": "Author", - "更新时间": "Update Time", - "格式化": "Format", - "插入文件链接": "Insert File Link", - "已安装": "Installed", - "全部插件": "All Plugins", - "插件开发": "Plugin Development", - "插件安装成功": "Plugin Installed Successfully", - "提示": "Tip", - "继续": "Continue", - "确定要卸载插件【{name}】吗?": "Are you sure you want to uninstall the plugin [{name}]?", - "卸载成功": "Uninstall success", - "启用成功": "Enable success", - "禁用成功": "Disable success", - "参数格式错误": "Parameter format error", - "设置": "Settings", - "参数": "Parameter", - "修改成功": "Modify success", - "检测到插件,是否安装": "Plugin detected. Install?", - "安装": "Install", - "确定要退出编码吗?": "Are you sure you want to exit encoding?", - "创建目录:{name}": "Create directory: {name}", - "创建菜单:{name}": "Create menu: {name}", - "创建 Node 文件": "Create Node file", - "正在重启服务": "Restarting service", - "创建 Vue 文件": "Create Vue file", - "自动添加": "Auto add", - "权限名称": "Permission name", - "实体数据": "Entity data", - "自动添加权限": "Auto add permission", - "一键添加": "Add in one click", - "权限列表": "Permission List", - "请选择实体数据": "Please Select Entity Data", - "请填写权限名称": "Please Fill in Permission Name", - "请至少选择一个权限": "Please Select at Least One Permission", - "添加权限成功": "Permission Added Successfully", - "快速创建": "Quick Create", - "请选择数据结构": "Please Select Data Structure", - "数据结构": "Data Structure", - "上级节点": "Parent Node", - "请选择上级节点": "Please Select Parent Node", - "菜单名称": "Menu Name", - "请输入菜单名称": "Please Enter Menu Name", - "菜单路由": "Menu Route", - "请输入菜单路由,如:/test": "Please Enter Menu Route, e.g.: /test", - "必须以 / 开头": "Must Start with /", - "菜单排序": "Menu Sort", - "请填写菜单排序": "Please Fill in Menu Sort", - "菜单图标": "Menu Icon", - "请选择图标": "Please Select Icon", - "路由缓存": "Route Cache", - "开始创建": "Start Creation", - "极速编码": "Fast Encoding" -} \ No newline at end of file + "请选择图标": "Please select an icon", + "路由缓存": "Routing cache", + "开始创建": "Start creating", + "AI极速编码": "AI Coding", + "搜索插件名称": "Search plugin name", + "后端": "Backend", + "未知": "Unknown", + "暂无描述": "No description available", + "示例": "Example", + "预览": "Preview", + "文档": "Documentation", + "图片预览": "Image preview", + "说明文档": "Instruction document", + "作者": "Author", + "更新时间": "Update time", + "格式化": "Formatting", + "插入文件链接": "Insert file link", + "已安装": "Installed", + "全部插件": "All plugins", + "插件开发": "Plugin development", + "确定要卸载插件【{name}】吗?": "Are you sure you want to uninstall the plugin [{name}]?", + "提示": "Prompt", + "卸载成功": "Uninstallation successful", + "启用成功": "Enablement successful", + "禁用成功": "Disable successfully", + "参数格式错误": "Parameter format error", + "设置": "Settings", + "参数": "Parameter", + "修改成功": "Modify successfully", + "确定要退出编码吗?": "Are you sure you want to exit the encoding?", + "创建目录:{name}": "Create directory: {name}", + "创建菜单:{name}": "Create menu: {name}", + "创建 Java 文件": "Create Java file", + "创建 Node 文件": "Create Node file", + "正在重启服务": "Restarting service", + "创建 Vue 文件": "Create Vue file", + "检测到插件「{name}」,是否安装?": "Plugin 「{name}」 detected. Do you want to install it?", + "安装": "Install", + "插件「{name}」安装成功": "Plugin 「{name}」 installed successfully", + "点击查看": "Click to view", + "继续": "Continue", + "自动添加": "Automatically add", + "权限名称": "Permission name", + "实体数据": "Entity data", + "自动添加权限": "Automatically add permissions", + "一键添加": "Add in one click", + "权限列表": "Permission list", + "请选择实体数据": "Please select entity data", + "请填写权限名称": "Please fill in the permission name", + "请至少选择一个权限": "Please select at least one permission", + "添加权限成功": "Successfully added permissions", + "快速创建": "Quick creation", + "请选择数据结构": "Please select the data structure", + "数据结构": "Data structure", + "上级节点": "Parent node", + "请选择上级节点": "Please select the parent node", + "菜单名称": "Menu name", + "请输入菜单名称": "Please enter the menu name", + "菜单路由": "Menu route", + "请输入菜单路由,如:/test": "Please enter the menu route, e.g.: /test", + "必须以 / 开头": "Must start with /", + "菜单排序": "Menu sorting", + "请填写菜单排序": "Please fill in the menu sorting", + "菜单图标": "Menu icon" +} diff --git a/src/modules/helper/locales/zh-cn.json b/src/modules/helper/locales/zh-cn.json index 84310e8..f356d59 100644 --- a/src/modules/helper/locales/zh-cn.json +++ b/src/modules/helper/locales/zh-cn.json @@ -15,10 +15,8 @@ "已安装": "已安装", "全部插件": "全部插件", "插件开发": "插件开发", - "插件安装成功": "插件安装成功", - "提示": "提示", - "继续": "继续", "确定要卸载插件【{name}】吗?": "确定要卸载插件【{name}】吗?", + "提示": "提示", "卸载成功": "卸载成功", "启用成功": "启用成功", "禁用成功": "禁用成功", @@ -26,14 +24,18 @@ "设置": "设置", "参数": "参数", "修改成功": "修改成功", - "检测到插件,是否安装": "检测到插件,是否安装", - "安装": "安装", "确定要退出编码吗?": "确定要退出编码吗?", "创建目录:{name}": "创建目录:{name}", "创建菜单:{name}": "创建菜单:{name}", + "创建 Java 文件": "创建 Java 文件", "创建 Node 文件": "创建 Node 文件", "正在重启服务": "正在重启服务", "创建 Vue 文件": "创建 Vue 文件", + "检测到插件「{name}」,是否安装?": "检测到插件「{name}」,是否安装?", + "安装": "安装", + "插件「{name}」安装成功": "插件「{name}」安装成功", + "点击查看": "点击查看", + "继续": "继续", "自动添加": "自动添加", "权限名称": "权限名称", "实体数据": "实体数据", @@ -60,5 +62,5 @@ "请选择图标": "请选择图标", "路由缓存": "路由缓存", "开始创建": "开始创建", - "极速编码": "极速编码" + "AI极速编码": "AI极速编码" } \ No newline at end of file diff --git a/src/modules/helper/locales/zh-tw.json b/src/modules/helper/locales/zh-tw.json index a1b10d4..5c3653e 100644 --- a/src/modules/helper/locales/zh-tw.json +++ b/src/modules/helper/locales/zh-tw.json @@ -1,6 +1,8 @@ { + "请选择图标": "請選擇圖標", + "路由缓存": "路由緩存", "开始创建": "開始創建", - "极速编码": "極速編碼", + "AI极速编码": "AI極速編碼", "搜索插件名称": "搜尋插件名稱", "后端": "後端", "未知": "未知", @@ -17,10 +19,8 @@ "已安装": "已安裝", "全部插件": "全部插件", "插件开发": "插件開發", - "插件安装成功": "插件安裝成功", - "提示": "提示", - "继续": "繼續", "确定要卸载插件【{name}】吗?": "確定要卸載插件【{name}】嗎?", + "提示": "提示", "卸载成功": "卸載成功", "启用成功": "啟用成功", "禁用成功": "禁用成功", @@ -28,14 +28,18 @@ "设置": "設置", "参数": "參數", "修改成功": "修改成功", - "检测到插件,是否安装": "檢測到插件,是否安裝", - "安装": "安裝", "确定要退出编码吗?": "確定要退出編碼嗎?", "创建目录:{name}": "創建目錄:{name}", "创建菜单:{name}": "創建菜單:{name}", + "创建 Java 文件": "創建 Java 文件", "创建 Node 文件": "創建 Node 文件", "正在重启服务": "正在重啟服務", "创建 Vue 文件": "創建 Vue 文件", + "检测到插件「{name}」,是否安装?": "檢測到插件「{name}」,是否安裝?", + "安装": "安裝", + "插件「{name}」安装成功": "插件「{name}」安裝成功", + "点击查看": "點擊查看", + "继续": "繼續", "自动添加": "自動添加", "权限名称": "權限名稱", "实体数据": "實體數據", @@ -58,7 +62,5 @@ "必须以 / 开头": "必須以 / 開頭", "菜单排序": "菜單排序", "请填写菜单排序": "請填寫菜單排序", - "菜单图标": "菜單圖標", - "请选择图标": "請選擇圖標", - "路由缓存": "路由緩存" + "菜单图标": "菜單圖標" } \ No newline at end of file diff --git a/src/modules/helper/views/plugins.vue b/src/modules/helper/views/plugins.vue index f7e44ce..c343ab7 100644 --- a/src/modules/helper/views/plugins.vue +++ b/src/modules/helper/views/plugins.vue @@ -27,8 +27,6 @@ :class="{ 'is-installed': isInstalled }" - @dragover="onDragover" - @drop="onDrop" @mousemove="onMousemove" > @@ -279,6 +277,7 @@ import { import { ElMessage, ElMessageBox } from 'element-plus'; import { marked } from 'marked'; import { useI18n } from 'vue-i18n'; +import { usePlugin } from '../hooks'; interface Plugin { name?: string; @@ -297,9 +296,10 @@ interface Plugin { [key: string]: any; } -const { router, service, refs, setRefs } = useCool(); +const { router, service, refs, setRefs, mitt } = useCool(); const helper = module.get('helper'); const { t } = useI18n(); +const { install } = usePlugin(); // 选项卡 const tab = reactive({ @@ -354,66 +354,15 @@ const plugin = reactive({ // 初始化 init() { plugin.refresh(); - }, - // 安装 - install(file: File) { - const next = (force: boolean) => { - const data = new FormData(); + // 移除事件 + mitt.off('plugin.refresh'); - data.append('files', file); - data.append('force', String(force)); - - service.plugin.info - .request({ - url: '/install', - method: 'POST', - data, - headers: { - 'Content-Type': 'multipart/form-data' - } - }) - .then(res => { - if (!res) { - ElMessage.success(t('插件安装成功')); - tab.change('installed'); - plugin.refresh(); - - return; - } - - if (res.type == 0) { - ElMessageBox.confirm(res.message, t('提示'), { - type: 'error', - showConfirmButton: false - }) - .then(() => { - next(true); - }) - .catch(() => null); - } - - if (res.type == 1 || res.type == 2) { - ElMessageBox.confirm(res.message, t('提示'), { - type: 'warning', - confirmButtonText: t('继续') - }) - .then(() => { - next(true); - }) - .catch(() => null); - } - - if (res.type == 3) { - next(true); - } - }) - .catch(err => { - ElMessage.error(err.message); - }); - }; - - next(false); + // 监听刷新事件 + mitt.on('plugin.refresh', () => { + tab.change('installed'); + plugin.refresh(); + }); }, // 卸载 @@ -786,33 +735,10 @@ const pic = reactive({ // 上传 function onBeforeUpload(file: File) { - plugin.install(file); + install(file); return false; } -// 拖拽 -function onDragover(e: DragEvent) { - e.preventDefault(); -} - -// 放下 -function onDrop(e: DragEvent) { - e.preventDefault(); - - if (e.dataTransfer) { - const file = e.dataTransfer.files[0]; - - ElMessageBox.confirm(t('检测到插件,是否安装'), t('提示'), { - type: 'warning', - confirmButtonText: t('安装') - }) - .then(() => { - plugin.install(file); - }) - .catch(() => null); - } -} - // 鼠标移动 function onMousemove(e: MouseEvent) { if (!isInstalled.value) {