diff --git a/plugins/test-plugin-090802/.gitignore b/plugins/test-plugin-090802/.gitignore new file mode 100644 index 000000000..cb45445de --- /dev/null +++ b/plugins/test-plugin-090802/.gitignore @@ -0,0 +1,25 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +src-ztools/dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/plugins/test-plugin-090802/CHANGELOG.md b/plugins/test-plugin-090802/CHANGELOG.md new file mode 100644 index 000000000..91d6f895b --- /dev/null +++ b/plugins/test-plugin-090802/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 0.0.1 - 2026-09-08 + +- 初次发布,将插件提交至 ZTools 插件仓库。 diff --git a/plugins/test-plugin-090802/README.md b/plugins/test-plugin-090802/README.md new file mode 100644 index 000000000..aa31efdac --- /dev/null +++ b/plugins/test-plugin-090802/README.md @@ -0,0 +1,281 @@ +# test-plugin-090802 + +> A ZTools plugin + +这是一个使用 **Vue 3 + Vite + TypeScript** 构建的 ZTools 插件。 + +## ✨ 功能特性 + +### 📌 已包含的示例功能 + +- **Hello** - 基础功能指令示例 + - 触发指令:`你好` / `hello` + - 展示简单的 Vue 组件界面 + +- **读文件** - 文件读取功能示例 + - 功能指令:`读文件` + - 匹配指令:支持拖拽文件触发 + - 演示如何使用 Node.js 能力读取文件内容 + +- **保存为文件** - 文件写入功能示例 + - 匹配指令:任意文本/图片 → `保存为文件` + - 演示如何将剪贴板内容保存为文件 + +## 📁 项目结构 + +``` +. +├── src-ztools/ +│ ├── logo.png # 插件图标 +│ ├── plugin.json # 插件配置文件 +│ └── preload/ # Preload 脚本目录 +│ ├── package.json # Preload 依赖配置 +│ └── services.js # Node.js 能力扩展 +├── src/ +│ ├── main.ts # 入口文件 +│ ├── main.css # 全局样式 +│ ├── App.vue # 根组件 +│ ├── env.d.ts # 类型声明 +│ ├── Hello/ # Hello 功能组件 +│ │ └── index.vue +│ ├── Read/ # 读文件功能组件 +│ │ └── index.vue +│ └── Write/ # 写文件功能组件 +│ └── index.vue +├── index.html # HTML 模板 +├── vite.config.js # Vite 配置 +├── tsconfig.json # TypeScript 配置 +├── package.json # 项目依赖 +└── README.md # 项目文档 +``` + +## 🚀 快速开始 + +### 安装依赖 + +```bash +npm install +``` + +### 开发模式 + +```bash +npm run dev +``` + +开发服务器将在 `http://localhost:5173` 启动。ZTools 会自动加载开发版本。 + +### 构建生产版本 + +```bash +npm run build +``` + +构建产物将输出到 `src-ztools/dist/` 目录,`src-ztools/` 是完整的 ZTools 插件目录。 + +## 📖 开发指南 + +### 1. 修改插件配置 + +编辑 `src-ztools/plugin.json` 文件: + +```json +{ + "name": "你的插件名称", + "description": "插件描述", + "author": "作者名称", + "version": "1.0.0", + "features": [ + // 添加你的功能配置 + ] +} +``` + +### 2. 创建新功能 + +#### 步骤 1: 创建 Vue 组件 + +在 `src/` 目录下创建新的功能组件: + +```vue + + + + + + +``` + +#### 步骤 2: 注册路由 + +在 `src/App.vue` 中添加路由: + +```vue + +``` + +#### 步骤 3: 配置功能 + +在 `plugin.json` 中添加功能配置: + +```json +{ + "code": "myfeature", + "explain": "我的新功能", + "icon": "logo.png", + "cmds": ["触发指令"] +} +``` + +### 3. 使用 Node.js 能力 + +#### 扩展 Preload 服务 + +编辑 `src-ztools/preload/services.js`: + +```javascript +const fs = require('fs') +const path = require('path') + +module.exports = { + // 示例:读取文件 + readFile: (filePath) => { + return fs.readFileSync(filePath, 'utf-8') + }, + + // 添加你的服务 + myService: (params) => { + // 实现你的逻辑 + return result + } +} +``` + +#### 在 Vue 组件中调用 + +```vue + +``` + +### 4. 使用 ZTools API + +```vue + +``` + +## 🎨 样式开发 + +### 使用 CSS 变量 + +ZTools 提供了一套 CSS 变量用于主题适配: + +```css +.my-component { + background: var(--bg-color); + color: var(--text-color); + border: 1px solid var(--border-color); +} +``` + +### 暗色模式支持 + +```css +@media (prefers-color-scheme: dark) { + .my-component { + /* 暗色模式样式 */ + } +} +``` + +## 📦 构建与发布 + +### 1. 构建插件 + +```bash +npm run build +``` + +### 2. 测试构建产物 + +将 `src-ztools/` 目录作为完整插件目录复制到 ZTools 插件目录进行测试。 + +### 3. 发布到插件市场 + +1. 确保 `plugin.json` 中的信息完整准确 +2. 准备好插件截图和详细说明 +3. 访问 ZTools 插件市场提交插件 + +## 📚 相关资源 + +- [ZTools 官方文档](https://github.com/ztool-center/ztools) +- [ZTools API 文档](https://github.com/ztool-center/ztools-api-types) +- [Vue 3 文档](https://vuejs.org/) +- [Vite 文档](https://vitejs.dev/) + +## ❓ 常见问题 + +### Q: 如何调试插件? + +A: 使用 `npm run dev` 启动开发服务器,在插件界面中点击插件头像图标,在弹出的菜单中选择"打开开发者工具"进行调试。 + +### Q: 如何访问 Node.js 能力? + +A: 通过 `src-ztools/preload/services.js` 文件扩展服务,然后在组件中使用 `window.services` 调用。 + +### Q: 插件图标不显示? + +A: 确保 `src-ztools/logo.png` 文件存在,且在 `plugin.json` 中正确配置了 `logo` 字段。 + +### Q: 如何处理大文件上传? + +A: 建议使用 Node.js 流式处理,在 preload 脚本中实现文件分块处理逻辑。 + +## 📄 开源协议 + +MIT License + +--- + +**祝你开发愉快!** 🎉 diff --git a/plugins/test-plugin-090802/index.html b/plugins/test-plugin-090802/index.html new file mode 100644 index 000000000..eaa17316c --- /dev/null +++ b/plugins/test-plugin-090802/index.html @@ -0,0 +1,11 @@ + + + + + + + +
+ + + diff --git a/plugins/test-plugin-090802/package.json b/plugins/test-plugin-090802/package.json new file mode 100644 index 000000000..8cfec29a5 --- /dev/null +++ b/plugins/test-plugin-090802/package.json @@ -0,0 +1,20 @@ +{ + "name": "test-plugin-090802", + "version": "1.0.0", + "description": "A ZTools plugin", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc && vite build" + }, + "dependencies": { + "vue": "^3.5.13" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.2.1", + "@ztools-center/ztools-api-types": "^1.0.1", + "typescript": "^5.3.0", + "vite": "^6.0.11", + "vue-tsc": "^2.0.0" + } +} diff --git a/plugins/test-plugin-090802/src-ztools/logo.png b/plugins/test-plugin-090802/src-ztools/logo.png new file mode 100644 index 000000000..f17f4cecb Binary files /dev/null and b/plugins/test-plugin-090802/src-ztools/logo.png differ diff --git a/plugins/test-plugin-090802/src-ztools/plugin.json b/plugins/test-plugin-090802/src-ztools/plugin.json new file mode 100644 index 000000000..ac50c05a8 --- /dev/null +++ b/plugins/test-plugin-090802/src-ztools/plugin.json @@ -0,0 +1,52 @@ +{ + "$schema": "node_modules/@ztools-center/ztools-api-types/resource/ztools.schema.json", + "name": "test-plugin-090802", + "title": "test plugin 090802", + "description": "A ZTools plugin", + "author": "Your Name", + "version": "0.0.1", + "main": "dist/index.html", + "preload": "preload/services.js", + "logo": "logo.png", + "development": { + "main": "http://localhost:5173" + }, + "features": [ + { + "code": "hello", + "explain": "这是插件应用的第一个功能", + "icon": "logo.png", + "cmds": ["你好", "hello"] + }, + { + "code": "read", + "explain": "功能指令+匹配指令示例,使用 node.js 能力读文件", + "icon": "logo.png", + "cmds": [ + "读文件", + { + "type": "files", + "fileType": "file", + "maxLength": 1, + "label": "读文件" + } + ] + }, + { + "code": "write", + "explain": "匹配指令示例,使用 node.js 能力写文件", + "icon": "logo.png", + "mainHide": true, + "cmds": [ + { + "type": "over", + "label": "保存为文件" + }, + { + "type": "img", + "label": "保存为文件" + } + ] + } + ] +} diff --git a/plugins/test-plugin-090802/src-ztools/preload/package.json b/plugins/test-plugin-090802/src-ztools/preload/package.json new file mode 100644 index 000000000..5bbefffba --- /dev/null +++ b/plugins/test-plugin-090802/src-ztools/preload/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/plugins/test-plugin-090802/src-ztools/preload/services.js b/plugins/test-plugin-090802/src-ztools/preload/services.js new file mode 100644 index 000000000..83c3ef1f5 --- /dev/null +++ b/plugins/test-plugin-090802/src-ztools/preload/services.js @@ -0,0 +1,27 @@ +const fs = require('node:fs') +const path = require('node:path') + +// 通过 window 对象向渲染进程注入 nodejs 能力 +window.services = { + // 读文件 + readFile(file) { + return fs.readFileSync(file, { encoding: 'utf-8' }) + }, + // 文本写入到下载目录 + writeTextFile(text) { + const filePath = path.join(window.ztools.getPath('downloads'), Date.now().toString() + '.txt') + fs.writeFileSync(filePath, text, { encoding: 'utf-8' }) + return filePath + }, + // 图片写入到下载目录 + writeImageFile(base64Url) { + const matchs = /^data:image\/([a-z]{1,20});base64,/i.exec(base64Url) + if (!matchs) return + const filePath = path.join( + window.ztools.getPath('downloads'), + Date.now().toString() + '.' + matchs[1] + ) + fs.writeFileSync(filePath, base64Url.substring(matchs[0].length), { encoding: 'base64' }) + return filePath + } +} diff --git a/plugins/test-plugin-090802/src/App.vue b/plugins/test-plugin-090802/src/App.vue new file mode 100644 index 000000000..d4fabacba --- /dev/null +++ b/plugins/test-plugin-090802/src/App.vue @@ -0,0 +1,25 @@ + + + diff --git a/plugins/test-plugin-090802/src/Hello/index.vue b/plugins/test-plugin-090802/src/Hello/index.vue new file mode 100644 index 000000000..8fc58146c --- /dev/null +++ b/plugins/test-plugin-090802/src/Hello/index.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/plugins/test-plugin-090802/src/Read/index.vue b/plugins/test-plugin-090802/src/Read/index.vue new file mode 100644 index 000000000..903fea36d --- /dev/null +++ b/plugins/test-plugin-090802/src/Read/index.vue @@ -0,0 +1,105 @@ + + + + + diff --git a/plugins/test-plugin-090802/src/Write/index.vue b/plugins/test-plugin-090802/src/Write/index.vue new file mode 100644 index 000000000..f8021de04 --- /dev/null +++ b/plugins/test-plugin-090802/src/Write/index.vue @@ -0,0 +1,40 @@ + + + diff --git a/plugins/test-plugin-090802/src/env.d.ts b/plugins/test-plugin-090802/src/env.d.ts new file mode 100644 index 000000000..94ae981d0 --- /dev/null +++ b/plugins/test-plugin-090802/src/env.d.ts @@ -0,0 +1,23 @@ +/// +/// + +declare module '*.vue' { + import type { DefineComponent } from 'vue' + const component: DefineComponent, Record, unknown> + export default component +} + +// Preload services 类型声明(对应 public/preload/services.js) +interface Services { + readFile: (file: string) => string + writeTextFile: (text: string) => string + writeImageFile: (base64Url: string) => string | undefined +} + +declare global { + interface Window { + services: Services + } +} + +export {} diff --git a/plugins/test-plugin-090802/src/main.css b/plugins/test-plugin-090802/src/main.css new file mode 100644 index 000000000..c372a2a3f --- /dev/null +++ b/plugins/test-plugin-090802/src/main.css @@ -0,0 +1,63 @@ +:root { + --blue: rgb(88, 164, 246); + --light: #fff; +} + +html, +body { + margin: 0; + padding: 0; +} + +button { + border: none; + background: none var(--blue); + color: var(--light); + line-height: 2.5; + cursor: pointer; + transition: opacity 0.2s; +} + +button:disabled { + filter: grayscale(1); + cursor: not-allowed; +} + +button:not(:disabled):active { + opacity: 0.6; +} + +textarea { + display: block; + margin: 0; +} + +@media (prefers-color-scheme: light) { + body { + background-color: #f4f4f4; + } + + ::-webkit-scrollbar-track-piece { + background-color: #f4f4f4; + } + + ::-webkit-scrollbar-thumb { + border-color: #f4f4f4; + } +} + +@media (prefers-color-scheme: dark) { + &::-webkit-scrollbar-track-piece { + background-color: #303133; + } + + &::-webkit-scrollbar-thumb { + background-color: #666; + border-color: #303133; + } + + body { + background-color: #303133; + color: #fff; + } +} diff --git a/plugins/test-plugin-090802/src/main.ts b/plugins/test-plugin-090802/src/main.ts new file mode 100644 index 000000000..8a3c77bc5 --- /dev/null +++ b/plugins/test-plugin-090802/src/main.ts @@ -0,0 +1,5 @@ +import { createApp } from 'vue' +import './main.css' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/plugins/test-plugin-090802/tsconfig.json b/plugins/test-plugin-090802/tsconfig.json new file mode 100644 index 000000000..39b73bc6f --- /dev/null +++ b/plugins/test-plugin-090802/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "strict": false, + "noImplicitAny": false, + "types": ["@ztools-center/ztools-api-types"] + }, + "include": ["src"] +} diff --git a/plugins/test-plugin-090802/vite.config.js b/plugins/test-plugin-090802/vite.config.js new file mode 100644 index 000000000..ce331609e --- /dev/null +++ b/plugins/test-plugin-090802/vite.config.js @@ -0,0 +1,12 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue()], + base: './', + build: { + outDir: 'src-ztools/dist', + emptyOutDir: true + } +})