mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-07 10:16:38 +08:00
fix: improve batch tunnel migration and simplify batch action labels
This commit is contained in:
@@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
active: true
|
|
||||||
iteration: 1
|
|
||||||
max_iterations: 100
|
|
||||||
completion_promise: "DONE"
|
|
||||||
started_at: "2026-01-24T05:20:50.887Z"
|
|
||||||
session_id: "ses_41192b7d7ffewFHxf1dDS7ESHO"
|
|
||||||
---
|
|
||||||
Complete the task as instructed
|
|
||||||
@@ -1385,6 +1385,15 @@ public class ForwardServiceImpl extends ServiceImpl<ForwardMapper, Forward> impl
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<ForwardPort> existingForwardPorts = forwardPortService.list(
|
||||||
|
new QueryWrapper<ForwardPort>().eq("forward_id", forwardId).orderByAsc("id")
|
||||||
|
);
|
||||||
|
Integer originalInPort = existingForwardPorts.stream()
|
||||||
|
.map(ForwardPort::getPort)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
Tunnel oldTunnel = validateTunnel(forward.getTunnelId());
|
Tunnel oldTunnel = validateTunnel(forward.getTunnelId());
|
||||||
if (oldTunnel != null) {
|
if (oldTunnel != null) {
|
||||||
UserTunnel oldUserTunnel = null;
|
UserTunnel oldUserTunnel = null;
|
||||||
@@ -1424,7 +1433,7 @@ public class ForwardServiceImpl extends ServiceImpl<ForwardMapper, Forward> impl
|
|||||||
List<ChainTunnel> newChainTunnels = chainTunnelService.list(
|
List<ChainTunnel> newChainTunnels = chainTunnelService.list(
|
||||||
new QueryWrapper<ChainTunnel>().eq("tunnel_id", targetTunnel.getId()).eq("chain_type", 1)
|
new QueryWrapper<ChainTunnel>().eq("tunnel_id", targetTunnel.getId()).eq("chain_type", 1)
|
||||||
);
|
);
|
||||||
List<ChainTunnel> chainTunnelsWithPort = get_port(newChainTunnels, null, forwardId);
|
List<ChainTunnel> chainTunnelsWithPort = allocatePortsForBatchTunnelChange(newChainTunnels, originalInPort, forwardId);
|
||||||
|
|
||||||
for (ChainTunnel chainTunnel : chainTunnelsWithPort) {
|
for (ChainTunnel chainTunnel : chainTunnelsWithPort) {
|
||||||
ForwardPort forwardPort = new ForwardPort();
|
ForwardPort forwardPort = new ForwardPort();
|
||||||
@@ -1450,4 +1459,23 @@ public class ForwardServiceImpl extends ServiceImpl<ForwardMapper, Forward> impl
|
|||||||
return R.ok(result);
|
return R.ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<ChainTunnel> allocatePortsForBatchTunnelChange(List<ChainTunnel> newChainTunnels, Integer originalInPort, Long forwardId) {
|
||||||
|
if (originalInPort == null) {
|
||||||
|
return get_port(newChainTunnels, null, forwardId);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return get_port(newChainTunnels, originalInPort, forwardId);
|
||||||
|
} catch (RuntimeException originalPortError) {
|
||||||
|
try {
|
||||||
|
return get_port(newChainTunnels, null, forwardId);
|
||||||
|
} catch (RuntimeException autoAllocateError) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"原入口端口 " + originalInPort + " 在目标隧道不可用,自动分配新端口也失败: " + autoAllocateError.getMessage(),
|
||||||
|
autoAllocateError
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1315,10 +1315,10 @@ export default function ForwardPage() {
|
|||||||
setBatchDeleteModalOpen(false);
|
setBatchDeleteModalOpen(false);
|
||||||
loadData(false);
|
loadData(false);
|
||||||
} else {
|
} else {
|
||||||
toast.error(res.msg || "批量删除失败");
|
toast.error(res.msg || "删除失败");
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
toast.error(e.message || "批量删除失败");
|
toast.error(e.message || "删除失败");
|
||||||
} finally {
|
} finally {
|
||||||
setBatchLoading(false);
|
setBatchLoading(false);
|
||||||
}
|
}
|
||||||
@@ -1340,10 +1340,10 @@ export default function ForwardPage() {
|
|||||||
setSelectMode(false);
|
setSelectMode(false);
|
||||||
loadData(false);
|
loadData(false);
|
||||||
} else {
|
} else {
|
||||||
toast.error(res.msg || "批量重新下发失败");
|
toast.error(res.msg || "下发失败");
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
toast.error(e.message || "批量重新下发失败");
|
toast.error(e.message || "下发失败");
|
||||||
} finally {
|
} finally {
|
||||||
setBatchLoading(false);
|
setBatchLoading(false);
|
||||||
}
|
}
|
||||||
@@ -1370,10 +1370,10 @@ export default function ForwardPage() {
|
|||||||
setBatchTargetTunnelId(null);
|
setBatchTargetTunnelId(null);
|
||||||
loadData(false);
|
loadData(false);
|
||||||
} else {
|
} else {
|
||||||
toast.error(res.msg || "批量换隧道失败");
|
toast.error(res.msg || "隧道失败");
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
toast.error(e.message || "批量换隧道失败");
|
toast.error(e.message || "隧道失败");
|
||||||
} finally {
|
} finally {
|
||||||
setBatchLoading(false);
|
setBatchLoading(false);
|
||||||
}
|
}
|
||||||
@@ -1786,7 +1786,7 @@ export default function ForwardPage() {
|
|||||||
color={selectMode ? "warning" : "default"}
|
color={selectMode ? "warning" : "default"}
|
||||||
onPress={toggleSelectMode}
|
onPress={toggleSelectMode}
|
||||||
>
|
>
|
||||||
{selectMode ? "退出选择" : "批量操作"}
|
{selectMode ? "退出" : "批量"}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button size="sm" variant="flat" color="primary" onPress={handleAdd}>
|
<Button size="sm" variant="flat" color="primary" onPress={handleAdd}>
|
||||||
@@ -1802,7 +1802,7 @@ export default function ForwardPage() {
|
|||||||
全选
|
全选
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="sm" variant="flat" onPress={deselectAll}>
|
<Button size="sm" variant="flat" onPress={deselectAll}>
|
||||||
取消全选
|
清空
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -1810,7 +1810,7 @@ export default function ForwardPage() {
|
|||||||
variant="flat"
|
variant="flat"
|
||||||
onPress={() => setBatchDeleteModalOpen(true)}
|
onPress={() => setBatchDeleteModalOpen(true)}
|
||||||
>
|
>
|
||||||
批量删除
|
删除
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -1819,7 +1819,7 @@ export default function ForwardPage() {
|
|||||||
onPress={handleBatchRedeploy}
|
onPress={handleBatchRedeploy}
|
||||||
isLoading={batchLoading}
|
isLoading={batchLoading}
|
||||||
>
|
>
|
||||||
批量重新下发
|
下发
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -1827,7 +1827,7 @@ export default function ForwardPage() {
|
|||||||
variant="flat"
|
variant="flat"
|
||||||
onPress={() => setBatchChangeTunnelModalOpen(true)}
|
onPress={() => setBatchChangeTunnelModalOpen(true)}
|
||||||
>
|
>
|
||||||
批量换隧道
|
隧道
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -3069,7 +3069,7 @@ export default function ForwardPage() {
|
|||||||
<ModalContent>
|
<ModalContent>
|
||||||
{(onClose) => (
|
{(onClose) => (
|
||||||
<>
|
<>
|
||||||
<ModalHeader>确认批量删除</ModalHeader>
|
<ModalHeader>确认删除</ModalHeader>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<p>确定要删除选中的 {selectedIds.size} 项转发吗?此操作不可撤销。</p>
|
<p>确定要删除选中的 {selectedIds.size} 项转发吗?此操作不可撤销。</p>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
@@ -3095,7 +3095,7 @@ export default function ForwardPage() {
|
|||||||
<ModalContent>
|
<ModalContent>
|
||||||
{(onClose) => (
|
{(onClose) => (
|
||||||
<>
|
<>
|
||||||
<ModalHeader>批量换隧道</ModalHeader>
|
<ModalHeader>隧道</ModalHeader>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<p className="mb-4">将选中的 {selectedIds.size} 项转发迁移到新隧道:</p>
|
<p className="mb-4">将选中的 {selectedIds.size} 项转发迁移到新隧道:</p>
|
||||||
<Select
|
<Select
|
||||||
|
|||||||
@@ -939,7 +939,7 @@ export default function NodePage() {
|
|||||||
setBatchDeleteModalOpen(false);
|
setBatchDeleteModalOpen(false);
|
||||||
setSelectMode(false);
|
setSelectMode(false);
|
||||||
} else {
|
} else {
|
||||||
toast.error(res.msg || "批量删除失败");
|
toast.error(res.msg || "删除失败");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast.error("网络错误,请重试");
|
toast.error("网络错误,请重试");
|
||||||
@@ -1041,7 +1041,7 @@ export default function NodePage() {
|
|||||||
全选
|
全选
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="sm" variant="flat" onPress={deselectAll}>
|
<Button size="sm" variant="flat" onPress={deselectAll}>
|
||||||
取消全选
|
清空
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
color="danger"
|
color="danger"
|
||||||
@@ -1049,7 +1049,7 @@ export default function NodePage() {
|
|||||||
variant="flat"
|
variant="flat"
|
||||||
onPress={() => setBatchDeleteModalOpen(true)}
|
onPress={() => setBatchDeleteModalOpen(true)}
|
||||||
>
|
>
|
||||||
批量删除
|
删除
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1814,7 +1814,7 @@ export default function NodePage() {
|
|||||||
{(onClose) => (
|
{(onClose) => (
|
||||||
<>
|
<>
|
||||||
<ModalHeader className="flex flex-col gap-1">
|
<ModalHeader className="flex flex-col gap-1">
|
||||||
<h2 className="text-xl font-bold">确认批量删除</h2>
|
<h2 className="text-xl font-bold">确认删除</h2>
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -696,10 +696,10 @@ export default function TunnelPage() {
|
|||||||
setBatchDeleteModalOpen(false);
|
setBatchDeleteModalOpen(false);
|
||||||
loadData();
|
loadData();
|
||||||
} else {
|
} else {
|
||||||
toast.error(res.msg || "批量删除失败");
|
toast.error(res.msg || "删除失败");
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
toast.error(e.message || "批量删除失败");
|
toast.error(e.message || "删除失败");
|
||||||
} finally {
|
} finally {
|
||||||
setBatchLoading(false);
|
setBatchLoading(false);
|
||||||
}
|
}
|
||||||
@@ -721,10 +721,10 @@ export default function TunnelPage() {
|
|||||||
setSelectMode(false);
|
setSelectMode(false);
|
||||||
loadData();
|
loadData();
|
||||||
} else {
|
} else {
|
||||||
toast.error(res.msg || "批量重新下发失败");
|
toast.error(res.msg || "下发失败");
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
toast.error(e.message || "批量重新下发失败");
|
toast.error(e.message || "下发失败");
|
||||||
} finally {
|
} finally {
|
||||||
setBatchLoading(false);
|
setBatchLoading(false);
|
||||||
}
|
}
|
||||||
@@ -845,7 +845,7 @@ export default function TunnelPage() {
|
|||||||
color={selectMode ? "warning" : "default"}
|
color={selectMode ? "warning" : "default"}
|
||||||
onPress={toggleSelectMode}
|
onPress={toggleSelectMode}
|
||||||
>
|
>
|
||||||
{selectMode ? "退出选择" : "批量操作"}
|
{selectMode ? "退出" : "批量"}
|
||||||
</Button>
|
</Button>
|
||||||
<Button color="primary" size="sm" variant="flat" onPress={handleAdd}>
|
<Button color="primary" size="sm" variant="flat" onPress={handleAdd}>
|
||||||
新增
|
新增
|
||||||
@@ -860,7 +860,7 @@ export default function TunnelPage() {
|
|||||||
全选
|
全选
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="sm" variant="flat" onPress={deselectAll}>
|
<Button size="sm" variant="flat" onPress={deselectAll}>
|
||||||
取消全选
|
清空
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -868,7 +868,7 @@ export default function TunnelPage() {
|
|||||||
variant="flat"
|
variant="flat"
|
||||||
onPress={() => setBatchDeleteModalOpen(true)}
|
onPress={() => setBatchDeleteModalOpen(true)}
|
||||||
>
|
>
|
||||||
批量删除
|
删除
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -877,7 +877,7 @@ export default function TunnelPage() {
|
|||||||
onPress={handleBatchRedeploy}
|
onPress={handleBatchRedeploy}
|
||||||
isLoading={batchLoading}
|
isLoading={batchLoading}
|
||||||
>
|
>
|
||||||
批量重新下发
|
下发
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -2514,7 +2514,7 @@ export default function TunnelPage() {
|
|||||||
<ModalContent>
|
<ModalContent>
|
||||||
{(onClose) => (
|
{(onClose) => (
|
||||||
<>
|
<>
|
||||||
<ModalHeader>确认批量删除</ModalHeader>
|
<ModalHeader>确认删除</ModalHeader>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<p>确定要删除选中的 {selectedIds.size} 项隧道吗?此操作不可撤销,相关转发也将被删除。</p>
|
<p>确定要删除选中的 {selectedIds.size} 项隧道吗?此操作不可撤销,相关转发也将被删除。</p>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|||||||
Reference in New Issue
Block a user