123pan Sync在 VS Code 里通过 WebDAV 把工作区文件同步到 123pan。 扩展会在活动栏(Activity Bar)里新增一个 123pan 视图,可以浏览云端目录、上传下载文件、回滚历史版本,并自动为每次上传保留一份带时间戳的备份。 功能
环境要求
配置1. 在工作区创建
|
| 配置项 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
username |
string | 是 | — | 123pan WebDAV 用户名。 |
password |
string | 是 | — | 123pan WebDAV 密码。 |
remoteFolder |
string | 是 | — | 123pan 账号内作为同步根目录的路径,结尾斜杠会自动补齐。 |
baseUrl |
string | 否 | https://webdav.123pan.cn/webdav/ |
WebDAV 地址,扩展会自动补上结尾斜杠。 |
recordHistory |
boolean | 否 | false |
每次上传时在云端 .history/ 目录额外保存一份带时间戳的副本。 |
uploadOnSave |
boolean | 否 | false |
保存文件或 Notebook 时自动上传。 |
fileURLPrefix |
string | 否 | — | 设置后,每次上传都会把该文件的链接复制到剪贴板。留空或省略则不复制。 |
autoCopyType |
string | 否 | direct |
复制链接的格式:direct(纯 URL)或 markdown([文件名](https://example.com/a.ts))。 |
additionalConfigs |
array | 否 | — | 额外网盘列表。右键「Upload To 123」时,主网盘上传成功后会继续同步到这些网盘,见多网盘上传。 |
barkNotification |
object | 否 | — | 手动上传成功后向 Bark 发送推送,见Bark 通知。 |
完整示例
{
"username": "你的-webdav-用户名",
"password": "你的-webdav-密码",
"remoteFolder": "example/example/",
"baseUrl": "https://webdav.123pan.cn/webdav/",
"recordHistory": true,
"uploadOnSave": true,
"fileURLPrefix": "https://example.com/my-share-links/",
"autoCopyType": "markdown",
"additionalConfigs": [
{
"name": "备份盘",
"username": "另一个账号的-webdav-用户名",
"password": "另一个账号的-webdav-密码",
"remoteFolder": "code-backup/"
}
],
"barkNotification": {
"enable": true,
"token": "你的-bark-token",
"urlParam": "marginnote4app://addon/installAddon?url={{fileURL}}",
"url": "https://api.day.app/{{token}}/InstallAddon?url={{urlParam}}"
}
}
多网盘上传
在 .vscode/123pan.json 里配置 additionalConfigs 数组,可以把同一段代码同步到多个 123pan
账号(或同一账号的不同目录):
{
"username": "主网盘用户名",
"password": "主网盘密码",
"remoteFolder": "dl",
"additionalConfigs": [
{ "name": "备份盘", "username": "…", "password": "…", "remoteFolder": "backup/" },
{ "name": "异地盘", "username": "…", "password": "…", "remoteFolder": "offsite/" }
]
}
行为规则:
只在右键菜单点「Upload To 123」时生效(编辑器右键、资源管理器右键、命令面板均是)。 保存自动上传(
uploadOnSave)只传主网盘,不会触发额外网盘。主网盘成功后才会继续额外网盘;主网盘失败即停止,不会传额外网盘。
上传顺序与数组顺序一致,逐个进行;单个额外网盘失败不会中断其余网盘。
整个过程共用一个通知:每个网盘的状态在这条通知里就地更新(
主网盘 ✅,备份盘…), 结束时也只弹一条通知。VS Code 的通知不支持换行,各项状态用全角竖线|连成一行:✅ 上传成功:「a.txt」,链接已复制|备份盘 ✅|异地盘 ✅有失败时同样点名原因:
⚠️ 上传完成,部分步骤失败:「a.txt」,链接已复制|备份盘 ✅|坏盘 ❌ Invalid response: 401(HTTP 401)每个额外网盘支持的字段:
name(仅用于通知显示,可选)、username、password、remoteFolder(必填)、baseUrl、recordHistory。剪贴板链接始终来自主网盘——额外网盘即使配置了
fileURLPrefix也不会覆盖剪贴板。
Bark 通知
配置 barkNotification 后,手动上传成功会向 Bark
(iOS 推送)发一个 GET 请求。请求地址完全由你的模板决定,用大胡子变量注入上传信息:
{
"barkNotification": {
"enable": true,
"token": "你的-bark-token",
"urlParam": "marginnote4app://addon/installAddon?url={{fileURL}}",
"url": "https://api.day.app/{{token}}/InstallAddon?url={{urlParam}}"
}
}
可用变量
| 变量 | 展开为 |
|---|---|
{{fileURL}} |
本次上传文件的完整地址:fileURLPrefix + 云端相对路径。 |
{{token}} |
barkNotification.token 的值。 |
{{urlParam}} |
urlParam 模板展开后的结果(可选配置项,本身可用 {{fileURL}})。 |
展开顺序:先在 urlParam 里展开 {{fileURL}},再在 url 里展开 {{token}}、
{{urlParam}}、{{fileURL}};嵌套各展开一层,展开结果不再递归替换。未知的变量
原样保留,方便发现拼写错误。{{urlParam}} 是可选的——不需要深链接时可以直接写
"url": "https://api.day.app/{{token}}/已上传?url={{fileURL}}"。
行为规则
只在手动上传后发送(右键菜单、命令面板);保存自动上传(
uploadOnSave)不会触发 推送,避免每次保存都弹通知。主网盘上传成功后发一次,与
additionalConfigs的成败无关;主网盘失败不发。上传的是文件夹时整个操作只发一条,
{{fileURL}}是文件夹的地址。模板引用了
{{fileURL}}但没配fileURLPrefix会直接报错,不会把空链接发出去。最终 URL 只做最小编码:中文、空格等会让请求无法发出的字符会被编码,
: / ? & =等 URL 结构和你预先编码好的%XX序列原样保留。发送结果会显示在上传通知里,成功与失败都不会静默:
✅ 上传成功:「a.md」,链接已复制到剪贴板,Bark 已发送多网盘上传时 Bark 是
|分隔的状态项之一;失败时同样点名原因,但不影响上传结果本身:⚠️ 上传成功:「a.md」,链接已复制到剪贴板;Bark ❌ Bark 请求超时(10 秒)多根工作区中 barkNotification 跟随文件所在文件夹的有效配置,每个文件夹可以用不同的 token 与模板(见多根工作区)。
命令
可在命令面板执行,或在编辑器 / 资源管理器中右键使用。
| 命令 ID | 标题 | 说明 |
|---|---|---|
sync123pan.upload |
Upload To 123 | 上传选中的文件。若选中的是文件夹,则递归上传其中全部内容。配置了 additionalConfigs 时,主网盘成功后会继续同步到额外网盘。 |
sync123pan.download |
Download | 用云端版本覆盖本地文件。 |
sync123pan.history |
History | 列出该文件的历史版本,选中后打开 remote <-> local 对比视图。 |
sync123pan.downloadHistory |
Download History | 同样的版本选择器,但会直接把选中的历史版本写回本地文件。 |
sync123pan.refresh |
Refresh | 刷新活动栏目录树。 |
sync123pan.downloadFromTreeView |
download | 目录树上的行内按钮:下载并打开文件,或递归下载整个远程文件夹。 |
sync123pan.delete |
delete | 目录树上的行内按钮:递归删除远程文件或文件夹,删除前有确认。 |
sync123pan.configurate |
Create 123pan.json | 写入配置模板并打开;多根工作区会先让你选择写到哪个文件夹。 |
sync123pan.open |
Open File | 内部命令:以只读方式打开目录树中的文件。 |
云端文件组织方式
扩展使用相对于 remoteFolder 的路径访问云端文件,与本地工作区保持一致。假设
"remoteFolder": "example/example/":
工作区根目录/ <-> 123pan / example/example/
工作区根目录/src/a.ts <-> 123pan / example/example/src/a.ts
所需的目录若不存在会自动创建。
多根工作区
上传、下载、历史版本都按文件所在的工作区文件夹取配置与换算云端路径:
- 该文件夹有自己的
.vscode/123pan.json就用它,云端路径相对该文件夹的根; - 没有配置文件时回退用第一个工作区文件夹(
workspaceFolders[0])的配置,云端路径 依然相对该文件夹自己的根——此时若它与第一个文件夹里某个文件相对路径相同,两者在 云端会互相覆盖,想隔离就给该文件夹单独建一份配置; - 配置文件存在(哪怕还没填凭据)就视为有意隔离,不会回退,而是直接报错。
// .code-workspace
{
"folders": [
{ "name": "FeliksPro", "path": "." },
{ "name": "mnaddonStore", "path": "../mnaddonStore" }
]
}
FeliksPro/src/a.ts <-> 123pan / remoteFolder/src/a.ts
mnaddonStore/mnutils/x.md <-> 123pan / remoteFolder/mnutils/x.md ← 回退主配置时
mnaddonStore/mnutils/x.md <-> 123pan / mnaddonStore自己的remoteFolder/mnutils/x.md
← 有自己的配置时
目录树始终展示第一个文件夹配置对应的远程目录。
历史记录结构
开启 recordHistory 后,每次上传还会在隐藏的 .history 目录下多写一份副本,文件名为
<文件名>_<unix毫秒时间戳><扩展名>,目录结构与本地保持一致:
.history/src/a_1699999999999.ts
History 与 Download History 会读取该目录来生成版本列表,按时间从新到旧排序,并用本地时间
显示每个时间戳。
历史版本不会被自动清理——它们会占用 123pan 空间。不再需要时,请到 123pan 网页端或活动栏 目录树中手动删除旧版本。
保存即自动上传
开启 uploadOnSave 后,保存文本文件或 Notebook 会触发一次上传,频率限制为最多每 60 秒一次
(窗口刚打开时的第一次保存不受限制)。扩展会在保存前对比编辑器内容与磁盘上的文件,未修改过的
文件会被跳过。修改 .vscode/123pan.json 里的 uploadOnSave 无需重载窗口即可生效。
注意事项与已知限制
- 多根工作区中目录树只跟随第一个文件夹。 上传/下载/历史按文件所在文件夹取配置(见 「多根工作区」),但目录树、树内的下载与删除始终使用第一个文件夹配置对应的远程目录。
- 下载会直接覆盖且没有确认提示。
Download与Download History会直接替换本地文件;History会在文件旁生成一个临时的remote_<文件名>(关闭对比视图后自动删除)。删除远程文件 和文件夹都会先弹确认框。 - 在目录树中点击文件需要开启
recordHistory: true。Open File这条路径会检查该配置项,未开启 时会直接报错,尽管它并不会读取任何历史记录。 - 递归有 32 层深度上限,且会跳过软链接。 这是为了防止软链接指回祖先目录导致无限下钻。
- 扩展为按需激活:打开活动栏的 123pan 视图、或执行任意 123pan 命令时才会启动,不随窗口
加载。打开包含有效
.vscode/123pan.json的工作区后,目录树会自动列出远程内容。
开发
npm install # 安装依赖
npm run compile # 清空 out/ → 类型检查 → 打包扩展 → 编译测试
npm run lint # 对 src/ 执行 eslint
npm test # 在无头 VS Code 实例中运行测试
npm run watch # 监听模式
npm run dev # 扩展与测试的并行监听模式
在 VS Code 中按 F5 启动扩展开发宿主(Extension Development Host)进行调试。
打包发布用的 .vsix:
npx vsce package
入口文件是 src/extension/extension.ts,WebDAV 层在 src/extension/webdav.ts。扩展用
esbuild 打包为 CommonJS 产物 out/extension/extension.js(源码由
tsc 只做类型检查,不产出)——因为 webdav 是纯 ESM 包,
而 VS Code 扩展宿主是 CommonJS,直接 require 会抛 ERR_REQUIRE_ESM。
许可证
GPL-2.0,完整文本见扩展内的 LICENSE 文件。