7ce4a3a9c6
- 新增 ResourceTypePanel(src/view/project-development/ResourceTypePanel.tsx):类型选一项即落盘,category 传用户选中值、tags 逐字回传落盘原值,保存在飞时沿用 closeOnBackdrop/closeOnEscape = !saving - 新增 resourceAssetDisplayName.ts:两块面板共用同一个素材名副标题口径(localPath basename),不再各写一份 - 新增 resourceTypePanel.css:类型面板的弹窗骨架与信息浮层「分类」行入口样式,按 AGC 内独立文件约定,不动 packages/** 与 styles.css - ResourceClassificationPanel 删掉类型 chip 与 categoryChoice:保存时恒回传 gameCreationAppAssetPersistedCategory(asset),「只改标签不动分类」由结构保证 - index.tsx 新增 resourceTypeAssetId 与 resourceTypeAsset;工具条在「编辑标签」旁新增「素材类型」按钮(Shapes 图标) - index.tsx 用合并后的 resourceClassificationOverlayOpen 纳入点外部/Esc 浮层遮挡判据,并同步 useEffect 依赖项 - index.tsx 渲染新面板:保存成功后由宿主收起面板并沿用 manifest 重载路径,让卡片立刻落到新栏目 - 信息浮层「分类」行接出第二入口:按钮渲染在 dd 之外,不污染 dt/dd 字段读取口径;非 manifest 资产不给入口 - resourceCanvasInfoModel 导出 RESOURCE_INFO_CATEGORY_FIELD_LABEL,模型与入口共用同一行标识 - 新增 tests/resourceTypePanel.test.tsx:选中即落盘、tags 逐字回传、没碰过不写盘、显式待归类、失败回退、saving 锁、Esc/遮罩、面板骨架共 11 条 - 迁移「没碰过分类就回传落盘原值」对照用例并保留两条(标签面板侧),chip 用例搬到新面板文件 - 集成用例改走新入口:选中即落盘并自动关窗,另补 Esc/点外部不串台、只改标签后 manifest category 逐字不变两条宿主级用例 - appSurface 工具条清单补上「素材类型」
109 lines
3.1 KiB
TypeScript
109 lines
3.1 KiB
TypeScript
import { Info, X } from 'lucide-react';
|
|
|
|
import {
|
|
resolveResourceInfoFieldRows,
|
|
resolveResourceInfoPanelStyle,
|
|
RESOURCE_INFO_CATEGORY_FIELD_LABEL,
|
|
type ResourceInfoPanelAnchor,
|
|
} from '../../features/resource-canvas/resourceCanvasInfoModel';
|
|
import type { ProjectResource } from './resourceProjectionModel';
|
|
|
|
/**
|
|
* 只读资源信息字段。运行页签的「信息展示」与画布上的信息浮层共用这一份,
|
|
* 字段清单只在 `resolveResourceInfoFieldRows` 里定义,两处不会各说一套。
|
|
*
|
|
* `onEditCategory` 是「分类」行的可选入口(只有画布浮层传):分类值本身仍然只读展示,
|
|
* 入口按钮渲染在 `dd` **外面** —— 字段值的读取口径是 `dt` / `dd` 的文本,
|
|
* 把按钮塞进 `dd` 会让分类值变成「角色与对象设置」这类拼接文案。
|
|
*/
|
|
export function ResourceInfoFieldsView({
|
|
resource,
|
|
onEditCategory,
|
|
}: {
|
|
resource: ProjectResource;
|
|
onEditCategory?: () => void;
|
|
}) {
|
|
return (
|
|
<dl className="game-resource-info-fields">
|
|
{resolveResourceInfoFieldRows(resource).map((row) => (
|
|
<div key={row.label}>
|
|
<dt>{row.label}</dt>
|
|
<dd>{row.value}</dd>
|
|
{onEditCategory &&
|
|
row.label === RESOURCE_INFO_CATEGORY_FIELD_LABEL ? (
|
|
<button
|
|
type="button"
|
|
className="game-resource-info-field-action"
|
|
aria-label="设置素材类型"
|
|
title="设置素材类型"
|
|
onClick={onEditCategory}
|
|
>
|
|
设置
|
|
</button>
|
|
) : null}
|
|
</div>
|
|
))}
|
|
</dl>
|
|
);
|
|
}
|
|
|
|
export type ResourceInfoPanelViewProps = ResourceInfoPanelAnchor & {
|
|
resource: ProjectResource;
|
|
/**
|
|
* 「分类」行的类型设置入口;不传就没有入口(资源不是 manifest 资产时宿主不传)。
|
|
*/
|
|
onEditCategory?: () => void;
|
|
onClose: () => void;
|
|
};
|
|
|
|
/**
|
|
* 画布上的信息浮层:贴着选中资源卡,非模态。
|
|
*
|
|
* 关闭时机(Esc / 点边界外)由宿主复用 `useImageCanvasFloatingOptionDismiss` 接管,
|
|
* 这里只负责渲染,所以面板本身不注册任何 document 监听。
|
|
*/
|
|
export function ResourceInfoPanelView({
|
|
resource,
|
|
sourceLayer,
|
|
viewport,
|
|
canvasSize,
|
|
onEditCategory,
|
|
onClose,
|
|
}: ResourceInfoPanelViewProps) {
|
|
const style = resolveResourceInfoPanelStyle({
|
|
sourceLayer,
|
|
viewport,
|
|
canvasSize,
|
|
});
|
|
if (!style) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<section
|
|
className="game-resource-info-panel"
|
|
role="dialog"
|
|
aria-label="资源信息"
|
|
style={style}
|
|
>
|
|
<header className="game-resource-info-panel__header">
|
|
<Info size={14} aria-hidden="true" />
|
|
<strong>信息</strong>
|
|
<button
|
|
type="button"
|
|
className="game-resource-info-panel__close"
|
|
aria-label="关闭信息面板"
|
|
title="关闭"
|
|
onClick={onClose}
|
|
>
|
|
<X size={14} aria-hidden="true" />
|
|
</button>
|
|
</header>
|
|
<ResourceInfoFieldsView
|
|
resource={resource}
|
|
onEditCategory={onEditCategory}
|
|
/>
|
|
</section>
|
|
);
|
|
}
|