feat(frontend): 优化加密价差监控页面体验
- 刷新页面时保留当前选择的策略(localStorage 缓存) - 移动端下单弹窗改为 BottomSheet 样式,更紧凑 - 买入按钮实时显示当前价格,如 "买入 Up (0.50)" - 周期切换时自动关闭弹窗并提示用户 Made-with: Cursor
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
InputNumber,
|
||||
message
|
||||
} from 'antd'
|
||||
import { Popup as AntdMobilePopup } from 'antd-mobile'
|
||||
import { ClockCircleOutlined, SyncOutlined, InfoCircleOutlined, ShoppingCartOutlined } from '@ant-design/icons'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useMediaQuery } from 'react-responsive'
|
||||
@@ -33,6 +34,10 @@ import type {
|
||||
|
||||
const { Title, Text } = Typography
|
||||
|
||||
// localStorage keys
|
||||
const PERIOD_SWITCH_MODE_KEY = 'cryptoTailMonitor_periodSwitchMode'
|
||||
const SELECTED_STRATEGY_ID_KEY = 'cryptoTailMonitor_selectedStrategyId'
|
||||
|
||||
/** 分时图数据点:时间戳、BTC 价格 USDC、市场 Up/Down 价格 0-1 */
|
||||
interface PriceDataPoint {
|
||||
time: number
|
||||
@@ -49,8 +54,11 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
const [strategies, setStrategies] = useState<CryptoTailStrategyDto[]>([])
|
||||
const [strategiesLoading, setStrategiesLoading] = useState(false)
|
||||
|
||||
// 选中的策略
|
||||
const [selectedStrategyId, setSelectedStrategyId] = useState<number | null>(null)
|
||||
// 选中的策略(从 localStorage 恢复)
|
||||
const [selectedStrategyId, setSelectedStrategyId] = useState<number | null>(() => {
|
||||
const cached = localStorage.getItem(SELECTED_STRATEGY_ID_KEY)
|
||||
return cached != null ? parseInt(cached, 10) : null
|
||||
})
|
||||
|
||||
// 监控数据
|
||||
const [initData, setInitData] = useState<CryptoTailMonitorInitResponse | null>(null)
|
||||
@@ -69,9 +77,6 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
selectedStrategyIdRef.current = selectedStrategyId
|
||||
}, [selectedStrategyId])
|
||||
|
||||
// localStorage key for period switch mode
|
||||
const PERIOD_SWITCH_MODE_KEY = 'cryptoTailMonitor_periodSwitchMode'
|
||||
|
||||
// 记录首次数据进入时间(用于中途进入时的横轴起点)
|
||||
const [firstDataTime, setFirstDataTime] = useState<number | null>(null)
|
||||
// 标记是否已切换过周期(切换后使用完整周期)
|
||||
@@ -100,6 +105,7 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
totalAmount: string
|
||||
bestBid: string
|
||||
availableBalance: string
|
||||
periodStartUnix: number | null
|
||||
}>({
|
||||
visible: false,
|
||||
direction: 'UP',
|
||||
@@ -107,10 +113,21 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
size: '',
|
||||
totalAmount: '',
|
||||
bestBid: '',
|
||||
availableBalance: ''
|
||||
availableBalance: '',
|
||||
periodStartUnix: null
|
||||
})
|
||||
const [ordering, setOrdering] = useState(false)
|
||||
|
||||
// 检测周期切换,关闭弹窗并提示用户
|
||||
useEffect(() => {
|
||||
if (manualOrderModal.visible && manualOrderModal.periodStartUnix != null && pushData) {
|
||||
if (pushData.periodStartUnix !== manualOrderModal.periodStartUnix) {
|
||||
message.warning(t('cryptoTailMonitor.manualOrder.periodChanged'))
|
||||
handleCloseManualOrderModal()
|
||||
}
|
||||
}
|
||||
}, [pushData?.periodStartUnix, manualOrderModal.visible, manualOrderModal.periodStartUnix])
|
||||
|
||||
// 获取策略列表
|
||||
useEffect(() => {
|
||||
const fetchStrategies = async () => {
|
||||
@@ -118,10 +135,18 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
try {
|
||||
const res = await apiService.cryptoTailStrategy.list({ enabled: true })
|
||||
if (res.data.code === 0 && res.data.data) {
|
||||
setStrategies(res.data.data.list ?? [])
|
||||
// 自动选择第一个策略
|
||||
if (res.data.data.list?.length > 0 && !selectedStrategyId) {
|
||||
setSelectedStrategyId(res.data.data.list[0].id)
|
||||
const strategyList = res.data.data.list ?? []
|
||||
setStrategies(strategyList)
|
||||
// 从 localStorage 恢复选中的策略
|
||||
const cachedId = localStorage.getItem(SELECTED_STRATEGY_ID_KEY)
|
||||
const cachedStrategyId = cachedId != null ? parseInt(cachedId, 10) : null
|
||||
// 检查缓存的策略是否在列表中
|
||||
const isValidCached = cachedStrategyId != null && strategyList.some(s => s.id === cachedStrategyId)
|
||||
if (isValidCached) {
|
||||
setSelectedStrategyId(cachedStrategyId)
|
||||
} else if (strategyList.length > 0) {
|
||||
// 自动选择第一个策略
|
||||
setSelectedStrategyId(strategyList[0].id)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -133,6 +158,13 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
fetchStrategies()
|
||||
}, [])
|
||||
|
||||
// 保存选中的策略到 localStorage
|
||||
useEffect(() => {
|
||||
if (selectedStrategyId != null) {
|
||||
localStorage.setItem(SELECTED_STRATEGY_ID_KEY, String(selectedStrategyId))
|
||||
}
|
||||
}, [selectedStrategyId])
|
||||
|
||||
// 初始化监控数据
|
||||
useEffect(() => {
|
||||
if (!selectedStrategyId) {
|
||||
@@ -818,7 +850,8 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
size: defaultSize,
|
||||
totalAmount: defaultTotalAmount,
|
||||
bestBid,
|
||||
availableBalance
|
||||
availableBalance,
|
||||
periodStartUnix: pushData.periodStartUnix
|
||||
})
|
||||
}
|
||||
|
||||
@@ -854,7 +887,8 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
size: '',
|
||||
totalAmount: '',
|
||||
bestBid: '',
|
||||
availableBalance: ''
|
||||
availableBalance: '',
|
||||
periodStartUnix: null
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1160,7 +1194,7 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
block
|
||||
style={{ backgroundColor: '#1890ff', borderColor: '#1890ff' }}
|
||||
>
|
||||
{t('cryptoTailMonitor.manualOrder.buttonUp')}
|
||||
{t('cryptoTailMonitor.manualOrder.buttonUp')} {pushData?.currentPriceUp ? `(${formatNumber(pushData.currentPriceUp, 2)})` : ''}
|
||||
</Button>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
@@ -1173,7 +1207,7 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
block
|
||||
style={{ backgroundColor: '#fa8c16', borderColor: '#fa8c16' }}
|
||||
>
|
||||
{t('cryptoTailMonitor.manualOrder.buttonDown')}
|
||||
{t('cryptoTailMonitor.manualOrder.buttonDown')} {pushData?.currentPriceDown ? `(${formatNumber(pushData.currentPriceDown, 2)})` : ''}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -1211,48 +1245,162 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* 手动下单确认弹窗 */}
|
||||
<Modal
|
||||
title={t('cryptoTailMonitor.manualOrder.confirmTitle')}
|
||||
open={manualOrderModal.visible}
|
||||
onCancel={handleCloseManualOrderModal}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={handleCloseManualOrderModal}>
|
||||
{t('cryptoTailMonitor.manualOrder.cancel')}
|
||||
</Button>,
|
||||
<Button
|
||||
key="confirm"
|
||||
type="primary"
|
||||
onClick={handleManualOrder}
|
||||
loading={ordering}
|
||||
style={
|
||||
manualOrderModal.direction === 'UP'
|
||||
? { backgroundColor: '#1890ff', borderColor: '#1890ff' }
|
||||
: { backgroundColor: '#fa8c16', borderColor: '#fa8c16' }
|
||||
}
|
||||
>
|
||||
{t('cryptoTailMonitor.manualOrder.confirm')}
|
||||
</Button>
|
||||
]}
|
||||
width={isMobile ? '100%' : 480}
|
||||
style={isMobile ? { maxWidth: '100%', top: 0, paddingBottom: 0 } : undefined}
|
||||
>
|
||||
{initData && (
|
||||
<Space direction="vertical" style={{ width: '100%' }} size={16}>
|
||||
<Row gutter={[12, 8]}>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.marketTitle')}
|
||||
</Text>
|
||||
<Text>{pushData?.marketTitle ?? initData.marketTitle}</Text>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.direction')}
|
||||
{/* 手动下单确认弹窗 - 桌面端使用 Modal */}
|
||||
{!isMobile && (
|
||||
<Modal
|
||||
title={t('cryptoTailMonitor.manualOrder.confirmTitle')}
|
||||
open={manualOrderModal.visible}
|
||||
onCancel={handleCloseManualOrderModal}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={handleCloseManualOrderModal}>
|
||||
{t('cryptoTailMonitor.manualOrder.cancel')}
|
||||
</Button>,
|
||||
<Button
|
||||
key="confirm"
|
||||
type="primary"
|
||||
onClick={handleManualOrder}
|
||||
loading={ordering}
|
||||
style={
|
||||
manualOrderModal.direction === 'UP'
|
||||
? { backgroundColor: '#1890ff', borderColor: '#1890ff' }
|
||||
: { backgroundColor: '#fa8c16', borderColor: '#fa8c16' }
|
||||
}
|
||||
>
|
||||
{t('cryptoTailMonitor.manualOrder.confirm')}
|
||||
</Button>
|
||||
]}
|
||||
width={480}
|
||||
>
|
||||
{initData && (
|
||||
<Space direction="vertical" style={{ width: '100%' }} size={16}>
|
||||
<Row gutter={[12, 8]}>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.marketTitle')}
|
||||
</Text>
|
||||
<Text>{pushData?.marketTitle ?? initData.marketTitle}</Text>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.direction')}
|
||||
</Text>
|
||||
<Text
|
||||
strong
|
||||
style={{
|
||||
color: manualOrderModal.direction === 'UP' ? '#1890ff' : '#fa8c16'
|
||||
}}
|
||||
>
|
||||
{manualOrderModal.direction === 'UP'
|
||||
? t('cryptoTailMonitor.manualOrder.directionUp')
|
||||
: t('cryptoTailMonitor.manualOrder.directionDown')}
|
||||
</Text>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.availableBalance')}
|
||||
</Text>
|
||||
<Text strong style={{ fontSize: 16, color: '#52c41a' }}>
|
||||
{manualOrderModal.availableBalance ? formatNumber(manualOrderModal.availableBalance, 2) : '-'} {t('cryptoTailMonitor.manualOrder.orderUnit')}
|
||||
</Text>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.orderPrice')} ({t('cryptoTailMonitor.manualOrder.orderUnit')})
|
||||
</Text>
|
||||
<Space.Compact style={{ width: '100%' }}>
|
||||
<InputNumber
|
||||
style={{ width: '100%' }}
|
||||
value={manualOrderModal.price ? parseFloat(manualOrderModal.price) : undefined}
|
||||
onChange={handlePriceChange}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.0001}
|
||||
precision={4}
|
||||
placeholder="0.0000"
|
||||
/>
|
||||
<Button onClick={handleFetchLatestPrice} icon={<SyncOutlined />}>
|
||||
{t('cryptoTailMonitor.manualOrder.fetchLatestPrice')}
|
||||
</Button>
|
||||
</Space.Compact>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.orderSize')} ({t('cryptoTailMonitor.manualOrder.sizeUnit')})
|
||||
</Text>
|
||||
<Space.Compact style={{ width: '100%' }}>
|
||||
<InputNumber
|
||||
style={{ width: '100%' }}
|
||||
value={manualOrderModal.size ? parseFloat(manualOrderModal.size) : undefined}
|
||||
onChange={handleSizeChange}
|
||||
min={1}
|
||||
precision={2}
|
||||
placeholder="1"
|
||||
/>
|
||||
<Button onClick={handleMaxSize} type="primary" ghost>
|
||||
{t('cryptoTailMonitor.manualOrder.maxSize')}
|
||||
</Button>
|
||||
</Space.Compact>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.totalAmount')}
|
||||
</Text>
|
||||
<Text strong style={{ fontSize: 16 }}>
|
||||
{manualOrderModal.totalAmount} {t('cryptoTailMonitor.manualOrder.orderUnit')}
|
||||
</Text>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.account')}
|
||||
</Text>
|
||||
<Text>{initData.accountName || `#${initData.accountId}`}</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
</Space>
|
||||
)}
|
||||
</Modal>
|
||||
)}
|
||||
|
||||
{/* 移动端 BottomSheet 弹窗 */}
|
||||
{isMobile && (
|
||||
<AntdMobilePopup
|
||||
visible={manualOrderModal.visible}
|
||||
onMaskClick={handleCloseManualOrderModal}
|
||||
onClose={handleCloseManualOrderModal}
|
||||
bodyStyle={{
|
||||
borderRadius: '16px 16px 0 0',
|
||||
padding: '12px 16px',
|
||||
maxHeight: '70vh',
|
||||
overflow: 'auto'
|
||||
}}
|
||||
>
|
||||
{initData && (
|
||||
<div>
|
||||
{/* 标题栏 */}
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: 12
|
||||
}}>
|
||||
<Text strong style={{ fontSize: 16 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.confirmTitle')}
|
||||
</Text>
|
||||
<Button type="text" onClick={handleCloseManualOrderModal} style={{ padding: 0, fontSize: 18 }}>
|
||||
✕
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* 市场信息 + 方向 + 余额(一行) */}
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10, flexWrap: 'wrap', gap: 8 }}>
|
||||
<div style={{ flex: '1 1 auto', minWidth: 0 }}>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>{t('cryptoTailMonitor.manualOrder.marketTitle')}: </Text>
|
||||
<Text style={{ fontSize: 13 }} ellipsis>{pushData?.marketTitle ?? initData.marketTitle}</Text>
|
||||
</div>
|
||||
<Text
|
||||
strong
|
||||
style={{
|
||||
fontSize: 14,
|
||||
color: manualOrderModal.direction === 'UP' ? '#1890ff' : '#fa8c16'
|
||||
}}
|
||||
>
|
||||
@@ -1260,22 +1408,26 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
? t('cryptoTailMonitor.manualOrder.directionUp')
|
||||
: t('cryptoTailMonitor.manualOrder.directionDown')}
|
||||
</Text>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.availableBalance')}
|
||||
</div>
|
||||
|
||||
{/* 可用余额 */}
|
||||
<div style={{ marginBottom: 10 }}>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.availableBalance')}:
|
||||
</Text>
|
||||
<Text strong style={{ fontSize: 16, color: '#52c41a' }}>
|
||||
<Text strong style={{ fontSize: 14, color: '#52c41a', marginLeft: 4 }}>
|
||||
{manualOrderModal.availableBalance ? formatNumber(manualOrderModal.availableBalance, 2) : '-'} {t('cryptoTailMonitor.manualOrder.orderUnit')}
|
||||
</Text>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.orderPrice')} ({t('cryptoTailMonitor.manualOrder.orderUnit')})
|
||||
</div>
|
||||
|
||||
{/* 价格输入 */}
|
||||
<div style={{ marginBottom: 10 }}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 2, fontSize: 12 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.orderPrice')}
|
||||
</Text>
|
||||
<Space.Compact style={{ width: '100%' }}>
|
||||
<InputNumber
|
||||
style={{ width: '100%' }}
|
||||
style={{ width: '100%', height: 36 }}
|
||||
value={manualOrderModal.price ? parseFloat(manualOrderModal.price) : undefined}
|
||||
onChange={handlePriceChange}
|
||||
min={0}
|
||||
@@ -1284,47 +1436,65 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
precision={4}
|
||||
placeholder="0.0000"
|
||||
/>
|
||||
<Button onClick={handleFetchLatestPrice} icon={<SyncOutlined />}>
|
||||
<Button onClick={handleFetchLatestPrice} icon={<SyncOutlined />} style={{ height: 36, fontSize: 12 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.fetchLatestPrice')}
|
||||
</Button>
|
||||
</Space.Compact>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.orderSize')} ({t('cryptoTailMonitor.manualOrder.sizeUnit')})
|
||||
</div>
|
||||
|
||||
{/* 数量输入 */}
|
||||
<div style={{ marginBottom: 10 }}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 2, fontSize: 12 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.orderSize')}
|
||||
</Text>
|
||||
<Space.Compact style={{ width: '100%' }}>
|
||||
<InputNumber
|
||||
style={{ width: '100%' }}
|
||||
style={{ width: '100%', height: 36 }}
|
||||
value={manualOrderModal.size ? parseFloat(manualOrderModal.size) : undefined}
|
||||
onChange={handleSizeChange}
|
||||
min={1}
|
||||
precision={2}
|
||||
placeholder="1"
|
||||
/>
|
||||
<Button onClick={handleMaxSize} type="primary" ghost>
|
||||
<Button onClick={handleMaxSize} type="primary" ghost style={{ height: 36, fontSize: 12 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.maxSize')}
|
||||
</Button>
|
||||
</Space.Compact>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.totalAmount')}
|
||||
</Text>
|
||||
<Text strong style={{ fontSize: 16 }}>
|
||||
{manualOrderModal.totalAmount} {t('cryptoTailMonitor.manualOrder.orderUnit')}
|
||||
</Text>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text type="secondary" style={{ display: 'block', marginBottom: 4 }}>
|
||||
{t('cryptoTailMonitor.manualOrder.account')}
|
||||
</Text>
|
||||
<Text>{initData.accountName || `#${initData.accountId}`}</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
</Space>
|
||||
)}
|
||||
</Modal>
|
||||
</div>
|
||||
|
||||
{/* 总金额 + 账户(一行) */}
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
|
||||
<div>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>{t('cryptoTailMonitor.manualOrder.totalAmount')}: </Text>
|
||||
<Text strong style={{ fontSize: 16, marginLeft: 4 }}>
|
||||
{manualOrderModal.totalAmount} {t('cryptoTailMonitor.manualOrder.orderUnit')}
|
||||
</Text>
|
||||
</div>
|
||||
<div>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>{t('cryptoTailMonitor.manualOrder.account')}: </Text>
|
||||
<Text style={{ fontSize: 12 }}>{initData.accountName || `#${initData.accountId}`}</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 确认按钮 */}
|
||||
<Button
|
||||
type="primary"
|
||||
block
|
||||
onClick={handleManualOrder}
|
||||
loading={ordering}
|
||||
style={{
|
||||
height: 44,
|
||||
borderRadius: 8,
|
||||
backgroundColor: manualOrderModal.direction === 'UP' ? '#1890ff' : '#fa8c16',
|
||||
borderColor: manualOrderModal.direction === 'UP' ? '#1890ff' : '#fa8c16'
|
||||
}}
|
||||
>
|
||||
{t('cryptoTailMonitor.manualOrder.confirm')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</AntdMobilePopup>
|
||||
)}
|
||||
|
||||
{/* 移动端底部悬浮按钮 */}
|
||||
{isMobile && (
|
||||
@@ -1351,7 +1521,7 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
loading={ordering}
|
||||
style={{ flex: 1, backgroundColor: '#1890ff', borderColor: '#1890ff', height: 44, borderRadius: '6px 0 0 6px' }}
|
||||
>
|
||||
{t('cryptoTailMonitor.manualOrder.buttonUp')}
|
||||
{t('cryptoTailMonitor.manualOrder.buttonUp')} {pushData?.currentPriceUp ? `(${formatNumber(pushData.currentPriceUp, 2)})` : ''}
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
@@ -1361,7 +1531,7 @@ const CryptoTailMonitor: React.FC = () => {
|
||||
loading={ordering}
|
||||
style={{ flex: 1, backgroundColor: '#fa8c16', borderColor: '#fa8c16', height: 44, borderRadius: '0 6px 6px 0' }}
|
||||
>
|
||||
{t('cryptoTailMonitor.manualOrder.buttonDown')}
|
||||
{t('cryptoTailMonitor.manualOrder.buttonDown')} {pushData?.currentPriceDown ? `(${formatNumber(pushData.currentPriceDown, 2)})` : ''}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user