@@ -80,6 +80,7 @@ def add_position(
|
|||||||
round_id: int,
|
round_id: int,
|
||||||
open_price: int = Form(...),
|
open_price: int = Form(...),
|
||||||
amp_threshold: int = Form(...),
|
amp_threshold: int = Form(...),
|
||||||
|
lock_price: str = Form(""),
|
||||||
hands: int = Form(1),
|
hands: int = Form(1),
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
):
|
):
|
||||||
@@ -87,12 +88,12 @@ def add_position(
|
|||||||
if not r or r.status != "active":
|
if not r or r.status != "active":
|
||||||
return RedirectResponse("/positions/?error=轮次不存在或已结束", status_code=303)
|
return RedirectResponse("/positions/?error=轮次不存在或已结束", status_code=303)
|
||||||
|
|
||||||
lock_price = open_price + amp_threshold
|
final_lock = int(lock_price) if lock_price else open_price + amp_threshold
|
||||||
p = Position(
|
p = Position(
|
||||||
round_id=r.id,
|
round_id=r.id,
|
||||||
open_price=open_price,
|
open_price=open_price,
|
||||||
amp_threshold=amp_threshold,
|
amp_threshold=amp_threshold,
|
||||||
lock_price=lock_price,
|
lock_price=final_lock,
|
||||||
hands=hands,
|
hands=hands,
|
||||||
opened_at=date.today(),
|
opened_at=date.today(),
|
||||||
)
|
)
|
||||||
@@ -102,9 +103,15 @@ def add_position(
|
|||||||
|
|
||||||
|
|
||||||
@router.post("/{position_id}/lock")
|
@router.post("/{position_id}/lock")
|
||||||
def lock_position(position_id: int, db: Session = Depends(get_db)):
|
def lock_position(
|
||||||
|
position_id: int,
|
||||||
|
lock_price: str = Form(""),
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
):
|
||||||
p = db.query(Position).filter(Position.id == position_id).first()
|
p = db.query(Position).filter(Position.id == position_id).first()
|
||||||
if p and p.locked_count < p.hands:
|
if p and p.locked_count < p.hands:
|
||||||
|
if lock_price:
|
||||||
|
p.lock_price = int(lock_price)
|
||||||
p.locked_count += 1
|
p.locked_count += 1
|
||||||
db.commit()
|
db.commit()
|
||||||
return RedirectResponse("/positions/", status_code=303)
|
return RedirectResponse("/positions/", status_code=303)
|
||||||
@@ -119,6 +126,19 @@ def unlock_position(position_id: int, db: Session = Depends(get_db)):
|
|||||||
return RedirectResponse("/positions/", status_code=303)
|
return RedirectResponse("/positions/", status_code=303)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{position_id}/update-lock-price")
|
||||||
|
def update_lock_price(
|
||||||
|
position_id: int,
|
||||||
|
lock_price: int = Form(...),
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
):
|
||||||
|
p = db.query(Position).filter(Position.id == position_id).first()
|
||||||
|
if p and p.locked_count == 0:
|
||||||
|
p.lock_price = lock_price
|
||||||
|
db.commit()
|
||||||
|
return RedirectResponse("/positions/", status_code=303)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/{round_id}/close")
|
@router.post("/{round_id}/close")
|
||||||
def close_round(
|
def close_round(
|
||||||
request: Request,
|
request: Request,
|
||||||
|
|||||||
@@ -145,10 +145,9 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div style="display:flex;gap:6px;justify-content:center;">
|
<div style="display:flex;gap:6px;justify-content:center;">
|
||||||
<form method="post" action="/positions/{{ p.id }}/lock" style="display:inline;">
|
|
||||||
<button style="background:var(--warn-bg);color:var(--warn-fg);border:1px solid var(--warn);padding:2px 8px;border-radius:4px;cursor:pointer;font-size:0.75rem;font-weight:600;"
|
<button style="background:var(--warn-bg);color:var(--warn-fg);border:1px solid var(--warn);padding:2px 8px;border-radius:4px;cursor:pointer;font-size:0.75rem;font-weight:600;"
|
||||||
{% if p.locked_count >= p.hands %}disabled style="opacity:0.4;cursor:default;"{% endif %}>锁</button>
|
{% if p.locked_count >= p.hands %}disabled style="opacity:0.4;cursor:default;"{% endif %}
|
||||||
</form>
|
onclick="showLockConfirm({{ p.id }}, {{ p.lock_price }})">锁</button>
|
||||||
<form method="post" action="/positions/{{ p.id }}/unlock" style="display:inline;">
|
<form method="post" action="/positions/{{ p.id }}/unlock" style="display:inline;">
|
||||||
<button style="background:var(--surface);color:var(--sub);border:1px solid var(--border);padding:2px 8px;border-radius:4px;cursor:pointer;font-size:0.75rem;"
|
<button style="background:var(--surface);color:var(--sub);border:1px solid var(--border);padding:2px 8px;border-radius:4px;cursor:pointer;font-size:0.75rem;"
|
||||||
{% if p.locked_count == 0 %}disabled style="opacity:0.4;cursor:default;"{% endif %}>撤</button>
|
{% if p.locked_count == 0 %}disabled style="opacity:0.4;cursor:default;"{% endif %}>撤</button>
|
||||||
@@ -181,8 +180,40 @@ function filterContracts() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function showLockConfirm(pid, lockPrice) {
|
||||||
|
document.getElementById('lockPid').value = pid;
|
||||||
|
document.getElementById('lockPriceInput').value = lockPrice;
|
||||||
|
document.getElementById('lockModal').style.display = 'block';
|
||||||
|
document.getElementById('lockModalOverlay').style.display = 'block';
|
||||||
|
document.getElementById('lockPriceInput').focus();
|
||||||
|
}
|
||||||
|
function hideLockModal() {
|
||||||
|
document.getElementById('lockModal').style.display = 'none';
|
||||||
|
document.getElementById('lockModalOverlay').style.display = 'none';
|
||||||
|
}
|
||||||
|
function doLock() {
|
||||||
|
var pid = document.getElementById('lockPid').value;
|
||||||
|
var fd = new FormData();
|
||||||
|
fd.append('lock_price', document.getElementById('lockPriceInput').value);
|
||||||
|
fetch('/positions/' + pid + '/lock', {method:'POST', body:fd})
|
||||||
|
.then(function() { location.reload(); });
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<div id="lockModalOverlay" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.35);z-index:149;" onclick="hideLockModal()"></div>
|
||||||
|
<div id="lockModal" style="display:none;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:24px;z-index:150;width:300px;max-width:90vw;">
|
||||||
|
<h3 style="margin-bottom:16px;">确认锁仓</h3>
|
||||||
|
<input type="hidden" id="lockPid">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>锁仓价位</label>
|
||||||
|
<input type="number" id="lockPriceInput" required style="font-size:1rem;text-align:center;font-weight:600;color:var(--danger-fg);">
|
||||||
|
</div>
|
||||||
|
<div style="display:flex;gap:10px;justify-content:flex-end;margin-top:8px;">
|
||||||
|
<button class="btn" style="background:var(--th-bg);color:var(--fg);" onclick="hideLockModal()">取消</button>
|
||||||
|
<button class="btn" style="background:var(--warn);color:#fff;" onclick="doLock()">确认锁仓</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="confirmOverlay" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.35);z-index:199;" onclick="hideConfirm()"></div>
|
<div id="confirmOverlay" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.35);z-index:199;" onclick="hideConfirm()"></div>
|
||||||
<div id="confirmBox" style="display:none;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:28px 32px;z-index:200;text-align:center;max-width:90vw;">
|
<div id="confirmBox" style="display:none;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:28px 32px;z-index:200;text-align:center;max-width:90vw;">
|
||||||
<p id="confirmMsg" style="font-size:0.95rem;margin-bottom:20px;"></p>
|
<p id="confirmMsg" style="font-size:0.95rem;margin-bottom:20px;"></p>
|
||||||
|
|||||||
Reference in New Issue
Block a user