diff --git a/plugins/datatimeutc/.gitignore b/plugins/datatimeutc/.gitignore new file mode 100755 index 00000000..8cd0e9d1 --- /dev/null +++ b/plugins/datatimeutc/.gitignore @@ -0,0 +1,17 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +src-ztools/dist +src-ztools/dist-ssr +*.local + +AGENTS.md +ztools-dev-reference.md +*.zpx diff --git a/plugins/datatimeutc/CHANGELOG.md b/plugins/datatimeutc/CHANGELOG.md new file mode 100755 index 00000000..67f1edf4 --- /dev/null +++ b/plugins/datatimeutc/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog + +## 1.0.2 - 2026-08-23 + +- 获取当前UTC时间,支持更改时区、悬浮窗显示、日期显示格式、悬浮窗透明度和大小调整 + diff --git a/plugins/datatimeutc/README.md b/plugins/datatimeutc/README.md new file mode 100755 index 00000000..ad1f81a7 --- /dev/null +++ b/plugins/datatimeutc/README.md @@ -0,0 +1,67 @@ +# datatimeutc — UTC 标准时间 + +> ZTools 插件:实时显示 UTC 时间,支持多时区切换、自定义日期时间格式、NTP 网络校时,以及可拖拽的置顶悬浮时间小窗。 + +基于 **Vue 3 + Vite + TypeScript** 构建。 + +## ✨ 功能特性 + +- **实时 UTC 时间**:大字时钟,250ms 刷新,毫秒级显示 +- **多时区切换**:覆盖 Intl 全部时区(按 UTC 偏移去重,约 40 项),中文显示名 +- **自定义格式**:日期、时间、星期、毫秒可自由组合 +- **NTP 网络校时**:依次尝试 `cn.ntp.org.cn` → `pool.ntp.org` → `time.nist.gov`,每 5 分钟自动校准一次;校准偏移持久化,悬浮窗启动即可用 +- **悬浮时间窗**:无边框、透明、置顶、不占任务栏,可拖拽移动;透明度与大小(缩放)可调,偏好自动记忆 +- **亮/暗双主题**:跟随系统 + +## 🚀 使用 + +在 ZTools 中触发以下指令: + +| 指令 | 功能 | +| --- | --- | +| `utc` / `时间` / `时区` / `utc时间` | 打开主界面(时钟 + 时区/格式设置) | +| `悬浮时间` / `utc悬浮` / `时间悬浮` | 直接开启悬浮时间窗 | + +悬浮窗内可用滑块调节透明度与大小,点击关闭按钮退出。 + +## 🛠️ 开发 + +```bash +npm install # 安装依赖 +npm run dev # 开发服务器(端口 5173),ZTools 客户端自动加载 dev 版 +npm run build # 类型检查 + 构建 → 输出到 src-ztools/dist/ +``` + +## 📁 项目结构 + +``` +. +├── src/ # Vue 3 前端源码 +│ ├── main.ts # 入口 +│ ├── App.vue # 根组件(三态路由:#float / utc-float / 主界面) +│ ├── env.d.ts # window.services 类型声明 +│ └── Utc/ +│ ├── index.vue # 主界面:大字时钟 + 时区/格式设置 +│ ├── Float.vue # 悬浮窗界面 +│ ├── AutoFloat.vue # 自动开悬浮窗(无 UI) +│ ├── time.ts # NTP offset 单例(getNow / 周期校准) +│ └── format.ts # Intl 时间格式化 + 时区列表/中文名 +├── src-ztools/ # 插件发布单元 +│ ├── plugin.json # 插件清单(实际生效的配置) +│ ├── preload/services.js # Node 能力桥接(NTP 校时、悬浮窗管理) +│ ├── dist/ # 构建产物 +│ └── logo.png +├── index.html +├── vite.config.js # base: './'(file:// 加载必需) +└── package.json +``` + +## 📚 相关资源 + +- [ZTools 文档](https://ztoolscenter.github.io/ZTools-doc) +- [Vue 3 文档](https://vuejs.org/) +- [Vite 文档](https://vitejs.dev/) + +## 📄 开源协议 + +MIT License diff --git a/plugins/datatimeutc/index.html b/plugins/datatimeutc/index.html new file mode 100755 index 00000000..eaa17316 --- /dev/null +++ b/plugins/datatimeutc/index.html @@ -0,0 +1,11 @@ + + + + + + + +
+ + + diff --git a/plugins/datatimeutc/package-lock.json b/plugins/datatimeutc/package-lock.json new file mode 100755 index 00000000..93c10a98 --- /dev/null +++ b/plugins/datatimeutc/package-lock.json @@ -0,0 +1,1524 @@ +{ + "name": "datatimeutc", + "version": "1.0.4", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "datatimeutc", + "version": "1.0.4", + "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" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.5.tgz", + "integrity": "sha512-jfkGfTwhQpsiSckPF8r9bU3pn3vyd72NlWaO+TgEO6WPSDnUhXzrNYCHBMOYj0ACaUgjm6eERLF+XV9a6RstoA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.5.tgz", + "integrity": "sha512-oGVqyQlxnrz9/ty89oHpU857VUHEl5/Xu4R2lS+aivCTrNnSsbiENzTnNaBsjxH0CNWGPhzHArOLFwo+oKXveA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.5.tgz", + "integrity": "sha512-bW7B8xMEq8n99Q3ieEcPRGuphurdZAaFzQc9Efyyw3FL6DZO6pMy9xhdN+kBoD7Sy05xNXSr4OyPPnpkYriS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.5.tgz", + "integrity": "sha512-YSwBS86QeHOGlrxJ1PSOIZSkzRL/JmKeunhc+lV6M1a6En8QuVCD/T/qIA0J4Gd2Y86RIOBYrLcOUtqGh9+/1w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.5.tgz", + "integrity": "sha512-2fST8lILgl7cKbme/1KDdPCmbXbG+gqoV3bHp19L0ypX/3akYMBVdOunPleRCwonoLnXOZ/0F+Mt/v8POFmfcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.5.tgz", + "integrity": "sha512-cpIxQCP9J+EVad0a6LO1kY3ZGODlk80VlI+2I96B8xMcdHZ4pLVhfQ49JFpYqjPF91FFkQWftf57YlDcTiw9yQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.5.tgz", + "integrity": "sha512-r9fGh3eFs3e/udWh5ZjXQtxiYK/xoFxQaYR/cELxac/Udkl5Th+IsFm0CX3Kl9hmUH/we7EoMpjJgeQNnE0+IA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.5.tgz", + "integrity": "sha512-xdvFdp7OM6KLJviJT2g/YuRSUjnZgGHk4RNgwIbN7X6cPugOucV60DdHXWzsBVCUdrGb6qSXnJQrrAKMmQuj3Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.5.tgz", + "integrity": "sha512-rRqILAndyzHzP7T9NFQrq+4HFWNhqkqkKur7eiBpfLmz01PO0JKx5Vchu3YllE4YXI/Ftgq/szrDWg5GJ0mI8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.5.tgz", + "integrity": "sha512-Gf4X3qVMucayUvux6aXXPgXovocSFUC0rrffDuPI/S2nHhNMhjcZxsrAFYCOF350PRreW1XwzFj3CT/3bKsWCw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.5.tgz", + "integrity": "sha512-+s5qA0TNM0qm8PK/a5gt/1Hpx+NV08uSuCncvhziIlQzT6AEV2fnUQo7eBtFTFO0nA9scauvoR2HusfXmQnO4w==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.5.tgz", + "integrity": "sha512-ybb6QvWwWJCbBWqERpc8K3pYVGIrXlG8MEQ8IIuJY6Y9KdHQxoFoNyfkAOtKn1VHu3KuLidXvwrvGR1mEjeWCw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.5.tgz", + "integrity": "sha512-nZb1DtnOyhCmYvsC8A2CwOkopVg+IS1+fPUa7rMOAXtNw5+lLCLLPqd6XAiNrGtoQKsbvIBOwsHnBH/3wnb4HQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.5.tgz", + "integrity": "sha512-yMbj63Sp89ryrXLWyz+sy+fYD2HpOnMCLGbe4Oa1smclFSUukdtD/BgdiHaAetJNb74URD8U4hM+qG5KVzMEkg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.5.tgz", + "integrity": "sha512-mhoan3OJw2kYV/e1jtIdmvUZgyBFeA6zGWsOswmR0Tg19TQbowZuR+JMLID6spbbBN7Zee2ejrgmy3+FxGrIdA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.5.tgz", + "integrity": "sha512-5ZTLmjWbb1VZdjuyhe83K/8QO0/h11midQCBP+X5OYn32ra7eOBoM0ZqtaY4nkgNsYgmdVhMYPoyVPTjUpHf3w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.5.tgz", + "integrity": "sha512-m53kG+br6PGxOTmgBEM2DHSDs9RVjsyEbUwjJPJGTFm1grWOG8EKJggDCTb60unD4Tjby8fi7/m9XfkEWasVWg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.5.tgz", + "integrity": "sha512-6RHPJR1g/uvdYU8uXBnfq3nlqyZCP82Fr6NHgfGoaIeSh0YEqnX/x6uA9MmJJbnSH7swqX4F+CkGdUF+6doiQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.5.tgz", + "integrity": "sha512-xs+OXQtEXgpXT0DmA5+U3qnRZHdCST/5HRQxS8wSPZTUZN/EMWeHuSIod32LQklTBZBV9DyfncKBQ8n5V3eFdw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.5.tgz", + "integrity": "sha512-e7hD+sl3s+mcLQDZ8pbudBVsdG6r5yN4w3LqG2TJ8sQHDpblWj5lrJs/3m01Cvlxbt4x13zu5thLjgypgtkYzw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.5.tgz", + "integrity": "sha512-GiyJaCf+WpMub/17aPcKk27QMl5W6f+KhdPTjlFOn5akH5Wa/DCM9Stdx5cDfmasyKB08MqpVQ1uJE2RkkpbXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.5.tgz", + "integrity": "sha512-+OQ8U2DdoEfXl8T4Fb18AjmEwbXMerKDKCL8yCPAYhKCEEKoul7rkbeGCBFCbAlaGaa7pmtRTpkAJM2LE/i5FA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.5.tgz", + "integrity": "sha512-KanvAZrPKbDBFwrgiU9yEVpQoox9QPV1WZOXX7HudJQY+eSlu82CtWxDU8WtuRRvtN5EGkLczkd6Y6DTcvm9wA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.5.tgz", + "integrity": "sha512-1aC3UEWTtRl3RK3VpDJ/Tqk1XI4SLTmXIthAq6wRWo8XiSXJNd+VprJM4/1P4+i6HIaFEFlVi9sTTziniD2tOQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.5.tgz", + "integrity": "sha512-/gDJaRs4gl0NPIwqCz+6PkpmhhjRAD2j6P4rSNHBzUkO3naEx2mIU0pRle1vUNRQ7mE/+8OOeXLTv/J56FKiQg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.15.tgz", + "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.15" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.15.tgz", + "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.15.tgz", + "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.15", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.41", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.41.tgz", + "integrity": "sha512-q0Xtv/F9w2YO/7htQhtiL+Ev2WCJbe5N2hc+XfgyKkEKqWpSxknmT8QOuGdEKNdjPq0c3F7rNpFkTo3Kfrm7pg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/shared": "3.5.41", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.41", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.41.tgz", + "integrity": "sha512-oKacVfNglLvGjnS6BXOlGL7EyG2h8X03pqXCjzotRZUaXGjbrTJUnVAQjrCqUnS+lyu31nwQjZY/d817GmCnfw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.41", + "@vue/shared": "3.5.41" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.41", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.41.tgz", + "integrity": "sha512-XJhip7R2wy6vX3knCxdZN4KracFaZUef58s1KYewqluedHIJaPIVfXoYT7MF1F8nCvv6k8bWWxDC8opMkg1VTQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/compiler-core": "3.5.41", + "@vue/compiler-dom": "3.5.41", + "@vue/compiler-ssr": "3.5.41", + "@vue/shared": "3.5.41", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.19", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.41", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.41.tgz", + "integrity": "sha512-U3v5OejKEGqOI0Wy0+Sz7hGuIFZHA4LSXzrNM3IMIeDyJEBBfTpX26n3SDgToRpP2bLc9FfI2j/kSgcJ8Emq5A==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.41", + "@vue/shared": "3.5.41" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/language-core": { + "version": "2.2.12", + "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.12.tgz", + "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.15", + "@vue/compiler-dom": "^3.5.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.5.0", + "alien-signals": "^1.0.3", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.41", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.41.tgz", + "integrity": "sha512-rznsqKM0np0x18EjzF8x88MpEhdNsffbvFbckLL5+oUKz1BxAImEmO7J1ArRYSyo6aQaVoBDp7jEkT91OOxydA==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.41" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.41", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.41.tgz", + "integrity": "sha512-Vcry58hiAKwGen9Z1jUZE0feFsNArPCMOImYI8el48A9Idf6DuQYD0U05zZIF2Iad1hGhPSvcbBbAOhNr55fhg==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.41", + "@vue/shared": "3.5.41" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.41", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.41.tgz", + "integrity": "sha512-3vVBahVBS9+U6cmXBLyb8nE6/yYo4J/CGI9eVFs3KiMc0YHuudwKyShTD65jtJy/L9PUUxNAFu4cj4LiJ0UFbw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.41", + "@vue/runtime-core": "3.5.41", + "@vue/shared": "3.5.41", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.41", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.41.tgz", + "integrity": "sha512-n6hx/pNFfbD6SuyeuMVkvqox8bwf/ET9JlA/kAz/imw8sw++wkqKe2mHX5KutjPpbKE4Z56yTHszoOjGMI9igQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.41", + "@vue/runtime-dom": "3.5.41", + "@vue/shared": "3.5.41" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.41", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.41.tgz", + "integrity": "sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==", + "license": "MIT" + }, + "node_modules/@ztools-center/ztools-api-types": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/@ztools-center/ztools-api-types/-/ztools-api-types-1.0.3.tgz", + "integrity": "sha512-dv1eOAIasAupqKaQL/gESk1i2+RebdM/1gvZhrvH2D/bo3enCUsAGJ8nrHnlCLBSOGB81eC/SU0IH8BNsUlmvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/alien-signals": { + "version": "1.0.13", + "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz", + "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.62.5", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.62.5.tgz", + "integrity": "sha512-/tqMfgP7GPA3PHhCmuiS4vIjrSVhHLgY++i+dhbG462euyAj7FpM4D9uq1X3BgjlqRdpcOrYhcQtfiQLNc8tqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.62.5", + "@rollup/rollup-android-arm64": "4.62.5", + "@rollup/rollup-darwin-arm64": "4.62.5", + "@rollup/rollup-darwin-x64": "4.62.5", + "@rollup/rollup-freebsd-arm64": "4.62.5", + "@rollup/rollup-freebsd-x64": "4.62.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.5", + "@rollup/rollup-linux-arm-musleabihf": "4.62.5", + "@rollup/rollup-linux-arm64-gnu": "4.62.5", + "@rollup/rollup-linux-arm64-musl": "4.62.5", + "@rollup/rollup-linux-loong64-gnu": "4.62.5", + "@rollup/rollup-linux-loong64-musl": "4.62.5", + "@rollup/rollup-linux-ppc64-gnu": "4.62.5", + "@rollup/rollup-linux-ppc64-musl": "4.62.5", + "@rollup/rollup-linux-riscv64-gnu": "4.62.5", + "@rollup/rollup-linux-riscv64-musl": "4.62.5", + "@rollup/rollup-linux-s390x-gnu": "4.62.5", + "@rollup/rollup-linux-x64-gnu": "4.62.5", + "@rollup/rollup-linux-x64-musl": "4.62.5", + "@rollup/rollup-openbsd-x64": "4.62.5", + "@rollup/rollup-openharmony-arm64": "4.62.5", + "@rollup/rollup-win32-arm64-msvc": "4.62.5", + "@rollup/rollup-win32-ia32-msvc": "4.62.5", + "@rollup/rollup-win32-x64-gnu": "4.62.5", + "@rollup/rollup-win32-x64-msvc": "4.62.5", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/vite": { + "version": "6.4.3", + "resolved": "https://registry.npmmirror.com/vite/-/vite-6.4.3.tgz", + "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.41", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.41.tgz", + "integrity": "sha512-2laE0p+aK+/AOPG/XL/WepOs/GlK755LJ1XECi9kDUrz1FKNw8rb2Xzlw9JS1rqEV55nb0ttsKxVlTCcd+R5cg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.41", + "@vue/compiler-sfc": "3.5.41", + "@vue/runtime-dom": "3.5.41", + "@vue/server-renderer": "3.5.41", + "@vue/shared": "3.5.41" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-tsc": { + "version": "2.2.12", + "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.2.12.tgz", + "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.15", + "@vue/language-core": "2.2.12" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + } + } +} diff --git a/plugins/datatimeutc/package.json b/plugins/datatimeutc/package.json new file mode 100755 index 00000000..950af8b9 --- /dev/null +++ b/plugins/datatimeutc/package.json @@ -0,0 +1,20 @@ +{ + "name": "datatimeutc", + "version": "1.0.4", + "description": "实时显示 UTC 时间,支持多时区切换、自定义日期时间格式,悬浮小窗", + "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/datatimeutc/src-ztools/logo.png b/plugins/datatimeutc/src-ztools/logo.png new file mode 100755 index 00000000..821fa0fb Binary files /dev/null and b/plugins/datatimeutc/src-ztools/logo.png differ diff --git a/plugins/datatimeutc/src-ztools/plugin.json b/plugins/datatimeutc/src-ztools/plugin.json new file mode 100755 index 00000000..029935a0 --- /dev/null +++ b/plugins/datatimeutc/src-ztools/plugin.json @@ -0,0 +1,42 @@ +{ + "$schema": "node_modules/@ztools-center/ztools-api-types/resource/ztools.schema.json", + "name": "datatimeutc", + "title": "UTC时间悬浮", + "description": "实时显示 UTC 时间,支持多时区切换、自定义日期时间格式,悬浮小窗", + "author": "paff", + "version": "1.0.4", + "main": "dist/index.html", + "preload": "preload/services.js", + "logo": "logo.png", + "development": { + "main": "http://localhost:5173/" + }, + "features": [ + { + "code": "utc", + "explain": "实时 UTC 时间 / 多时区 / 自定义格式", + "icon": "logo.png", + "cmds": [ + "utc", + "时间", + "时区", + "utc时间" + ] + }, + { + "code": "utc-float", + "explain": "直接开启 UTC 悬浮时间窗", + "icon": "logo.png", + "cmds": [ + "悬浮时间", + "utc悬浮", + "时间悬浮" + ] + } + ], + "platform": [ + "darwin", + "win32", + "linux" + ] +} diff --git a/plugins/datatimeutc/src-ztools/preload/package.json b/plugins/datatimeutc/src-ztools/preload/package.json new file mode 100755 index 00000000..5bbefffb --- /dev/null +++ b/plugins/datatimeutc/src-ztools/preload/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/plugins/datatimeutc/src-ztools/preload/services.js b/plugins/datatimeutc/src-ztools/preload/services.js new file mode 100755 index 00000000..3a4fc04d --- /dev/null +++ b/plugins/datatimeutc/src-ztools/preload/services.js @@ -0,0 +1,205 @@ +const fs = require('node:fs') +const path = require('node:path') +const dgram = require('node:dgram') + +// 通过 window 对象向渲染进程注入能力 +// 悬浮窗引用:主插件窗口持有,便于 focus/复用 +let floatWin = null + +// 监听悬浮窗关闭通知:悬浮窗关闭时通过 sendToParent 通知主插件彻底退出(杀进程) +// 避免主插件窗口残留导致下次打开 ztools 时仍显示 +// 监听悬浮窗大小调节:悬浮窗自身无窗口句柄,由主窗口持有句柄代为 setBounds +try { + const ipcRenderer = require('electron').ipcRenderer + if (ipcRenderer) { + ipcRenderer.on('ztools-float-closed', () => { + try { window.ztools.outPlugin(true) } catch (_e) {} + }) + ipcRenderer.on('ztools-float-resize', (_e, size) => { + try { + if ( + floatWin && typeof floatWin.setBounds === 'function' && + size && Number.isFinite(size.width) && Number.isFinite(size.height) && + size.width > 0 && size.height > 0 + ) { + floatWin.setBounds({ width: Math.round(size.width), height: Math.round(size.height) }) + } + } catch (_e) {} + }) + } +} catch (_e) { + // require electron 失败则忽略 +} + +// ===== 悬浮窗尺寸偏好 ===== +// 透明度/大小由悬浮窗 UI 写入 dbStorage;主窗口创建悬浮窗时按上次缩放取尺寸 +const FLOAT_PREFS_KEY = 'utc-float-prefs' +const FLOAT_BASE_W = 300 +const FLOAT_BASE_H = 118 + +// 读取悬浮窗缩放偏好(脏数据钳制到 0.8–1.4) +function readFloatScale() { + try { + const prefs = window.ztools.dbStorage.getItem(FLOAT_PREFS_KEY) + if (prefs && typeof prefs.scale === 'number' && isFinite(prefs.scale)) { + return Math.min(1.4, Math.max(0.8, prefs.scale)) + } + } catch (_e) { + // ignore + } + return 1 +} + +// ===== NTP 授时 ===== +// 依次尝试多个 NTP 服务器,主用国家授时中心 cn.ntp.org.cn +const NTP_SERVERS = ['cn.ntp.org.cn', 'pool.ntp.org', 'time.nist.gov'] +const NTP_PORT = 123 +// NTP 时间从 1900-01-01 起算,Unix 从 1970-01-01,差 70 年 = 2208988800 秒 +const NTP_EPOCH_OFFSET_MS = 2208988800 * 1000 + +// 发送 NTP 请求并解析响应,返回 { offset, server, rtt }(毫秒) +// offset = 服务器真实时间 - 本地时间,用于修正本地时钟偏差 +function queryNtp(server, timeout) { + timeout = timeout || 3000 + return new Promise((resolve, reject) => { + let socket + try { + socket = dgram.createSocket('udp4') + } catch (e) { + reject(e) + return + } + // NTP 包:48 字节,首字节 0x1B = LI(0)+Version(3)+Mode(3 client),其余补零 + const packet = Buffer.alloc(48) + packet[0] = 0x1B + const t0 = Date.now() + const cleanup = () => { try { socket.close() } catch (_e) {} } + const timer = setTimeout(() => { cleanup(); reject(new Error('NTP timeout')) }, timeout) + socket.on('error', (err) => { + clearTimeout(timer) + cleanup() + reject(err) + }) + socket.on('message', (msg) => { + clearTimeout(timer) + const t1 = Date.now() + // 传输时间戳:byte 40-43 秒, 44-47 小数部分(NTP 1900 起算) + const seconds = msg.readUInt32BE(40) + const fraction = msg.readUInt32BE(44) + if (seconds === 0) { + cleanup() + reject(new Error('NTP invalid response')) + return + } + const ntpMs = seconds * 1000 + Math.floor(fraction / 4294967296 * 1000) + const serverTime = ntpMs - NTP_EPOCH_OFFSET_MS + const rtt = t1 - t0 + // 估算真实时间 = 服务器发送时间 + 单程延迟(rtt/2) + const realTime = serverTime + Math.floor(rtt / 2) + const offset = realTime - t1 + cleanup() + resolve({ offset: offset, server: server, rtt: rtt }) + }) + socket.send(packet, 0, 48, NTP_PORT, server, (err) => { + if (err) { + clearTimeout(timer) + cleanup() + reject(err) + } + }) + }) +} + +window.services = { + // 开启置顶悬浮窗(独立 Electron 窗口) + // 返回 winId;失败返回 null(具体原因已通过 notification 提示) + openFloatWindow() { + const ztools = window.ztools + + // 已存在则聚焦复用 + if (floatWin) { + try { + if (typeof floatWin.focus === 'function') floatWin.focus() + else if (typeof floatWin.show === 'function') floatWin.show() + const id = floatWin.id + return typeof id === 'number' ? id : null + } catch (_e) { + floatWin = null + } + } + // createBrowserWindow 要求 url 必须是 file:// 本地地址(不接受 http://) + // 因此 dev 与生产模式都指向 dist 构建产物 + const htmlPath = path.join(__dirname, '..', 'dist', 'index.html') + if (!fs.existsSync(htmlPath)) { + try { ztools.showNotification && ztools.showNotification('悬浮窗需要构建产物,请先运行 npm run build') } catch (_e) {} + return null + } + const url = 'file://' + htmlPath + '#float' + // 最小 options,不传 webPreferences(main 模式下指定 preload 可能被安全策略拒绝) + // 悬浮窗依赖全局 window.ztools(由客户端注入)+ window.close() 关闭,不依赖 services + // 透明窗口:配合卡片背景 alpha 实现透明度调节;尺寸按上次缩放偏好创建 + const scale = readFloatScale() + const options = { + width: Math.round(FLOAT_BASE_W * scale), + height: Math.round(FLOAT_BASE_H * scale), + frame: false, + resizable: false, + skipTaskbar: true, + transparent: true + } + try { + floatWin = ztools.createBrowserWindow(url, options, function () { + floatWin = null + }) + } catch (e) { + floatWin = null + const msg = e && e.message ? e.message : String(e) + try { ztools.showNotification && ztools.showNotification('悬浮窗创建失败: ' + msg) } catch (_e2) {} + return null + } + if (!floatWin) { + try { ztools.showNotification && ztools.showNotification('悬浮窗创建失败: createBrowserWindow 返回空') } catch (_e2) {} + return null + } + // 创建成功后再设置置顶 + try { + if (typeof floatWin.setAlwaysOnTop === 'function') floatWin.setAlwaysOnTop(true) + } catch (_e) { + // 置顶失败不阻塞 + } + const id = floatWin.id + return typeof id === 'number' ? id : null + }, + + // 关闭主插件持有的悬浮窗 + closeFloatWindow() { + if (!floatWin) return + try { + if (typeof floatWin.close === 'function') floatWin.close() + } catch (_e) { + // 忽略 + } + floatWin = null + }, + + // 悬浮窗自身关闭(在悬浮窗 renderer 进程中调用) + closeSelf() { + try { window.close() } catch (_e) { + try { window.ztools && window.ztools.outPlugin && window.ztools.outPlugin(true) } catch (_e2) {} + } + }, + + // NTP 校时:依次尝试多个服务器,返回 { offset, server, rtt } 或 null + // offset = 服务器真实时间 - 本地时间(毫秒),renderer 用 Date.now()+offset 显示真实时间 + async syncNtpTime() { + for (const server of NTP_SERVERS) { + try { + const result = await queryNtp(server) + return result + } catch (_e) { + // 试下一个服务器 + } + } + return null + } +} diff --git a/plugins/datatimeutc/src/App.vue b/plugins/datatimeutc/src/App.vue new file mode 100755 index 00000000..41ecb1ec --- /dev/null +++ b/plugins/datatimeutc/src/App.vue @@ -0,0 +1,29 @@ + + + diff --git a/plugins/datatimeutc/src/Utc/AutoFloat.vue b/plugins/datatimeutc/src/Utc/AutoFloat.vue new file mode 100755 index 00000000..ff1282ce --- /dev/null +++ b/plugins/datatimeutc/src/Utc/AutoFloat.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/plugins/datatimeutc/src/Utc/Float.vue b/plugins/datatimeutc/src/Utc/Float.vue new file mode 100755 index 00000000..32b927ec --- /dev/null +++ b/plugins/datatimeutc/src/Utc/Float.vue @@ -0,0 +1,393 @@ + + + + + diff --git a/plugins/datatimeutc/src/Utc/format.ts b/plugins/datatimeutc/src/Utc/format.ts new file mode 100755 index 00000000..b6a5904f --- /dev/null +++ b/plugins/datatimeutc/src/Utc/format.ts @@ -0,0 +1,324 @@ +// 时间格式化与时区列表工具 + +export interface FormatOptions { + /** 显示年月日 */ + showDate: boolean + /** 显示星期 */ + showWeekday: boolean + /** 显示时分秒 */ + showTime: boolean + /** 显示毫秒 */ + showMs: boolean + /** 12 小时制 */ + hour12: boolean +} + +export const DEFAULT_FORMAT: FormatOptions = { + showDate: true, + showWeekday: false, + showTime: true, + showMs: true, + hour12: false +} + +// Intl.supportedValuesOf 不可用时的兜底时区列表 +const FALLBACK_TIMEZONES: string[] = [ + 'UTC', + 'Africa/Cairo', + 'America/Argentina/Buenos_Aires', + 'America/Chicago', + 'America/Los_Angeles', + 'America/New_York', + 'America/Sao_Paulo', + 'Asia/Bangkok', + 'Asia/Dubai', + 'Asia/Hong_Kong', + 'Asia/Shanghai', + 'Asia/Singapore', + 'Asia/Tokyo', + 'Australia/Sydney', + 'Europe/Berlin', + 'Europe/London', + 'Europe/Moscow', + 'Europe/Paris', + 'Pacific/Auckland' +] + +/** 获取完整时区列表(Intl.supportedValuesOf 不可用时回退到内置列表) */ +export function getTimezones(): string[] { + try { + const supported = (Intl as any).supportedValuesOf + ? (Intl as any).supportedValuesOf('timeZone') + : null + if (Array.isArray(supported) && supported.length > 0) { + // 确保 UTC 排首位 + const list = supported.filter((tz: string) => tz !== 'UTC') + return ['UTC', ...list] + } + } catch (_e) { + // ignore + } + return FALLBACK_TIMEZONES.slice() +} + +// 常用时区的中文名称(仅用于显示;未收录的时区回退显示 IANA 名称) +const TZ_DISPLAY_NAMES: Record = { + 'UTC': '协调世界时', + 'Africa/Cairo': '埃及标准时间', + 'Africa/Johannesburg': '南非标准时间', + 'Africa/Lagos': '西非时间', + 'Africa/Nairobi': '东非时间', + 'America/Anchorage': '阿拉斯加时间', + 'America/Argentina/Buenos_Aires': '阿根廷时间', + 'America/Chicago': '美国中部时间', + 'America/Denver': '美国山地时间', + 'America/Los_Angeles': '美国太平洋时间', + 'America/Mexico_City': '墨西哥时间', + 'America/New_York': '美国东部时间', + 'America/Phoenix': '亚利桑那时间', + 'America/Sao_Paulo': '巴西时间', + 'America/Toronto': '加拿大多伦多时间', + 'America/Vancouver': '加拿大温哥华时间', + 'Asia/Bangkok': '泰国时间', + 'Asia/Dhaka': '孟加拉时间', + 'Asia/Dubai': '海湾标准时间', + 'Asia/Hong_Kong': '香港时间', + 'Asia/Jakarta': '印尼西部时间', + 'Asia/Karachi': '巴基斯坦时间', + 'Asia/Kolkata': '印度标准时间', + 'Asia/Kuala_Lumpur': '马来西亚时间', + 'Asia/Manila': '菲律宾时间', + 'Asia/Riyadh': '阿拉伯标准时间', + 'Asia/Seoul': '韩国标准时间', + 'Asia/Shanghai': '中国标准时间', + 'Asia/Singapore': '新加坡时间', + 'Asia/Taipei': '台北时间', + 'Asia/Tehran': '伊朗时间', + 'Asia/Tokyo': '日本标准时间', + 'Asia/Urumqi': '乌鲁木齐时间', + 'Asia/Vladivostok': '海参崴时间', + 'Asia/Yekaterinburg': '叶卡捷琳堡时间', + 'Australia/Adelaide': '澳大利亚中部时间', + 'Australia/Brisbane': '澳大利亚东部时间', + 'Australia/Melbourne': '澳大利亚东部时间', + 'Australia/Perth': '澳大利亚西部时间', + 'Australia/Sydney': '澳大利亚东部时间', + 'Europe/Amsterdam': '阿姆斯特丹时间', + 'Europe/Athens': '东欧时间', + 'Europe/Berlin': '中欧时间', + 'Europe/Brussels': '布鲁塞尔时间', + 'Europe/Helsinki': '东欧时间', + 'Europe/Istanbul': '土耳其时间', + 'Europe/Kiev': '东欧时间', + 'Europe/Lisbon': '西欧时间', + 'Europe/London': '格林尼治时间', + 'Europe/Madrid': '中欧时间', + 'Europe/Moscow': '莫斯科时间', + 'Europe/Oslo': '中欧时间', + 'Europe/Paris': '中欧时间', + 'Europe/Prague': '中欧时间', + 'Europe/Rome': '中欧时间', + 'Europe/Stockholm': '中欧时间', + 'Europe/Vienna': '中欧时间', + 'Europe/Warsaw': '中欧时间', + 'Europe/Zurich': '中欧时间', + 'Pacific/Auckland': '新西兰时间', + 'Pacific/Fiji': '斐济时间', + 'Pacific/Honolulu': '夏威夷时间', + // Intl.supportedValuesOf 在部分 ICU 版本返回的旧别名,补充对应中文显示名 + 'Asia/Calcutta': '印度标准时间', + 'Asia/Kathmandu': '尼泊尔时间', + 'Asia/Katmandu': '尼泊尔时间', + 'Asia/Yangon': '缅甸时间', + 'Asia/Rangoon': '缅甸时间', + 'Asia/Kabul': '阿富汗时间', + 'Asia/Magadan': '马加丹时间', + 'America/Nuuk': '格陵兰时间', + 'America/Godthab': '格陵兰时间', + 'America/St_Johns': '纽芬兰时间', + 'America/Miquelon': '圣皮埃尔和密克隆时间', + 'America/Adak': '阿留申群岛时间', + 'Pacific/Midway': '中途岛时间', + 'Pacific/Marquesas': '马克萨斯群岛时间', + 'Pacific/Chatham': '查塔姆群岛时间', + 'Pacific/Apia': '萨摩亚时间', + 'Pacific/Kiritimati': '莱恩群岛时间', + 'Australia/Eucla': '尤克拉时间', + 'Australia/Lord_Howe': '豪勋爵群岛时间' +} + +/** 计算时区在指定时刻相对 UTC 的偏移分钟数(含夏令时),失败返回 null */ +export function getTimezoneOffsetMinutes(tz: string, date = new Date()): number | null { + try { + const dtf = new Intl.DateTimeFormat('en-US', { + timeZone: tz, + hour12: false, + year: 'numeric', month: '2-digit', day: '2-digit', + hour: '2-digit', minute: '2-digit', second: '2-digit' + }) + const parts = dtf.formatToParts(date) + const get = (type: string) => Number(parts.find(p => p.type === type)?.value) + const asUTC = Date.UTC( + get('year'), get('month') - 1, get('day'), + get('hour') % 24, get('minute'), get('second') + ) + return Math.round((asUTC - Math.floor(date.getTime() / 1000) * 1000) / 60000) + } catch (_e) { + return null + } +} + +/** 偏移分钟 → "UTC+8" / "UTC-5:30" / "UTC+5:30" 样式 */ +export function formatOffsetLabel(offsetMinutes: number): string { + const sign = offsetMinutes >= 0 ? '+' : '-' + const abs = Math.abs(offsetMinutes) + const h = Math.floor(abs / 60) + const m = abs % 60 + return `UTC${sign}${h}${m ? ':' + String(m).padStart(2, '0') : ''}` +} + +// 同偏移去重时的代表时区(排名靠前优先;如 UTC+8 保留 Asia/Shanghai 而非台北/新加坡等) +const REPRESENTATIVE_TIMEZONES = [ + 'Asia/Shanghai', + 'Asia/Tokyo', + 'Asia/Kolkata', + 'Asia/Dubai', + 'Asia/Karachi', + 'Asia/Dhaka', + 'Asia/Bangkok', + 'Asia/Tehran', + 'Asia/Kathmandu', + 'Europe/London', + 'Europe/Berlin', + 'Europe/Moscow', + 'Europe/Istanbul', + 'Africa/Cairo', + 'Africa/Lagos', + 'Africa/Johannesburg', + 'Africa/Nairobi', + 'America/New_York', + 'America/Chicago', + 'America/Denver', + 'America/Los_Angeles', + 'America/Anchorage', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'Australia/Sydney', + 'Australia/Melbourne', + 'Australia/Adelaide', + 'Pacific/Honolulu', + 'Pacific/Auckland' +] + +/** 时区在代表列表中的排名(不在列表返回 Infinity,越小越优先) */ +function representativeRank(tz: string): number { + const idx = REPRESENTATIVE_TIMEZONES.indexOf(tz) + return idx === -1 ? Number.POSITIVE_INFINITY : idx +} + +/** 同偏移去重时判断 candidate 是否优先于 current:代表排名靠前 > 有中文显示名 */ +function isPreferred(candidate: string, current: string): boolean { + const cr = representativeRank(candidate) + const cur = representativeRank(current) + if (cr !== cur) return cr < cur + // 均不在代表列表时,有中文显示名的优先;都无则保持先来者 + return !TZ_DISPLAY_NAMES[current] && !!TZ_DISPLAY_NAMES[candidate] +} + +export interface TimezoneOption { + /** IANA 时区名(存储值) */ + value: string + /** 显示名:如 "UTC+8 中国标准时间" */ + label: string + /** 排序权重(偏移分钟) */ + offset: number +} + +/** + * 生成 "UTC±X 中文名" 的时区选项列表 + * 每个 UTC 偏移仅保留一个代表时区(如 UTC+8 只保留中国标准时间),按偏移排序 + */ +export function getTimezoneOptions(date = new Date()): TimezoneOption[] { + const tzs = getTimezones() + // 按偏移去重:offset -> 该偏移的代表选项 + const byOffset = new Map() + for (const tz of tzs) { + if (tz === 'UTC') continue + const off = getTimezoneOffsetMinutes(tz, date) + // 偏移 0 固定由下方 UTC 选项代表 + if (off === null || off === 0) continue + const existing = byOffset.get(off) + if (existing && !isPreferred(tz, existing.value)) continue + byOffset.set(off, { + value: tz, + label: `${formatOffsetLabel(off)} ${TZ_DISPLAY_NAMES[tz] || tz}`, + offset: off + }) + } + // UTC 固定第一,其余按偏移升序 + return [ + { value: 'UTC', label: 'UTC+0 协调世界时', offset: 0 }, + ...[...byOffset.values()].sort((a, b) => a.offset - b.offset) + ] +} + +/** 取某时区的显示名(当前偏移 + 中文名),用于界面展示当前选择 */ +export function getTimezoneLabel(tz: string, date = new Date()): string { + if (tz === 'UTC') return 'UTC+0 协调世界时' + const off = getTimezoneOffsetMinutes(tz, date) + if (off === null) return tz + return `${formatOffsetLabel(off)} ${TZ_DISPLAY_NAMES[tz] || tz}` +} + +/** + * 按勾选组件格式化时间字符串 + * 使用 Intl.DateTimeFormat 支持任意 IANA 时区 + */ +export function formatTime(date: Date, opts: FormatOptions, timeZone: string): string { + const parts: string[] = [] + + // 日期部分 + if (opts.showDate || opts.showWeekday) { + const dateOpts: Intl.DateTimeFormatOptions = { timeZone } + if (opts.showWeekday) dateOpts.weekday = 'long' + if (opts.showDate) { + dateOpts.year = 'numeric' + dateOpts.month = '2-digit' + dateOpts.day = '2-digit' + } + try { + const formatted = new Intl.DateTimeFormat('zh-CN', dateOpts).format(date) + if (formatted) parts.push(formatted) + } catch (_e) { + // 时区非法时退回本地时区 + const fallback = new Intl.DateTimeFormat('zh-CN', { ...dateOpts, timeZone: undefined }).format(date) + if (fallback) parts.push(fallback) + } + } + + // 时间部分 + if (opts.showTime) { + const timeOpts: Intl.DateTimeFormatOptions = { + timeZone, + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + hour12: opts.hour12 + } + try { + const formatted = new Intl.DateTimeFormat('zh-CN', timeOpts).format(date) + if (formatted) parts.push(formatted) + } catch (_e) { + const fallback = new Intl.DateTimeFormat('zh-CN', { ...timeOpts, timeZone: undefined }).format(date) + if (fallback) parts.push(fallback) + } + } + + // 毫秒部分(Intl fractionalSecondDigits 仅支持 3 位,这里直接补零拼接) + if (opts.showMs) { + const ms = String(date.getMilliseconds()).padStart(3, '0') + parts.push('.' + ms) + } + + return parts.filter(Boolean).join(' ').trim() +} diff --git a/plugins/datatimeutc/src/Utc/index.vue b/plugins/datatimeutc/src/Utc/index.vue new file mode 100755 index 00000000..8fb5af94 --- /dev/null +++ b/plugins/datatimeutc/src/Utc/index.vue @@ -0,0 +1,513 @@ + + + + + diff --git a/plugins/datatimeutc/src/Utc/time.ts b/plugins/datatimeutc/src/Utc/time.ts new file mode 100755 index 00000000..68d24d72 --- /dev/null +++ b/plugins/datatimeutc/src/Utc/time.ts @@ -0,0 +1,113 @@ +// 时间校准模块:NTP 校准 + 真实时间获取 +// 校准前/失败时 offset=0,getNow() 退化为本地系统时间(不阻塞显示) + +const OFFSET_KEY = 'utc-ntp-offset' + +let offset = 0 +let synced = false + +// 从 dbStorage 加载上次校准的 offset(悬浮窗等无 services 的进程用此路径) +function loadOffset() { + try { + const stored = window.ztools.dbStorage.getItem(OFFSET_KEY) + if (typeof stored === 'number' && isFinite(stored)) offset = stored + } catch (_e) { + // ignore + } +} + +/** 获取真实时间戳(毫秒)= 本地 Date.now() + NTP offset */ +export function getNow(): number { + return Date.now() + offset +} + +/** 获取当前 NTP 偏移量(毫秒),offset = 服务器时间 - 本地时间 */ +export function getOffset(): number { + return offset +} + +/** 是否已成功 NTP 校准 */ +export function isSynced(): boolean { + return synced +} + +export interface SyncResult { + ok: boolean + server?: string + offset?: number + rtt?: number +} + +/** + * 启动时调用:从 NTP 服务器校准时间 + * - 主插件窗口(有 services.syncNtpTime):发 NTP 包校准,写 dbStorage + * - 悬浮窗(无 services):跳过校准,读 dbStorage 的 offset + * 失败则保持 offset=0(用本地系统时间),不影响显示 + */ +export async function syncTime(): Promise { + if (!window.services || typeof window.services.syncNtpTime !== 'function') { + loadOffset() + return { ok: false } + } + try { + const result = await window.services.syncNtpTime() + if (result && typeof result.offset === 'number') { + offset = result.offset + synced = true + try { window.ztools.dbStorage.setItem(OFFSET_KEY, offset) } catch (_e) {} + return { ok: true, server: result.server, offset: result.offset, rtt: result.rtt } + } + } catch (_e) { + // ignore + } + loadOffset() + return { ok: false } +} + +// ===== 周期校准调度 ===== +// 打开插件期间持续定时校准;界面可通过 onSyncTick 注册回调实时刷新 UI +type SyncTickCallback = (result: SyncResult) => void +const tickCallbacks = new Set() +let syncTimer: number | undefined +let syncing = false + +/** 注册周期校准回调(每次校准完成触发,无论成败)。返回解绑函数 */ +export function onSyncTick(cb: SyncTickCallback): () => void { + tickCallbacks.add(cb) + return () => tickCallbacks.delete(cb) +} + +async function runSyncTick() { + if (syncing) return + syncing = true + try { + const result = await syncTime() + tickCallbacks.forEach(cb => { + try { cb(result) } catch (_e) { /* 单个回调异常不影响其他 */ } + }) + } finally { + syncing = false + } +} + +/** + * 启动周期校准(主插件窗口调用;悬浮窗无 services 会自动退化为仅读存储) + * @param intervalMs 校准间隔,默认 5 分钟 + */ +export function startPeriodicSync(intervalMs = 5 * 60 * 1000): void { + stopPeriodicSync() + // 立即校准一次 + runSyncTick() + syncTimer = window.setInterval(runSyncTick, intervalMs) +} + +/** 停止周期校准 */ +export function stopPeriodicSync(): void { + if (syncTimer !== undefined) { + window.clearInterval(syncTimer) + syncTimer = undefined + } +} + +// 模块加载时尝试读 dbStorage 的 offset(快速恢复上次校准值) +loadOffset() diff --git a/plugins/datatimeutc/src/env.d.ts b/plugins/datatimeutc/src/env.d.ts new file mode 100755 index 00000000..05e71ffc --- /dev/null +++ b/plugins/datatimeutc/src/env.d.ts @@ -0,0 +1,31 @@ +/// +/// + +declare module '*.vue' { + import type { DefineComponent } from 'vue' + const component: DefineComponent, Record, unknown> + export default component +} + +// Preload services 类型声明(对应 src-ztools/preload/services.js) +interface NtpSyncResult { + /** 服务器真实时间 - 本地时间(毫秒),用于修正本地时钟偏差 */ + offset: number + server: string + rtt: number +} + +interface Services { + openFloatWindow: () => number | null + closeFloatWindow: () => void + closeSelf: () => void + syncNtpTime: () => Promise +} + +declare global { + interface Window { + services: Services + } +} + +export {} diff --git a/plugins/datatimeutc/src/main.css b/plugins/datatimeutc/src/main.css new file mode 100755 index 00000000..f58ab978 --- /dev/null +++ b/plugins/datatimeutc/src/main.css @@ -0,0 +1,86 @@ +:root { + --blue: rgb(88, 164, 246); + --light: #fff; +} + +html, +body { + margin: 0; + padding: 0; + overflow: hidden; +} + +/* 主插件视图需要撑满视口高度,配合组件内弹性布局 */ +#app { + height: 100vh; + display: flex; + flex-direction: column; +} + +#app > * { + flex: 1; + min-height: 0; +} + +/* 悬浮窗模式:透明背景,由内部卡片承载视觉 */ +body.float-mode { + background: transparent; +} + +/* 悬浮窗模式下的暗色卡片由组件 scoped 样式负责 */ +body.float-mode::-webkit-scrollbar { + display: none; +} + +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/datatimeutc/src/main.ts b/plugins/datatimeutc/src/main.ts new file mode 100755 index 00000000..16331c38 --- /dev/null +++ b/plugins/datatimeutc/src/main.ts @@ -0,0 +1,14 @@ +import { createApp } from 'vue' +import './main.css' +import App from './App.vue' + +const app = createApp(App) +app.mount('#app') + +// 暗色模式适配:跟随系统(ztools 通常跟随系统,且无暗色变化事件 API) +const mql = window.matchMedia('(prefers-color-scheme: dark)') +const applyTheme = (dark: boolean) => { + document.documentElement.classList.toggle('dark', dark) +} +applyTheme(mql.matches) +mql.addEventListener('change', (e) => applyTheme(e.matches)) diff --git a/plugins/datatimeutc/tsconfig.json b/plugins/datatimeutc/tsconfig.json new file mode 100755 index 00000000..39b73bc6 --- /dev/null +++ b/plugins/datatimeutc/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/datatimeutc/vite.config.js b/plugins/datatimeutc/vite.config.js new file mode 100755 index 00000000..5ca697ff --- /dev/null +++ b/plugins/datatimeutc/vite.config.js @@ -0,0 +1,13 @@ +import { fileURLToPath } from 'node:url' +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue()], + base: './', + build: { + outDir: fileURLToPath(new URL('./src-ztools/dist', import.meta.url)), + emptyOutDir: true + } +})