@{
var theme = NewLife.Cube.CubeSetting.Current.Theme;
if (String.IsNullOrEmpty(theme)) theme = "ACE";
Layout = "~/Views/" + theme + "/_Layout.cshtml";
ViewBag.Title = "StarAgent远程部署";
}
<div class="clearfix">
<div class="container-fluid">
<h3><i class="fa fa-rocket"></i> StarAgent远程部署</h3>
<p class="text-muted">通过SSH远程部署StarAgentåˆ°ç›®æ ‡æœåС噍</p>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">部署é…ç½®</h4>
</div>
<div class="panel-body">
<form id="deployForm" class="form-horizontal" role="form">
<!-- ç›®æ ‡ä¸»æœº -->
<div class="form-group">
<label class="col-sm-2 control-label">ç›®æ ‡ä¸»æœº *</label>
<div class="col-sm-8">
<textarea id="hosts" name="hosts" class="form-control" rows="4" placeholder="支æŒå•个IPã€å¤šä¸ªIPï¼ˆé€—å·æˆ–æ¢è¡Œåˆ†éš”ï¼‰ã€æˆ–CIDR网段(如192.168.1.0/24)"></textarea>
<span class="help-block">示例:192.168.1.100 或 192.168.1.100,192.168.1.101 或 192.168.1.0/24</span>
</div>
</div>
<!-- SSHè¿žæŽ¥ä¿¡æ¯ -->
<div class="form-group">
<label class="col-sm-2 control-label">用户å *</label>
<div class="col-sm-4">
<input type="text" id="userName" name="userName" class="form-control" placeholder="root" />
</div>
<label class="col-sm-2 control-label">SSH端å£</label>
<div class="col-sm-2">
<input type="number" id="port" name="port" class="form-control" value="22" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">密ç *</label>
<div class="col-sm-8">
<input type="password" id="password" name="password" class="form-control" />
</div>
</div>
<!-- 系统é…ç½® -->
<div class="form-group">
<label class="col-sm-2 control-label">æ“作系统</label>
<div class="col-sm-4">
<select id="osType" name="osType" class="form-control">
<option value="Linux">Linux</option>
<option value="Windows">Windows</option>
</select>
</div>
<label class="col-sm-2 control-label">.NET版本</label>
<div class="col-sm-2">
<select id="dotnetVersion" name="dotnetVersion" class="form-control">
<option value="9">9.0</option>
<option value="8">8.0</option>
<option value="10">10.0</option>
</select>
</div>
</div>
<!-- StarServeråœ°å€ -->
<div class="form-group">
<label class="col-sm-2 control-label">æœåŠ¡å™¨åœ°å€ *</label>
<div class="col-sm-8">
<input type="text" id="serverUrl" name="serverUrl" class="form-control" value="@ViewBag.ServerUrl" />
<span class="help-block">StarAgent安装åŽå°†è¿žæŽ¥åˆ°æ¤æœåС噍</span>
</div>
</div>
<!-- ä¸‹è½½åœ°å€ -->
<div class="form-group">
<label class="col-sm-2 control-label">下载地å€</label>
<div class="col-sm-8">
<input type="text" id="downloadUrl" name="downloadUrl" class="form-control" value="@ViewBag.DownloadUrl" />
<span class="help-block">StarAgent安装包下载地å€</span>
</div>
</div>
<!-- 执行ä½ç½® -->
<div class="form-group">
<label class="col-sm-2 control-label">执行ä½ç½®</label>
<div class="col-sm-8">
<label class="radio-inline">
<input type="radio" name="executeOn" value="server" checked> StarServer执行(推è)
</label>
<label class="radio-inline">
<input type="radio" name="executeOn" value="web"> StarWeb本地执行
</label>
<span class="help-block">StarServer执行适åˆå¤§è§„模部署,StarWeb执行适åˆå¿«é€Ÿæµ‹è¯•</span>
</div>
</div>
<!-- 按钮 -->
<div class="form-group">
<div class="col-sm-offset-2 col-sm-8">
<button type="button" class="btn btn-info" onclick="testConnection()">
<i class="fa fa-plug"></i> 测试连接
</button>
<button type="button" class="btn btn-primary" onclick="startDeploy()">
<i class="fa fa-rocket"></i> 开始部署
</button>
<button type="reset" class="btn btn-default">
<i class="fa fa-refresh"></i> é‡ç½®
</button>
</div>
</div>
</form>
</div>
</div>
<!-- 部署结果 -->
<div id="resultPanel" class="panel panel-info" style="display:none;">
<div class="panel-heading">
<h4 class="panel-title">部署结果</h4>
</div>
<div class="panel-body">
<div id="deployResult"></div>
</div>
</div>
</div>
</div>
<script>
function getFormData() {
return {
hosts: $('#hosts').val().trim(),
port: parseInt($('#port').val()) || 22,
userName: $('#userName').val().trim(),
password: $('#password').val(),
osType: $('#osType').val(),
serverUrl: $('#serverUrl').val().trim(),
downloadUrl: $('#downloadUrl').val().trim(),
dotnetVersion: parseInt($('#dotnetVersion').val()) || 9
};
}
function validateForm() {
var data = getFormData();
if (!data.hosts) {
alert('è¯·è¾“å…¥ç›®æ ‡ä¸»æœº');
return false;
}
if (!data.userName) {
alert('请输入用户å');
return false;
}
if (!data.password) {
alert('请输入密ç ');
return false;
}
if (!data.serverUrl) {
alert('请输入æœåŠ¡å™¨åœ°å€');
return false;
}
return true;
}
function testConnection() {
if (!validateForm()) return;
var data = getFormData();
var executeOn = $('input[name="executeOn"]:checked').val();
// åªæµ‹è¯•第一个IP
var host = data.hosts.split(/[,;\n\r]/)[0].trim();
$.ajax({
url: '/Nodes/AgentDeploy/TestConnection',
type: 'POST',
data: {
host: host,
port: data.port,
userName: data.userName,
password: data.password,
executeOn: executeOn
},
success: function(response) {
if (response.code === 0 && response.data && response.data.success) {
alert('连接测试æˆåŠŸï¼');
} else {
alert('连接测试失败:' + (response.data?.message || response.message || '未知错误'));
}
},
error: function(xhr, status, error) {
alert('连接测试失败:' + error);
}
});
}
function startDeploy() {
if (!validateForm()) return;
if (!confirm('确定è¦å¼€å§‹éƒ¨ç½²å—?')) return;
var data = getFormData();
var executeOn = $('input[name="executeOn"]:checked').val();
$('#deployResult').html('<div class="alert alert-info"><i class="fa fa-spinner fa-spin"></i> æ£åœ¨éƒ¨ç½²ï¼Œè¯·ç¨å€™...</div>');
$('#resultPanel').show();
$.ajax({
url: '/Nodes/AgentDeploy/Deploy?executeOn=' + executeOn,
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(data),
success: function(response) {
if (response.code === 0 && response.data) {
showDeployResult(response.data);
} else {
$('#deployResult').html('<div class="alert alert-danger"><i class="fa fa-times"></i> 部署失败:' + (response.message || '未知错误') + '</div>');
}
},
error: function(xhr, status, error) {
var errorMsg = '部署失败:' + error;
if (xhr.responseJSON && xhr.responseJSON.message) {
errorMsg = '部署失败:' + xhr.responseJSON.message;
}
$('#deployResult').html('<div class="alert alert-danger"><i class="fa fa-times"></i> ' + errorMsg + '</div>');
}
});
}
function showDeployResult(results) {
var html = '<div class="table-responsive"><table class="table table-striped table-bordered">';
html += '<thead><tr><th>主机</th><th>状æ€</th><th>消æ¯</th><th>详细输出</th></tr></thead><tbody>';
var successCount = 0;
var failCount = 0;
for (var i = 0; i < results.length; i++) {
var result = results[i];
var statusClass = result.success ? 'success' : 'danger';
var statusIcon = result.success ? 'fa-check' : 'fa-times';
var statusText = result.success ? 'æˆåŠŸ' : '失败';
if (result.success) successCount++;
else failCount++;
html += '<tr class="' + statusClass + '">';
html += '<td>' + result.host + '</td>';
html += '<td><i class="fa ' + statusIcon + '"></i> ' + statusText + '</td>';
html += '<td>' + (result.message || '') + '</td>';
html += '<td><button class="btn btn-xs btn-info" onclick="showOutput(' + i + ')">查看</button></td>';
html += '</tr>';
}
html += '</tbody></table></div>';
html = '<div class="alert alert-info"><strong>部署完æˆ</strong>:æˆåŠŸ ' + successCount + ' 个,失败 ' + failCount + ' 个</div>' + html;
$('#deployResult').html(html);
// ä¿å˜ç»“果用于详细输出
window.deployResults = results;
}
function showOutput(index) {
var result = window.deployResults[index];
var output = result.output || 'æ— è¾“å‡º';
var modal = $('<div class="modal fade" tabindex="-1" role="dialog">' +
'<div class="modal-dialog modal-lg" role="document">' +
'<div class="modal-content">' +
'<div class="modal-header">' +
'<button type="button" class="close" data-dismiss="modal">×</button>' +
'<h4 class="modal-title">部署输出 - ' + result.host + '</h4>' +
'</div>' +
'<div class="modal-body">' +
'<pre style="max-height: 400px; overflow-y: auto;">' + output + '</pre>' +
'</div>' +
'<div class="modal-footer">' +
'<button type="button" class="btn btn-default" data-dismiss="modal">å…³é—</button>' +
'</div>' +
'</div></div></div>');
modal.modal('show');
modal.on('hidden.bs.modal', function () {
modal.remove();
});
}
</script>
|