diff --git a/internal/web/actions/default/clusters/cluster/init.go b/internal/web/actions/default/clusters/cluster/init.go
index ca35f7ae..a8a8c56d 100644
--- a/internal/web/actions/default/clusters/cluster/init.go
+++ b/internal/web/actions/default/clusters/cluster/init.go
@@ -23,6 +23,7 @@ func init() {
GetPost("/createNode", new(CreateNodeAction)).
GetPost("/createBatch", new(CreateBatchAction)).
GetPost("/updateNodeSSH", new(UpdateNodeSSHAction)).
+ GetPost("/installManual", new(InstallManualAction)).
// 节点相关
Get("/node", new(node.NodeAction)).
diff --git a/internal/web/actions/default/clusters/cluster/installManual.go b/internal/web/actions/default/clusters/cluster/installManual.go
new file mode 100644
index 00000000..bbc29093
--- /dev/null
+++ b/internal/web/actions/default/clusters/cluster/installManual.go
@@ -0,0 +1,67 @@
+package cluster
+
+import (
+ "encoding/json"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/iwind/TeaGo/maps"
+)
+
+type InstallManualAction struct {
+ actionutils.ParentAction
+}
+
+func (this *InstallManualAction) Init() {
+ this.Nav("", "node", "install")
+ this.SecondMenu("nodes")
+}
+
+func (this *InstallManualAction) RunGet(params struct {
+ ClusterId int64
+}) {
+ this.Data["leftMenuItems"] = LeftMenuItemsForInstall(params.ClusterId, "manual")
+
+ nodesResp, err := this.RPC().NodeRPC().FindAllNotInstalledNodesWithClusterId(this.AdminContext(), &pb.FindAllNotInstalledNodesWithClusterIdRequest{ClusterId: params.ClusterId})
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ nodeMaps := []maps.Map{}
+ for _, node := range nodesResp.Nodes {
+ loginParams := maps.Map{}
+ if node.Login != nil && len(node.Login.Params) > 0 {
+ err := json.Unmarshal(node.Login.Params, &loginParams)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ }
+
+ installStatus := maps.Map{
+ "isRunning": false,
+ "isFinished": false,
+ }
+ if node.InstallStatus != nil {
+ installStatus = maps.Map{
+ "isRunning": node.InstallStatus.IsRunning,
+ "isFinished": node.InstallStatus.IsFinished,
+ "isOk": node.InstallStatus.IsOk,
+ "error": node.InstallStatus.Error,
+ }
+ }
+
+ nodeMaps = append(nodeMaps, maps.Map{
+ "id": node.Id,
+ "isOn": node.IsOn,
+ "name": node.Name,
+ "addresses": node.IpAddresses,
+ "login": node.Login,
+ "loginParams": loginParams,
+ "installStatus": installStatus,
+ })
+ }
+ this.Data["nodes"] = nodeMaps
+
+ this.Show()
+}
diff --git a/internal/web/actions/default/clusters/cluster/utils.go b/internal/web/actions/default/clusters/cluster/utils.go
index 52647a9e..098a6a63 100644
--- a/internal/web/actions/default/clusters/cluster/utils.go
+++ b/internal/web/actions/default/clusters/cluster/utils.go
@@ -8,6 +8,11 @@ import (
// 安装升级相关的左侧菜单
func LeftMenuItemsForInstall(clusterId int64, selectedItem string) []maps.Map {
return []maps.Map{
+ {
+ "name": "手动安装",
+ "url": "/clusters/cluster/installManual?clusterId=" + numberutils.FormatInt64(clusterId),
+ "isActive": selectedItem == "manual",
+ },
{
"name": "自动注册",
"url": "/clusters/cluster/installNodes?clusterId=" + numberutils.FormatInt64(clusterId),
diff --git a/web/views/@default/clusters/cluster/@menu.html b/web/views/@default/clusters/cluster/@menu.html
index 0dbf2132..fdbf1e34 100644
--- a/web/views/@default/clusters/cluster/@menu.html
+++ b/web/views/@default/clusters/cluster/@menu.html
@@ -1,5 +1,5 @@
暂时没有需要远程安装的节点。
+ +| 节点名 | +访问IP | +SSH地址 | +节点状态 | +操作 | +
|---|---|---|---|---|
| + {{node.name}} + | ++ {{addr.ip}} + | ++ + {{node.loginParams.host}}:{{node.loginParams.port}} + + 没有设置 + | ++ 等待安装 + | ++ 手动安装 + | +