修复工具条折行与资源编辑 400 的错误盲区

- resourceCanvasChrome.css:移除我自行添加的 max-width 与 flex-wrap: wrap,按网页端美术画布原始规则改回单行不换行(容器 nowrap + 溢出横向兜底),按钮统一 2.25rem 方块与 0.45rem 圆角,文字键 padding 改回 0 0.62rem,分隔线改回 1.125rem,消除动作变多时折叠成多层与按钮高矮不齐
- resource_editor.rs:新增 editor_api_rejection_reason,在 HTTP 400 分支把服务端响应体的可读原因(兼容 error.message / error 字符串 / details.message / 顶层 message,截断 200 字符)拼进用户可见错误,替换原先只有状态码的笼统提示
This commit is contained in:
2026-09-10 16:33:13 +08:00
parent f09f5f9e9c
commit 56c6e0fecc
2 changed files with 59 additions and 8 deletions
@@ -2457,6 +2457,35 @@ fn is_external_resource_edit_endpoint(endpoint: &str) -> bool {
)
}
/// 从服务端 4xx 响应体里取出**可读的失败原因**,让用户看到的不是笼统的 HTTP 状态码。
///
/// 平台错误体在不同路由上可能是 `{error:{message}}`、`{error:"文本"}`、`{details:{message}}`
/// 或顶层 `{message}`;这里按这个顺序兼容,并截断到 200 字符,避免把整段响应体塞进用户可见文案。
async fn editor_api_rejection_reason(response: reqwest::Response) -> Option<String> {
let body = response.text().await.ok()?;
let value: serde_json::Value = serde_json::from_str(body.trim()).ok()?;
let candidate = value
.get("error")
.and_then(|error| {
error
.get("message")
.and_then(|message| message.as_str())
.or_else(|| error.as_str())
})
.or_else(|| {
value
.get("details")
.and_then(|details| details.get("message"))
.and_then(|message| message.as_str())
})
.or_else(|| value.get("message").and_then(|message| message.as_str()))?;
let trimmed = candidate.trim();
if trimmed.is_empty() {
return None;
}
Some(trimmed.chars().take(200).collect())
}
async fn submit_resource_edit_remote(
root: &Path,
client: &reqwest::Client,
@@ -2527,7 +2556,10 @@ async fn submit_resource_edit_remote(
if let Some(error) = post_response_session_error.as_ref() {
return Err(error.clone());
}
return Err("remote-terminal-failed: 资源编辑请求被拒绝:HTTP 400".to_string());
return Err(match editor_api_rejection_reason(response).await {
Some(reason) => format!("remote-terminal-failed: 资源编辑请求被拒绝:HTTP 400({reason}"),
None => "remote-terminal-failed: 资源编辑请求被拒绝:HTTP 400".to_string(),
});
}
if !matches!(
status,
@@ -30,16 +30,23 @@
--image-canvas-brand-focus-ring: rgba(204, 117, 76, 0.18);
}
/* 选中工具条:贴在资源卡正上方浮出,层级高于卡片与画布标题栏。 */
/* 选中工具条:贴在资源卡正上方浮出,层级高于卡片与画布标题栏。
*
* 尺寸与排布严格对齐网页端美术画布(`src/index.css`):容器**单行不换行**、
* 图标键 `2.25rem` 方块、文字键靠同一高度撑开、分隔线 `1.125rem` 高。
* 早期实现多加了 `max-width` 与 `flex-wrap: wrap`,动作一多就折成两三层,
* 与美术画布不一致,已移除。窄屏用横向滚动兜底,仍然只占一行。 */
.game-resource-canvas-toolbar-host
.image-canvas-editor__floating-toolbar {
position: absolute;
z-index: 60;
display: inline-flex;
max-width: min(560px, 92vw);
max-width: min(92vw, 640px);
align-items: center;
flex-wrap: wrap;
flex-wrap: nowrap;
gap: 0.3rem;
overflow-x: auto;
overscroll-behavior-x: contain;
border: 1px solid var(--image-canvas-brand-border-soft);
border-radius: 0.5rem;
background: #ffffff;
@@ -47,6 +54,12 @@
box-shadow: 0 18px 34px rgba(15, 23, 42, 0.18);
transform: translate(-50%, -100%);
pointer-events: auto;
scrollbar-width: none;
}
.game-resource-canvas-toolbar-host
.image-canvas-editor__floating-toolbar::-webkit-scrollbar {
display: none;
}
.game-resource-canvas-toolbar-host
@@ -55,8 +68,11 @@
display: inline-flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
width: 2.25rem;
height: 2.25rem;
border: 1px solid var(--image-canvas-brand-border-soft);
border-radius: 0.375rem;
border-radius: 0.45rem;
background: #ffffff;
color: #334155;
cursor: pointer;
@@ -89,7 +105,7 @@
width: auto;
min-width: 0;
gap: 0.35rem;
padding: 0.34rem 0.62rem;
padding: 0 0.62rem;
font-size: 0.74rem;
font-weight: 850;
white-space: nowrap;
@@ -97,9 +113,12 @@
.game-resource-canvas-toolbar-host
.image-canvas-editor__floating-toolbar-divider {
display: block;
display: inline-block;
flex: 0 0 auto;
align-self: center;
width: 1px;
height: 1.1rem;
height: 1.125rem;
border-radius: 999px;
background: var(--image-canvas-brand-border-soft);
}