feat(web): 店铺管理页与页头平台选择器接入真实 API
- 页头平台选择器:PlatformProvider 加载平台目录与平台上下文
(X-Atlas-Platform-Id header),平台 id 仅作为非敏感 UI 偏好存
localStorage,默认取目录第一家(Ozon 优先)
- 店铺管理页覆盖 docs/api/stores-and-platforms.md 已实现接口:
游标分页列表、创建(202+operation)、编辑(If-Match 乐观锁、
409 刷新提示)、设为默认、重新验证凭据、仓库同步(422 脱敏
错误展示)、软删除(DEFAULT_STORE_REPLACEMENT_REQUIRED 提示)
- services/api.ts 新增 getList(保留 {data, meta} 分页信封)与
apiErrorCode;services/stores.ts 按契约生成 Idempotency-Key
- @atlas/contracts 补充只读响应类型 Platform / PlatformContext /
CursorPaginationMeta / StoreOperationResponse(无行为变更)
- API Key 仅存在于提交瞬间的内存表单,不落任何存储
- 浏览器实测:注册→平台切换→创建/编辑/设默认/删除保护/同步
错误路径→刷新会话恢复全部通过;typecheck + production build 通过
This commit is contained in:
@@ -102,6 +102,25 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* 页头平台选择器:图标 + 无边框下拉,视觉与用户触发区一致 */
|
||||
.platform-selector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 6px;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.platform-selector:hover {
|
||||
background: #f3f4f6;
|
||||
}
|
||||
|
||||
.platform-selector-icon {
|
||||
color: var(--primary-color);
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
/* 头像 + 用户名触发区:hover 有浅色背景反馈,暗示可下拉 */
|
||||
.header-user-trigger {
|
||||
display: flex;
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
UserOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import SidebarMenu from './SidebarMenu';
|
||||
import PlatformSelector from './PlatformSelector';
|
||||
import { getBreadcrumbItems } from './menuConfig';
|
||||
import { useSession } from '@/services/session';
|
||||
import './MainLayout.css';
|
||||
@@ -156,6 +157,7 @@ const MainLayout = () => {
|
||||
</div>
|
||||
{session && (
|
||||
<div className="header-right">
|
||||
<PlatformSelector />
|
||||
<Dropdown
|
||||
menu={{ items: userMenuItems, onClick: handleUserMenuClick }}
|
||||
trigger={['hover']}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { GlobalOutlined } from '@ant-design/icons';
|
||||
import { Select, Tooltip } from 'antd';
|
||||
import { usePlatform } from '@/services/platform';
|
||||
|
||||
/**
|
||||
* 页头平台选择器:采集编辑、发布等动作按页头当前平台取得发布配置与默认店铺
|
||||
* (docs/requirements/collector-browser-extension.md 的页头平台上下文约定)。
|
||||
* 首次使用默认选中目录第一家(Ozon 优先),选择结果仅作为非敏感 UI 偏好本地记忆。
|
||||
*/
|
||||
const PlatformSelector = () => {
|
||||
const {
|
||||
platforms,
|
||||
currentPlatform,
|
||||
selectPlatform,
|
||||
context,
|
||||
contextLoading,
|
||||
} = usePlatform();
|
||||
|
||||
if (platforms.length === 0) return null;
|
||||
|
||||
const tooltip = context?.default_store
|
||||
? `当前平台:${currentPlatform?.name},默认店铺:${context.default_store.name}`
|
||||
: '选择当前平台';
|
||||
|
||||
return (
|
||||
<Tooltip title={tooltip}>
|
||||
<div className="platform-selector">
|
||||
<GlobalOutlined className="platform-selector-icon" />
|
||||
<Select
|
||||
variant="borderless"
|
||||
loading={contextLoading && !currentPlatform}
|
||||
value={currentPlatform?.id}
|
||||
onChange={selectPlatform}
|
||||
options={platforms.map((platform) => ({
|
||||
value: platform.id,
|
||||
label: platform.name,
|
||||
}))}
|
||||
popupMatchSelectWidth={false}
|
||||
aria-label="选择当前平台"
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export default PlatformSelector;
|
||||
Reference in New Issue
Block a user