feat(UI): 交易记录归属分配改为 Modal 弹窗,行内只留精简态
This commit is contained in:
@@ -505,43 +505,23 @@ function OrderRows({ order, expanded, onToggle, targets, loadTargets, saveSegmen
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* R-018 归属单元格:展示段 chips;点开进入份额分配器(AttributionEditor)。
|
* R-018 归属单元格(行内精简态):只显示段 chips / 未关联 + 剩余提示 + 一个入口按钮。
|
||||||
* - 已关联段:策略名 + 量(段 chip);未关联(余额 > 0 且无段)显示「未关联」
|
* 份额分配操作在 AttributionModal(弹窗)中完成 —— 不在表格行内堆大量控件。
|
||||||
* - 点「分配」→ 打开编辑器(加载 targets 惰性)
|
|
||||||
*/
|
*/
|
||||||
function AttributionCell({ order, segments, totalSeg, targets, loadTargets, saveSegments, onNotice }) {
|
function AttributionCell({ order, segments, totalSeg, targets, loadTargets, saveSegments, onNotice }) {
|
||||||
const [editing, setEditing] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const hasSeg = (segments ?? []).length > 0;
|
const hasSeg = (segments ?? []).length > 0;
|
||||||
const aggVolume = Number(order.aggVolume ?? order.tradedVolume ?? 0);
|
const aggVolume = Number(order.aggVolume ?? order.tradedVolume ?? 0);
|
||||||
const leftover = Math.max(0, aggVolume - totalSeg); // 未分配余额(今日实时 aggVolume=已成交量;历史 aggVolume 由 fills 聚合并)
|
const leftover = Math.max(0, aggVolume - totalSeg); // 未分配余额
|
||||||
|
|
||||||
const open = () => {
|
|
||||||
loadTargets();
|
|
||||||
setEditing(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (editing) {
|
|
||||||
return (
|
|
||||||
<AttributionEditor
|
|
||||||
order={order}
|
|
||||||
segments={segments}
|
|
||||||
leftover={leftover}
|
|
||||||
targets={targets}
|
|
||||||
saveSegments={saveSegments}
|
|
||||||
onDone={() => setEditing(false)}
|
|
||||||
onNotice={onNotice}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span style={{ display: 'inline-flex', flexDirection: 'column', alignItems: 'flex-start', gap: 2, minWidth: 120 }}>
|
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, minWidth: 110 }}>
|
||||||
{hasSeg ? (
|
{hasSeg ? (
|
||||||
<span style={{ display: 'flex', flexWrap: 'wrap', gap: 2 }}>
|
<span style={{ display: 'inline-flex', flexWrap: 'wrap', gap: 2 }}>
|
||||||
{(segments ?? []).map((s) => (
|
{(segments ?? []).map((s) => (
|
||||||
<span
|
<span
|
||||||
key={s.strategyId}
|
key={s.strategyId}
|
||||||
title={s.strategyName || s.strategyId}
|
title={(s.strategyName || s.strategyId) + ' · ' + fmtNum(s.volume, 0) + ' 股'}
|
||||||
style={{
|
style={{
|
||||||
fontSize: 11, padding: '1px 5px', borderRadius: 3,
|
fontSize: 11, padding: '1px 5px', borderRadius: 3,
|
||||||
border: '1px solid var(--dsw-alias-state-success-primary, #2e7d32)',
|
border: '1px solid var(--dsw-alias-state-success-primary, #2e7d32)',
|
||||||
@@ -549,7 +529,7 @@ function AttributionCell({ order, segments, totalSeg, targets, loadTargets, save
|
|||||||
background: 'color-mix(in srgb, var(--dsw-alias-state-success-primary, #2e7d32) 10%, var(--dsw-alias-bg-layer-1, #fff))',
|
background: 'color-mix(in srgb, var(--dsw-alias-state-success-primary, #2e7d32) 10%, var(--dsw-alias-bg-layer-1, #fff))',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{(s.strategyName || s.strategyId)}·{fmtNum(s.volume, 0)}
|
{s.strategyName || s.strategyId}
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
</span>
|
</span>
|
||||||
@@ -557,14 +537,17 @@ function AttributionCell({ order, segments, totalSeg, targets, loadTargets, save
|
|||||||
<span style={{ color: 'var(--dsw-alias-label-tertiary, #999)', fontSize: 12 }}>未关联</span>
|
<span style={{ color: 'var(--dsw-alias-label-tertiary, #999)', fontSize: 12 }}>未关联</span>
|
||||||
)}
|
)}
|
||||||
{leftover > 1e-9 && (
|
{leftover > 1e-9 && (
|
||||||
<span style={{ fontSize: 11, color: 'var(--dsw-alias-state-error-primary, #d32f2f)' }}>
|
<span
|
||||||
未分配剩余 {fmtNum(leftover, 0)} 股
|
style={{ fontSize: 11, color: 'var(--dsw-alias-state-error-primary, #d32f2f)', whiteSpace: 'nowrap' }}
|
||||||
|
title={'未分配剩余 ' + fmtNum(leftover, 0) + ' 股'}
|
||||||
|
>
|
||||||
|
剩{fmtNum(leftover, 0)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={open}
|
onClick={() => { loadTargets(); setOpen(true); }}
|
||||||
style={{
|
style={{
|
||||||
fontSize: 11, padding: '1px 8px', cursor: 'pointer', borderRadius: 3,
|
fontSize: 11, padding: '1px 8px', cursor: 'pointer', borderRadius: 3, whiteSpace: 'nowrap',
|
||||||
border: '1px solid var(--dsw-alias-border-l2, #ccc)',
|
border: '1px solid var(--dsw-alias-border-l2, #ccc)',
|
||||||
background: 'var(--dsw-alias-bg-layer-1, #fff)', color: 'var(--dsw-alias-label-primary, #333)',
|
background: 'var(--dsw-alias-bg-layer-1, #fff)', color: 'var(--dsw-alias-label-primary, #333)',
|
||||||
}}
|
}}
|
||||||
@@ -572,29 +555,42 @@ function AttributionCell({ order, segments, totalSeg, targets, loadTargets, save
|
|||||||
>
|
>
|
||||||
{hasSeg ? '调整' : '分配'}
|
{hasSeg ? '调整' : '分配'}
|
||||||
</button>
|
</button>
|
||||||
|
{open && (
|
||||||
|
<AttributionModal
|
||||||
|
order={order}
|
||||||
|
segments={segments}
|
||||||
|
aggVolume={aggVolume}
|
||||||
|
totalSeg={totalSeg}
|
||||||
|
leftover={leftover}
|
||||||
|
targets={targets}
|
||||||
|
saveSegments={saveSegments}
|
||||||
|
onClose={() => setOpen(false)}
|
||||||
|
onNotice={onNotice}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* R-018 份额分配器(编辑器):策略下拉 + 段量输入 + 段列表(可撤)。
|
* R-018 归属分配弹窗(Modal):居中遮罩 + 面板。
|
||||||
* - 余额 = 已成交量 − 已分配段和(默认输入 = 余额全量,可改小)
|
* - 面板:委托摘要(code/名称/方向/已成交量)+ 已分配段列表(每段可撤)+ 新增段(策略下拉 + 量输入,默认余额全量)
|
||||||
* - 每步操作(加段/撤段)即时 saveSegments(全量替换,原子)
|
* - 操作即时保存(setSegments 全量替换原子);顶部余额与状态实时反馈
|
||||||
*/
|
*/
|
||||||
function AttributionEditor({ order, segments, leftover, targets, saveSegments, onDone, onNotice }) {
|
function AttributionModal({ order, segments, aggVolume, totalSeg, leftover, targets, saveSegments, onClose, onNotice }) {
|
||||||
const list = (targets ?? []).length > 0 ? targets : null;
|
const list = (targets ?? []).length > 0 ? targets : null;
|
||||||
const [selStrategy, setSelStrategy] = useState('');
|
const [selStrategy, setSelStrategy] = useState('');
|
||||||
const [amount, setAmount] = useState('');
|
const [amount, setAmount] = useState('');
|
||||||
const [busy, setBusy] = useState(false);
|
const [busy, setBusy] = useState(false);
|
||||||
const aggVolume = Number(order.aggVolume ?? order.tradedVolume ?? 0);
|
|
||||||
const segs = Array.isArray(segments) ? segments : [];
|
const segs = Array.isArray(segments) ? segments : [];
|
||||||
const totalSeg = segs.reduce((s, x) => s + Number(x?.volume ?? 0), 0);
|
const total = segs.reduce((s, x) => s + Number(x?.volume ?? 0), 0);
|
||||||
const remaining = Math.max(0, aggVolume - totalSeg);
|
const remaining = Math.max(0, aggVolume - total);
|
||||||
|
const fullyAllocated = remaining <= 1e-9;
|
||||||
|
const amountHint = remaining > 0 ? String(remaining) : '';
|
||||||
|
|
||||||
const notice = (msg, isErr) => {
|
const notice = (msg, isErr) => {
|
||||||
onNotice?.(msg);
|
onNotice?.(msg);
|
||||||
if (isErr) setTimeout(() => onNotice?.(null), 3000);
|
setTimeout(() => onNotice?.(null), isErr ? 3000 : 2000);
|
||||||
else setTimeout(() => onNotice?.(null), 2000);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const run = async (nextSegments) => {
|
const run = async (nextSegments) => {
|
||||||
@@ -614,14 +610,10 @@ function AttributionEditor({ order, segments, leftover, targets, saveSegments, o
|
|||||||
const v = Number(amount);
|
const v = Number(amount);
|
||||||
if (!Number.isFinite(v) || v <= 0) { notice('请输入有效份额量', true); return; }
|
if (!Number.isFinite(v) || v <= 0) { notice('请输入有效份额量', true); return; }
|
||||||
if (v > remaining + 1e-9) { notice('份额量超过未分配余额 ' + fmtNum(remaining, 0), true); return; }
|
if (v > remaining + 1e-9) { notice('份额量超过未分配余额 ' + fmtNum(remaining, 0), true); return; }
|
||||||
// 卖出场景:若该策略无活动仓(activityShares=0 且方向 sell)→ 服务端会拒绝;这里给前端提示
|
|
||||||
const t = (targets ?? []).find((x) => x.strategyId === selStrategy);
|
const t = (targets ?? []).find((x) => x.strategyId === selStrategy);
|
||||||
const isSell = String(order.direction ?? '') === 'sell';
|
const isSell = String(order.direction ?? '') === 'sell';
|
||||||
if (isSell && t && !t.hasActiveHolding) {
|
if (isSell && t && !t.hasActiveHolding) { notice('该策略无此持仓可减(关联失败)', true); return; }
|
||||||
notice('该策略无此持仓可减(关联失败)', true);
|
// sell 且 activityShares < 输入量 → 自动截断为可容纳量(R4:自动截断续分)
|
||||||
return;
|
|
||||||
}
|
|
||||||
// sell 且 activityShares < amount → 自动截断为可容纳量(R4 老师拍板:自动截断续分)
|
|
||||||
let vol = v;
|
let vol = v;
|
||||||
if (isSell && t && t.hasActiveHolding && Number(t.activityShares) + 1e-9 < v) {
|
if (isSell && t && t.hasActiveHolding && Number(t.activityShares) + 1e-9 < v) {
|
||||||
vol = Number(t.activityShares);
|
vol = Number(t.activityShares);
|
||||||
@@ -629,75 +621,145 @@ function AttributionEditor({ order, segments, leftover, targets, saveSegments, o
|
|||||||
}
|
}
|
||||||
const merged = [...segs.filter((s) => s.strategyId !== selStrategy), { strategyId: selStrategy, volume: vol }];
|
const merged = [...segs.filter((s) => s.strategyId !== selStrategy), { strategyId: selStrategy, volume: vol }];
|
||||||
await run(merged);
|
await run(merged);
|
||||||
|
setAmount('');
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeSegment = async (strategyId) => {
|
const removeSegment = async (strategyId) => {
|
||||||
const merged = segs.filter((s) => s.strategyId !== strategyId);
|
await run(segs.filter((s) => s.strategyId !== strategyId));
|
||||||
await run(merged);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const clearAll = async () => {
|
const clearAll = async () => {
|
||||||
await run([]);
|
await run([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const amountDefaultHint = remaining > 0 ? String(remaining) : '';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span style={{ display: 'inline-flex', flexDirection: 'column', gap: 4, alignItems: 'flex-start', minWidth: 190 }}>
|
<div style={{
|
||||||
<div style={{ fontSize: 11, color: 'var(--dsw-alias-label-secondary, #666)' }}>
|
position: 'fixed', inset: 0, background: 'var(--dsw-alias-bg-mask-1, rgba(0,0,0,0.4))',
|
||||||
已成交量 {fmtNum(aggVolume, 0)} | 已分配 {fmtNum(totalSeg, 0)} | 余额 <span style={{ color: remaining > 1e-9 ? 'var(--dsw-alias-state-error-primary, #d32f2f)' : 'var(--dsw-alias-state-success-primary, #1b5e20)', fontWeight: 'bold' }}>{fmtNum(remaining, 0)}</span>
|
display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 10000,
|
||||||
</div>
|
}} onClick={() => !busy && onClose()}>
|
||||||
{(segs.length > 0) && (
|
<div
|
||||||
<span style={{ display: 'flex', flexWrap: 'wrap', gap: 2, alignItems: 'center' }}>
|
onClick={(e) => e.stopPropagation()}
|
||||||
{segs.map((s) => (
|
style={{
|
||||||
<span key={s.strategyId} style={{ display: 'inline-flex', alignItems: 'center', gap: 3, fontSize: 11, padding: '1px 5px', borderRadius: 3, border: '1px solid var(--dsw-alias-state-success-primary, #2e7d32)', color: 'var(--dsw-alias-state-success-primary, #1b5e20)' }}>
|
background: 'var(--dsw-alias-bg-layer-1, #fff)', borderRadius: 8,
|
||||||
{s.strategyName || s.strategyId}·{fmtNum(s.volume, 0)}
|
maxWidth: 480, width: '92%', maxHeight: '80vh', overflow: 'auto',
|
||||||
<span
|
boxShadow: '0 6px 24px rgba(0,0,0,0.18)',
|
||||||
title="撤销该段(逆操作账本)"
|
}}
|
||||||
onClick={() => !busy && removeSegment(s.strategyId)}
|
>
|
||||||
style={{ cursor: busy ? 'wait' : 'pointer', color: 'var(--dsw-alias-state-error-primary, #c62828)' }}
|
{/* 头部:委托摘要 + 关闭 */}
|
||||||
>✕</span>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '14px 18px', borderBottom: '1px solid var(--dsw-alias-border-l1, #eee)' }}>
|
||||||
|
<h3 style={{ margin: 0, fontSize: 15 }}>
|
||||||
|
<span style={directionStyle(order.direction)}>{directionText(order.direction)}</span>
|
||||||
|
{' '}{order.code} {order.name || ''}
|
||||||
|
<span style={{ marginLeft: 8, color: 'var(--dsw-alias-label-secondary, #666)', fontWeight: 400, fontSize: 12 }}>
|
||||||
|
委托 {order.orderId}
|
||||||
</span>
|
</span>
|
||||||
))}
|
</h3>
|
||||||
</span>
|
<button onClick={() => !busy && onClose()} disabled={busy} style={{ cursor: busy ? 'wait' : 'pointer', border: 'none', background: 'transparent', fontSize: 16, color: 'var(--dsw-alias-label-tertiary, #999)' }} title="关闭">✕</button>
|
||||||
)}
|
</div>
|
||||||
{list && list.length > 0 && remaining > 1e-9 && (
|
|
||||||
<span style={{ display: 'inline-flex', gap: 3, alignItems: 'center' }}>
|
{/* 余额统计行 */}
|
||||||
<select value={selStrategy} onChange={(e) => setSelStrategy(e.target.value)} style={{ fontSize: 11, padding: '1px 3px' }} title="选择归属策略">
|
<div style={{ padding: '12px 18px 4px', display: 'flex', gap: 16, flexWrap: 'wrap', fontSize: 13 }}>
|
||||||
<option value="">策略…</option>
|
<span>已成交量 <b>{fmtNum(aggVolume, 0)}</b></span>
|
||||||
{list.map((t) => (
|
<span>已分配 <b>{fmtNum(total, 0)}</b></span>
|
||||||
<option key={t.strategyId} value={t.strategyId}>
|
<span>
|
||||||
{t.strategyName || t.strategyId}{t.hasActiveHolding ? '(仓 ' + fmtNum(t.activityShares, 0) + ')' : ''}
|
待分配余额{' '}
|
||||||
</option>
|
<b style={{ color: fullyAllocated ? 'var(--dsw-alias-state-success-primary, #1b5e20)' : 'var(--dsw-alias-state-error-primary, #d32f2f)' }}>
|
||||||
))}
|
{fmtNum(remaining, 0)}
|
||||||
</select>
|
</b>
|
||||||
<input
|
</span>
|
||||||
type="number"
|
{fullyAllocated && <span style={{ color: 'var(--dsw-alias-state-success-primary, #1b5e20)', fontSize: 12 }}>已全部分配</span>}
|
||||||
min="1"
|
</div>
|
||||||
step={100}
|
|
||||||
value={amount}
|
{/* 已分配段列表 */}
|
||||||
placeholder={amountDefaultHint}
|
<div style={{ padding: '10px 18px' }}>
|
||||||
onChange={(e) => setAmount(e.target.value)}
|
{segs.length === 0 ? (
|
||||||
style={{ width: 70, padding: '1px 3px', fontSize: 11 }}
|
<div style={{ color: 'var(--dsw-alias-label-tertiary, #999)', fontSize: 13, padding: '4px 0' }}>
|
||||||
title="分配份额量(默认 = 未分配余额全量,可改小)"
|
尚未关联任何策略(可在下方选择策略并分配份额;关联会同步调整对应策略持仓)
|
||||||
/>
|
</div>
|
||||||
<button onClick={() => !busy && addSegment()} disabled={busy} style={{ fontSize: 11, padding: '1px 6px', cursor: 'pointer' }}>
|
) : (
|
||||||
分配
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
||||||
</button>
|
{segs.map((s) => (
|
||||||
</span>
|
<div key={s.strategyId} style={{ display: 'flex', alignItems: 'center', gap: 8, background: 'var(--dsw-alias-bg-layer-2, #fafafa)', borderRadius: 6, padding: '6px 10px' }}>
|
||||||
)}
|
<span style={{ flex: 1, fontSize: 13 }}>{s.strategyName || s.strategyId}</span>
|
||||||
{remaining <= 1e-9 && (
|
<span style={{ fontSize: 13, fontWeight: 'bold' }}>{fmtNum(s.volume, 0)} 股</span>
|
||||||
<span style={{ fontSize: 11, color: 'var(--dsw-alias-state-success-primary, #1b5e20)' }}>已全部分配</span>
|
<button
|
||||||
)}
|
onClick={() => !busy && removeSegment(s.strategyId)}
|
||||||
<span style={{ display: 'inline-flex', gap: 4 }}>
|
disabled={busy}
|
||||||
{segs.length > 0 && (
|
style={{ cursor: busy ? 'wait' : 'pointer', border: '1px solid var(--dsw-alias-border-l2, #ccc)', borderRadius: 4, background: 'var(--dsw-alias-bg-layer-1, #fff)', color: 'var(--dsw-alias-state-error-primary, #c62828)', fontSize: 11, padding: '2px 8px' }}
|
||||||
<button onClick={() => !busy && clearAll()} disabled={busy} style={{ fontSize: 11, padding: '1px 6px', cursor: 'pointer', color: 'var(--dsw-alias-state-error-primary, #c62828)' }}>
|
title="撤销该段(逆操作账本,恢复对应持仓份额)"
|
||||||
|
>
|
||||||
|
撤除
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 新增段 */}
|
||||||
|
<div style={{ padding: '6px 18px 14px', borderTop: '1px solid var(--dsw-alias-border-l1, #eee)' }}>
|
||||||
|
<div style={{ fontSize: 12, color: 'var(--dsw-alias-label-secondary, #666)', margin: '10px 0 6px' }}>
|
||||||
|
分配给策略{fullyAllocated ? '(已全部分配,如需调整请先撤除某段)' : ''}
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
|
||||||
|
<select
|
||||||
|
value={selStrategy}
|
||||||
|
onChange={(e) => setSelStrategy(e.target.value)}
|
||||||
|
style={{ fontSize: 13, padding: '4px 6px', border: '1px solid var(--dsw-alias-border-l2, #ccc)', borderRadius: 4, flex: 1, minWidth: 140 }}
|
||||||
|
disabled={fullyAllocated || busy}
|
||||||
|
title="选择归属策略(候选 = 全部策略;卖出需该策略有对应持仓)"
|
||||||
|
>
|
||||||
|
<option value="">选择策略…</option>
|
||||||
|
{(list ?? []).map((t) => (
|
||||||
|
<option key={t.strategyId} value={t.strategyId}>
|
||||||
|
{t.strategyName || t.strategyId}{t.hasActiveHolding ? '(当前仓 ' + fmtNum(t.activityShares, 0) + ')' : ''}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
step={100}
|
||||||
|
value={amount}
|
||||||
|
placeholder={amountHint || '股数'}
|
||||||
|
onChange={(e) => setAmount(e.target.value)}
|
||||||
|
disabled={fullyAllocated || busy}
|
||||||
|
style={{ width: 110, padding: '4px 6px', fontSize: 13, border: '1px solid var(--dsw-alias-border-l2, #ccc)', borderRadius: 4 }}
|
||||||
|
title={'分配份额量(默认 = 待分配余额 ' + fmtNum(remaining, 0) + ',可改小)'}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={addSegment}
|
||||||
|
disabled={fullyAllocated || busy}
|
||||||
|
style={{ cursor: busy ? 'wait' : 'pointer', padding: '4px 14px', fontSize: 13, border: 'none', borderRadius: 4, background: 'var(--dsw-alias-state-business-primary, #1565c0)', color: 'var(--dsw-alias-button-contrast-fill, #fff)' }}
|
||||||
|
>
|
||||||
|
分配
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{list === null && (
|
||||||
|
<div style={{ fontSize: 12, color: 'var(--dsw-alias-label-tertiary, #999)', marginTop: 6 }}>策略加载中…</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 底部操作 */}
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, padding: '10px 18px 14px', borderTop: '1px solid var(--dsw-alias-border-l1, #eee)' }}>
|
||||||
|
<button
|
||||||
|
onClick={() => !busy && clearAll()}
|
||||||
|
disabled={busy || segs.length === 0}
|
||||||
|
style={{ cursor: busy ? 'wait' : 'pointer', padding: '5px 12px', fontSize: 13, border: '1px solid var(--dsw-alias-state-error-primary, #c62828)', borderRadius: 4, background: 'var(--dsw-alias-bg-layer-1, #fff)', color: 'var(--dsw-alias-state-error-primary, #c62828)' }}
|
||||||
|
title="清除全部归属(逆操作:建仓买入段作废 / 卖出段恢复持仓)"
|
||||||
|
>
|
||||||
全部撤除
|
全部撤除
|
||||||
</button>
|
</button>
|
||||||
)}
|
<button
|
||||||
<button onClick={onDone} style={{ fontSize: 11, padding: '1px 6px', cursor: 'pointer' }}>完成</button>
|
onClick={() => !busy && onClose()}
|
||||||
</span>
|
disabled={busy}
|
||||||
</span>
|
style={{ cursor: busy ? 'wait' : 'pointer', padding: '5px 16px', fontSize: 13, border: '1px solid var(--dsw-alias-border-l2, #ccc)', borderRadius: 4, background: 'var(--dsw-alias-bg-layer-1, #fff)' }}
|
||||||
|
>
|
||||||
|
完成
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user