关于 orderly-sdk-page-components
为使用 Orderly SDK 构建 DEX 的开发者介绍预置页面组件及路由组织方式。组件覆盖交易、投资组合、市场、排行榜、积分、金库和联盟页面,并支持响应式界面。
主要功能
- 01预置交易与投资组合页面
- 02市场列表与资金费率比较
- 03排行榜、积分及金库页面
- 04联盟仪表盘组件
- 05页面懒加载与 Scaffold 布局
- 06内置桌面与移动端适配
适用场景
- 01快速组装完整 DEX 页面
- 02添加持仓、订单和资产页面
- 03构建市场、排行榜或积分页面
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ orderlynetwork/ skills --skill orderly-sdk-page-components安装后在 Claude Code 中输入/orderly-sdk-page-components确认已加载。
详细介绍
Orderly Network:SDK 页面组件
用于构建完整 DEX 的预构建全功能页面组件。每个页面都处理响应式设计(桌面端/移动端)、状态和 UI。在参考模板中,每个页面都会从 app/pages/... 延迟加载,并封装在共享的 Scaffold 布局中。
适用场景
- 快速构建完整 DEX
- 使用预构建、可用于生产环境的页面
- 实现标准 DEX 页面(交易、投资组合、市场、排行榜)
前置条件
- 已安装 Orderly SDK 软件包(参见
orderly-sdk-install-dependency) - 已配置 Providers(参见
orderly-sdk-dex-architecture) - React Router v7(
react-router-dom)
概览
| 组件 | 软件包 | 描述 |
|---|---|---|
TradingPage | @orderly.network/trading | 完整交易界面(图表、订单簿、下单) |
OverviewModule.OverviewPage | @orderly.network/portfolio | 投资组合仪表板 |
PositionsModule.PositionsPage | @orderly.network/portfolio | 持仓 + 历史记录 |
OrdersModule.OrdersPage | @orderly.network/portfolio | 订单(未平仓、待处理、已成交) |
AssetsModule.AssetsPage | @orderly.network/portfolio | 余额、存款/提现 |
HistoryModule.HistoryPage | @orderly.network/portfolio | 交易 / 资金费 / 结算历史记录 |
APIManagerModule.APIManagerPage | @orderly.network/portfolio | API 密钥管理 |
FeeTierModule.FeeTierPage | @orderly.network/portfolio | 费率等级概览 |
SettingModule.SettingPage | @orderly.network/portfolio | 账户设置 |
MarketsHomePage | @orderly.network/markets | 市场列表 + 资金费比较 |
GeneralLeaderboardWidget | @orderly.network/trading-leaderboard | 交易竞赛排行榜 |
PointSystemPage | @orderly.network/trading-points | 积分/荣誉计划 |
VaultsPage | @orderly.network/vaults | Vault/Earn 产品 |
Dashboard.DashboardPage | @orderly.network/affiliate | 联盟/推荐仪表板(位于 ReferralProvider 内) |
名称很重要。 使用
GeneralLeaderboardWidget(而不是LeaderboardPage)、PointSystemPage(而不是TradingRewardsPage;不存在trading-rewards软件包)和VaultsPage。联盟页面是Dashboard.DashboardPage,不是单独的Dashboard。
Scaffold 包装模式
参考模板中的每个路由布局都会将 <Outlet/> 封装在来自 @orderly.network/ui-scaffold 的 <Scaffold> 中,并传入导航/页脚配置(在 useOrderlyConfig() 中构建一次)和 routerAdapter。
// app/pages/perp/Layout.tsx
import { Outlet } from 'react-router-dom';
import { Scaffold } from '@orderly.network/ui-scaffold';
import { useOrderlyConfig } from '@/utils/config';
import { useNav } from '@/hooks/useNav';
export default function PerpLayout() {
const config = useOrderlyConfig();
const { onRouteChange } = useNav();
return (
<Scaffold
mainNavProps={config.scaffold.mainNavProps}
footerProps={config.scaffold.footerProps}
bottomNavProps={config.scaffold.bottomNavProps}
routerAdapter={{ onRouteChange, currentPath: '/' }}
>
<Outlet />
</Scaffold>
);
}
每个部分(perp、portfolio、markets、leaderboard、rewards、vaults、swap、points)都有一个采用此模式的 Layout.tsx。
1. TradingPage
由 app/pages/perp/Symbol.tsx 渲染(路由 /perp/:symbol)。tradingViewConfig 和 sharePnLConfig 来自 useOrderlyConfig()(它们根据当前主题和 .env 配置构建)。
// app/pages/perp/Symbol.tsx
import { useCallback, useState } from 'react';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { API } from '@orderly.network/types';
import { TradingPage } from '@orderly.network/trading';
import { useOrderlyConfig } from '@/utils/config';
export default function PerpSymbol() {
const params = useParams();
const [symbol, setSymbol] = useState(params.symbol!);
const config = useOrderlyConfig();
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const onSymbolChange = useCallback(
(data: API.Symbol) => {
setSymbol(data.symbol);
const qs = searchParams.toString();
navigate(`/perp/${data.symbol}${qs ? `?${qs}` : ''}`);
},
[navigate, searchParams]
);
return (
<div className="h-full">
<TradingPage
symbol={symbol}
onSymbolChange={onSymbolChange}
tradingViewConfig={config.tradingPage.tradingViewConfig}
sharePnLConfig={config.tradingPage.sharePnLConfig}
/>
</div>
);
}
tradingViewConfig
tradingViewConfig: {
scriptSRC: string; // /tradingview/charting_library/charting_library.js
library_path: string; // /tradingview/charting_library/
customCssUrl?: string; // /tradingview/chart.css
colorConfig?: Partial<TradingViewColorConfig>; // only in legacy mode
}
使用 createTradingViewConfig(themeSource) 构建(参见 orderly-sdk-theming)。TradingView 库文件必须放在 public/tradingview/charting_library/ 中。
路由是
/perp/:symbol,而不是/trade。索引路由/perp会重定向到默认交易对。
2. 投资组合页面
投资组合按模块组织,每个模块都导出一个 …Page。模板路由:portfolio(索引)、positions、orders、assets、api-key、fee、history、setting。
import {
OverviewModule, PositionsModule, OrdersModule, AssetsModule,
HistoryModule, APIManagerModule, FeeTierModule, SettingModule,
} from '@orderly.network/portfolio';
<OverviewModule.OverviewPage />
<PositionsModule.PositionsPage />
<OrdersModule.OrdersPage sharePnLConfig={config.tradingPage.sharePnLConfig} />
<AssetsModule.AssetsPage />
<HistoryModule.HistoryPage />
<APIManagerModule.APIManagerPage />
<FeeTierModule.FeeTierPage />
<SettingModule.SettingPage />
投资组合路由(延迟加载页面组件,并由共用的 PortfolioLayout 包装,使用 Scaffold):
{
path: 'portfolio',
element: <PortfolioLayout />,
children: [
{ index: true, element: <PortfolioIndex /> }, // OverviewModule.OverviewPage
{ path: 'positions', element: <PortfolioPositions /> },
{ path: 'orders', element: <PortfolioOrders /> },
{ path: 'assets', element: <PortfolioAssets /> },
{ path: 'api-key', element: <PortfolioApiKey /> }, // APIManagerModule.APIManagerPage
{ path: 'fee', element: <PortfolioFee /> }, // FeeTierModule.FeeTierPage
{ path: 'history', element: <PortfolioHistory /> },
{ path: 'setting', element: <PortfolioSetting /> }, // SettingModule.SettingPage
],
}
3. MarketsHomePage
import { MarketsHomePage } from '@orderly.network/markets';
<MarketsHomePage
comparisonProps={{
// name + icon shown in the funding-comparison list (NOT an exchanges array)
exchangesName: import.meta.env.VITE_ORDERLY_BROKER_NAME,
exchangesIconSrc: '/logo-secondary.webp', // optional
}}
onSymbolChange={(symbol) => navigate(`/perp/${symbol.symbol}`)}
/>;
comparisonProps接受exchangesName和exchangesIconSrc(均为可选),而不是exchanges: string[]数组。
4. 排行榜
import { GeneralLeaderboardWidget } from '@orderly.network/trading-leaderboard';
export default function LeaderboardIndex() {
return (
<div className="oui-py-6 oui-px-4 lg:oui-px-6">
<GeneralLeaderboardWidget />
</div>
);
}
5. 积分 / 奖励
import { PointSystemPage } from '@orderly.network/trading-points';
import { RouteOption } from '@orderly.network/types';
export default function PointsIndex() {
const navigate = useNavigate();
const onRouteChange = (p: RouteOption) => {
if (p.href === '/perp') navigate(`/perp/${getSymbol()}`);
};
return <PointSystemPage onRouteChange={onRouteChange} />;
}
6. 金库
import { VaultsPage as VaultsPageComponent } from '@orderly.network/vaults';
<VaultsPageComponent />;
7. 联盟 / 推荐
在 <ReferralProvider> 中渲染 Dashboard.DashboardPage:
import { Dashboard, ReferralProvider } from '@orderly.network/affiliate';
export default function AffiliateIndex() {
return (
<ReferralProvider>
<Dashboard.DashboardPage />
</ReferralProvider>
);
}
路由
路由在 app/main.tsx 中通过 createBrowserRouter 定义,basename 为 import.meta.env.BASE_URL。所有页面均采用延迟加载。
const router = createBrowserRouter(
[
{
path: '/',
element: <App />,
errorElement: <ErrorBoundary />,
children: [
{ index: true, element: <IndexPage /> },
{
path: 'perp',
element: <PerpLayout />,
children: [
{ index: true, element: <PerpIndex /> },
{ path: ':symbol', element: <PerpSymbol /> },
],
},
{
path: 'portfolio',
element: <PortfolioLayout />,
children: [
/* …see above… */
],
},
{
path: 'markets',
element: <MarketsLayout />,
children: [{ index: true, element: <MarketsIndex /> }],
},
{
path: 'leaderboard',
element: <LeaderboardLayout />,
children: [{ index: true, element: <LeaderboardIndex /> }],
},
{
path: 'rewards',
element: <RewardsLayout />,
children: [
{ index: true, element: <RewardsIndex /> },
{ path: 'affiliate', element: <RewardsAffiliate /> },
],
},
{
path: 'vaults',
element: <VaultsLayout />,
children: [{ index: true, element: <VaultsIndex /> }],
},
{
path: 'swap',
element: <SwapLayout />,
children: [{ index: true, element: <SwapIndex /> }],
},
{
path: 'points',
element: <PointsLayout />,
children: [{ index: true, element: <PointsIndex /> }],
},
],
},
],
{ basename: basePath }
);
响应式设计
页面组件会在内部处理桌面端和移动端。对于自定义布局决策,请使用 useScreen()(来自 @orderly.network/ui):
import { useScreen } from '@orderly.network/ui';
const { isMobile } = useScreen();
最佳实践
- 延迟加载每个页面(模板在
main.tsx中延迟导入app/pages/...)。 - 使用
Scaffold包装路由,确保导航栏、页脚和账户菜单保持一致。 - 持久化交易对(模板会在交易对变更时调用
updateSymbol(symbol)),以便深层链接和索引路由能够恢复交易对。 - 通过
useOrderlyConfig()配置tradingViewConfig/sharePnLConfig,使其跟随当前主题。 - 使用
onSymbolChange更新 URL,让交易页面支持加入书签。
相关技能
- orderly-sdk-dex-architecture - 项目结构、providers、路由入口
- orderly-sdk-theming -
tradingViewConfig背后的主题配置 - orderly-sdk-trading-workflows - 交易功能详情
- orderly-ui-components - 与这些高级页面相对的细粒度组件