Files
chakcy f62704ca0e feat: 插件化桌面客户端 svfs-client(含凭据/会话/网络/日志的脚手架补齐)
一个插件 = 一个完整的 .svfs 包:客户端把插件前端经 svfs://<插件id>/ 直接加载
进 WebView(不落盘、不起端口、不解包),每个插件一个独立 origin(浏览器按
origin 隔离 localStorage)与独立键值存储;快照即版本——升级 = 派生快照的增量
打包,回滚 = 把注册表指针切回旧快照,包文件一个字节不用动。svfs_client 复用
svfs_studio 的主题与基础部件,故两个包一并入库。

按评估结论补齐的 P0 三块:

* 会话:桥在"宿主注入的 token 被 401 拒绝"时通知壳层,提示一次并给出一键
  「重新登录…」;服务器状态灯把「在线但登录失效」(黄)与「离线」(红)分开,
  不再把凭据失效误报成网络不可达;
* 凭据:新增 credentials.py——token 不再明文进 settings.json。Windows 走 DPAPI
  (密文只有当前用户在本机解得开),其它平台走系统凭据库(可选依赖 keyring),
  都没有才明文兜底并在「设置 → 登录凭据」如实提示;令牌与签发它的 base_url
  绑定(换服务器不会把旧令牌发出去);老字段 auth_token 启动时自动迁移;
* 强登录链路保持:启动动画 → 静默校验 → 登录窗 → 主窗口,不可达时离线宽限。

P1/P2:net 超时与重试(只对幂等方法,避免重发 POST 变两单)可配、代理与
自签 CA 可配(loopback 永远直连);诊断日志滚动落盘(1MB×3,可关)——崩溃后
还能回看现场;客户端自更新检查(静态 <base_url>/client/manifest.json,缺失
即静默);插件清单可选 net_hosts 白名单;notify 改走系统托盘(无托盘降级状态栏);
设置界面新增网络 / 登录凭据 / 诊断日志三块。

examples/:示例服务端(FastAPI,含登录、上传即 publish、客户端版本接口)、
Vue 3 插件模板(带浏览器版宿主模拟器)、svfs-plugins-root/ 为模板配套的演示
插件实体。测试:tests/test_client_*.py(纯层 + Qt 层 + 一次真实 WebEngine 冒烟)、
tests/test_studio_*.py、tests/test_plugin_server.py。
2026-09-16 17:15:48 +08:00

54 lines
2.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SVFS 插件开发模板(Vue 3 + Vite)
用 Vue 3 开发 SVFS 插件的起点模板:构建产物打进 `.svfs` 包、在客户端的
WebView 里以 `svfs://<插件id>/` 独立 origin 运行。附赠浏览器 mock,让
`npm run dev` 不进客户端也能迭代 UI。
## 目录结构
```text
public/plugin.json 插件清单(vite 会原样拷进 dist 根目录——清单必须在包根)
src/main.js 入口;dev 模式自动装 window.svfs 模拟器
src/svfs.js window.svfs 的薄封装(Promise + JSON 便捷层),组件统一从这里用
src/mock-svfs.js 浏览器版宿主模拟器(storage→localStorage,net→fetch,对话框→confirm/alert)
src/App.vue 分页签的组织方式(主机信息 / 存储 / 网络 / 界面·对话框)
src/components/*.vue 每类能力一个面板组件,照着抄就行
```
## 开发流程
```bash
npm install
# 1) 浏览器里迭代 UI(mock 桥;net 相对路径打到 vite dev server)
npm run dev
# 2) 构建 + 打包(plugin.json 在 public/ 下,构建后位于 dist 根,满足"清单在包根")
npm run build
svfs pack ./dist plugin.svfs --compress
# 3a) 安装到客户端:客户端「设置 → 插件管理 → 安装本地插件…」选 plugin.svfs
# 3b) 或发布到示例服务端,客户端「从服务器安装」填 com.example.vue-demo:
svfs publish plugin.svfs svfs-plugins-root/com.example.vue-demo
```
## 桥能力速查(src/svfs.js)
| 能力 | 需要权限 | 说明 |
|---|---|---|
| `getHostInfo()` | 无 | `host.info`;含登录用户 `authUser`(v3+) |
| `createStorage(prefix)` | storage | 按插件隔离的键值存储 |
| `netRequest/netJson` | net | 宿主代发 HTTP,绕开 CORS,同源请求自动带登录 token |
| `notify / setTitle` | notify / title | 状态栏通知 / 改窗口标题 |
| `confirmDialog / messageBox` | dialog | 宿主**原生对话框**(v4+),Promise 返回用户选择 |
## 注意事项
* **`vite.config` 里 `base: "./"` 不能丢**:包内是独立 origin,绝对路径资源会 404。
* manifest 的 `api_version` 是你要求的最低宿主版本:用了 `dialog` 就写 4,
没用新能力可以写 2(兼容面更大)。改 id 记得同步 `public/plugin.json`
与上传路径——两处必须一致。
* 静态资源放 `src/assets/` 里 `import` 引用(会被 vite 重写为相对路径);
放 `public/` 的文件按根相对路径引用。
* 真实桥的行为以客户端「设置 → 桥调试台」插件为准;mock 只覆盖日常迭代。