feat(ui): streamline workspace settings and remove sharing

Unify compact workspace controls and panel transitions, move directory actions into the context menu, and remove backlink UI.

Reorganize settings with searchable sections, per-setting resets, shortcut search, and accurate save feedback.

Remove sharing UI, APIs, authentication helpers, and storage code; provide a transactional cleanup script with retirement tests. Reject directories during orphan image cleanup and cover mixed-batch preservation.
This commit is contained in:
eezd committed 2026-10-24 12:32:23 +08:00
1 parent a716794e41
commit 19aab631ec
63 files changed
+1077 -3343

No files matched your search

+3 -591
View File
@@ -3,7 +3,7 @@
"info": {
"title": "RawMark API",
"version": "1",
"description": "RawMark 的 REST API。自动化调用请在「API 令牌」中创建令牌,以 `Authorization: Bearer <token>` 访问;只读令牌可使用 GET 和 POST /export(只读导出)。分享与令牌的管理接口只接受登录会话。所有错误响应均为 `{\"error\": \"说明\"}`。"
"description": "RawMark 的 REST API。自动化调用请在「API 令牌」中创建令牌,以 `Authorization: Bearer <token>` 访问;只读令牌可使用 GET 和 POST /export(只读导出)。令牌的管理接口只接受登录会话。所有错误响应均为 `{\"error\": \"说明\"}`。"
},
"servers": [
{
@@ -617,7 +617,7 @@
"tags": [
"笔记"
],
"description": "笔记的 .assets 目录随之移动,改名时改写本篇图片目录链接;图片移动或改名保持扩展名,并更新仓库笔记中的本地引用。分享链接随主体更新。不改写其他笔记指向笔记或文件夹的链接。",
"description": "笔记的 .assets 目录随之移动,改名时改写本篇图片目录链接;图片移动或改名保持扩展名,并更新仓库笔记中的本地引用。维护笔记中的本地入链及相对出链。",
"requestBody": {
"required": true,
"content": {
@@ -1114,193 +1114,6 @@
}
}
},
"/shares": {
"get": {
"summary": "分享列表",
"tags": [
"分享"
],
"security": [
{
"cookie": []
}
],
"parameters": [
{
"name": "path",
"in": "query",
"description": "只列出该笔记的分享",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "分享",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"shares": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Share"
}
}
}
}
}
}
}
}
},
"post": {
"summary": "创建文件或文件夹的只读分享",
"tags": [
"分享"
],
"security": [
{
"cookie": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "仓库内的文件或文件夹;文件夹递归公开当前所有普通文件和子目录,含后续新增或移入的内容"
},
"password": {
"type": "string",
"description": "访问密码,留空为不设密码"
},
"expiresIn": {
"type": "integer",
"description": "有效时长(秒),0 为永久"
},
"paths": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
},
"description": "与 path 二选一;重叠路径只保留外层目录"
}
},
"required": [],
"oneOf": [
{
"required": [
"path"
],
"not": {
"required": [
"paths"
]
}
},
{
"required": [
"paths"
],
"not": {
"required": [
"path"
]
}
}
]
}
}
}
},
"responses": {
"200": {
"description": "新分享,token 为 128 位随机数的 URL 安全编码,访问地址为 /s/{token};移动分享主体不改变链接",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Share"
}
}
}
},
"400": {
"description": "路径或参数无效",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "笔记不存在",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"description": "创建一个随机只读链接。path 创建单主体分享;paths 创建集合。内容实时读取,主体移动后跟随,部分主体删除不影响其余项。"
}
},
"/shares/{token}": {
"parameters": [
{
"name": "token",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"delete": {
"summary": "撤销分享",
"tags": [
"分享"
],
"security": [
{
"cookie": []
}
],
"responses": {
"200": {
"description": "成功",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Ok"
}
}
}
},
"404": {
"description": "不存在",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/tokens": {
"get": {
"summary": "API 令牌列表",
@@ -1446,261 +1259,6 @@
}
}
},
"/public/shares/{token}": {
"parameters": [
{
"name": "token",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "path",
"in": "query",
"description": "文件夹分享中相对主体的子路径;省略时读取主体本身,不允许跳出分享范围",
"schema": {
"type": "string"
}
}
],
"get": {
"summary": "访客读取分享主体或其目录中的当前内容",
"tags": [
"分享(公开)"
],
"security": [
{}
],
"responses": {
"200": {
"description": "目录返回 dir=true 及递归 entries(路径相对此目录);Markdown 返回 dir=false、content 与 updatedAt;其他文件返回 dir=false,内容经 assets 接口读取或下载",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"content": {
"type": "string"
},
"updatedAt": {
"type": "integer"
},
"dir": {
"type": "boolean"
},
"entries": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Entry"
}
}
}
}
}
}
},
"401": {
"description": "需要访问密码",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"passwordRequired": {
"type": "boolean"
}
}
}
}
}
},
"404": {
"description": "分享不存在、已过期、主体已删除或子路径不在分享范围内",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"parameters": [
{
"name": "item",
"in": "query",
"schema": {
"type": "integer"
},
"description": "集合分享的稳定成员标识;单主体分享可省略。子路径及附件始终限制在该主体原有范围内。"
}
],
"description": "单主体沿用原响应。集合首页未指定 item 时返回 collection=true 及 items(仅含 id、title、dir、exists,不暴露仓库父路径);指定 item 后读取该主体,path 为其内部相对路径。"
}
},
"/public/shares/{token}/unlock": {
"parameters": [
{
"name": "token",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"post": {
"summary": "输入分享密码,成功后设置访客 Cookie",
"tags": [
"分享(公开)"
],
"security": [
{}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"password": {
"type": "string"
}
},
"required": [
"password"
]
}
}
}
},
"responses": {
"200": {
"description": "成功",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Ok"
}
}
}
},
"401": {
"description": "密码错误",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "分享不存在或已失效",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "失败次数过多",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/public/shares/{token}/assets/{path}": {
"parameters": [
{
"name": "token",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "path",
"in": "path",
"required": true,
"description": "文件夹分享中相对主体的文件路径;单文件分享仅允许其 .assets 图片,空路径读取该文件本身",
"schema": {
"type": "string"
}
},
{
"name": "download",
"in": "query",
"description": "设为 1 时以附件下载;其他情况下以带沙箱 CSP 的原始文件返回",
"schema": {
"type": "string",
"enum": [
"1"
]
}
}
],
"get": {
"summary": "访客读取或下载分享范围内的普通文件",
"tags": [
"分享(公开)"
],
"security": [
{}
],
"responses": {
"200": {
"description": "文件内容",
"content": {
"application/octet-stream": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"404": {
"description": "不存在或不在允许范围内",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"parameters": [
{
"name": "item",
"in": "query",
"schema": {
"type": "integer"
},
"description": "集合分享的稳定成员标识;单主体分享可省略。子路径及附件始终限制在该主体原有范围内。"
}
]
}
},
"/themes": {
"get": {
"summary": "列出主题(含内置默认主题)",
@@ -1774,98 +1332,6 @@
}
}
},
"/public/shares/{token}/appearance": {
"get": {
"summary": "读取有效分享使用的外观配置",
"description": "仅返回明暗模式、字号、正文宽度、主题 CSS 和启用的 CSS 片段;密码分享需先解锁,不返回其他设置,不加载插件。",
"tags": [
"分享"
],
"security": [
{}
],
"parameters": [
{
"name": "token",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "公开的外观配置",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"colorMode": {
"type": "string",
"enum": [
"system",
"light",
"dark"
]
},
"uiFontSize": {
"type": "integer",
"minimum": 14,
"maximum": 20,
"default": 16,
"description": "界面字号,与正文排版字号独立"
},
"fontSize": {
"type": "integer"
},
"contentWidth": {
"type": "integer"
},
"themeCSS": {
"type": "string"
},
"cssSnippets": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"css": {
"type": "string"
},
"enabled": {
"type": "boolean"
}
}
}
},
"theme": {
"type": "string"
}
}
}
}
}
},
"401": {
"description": "需要访问密码"
},
"404": {
"description": "分享不存在、已过期或已撤销"
}
}
}
},
"/plugins": {
"get": {
"summary": "列出已安装插件及启用状态",
@@ -2468,7 +1934,7 @@
},
"/assets/cleanup": {
"post": {
"summary": "重新核对全库引用和有效分享后,将孤立图片移入回收站",
"summary": "重新核对全库引用后,将孤立图片移入回收站",
"requestBody": {
"required": true,
"content": {
@@ -2614,60 +2080,6 @@
}
}
},
"Share": {
"type": "object",
"properties": {
"token": {
"type": "string",
"description": "新分享使用完全随机的 URL 安全标识,不包含文件名称或目录"
},
"path": {
"type": "string",
"description": "单主体分享的路径;集合分享不返回此字段"
},
"createdAt": {
"type": "integer"
},
"expiresAt": {
"type": "integer",
"description": "Unix 毫秒,0 为永久"
},
"hasPassword": {
"type": "boolean"
},
"exists": {
"type": "boolean",
"description": "分享的文件或文件夹是否仍存在"
},
"items": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"id",
"path",
"exists"
],
"properties": {
"id": {
"type": "integer",
"description": "稳定的分享成员标识"
},
"path": {
"type": "string"
},
"exists": {
"type": "boolean"
}
}
}
}
},
"required": [
"items"
]
},
"APIToken": {
"type": "object",
"properties": {