{% extends "base.html" %}
{% load format_tags %}
{% block title %}{{ workflow_detail.workflow_name }}-{{ block.super }}{% endblock %}
{% block content %}
<div class="form-inline">
<h4 style="display: inline;">
<a target="_blank"
href="{{ workflow_detail.demand_url }}">{{ workflow_detail.workflow_name }}</a>
</h4>
<!--只允许发起人提交其他实例-->
{% if user.username == workflow_detail.engineer and not workflow_detail.is_offline_export %}
<a type='button' id="btnSubmitOtherCluster" class='btn btn-warning' href="/submitotherinstance/">上线其他实例</a>
{% endif %}
{% if is_can_review or is_can_execute or is_can_rollback or user.is_superuser %}
{% if not workflow_detail.is_offline_export %}
<a type='button' id="btnViewSql" class='btn btn-default' onclick="loading(this)" href="/editsql/">查看提交信息</a>
{% endif %}
{% endif %}
</div>
<input type="hidden" id="sqlMaxRowNumber" value="{{ rows|length }}">
<input type="hidden" id="editSqlContent" value="{{ workflow_detail.sqlworkflowcontent.sql_content }}"/>
<hr>
<h4>
审批流
</h4>
<h5>
{% include "workflow_display.html" %}
<h4>
其他信息
</h4>
<table data-toggle="table" class="table table-striped table-hover"
style="table-layout:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
<thead>
<tr>
<th>
发起人
</th>
<th>
目标实例
</th>
<th>
数据库
</th>
<th>
发起时间
</th>
<th>
可执行时间范围
</th>
<th>
结束时间
</th>
<th>
备份
</th>
<th>
当前状态
</th>
<th>
组
</th>
<th>
类型
</th>
</tr>
</thead>
<tbody>
<tr class="success">
<td>
{{ workflow_detail.engineer_display }}
</td>
<td>
{{ workflow_detail.instance.instance_name }}
</td>
<td>
{{ workflow_detail.db_name }}
</td>
<td>
{{ workflow_detail.create_time }}
</td>
<td>
{% if workflow_detail.run_date_start and workflow_detail.run_date_end %}
{{ workflow_detail.run_date_start }} / {{ workflow_detail.run_date_end }}
{% else %}
无限制
{% endif %}
</td>
<td>
{{ workflow_detail.finish_time }}
</td>
<td>
{% if workflow_detail.is_backup %}
是
{% else %}
否
{% endif %}
</td>
<td>
{% if workflow_detail.status == "workflow_finish" or workflow_detail.status == "workflow_finish_manual" %}
<font color="green">
{% else %}
<font color="red">
{% endif %}
<B id="workflow_detail_disaply">{{ workflow_detail.get_status_display }}</B></font>
<span hidden="hidden" id="workflow_detail_status">{{ workflow_detail.status }}</span>
</td>
<td>
{{ workflow_detail.group_name }}
</td>
<td>
{{ workflow_detail.get_syntax_type_display }}
</td>
</tr>
</tbody>
</table>
<br>
<!-- Nav tabs -->
<ul id="nav-tabs" class="nav nav-tabs" role="tablist">
<li id="detail_tab" class="active">
<a href="#detail" role="tab" data-toggle="tab">工单详情</a>
</li>
<li id="logs_tab">
<a href="#logs" role="tab" data-toggle="tab">工单日志</a>
</li>
</ul>
<!-- Tab panes -->
<div id="tab-content" class="tab-content">
<!-- 工单详情-->
<div id="detail" role="tabpanel" class="tab-pane fade in active table-responsive">
<!-- 自定义操作按钮-->
<div id="detail-toolbar" class="btn-group right">
<button id="expandAllRows" class="btn btn-default navbar-btn" type="button">展开全部</button>
</div>
<table id="tb-detail" data-toggle="table" class="table table-condensed"
style="table-layout:inherit;word-break:break-word;overflow:hidden;text-overflow:ellipsis;"></table>
<!--最后操作信息-->
{% if last_operation_info %}
<table data-toggle="table" class="table table-striped table-hover"
style="table-layout:inherit;overflow:hidden;text-overflow:ellipsis;">
<thead>
<tr>
<th>
操作信息
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
{% format_str last_operation_info %}
</td>
</tr>
</tbody>
</table>
<br>
{% endif %}
</div>
<!-- 工单日志-->
<div id="logs" role="tabpanel" class="tab-pane fade table-responsive">
<table id="tb-logs" data-toggle="table" class="table table-hover"
style="table-layout:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
</table>
</div>
</div>
<!--审核备注输入框-->
{% if is_can_review or is_can_cancel %}
<textarea id="remark" name="remark" class="form-control" data-name="审核备注"
placeholder="请填写审核备注/终止原因" rows=3></textarea>
<br>
{% endif %}
<!--审核人修改可执行时间按钮-->
{% if is_can_review %}
<form id="from-passed" action="/passed/" method="post" style="display:inline-block;">
{% csrf_token %}
<input type="hidden" name="workflow_id" value="{{ workflow_detail.id }}">
<input type="hidden" id="audit_remark" name="audit_remark" value="">
<input type="button" class="btn btn-info" data-toggle="modal" data-target="#Executabletime"
value="可执行时间变更"/>
</form>
{% endif %}
<!--审核通过按钮-->
{% if is_can_review %}
<form id="from-passed" action="/passed/" method="post" style="display:inline-block;">
{% csrf_token %}
<input type="hidden" name="workflow_id" value="{{ workflow_detail.id }}">
<input type="hidden" id="audit_remark" name="audit_remark" value="">
<input type="button" id="btnPass" class="btn btn-success" value="审核通过"/>
</form>
{% endif %}
<!--立即执行按钮-->
{% if is_can_execute %}
<form id="from-execute" action="/execute/" method="post" style="display:inline-block;">
{% csrf_token %}
<input type="hidden" name="mode" value="auto">
<input type="hidden" name="workflow_id" value="{{ workflow_detail.id }}">
<input type="button" id="btnExecuteOnly" class="btn btn-danger"
value="立即执行"/>
</form>
{% if manual %}
<form id="from-execute-manual" action="/execute/" method="post" style="display:inline-block;">
{% csrf_token %}
<input type="hidden" name="mode" value="manual">
<input type="hidden" name="workflow_id" value="{{ workflow_detail.id }}">
<input type="button" id="btnExecuteOnly-manual" class="btn btn-warning"
value="已手动完成"/>
</form>
{% endif %}
{% endif %}
<!--定时执行按钮-->
{% if is_can_timingtask %}
{% if workflow_detail.status == 'workflow_review_pass' %}
<input type="button" class="btn btn-info" data-toggle="modal" data-target="#cronComfirm" value="定时执行"/>
{% elif workflow_detail.status == 'workflow_timingtask' %}
<input type="button" class="btn btn-info" data-toggle="modal" data-target="#cronComfirm" value="执行时间变更"/>
{% endif %}
{% endif %}
<!--终止执行按钮-->
{% if is_can_review or is_can_cancel %}
<form id="form-cancel" action="/cancel/" method="post" style="display:inline-block;">
{% csrf_token %}
<input type="hidden" name="workflow_id" value="{{ workflow_detail.id }}">
<input type="hidden" id="cancel_remark" name="cancel_remark" value="">
<input type="button" id="btnCancel" class="btn btn-default" value="终止流程"/>
</form>
{% endif %}
{% if workflow_detail.status == 'workflow_finish' and workflow_detail.is_offline_export %}
<form id="form-download" class="form-horizontal">
<button type="button" id="btnDownload" data-loading-text="下载中..."
class="btn btn-info">
下载文件
</button>
</form>
{% endif %}
<!--查看回滚按钮-->
{% if is_can_rollback %}
{% if workflow_detail.status == 'workflow_finish' or workflow_detail.status == 'workflow_exception' %}
<form action="/rollback/" method="get" style="display:inline-block;">
{% csrf_token %}
<input type="hidden" name="workflow_id" value="{{ workflow_detail.id }}">
<input type="submit" id="btnRollback" onclick="loading(this)" class="btn btn-default"
value="查看回滚SQL"/>
</form>
<form action="/rollback/" method="get" style="display:inline-block;">
{% csrf_token %}
<input type="hidden" name="workflow_id" value="{{ workflow_detail.id }}">
<input type="hidden" name="download" value="true">
<input type="submit" id="btnRollback" onclick="loading(this)" class="btn btn-info"
value="下载回滚SQL"/>
</form>
{% endif %}
{% endif %}
<!--重新修改按钮-->
{% if workflow_detail.status == 'workflow_autoreviewwrong' or workflow_detail.status == 'workflow_abort' or workflow_detail.status == 'workflow_exception' %}
{% if user.username == workflow_detail.engineer %}
<!--只允许发起人修改工单-->
{% csrf_token %}
{% if workflow_detail.is_offline_export %}
<!-- 离线导出工单跳转到导出提交页 -->
<a type='button' id="btnEditSql" onclick="loading(this)" class='btn btn-default'
href="/sqlexportsubmit/?source=resubmit">重新修改</a>
{% else %}
<!-- 非离线导出工单跳转到上线变更提交页 -->
<a type='button' id="btnEditSql" onclick="loading(this)" class='btn btn-default'
href="/editsql/">重新修改</a>
{% endif %}
{% endif %}
{% endif %}
<!-- 定时执行弹出框 -->
<form id="from-addsqlcronjob" action="/timingtask/" method="post" style="display:inline-block;">
<div class="modal fade" id="cronComfirm" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header ">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
<h4 class="modal-title text-danger">定时执行SQL</h4>
</div>
{% csrf_token %}
<div class="modal-body">
<div class="form-group">
<input type="hidden" name="workflow_id" value="{{ workflow_detail.id }}">
<div class='input-group date' id='datetimepicker'>
<input id="run_date" name="run_date" type='text' autocomplete="off" class="form-control"
placeholder="请选择执行时间"/>
<span class="input-group-addon"><span class="glyphicon glyphicon-time"></span></span>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-info" data-dismiss="modal">取消</button>
<input type="hidden" name="workflow_id" value="{{ workflow_detail.id }}">
<input type="button" id="btnAddsqlcronjob" class="btn btn-danger" value="确认提交"/>
</div>
</div>
</div>
</div>
</form>
<!-- 执行进度弹出框-->
<!-- 自定义操作按钮-->
<div id="osc-toolbar" class="btn-group left" style="display:none;">
<button id="pause_osc" class="btn btn-warning" type="button">暂停</button>
<button id="resume_osc" class="btn btn-success" type="button">恢复</button>
<button id="kill_osc" class="btn btn-danger" type="button">终止</button>
</div>
<div class="modal fade" id="osc_percent">
<div class="modal-dialog modal-lg">
<div class="modal-content message_align">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
<h4 class="modal-title text-danger">执行进度</h4>
</div>
<div class="modal-body">
<div class="table-responsive">
<table id="osc_percent_list" data-toggle="table" class="table table-striped table-hover"
style="table-layout:inherit;overflow:hidden;text-overflow:ellipsis;">
</table>
</div>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
<!-- 修改可执行时间弹出框 -->
<form id="from-alterexecutabletime" action="/alter_run_date/" method="post" style="display:inline-block;">
<div class="modal fade" id="Executabletime" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header ">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
<h4 class="modal-title text-danger">修改可执行时间</h4>
</div>
{% csrf_token %}
<div class="modal-body">
<!--可执行范围时间-->
<div class='form-group input-group'>
<input type="hidden" id="run_date_start" name="run_date_start">
<input type="hidden" id="run_date_end" name="run_date_end">
<input type="text" id="run_date_range" readonly
value="请选择可执行时间范围"
style="background-color: #fff;color: #999 "
class="form-control "/>
<span class="input-group-addon"><span class="fa fa-calendar"></span></span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-info" data-dismiss="modal">取消</button>
<input type="hidden" name="workflow_id" value="{{ workflow_detail.id }}">
<input type="button" id="btnalterExecutabletime" class="btn btn-danger" value="确认提交"/>
</div>
</div>
</div>
</div>
</form>
{% endblock content %}
{% block js %}
{% load static %}
<link href="{% static 'datetimepicker/css/bootstrap-datetimepicker.css' %}" rel="stylesheet" type="text/css"/>
<link href="{% static 'daterangepicker/css/daterangepicker.css' %}" rel="stylesheet" type="text/css"/>
<script src="{% static 'daterangepicker/js/moment.min.js' %}"></script>
<script src="{% static 'datetimepicker/js/bootstrap-datetimepicker.js' %}"></script>
<script src="{% static 'datetimepicker/js/bootstrap-datetimepicker.zh-CN.js' %}"></script>
<script src="{% static 'daterangepicker/js/daterangepicker.js' %}"></script>
<script src="{% static 'bootstrap-table/js/bootstrap-table-export.min.js' %}"></script>
<script src="{% static 'bootstrap-table/js/tableExport.min.js' %}"></script>
<!--初始化时间控件 -->
<script>
var date = new Date();
$("#datetimepicker").datetimepicker({
format: "yyyy-mm-dd hh:ii",
autoclose: true,
todayBtn: true,
pickerPosition: "bottom-left",
language: 'zh-CN',//中文,需要引用zh-CN.js包
startView: 1,//天视图
minView: 0,//分钟
startDate: date,
inline: true,
sideBySide: true,
minuteStep: 5,
});
$("#run_date_range").daterangepicker({
timePicker: true,
timePicker24Hour: true,
autoApply: true,
autoUpdateInput: false,
opens: "left",
drops: "down",
minDate: moment().startOf('minutes'),
startDate: moment().startOf('hour'),
endDate: moment().startOf('hour'),
locale: {
"applyLabel": "确定",
"cancelLabel": "清空",
"daysOfWeek": ["日", "一", "二", "三", "四", "五", "六"],
"monthNames": ["一月", "二月", "三月", "四月", "五月", "六", "七月", "八月", "九月", "十月", "十一月", "十二月"],
"firstDay": 1
},
}).on('apply.daterangepicker', function (ev, picker) {
$(this).css("color", "#333");
$("#run_date_start").val(picker.startDate.format('YYYY-MM-DD HH:mm'));
$("#run_date_end").val(picker.endDate.format('YYYY-MM-DD HH:mm'));
$(this).val(picker.startDate.format('YYYY-MM-DD HH:mm') + ' / ' + picker.endDate.format('YYYY-MM-DD HH:mm'));
}).on('cancel.daterangepicker', function (ev, picker) {
$(this).css("color", "#999");
$(this).val('请选择可执行时间范围');
});
</script>
<script>
var editWorkflowNname = "{{ workflow_detail.workflow_name|escapejs }}";
var editDemandUrl = "{{ workflow_detail.demand_url|escapejs }}";
var editSqlContent = $("#editSqlContent").val();
var editGroup = "{{ workflow_detail.group_name|escapejs }}";
var editClustername = "{{ workflow_detail.instance.instance_name|escapejs }}";
var editDbname = "{{ workflow_detail.db_name|escapejs }}";
var editIsbackup = "{{ workflow_detail.is_backup|escapejs }}";
</script>
<!--按钮控制 -->
<script>
// 表格展开折叠全部行
$("#expandAllRows").click(function () {
$(this).trigger("blur");
if ($(this).text() === '展开全部') {
$('#tb-detail').bootstrapTable('hideColumn', 'sql');
$('#tb-detail').bootstrapTable('expandAllRows');
$(this).text('折叠全部')
} else if ($(this).text() === '折叠全部') {
$('#tb-detail').bootstrapTable('showColumn', 'sql');
$('#tb-detail').bootstrapTable('collapseAllRows');
$(this).text('展开全部')
}
});
$("#btnEditSql").click(function () {
sessionStorage.setItem('editWorkflowNname', editWorkflowNname);
sessionStorage.setItem('editDemandUrl', editDemandUrl);
sessionStorage.setItem('editSqlContent', editSqlContent);
sessionStorage.setItem('editGroup', editGroup);
sessionStorage.setItem('editClustername', editClustername);
sessionStorage.setItem('editDbname', editDbname);
sessionStorage.setItem('editIsbackup', editIsbackup);
});
$("#btnViewSql").click(function () {
sessionStorage.removeItem('editWorkflowDetailId');
sessionStorage.setItem('editWorkflowNname', editWorkflowNname);
sessionStorage.setItem('editDemandUrl', editDemandUrl);
sessionStorage.setItem('editSqlContent', editSqlContent);
sessionStorage.setItem('editGroup', editGroup);
sessionStorage.setItem('editClustername', editClustername);
sessionStorage.setItem('editDbname', editDbname);
sessionStorage.setItem('editIsbackup', editIsbackup);
});
$("#btnSubmitOtherCluster").click(function () {
sessionStorage.setItem('editWorkflowNname', editWorkflowNname);
sessionStorage.setItem('editDemandUrl', editDemandUrl);
sessionStorage.setItem('editSqlContent', editSqlContent);
sessionStorage.setItem('editGroup', editGroup);
sessionStorage.setItem('editIsbackup', editIsbackup);
});
// 执行确认
$("#btnExecuteOnly").click(function () {
if ("{{ workflow_detail.is_backup }}" === 'False' &&
"{{workflow_detail.is_offline_export}}" === 0) {
var isContinue = confirm("该工单未选择备份,将不会自动备份数据,请确认是否立即执行?");
} else {
var isContinue = confirm("请确认是否立即执行?");
}
var formExecuteOnly = $("#from-execute");
if (isContinue) {
formExecuteOnly.submit();
loading(this)
}
});
// 执行确认手工执行
$("#btnExecuteOnly-manual").click(function () {
var isContinue = confirm("请确认是否已经手工执行结束?");
var formExecuteOnly = $("#from-execute-manual");
if (isContinue) {
formExecuteOnly.submit();
loading(this)
}
});
//审核通过
$("#btnPass").click(function () {
//获取form对象,判断输入,通过则提交
$("#audit_remark").val($("#remark").val());
var formPassed = $("#from-passed");
loading(this);
formPassed.submit();
});
// 审核不通过
$("#btnCancel").click(function () {
//获取form对象,判断输入,通过则提交
$("#cancel_remark").val($("#remark").val());
var formCancel = $("#form-cancel");
if ($("#cancel_remark").val()) {
loading(this);
formCancel.submit();
} else {
alert('请填写终止原因')
}
});
// 定时时间校验
$("#btnAddsqlcronjob").click(function () {
//获取form对象,判断输入,通过则提交
var formAddsqlcronjo = $("#from-addsqlcronjob");
if ($("#run_date").val()) {
loading(this);
formAddsqlcronjo.submit();
} else {
alert('请填写定时执行时间')
}
});
// 修改可执行时间
$("#btnalterExecutabletime").click(function () {
//获取form对象,判断输入,通过则提交
var formAlterexecutabletime = $("#from-alterexecutabletime");
loading(this);
formAlterexecutabletime.submit();
});
// 按钮禁用
function loading(obj) {
$(obj).button('loading').delay(2500).queue(function () {
$(obj).button('reset');
$(obj).dequeue();
});
}
</script>
<!--表格初始化 -->
<script>
//获取工单详情
function get_detail() {
$('#tb-detail').bootstrapTable('destroy').bootstrapTable({
escape: true,
method: 'get',
contentType: "application/x-www-form-urlencoded",
url: "/sqlworkflow/detail_content/",
striped: true, //是否显示行间隔色
cache: true, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
pagination: true, //是否显示分页(*)
sortable: true, //是否启用排序
sidePagination: "client", //分页方式:client客户端分页,server服务端分页(*)
pageNumber: 1, //初始化加载第一页,默认第一页,并记录
pageSize: 500, //每页的记录行数(*)
pageList: [500, 1000, 5000], //可供选择的每页的行数(*)
search: true, //是否显示表格搜索
strictSearch: false, //是否全匹配搜索
showColumns: true, //是否显示所有的列(选择显示的列)
showRefresh: true, //是否显示刷新按钮
minimumCountColumns: 1, //最少允许的列数
clickToSelect: false, //是否启用点击选中行
uniqueId: "id", //每一行的唯一标识,一般为主键列
showToggle: false, //是否显示详细视图和列表视图的切换按钮
toolbar: "#detail-toolbar", //指明自定义的toolbar
showExport: true,
exportDataType: "all",
exportOptions: {
ignoreColumn: [0], //忽略第一列
fileName: 'detail_content' //文件名称设置
},
cardView: false, //是否显示详细视图
detailView: true, //是否显示父子表
//格式化详情
detailFormatter: function (index, row) {
var html = [];
$.each(row, function (key, value) {
if (key === 'sql') {
//let sql = window.sqlFormatter.format(value);
let sql = value;
//替换标签
sql = sql.replace(/&/g, "&");
sql = sql.replace(/</g, "<");
sql = sql.replace(/>/g, ">");
sql = sql.replace(/"/g, """);
//替换所有的换行符
sql = sql.replace(/\r\n/g, "<br>");
sql = sql.replace(/\n/g, "<br>");
//替换所有的空格
sql = sql.replace(/\s/g, " ");
html.push('<span>' + sql + '</span>');
}
});
return html.join('');
},
queryParamsType: 'limit',
//请求服务数据时所传参数
queryParams:
function (params) {
return {
workflow_id: "{{ workflow_detail.id }}",
}
},
locale: 'zh-CN', //本地化
columns: [{
title: 'ID',
field: 'id',
sortable: true
}, {
title: '完整SQL内容',
field: 'sql',
visible: false // 默认不显示
}, {
title: 'SQL内容',
field: 'sql',
formatter: function (value, row, index) {
var sql=row.sql;
if (sql.length > 80) {
return sql.substr(0, 80) + '...';
} else {
return sql
}
},
sortable: false
}, {
title: '审核/执行状态',
field: 'errlevel',
formatter: function (value, row, index) {
if (String(value) === '0') {
return 'pass'
} else if (String(value) === '1') {
return 'warning'
} else if (String(value) === '2') {
return 'error'
}
},
sortable: true
}, {
title: '审核/执行信息',
field: 'errormessage',
formatter: function (value, row, index) {
return value.replace(/\n/g, '<br>');
},
sortable: true
}, {
title: '扫描/影响行数',
field: 'affected_rows',
sortable: true
}, {
title: '执行耗时',
field: 'execute_time',
sortable: true
}, {
title: '备份耗时',
field: 'backup_time',
sortable: true
}, {
title: '当前阶段',
field: 'stagestatus',
sortable: true
}, {
title: '操作',
field: 'sqlsha1',
formatter: function (value, row, index) {
let btn_percent = "<button class=\"btn btn-info btn-xs\" sqlsha1=\"" + row.sqlsha1 + "\" onclick=\"get_osc_percent(this)" + "\">查看进度</button>\n";
let status = $("#workflow_detail_status").text();
if (row.sqlsha1 && status === 'workflow_executing') {
return btn_percent;
}
},
}],
rowStyle: function (row, index) {
var style = "";
if (row.errlevel === 1) {
style = 'warning';
} else if (row.errlevel === 2) {
style = 'danger';
}
return {classes: style}
},
onLoadSuccess: function () {
},
onLoadError: onLoadErrorCallback,
});
}
// 获取操作日志
function get_logs() {
$.ajax({
type: "post",
url: "/workflow/log/",
dataType: "json",
data: {
workflow_id: "{{ workflow_detail.id }}",
workflow_type: 2,
},
complete: function () {
},
success: function (data) {
//初始化table
$('#tb-logs').bootstrapTable('destroy').bootstrapTable({
escape: true,
striped: true, //是否显示行间隔色
cache: true, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
pagination: true, //是否显示分页(*)
sortable: false, //是否启用排序
sortOrder: "asc", //排序方式
sidePagination: "client", //分页方式:client客户端分页,server服务端分页(*)
pageNumber: 1, //初始化加载第一页,默认第一页,并记录
pageSize: 20, //每页的记录行数(*)
pageList: [20, 30, 50, 100], //可供选择的每页的行数(*)
search: true, //是否显示表格搜索
strictSearch: false, //是否全匹配搜索
showColumns: false, //是否显示所有的列(选择显示的列)
showRefresh: false, //是否显示刷新按钮
minimumCountColumns: 2, //最少允许的列数
clickToSelect: false, //是否启用点击选中行
uniqueId: "id", //每一行的唯一标识,一般为主键列
showToggle: false, //是否显示详细视图和列表视图的切换按钮
cardView: false, //是否显示详细视图
detailView: false, //是否显示父子表
locale: 'zh-CN', //本地化
data: data.rows,
columns: [{
title: '操作',
field: 'operation_type_desc'
}, {
title: '操作人',
field: 'operator_display'
}, {
title: '操作时间',
field: 'operation_time'
}, {
title: '操作信息',
field: 'operation_info'
}],
onLoadSuccess: function () {
},
onLoadError: onLoadErrorCallback,
});
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
}
})
}
//获取osc执行进度信息
function get_osc_percent(obj) {
$('#osc_percent_list').bootstrapTable('destroy').bootstrapTable({
escape: true,
method: 'post',
contentType: "application/x-www-form-urlencoded",
url: "/inception/osc_control/",
striped: true, //是否显示行间隔色
cache: false, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
pagination: false, //是否显示分页(*)
sortable: false, //是否启用排序
sortOrder: "asc", //排序方式
sidePagination: "server", //分页方式:client客户端分页,server服务端分页(*)
pageNumber: 1, //初始化加载第一页,默认第一页,并记录
pageSize: 20, //每页的记录行数(*)
pageList: [20, 30, 50, 100], //可供选择的每页的行数(*)
search: false, //是否显示表格搜索
strictSearch: false, //是否全匹配搜索
showColumns: false, //是否显示所有的列(选择显示的列)
showRefresh: true, //是否显示刷新按钮
minimumCountColumns: 2, //最少允许的列数
checkboxHeader: false, //隐藏全选框
singleSelect: true, //单选框
clickToSelect: true, //是否启用点击选中行
uniqueId: "id", //每一行的唯一标识,一般为主键列
showToggle: false, //是否显示详细视图和列表视图的切换按钮
cardView: false, //是否显示详细视图
detailView: true, //是否显示父子表
//格式化详情
detailFormatter: function (index, row) {
var html = [];
$.each(row, function (key, value) {
if (key === 'INFOMATION') {
//替换所有的换行符
value = value.replace(/\r\n/g, "<br>");
value = value.replace(/\n/g, "<br>");
//替换所有的空格
value = value.replace(/\s/g, " ");
html.push('<span>' + value + '</span>');
}
});
return html.join('');
},
locale: 'zh-CN', //本地化
toolbar: "#osc-toolbar", //指明自定义的toolbar
queryParamsType: 'limit',
//请求服务数据时所传参数
queryParams:
function (params) {
return {
sqlsha1: $(obj).attr("sqlsha1"),
workflow_id: "{{ workflow_detail.id }}",
command: "get"
}
},
columns: [{
title: '',
field: 'checkbox',
checkbox: true,
formatter: function stateFormatter(value, row, index) {
return {
checked: true//设置选中
};
},
}, {
title: 'DBNAME',
field: 'DBNAME'
}, {
title: 'TABLENAME',
field: 'TABLENAME'
}, {
title: 'PERCENT',
field: 'PERCENT'
}, {
title: 'SQLSHA1',
field: 'SQLSHA1',
visible: false // 默认不显示
}, {
title: 'REMAINTIME',
field: 'REMAINTIME'
}, {
title: 'INFOMATION',
field: 'INFOMATION',
formatter: function (value, row, index) {
if (value.length > 300) {
value = value.substr(0, 300) + '...';
}
return value.replace(/\n/g, '<br>');
},
}],
onLoadSuccess: function () {
$("#osc-toolbar").show();
$('#osc_percent').modal('show');
},
onLoadError: onLoadErrorCallback,
});
}
</script>
<!--OSC控制-->
<script>
$(":input[id$='_osc']").bind('click', function () {
let AllSelections = $("#osc_percent_list").bootstrapTable('getSelections');
if (AllSelections.length === 1) {
//获取选择的sqlsha1
let sqlsha1 = AllSelections[0]['SQLSHA1'];
let command = '';
let isContinue = true;
// 判断command值
switch (this.id) {
case 'pause_osc':
command = 'pause';
break;
case 'resume_osc':
command = 'resume';
break;
case 'kill_osc':
command = 'kill';
isContinue = confirm("请确认是否立即终止?终止后需要手动清理触发器以及相关中间表!");
break;
default:
alert('命令错误!')
}
if (isContinue) {
//发送请求
$.ajax({
type: "post",
url: "/inception/osc_control/",
dataType: "json",
data: {
sqlsha1: sqlsha1,
workflow_id: "{{ workflow_detail.id }}",
command: command
},
complete: function () {
},
success: function (data) {
if (data.msg) {
alert(data.msg);
} else {
alert('操作成功!请稍后刷新获取最新状态');
}
}
})
}
} else {
alert("请先选择要终止进程")
}
});
</script>
<!--状态控制 -->
<script>
var workflow_id = "{{ workflow_detail.id }}";
var status = $("#workflow_detail_status").text();
var key;
var retryCnt = 1;
$(document).ready(function () {
sessionStorage.setItem('sql_workflow_active_li_id', 'detail_tab');
get_detail();
if (status === "workflow_executing") {
getWorkflowStatus(workflow_id);
}
});
function getWorkflowStatus(workflow_id) {
document.getElementById("workflow_detail_disaply").innerHTML = gettext("确认中...");
if (retryCnt <= 120) {
clearTimeout(key);
key = setTimeout(function () {
getWorkflowStatus(workflow_id);
}, 2500);
retryCnt++;
} else {
retryCnt = 1;
alert("该工单2分钟仍然未执行完毕,请稍后尝试手动刷新本页面");
}
if (workflow_id > 0) {
// console.log('get workflow status');
$.ajax({
type: "post",
async: false,
url: "/getWorkflowStatus/",
dataType: "json",
data: {
workflow_id: workflow_id
},
complete: function () {
if (wfStatus !== -1 && wfStatus !== "workflow_executing") {
window.location.reload(true);
}
},
success: function (data) {
wfStatus = data.status;
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
}
});
} else {
alter("参数不正确")
}
}
</script>
<!--TAB控制 -->
<script>
//tab切换,保留当前激活的标签id
$(function () {
$("#nav-tabs").on('shown.bs.tab', "li", function (e) {
var active_li_id = $(e.target).parents().attr('id');
sessionStorage.setItem('sql_workflow_active_li_id', active_li_id);
//当前激活的标签id
if (active_li_id === 'detail_tab') {
get_detail();
} else if (active_li_id === 'logs_tab') {
get_logs();
}
});
});
</script>
<!--下载导出文件-->
<script>
$('#btnDownload').click(async function() {
const $btn = $(this);
$btn.prop('disabled', true);
const originalText = $btn.html();
$btn.html('<i class="fa fa-spinner fa-spin"></i> 准备下载...');
try {
const workflow_id = "{{ workflow_detail.id }}";
const file_name = "{{ workflow_detail.file_name }}";
const filePath = `/downloadfile/?file_name=${encodeURIComponent(file_name)}&workflow_id=${workflow_id}`;
// 轻量级类型检查
const typeCheck = await fetch(filePath, {
method: 'HEAD',
cache: 'no-store'
});
if (typeCheck.headers.get('content-type')?.includes('application/json')) {
// 处理OSS重定向
const res = await fetch(filePath);
const data = await res.json();
// 优先处理错误响应
if (data.error) {
throw new Error(data.error); // 抛出后端返回的错误信息
}
// 处理重定向
if (data.type === 'redirect') {
window.location.href = data.url;
return;
}
throw new Error('未知的响应格式');
}
// 处理文件下载
const a = document.createElement('a');
a.href = filePath;
a.download = file_name;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
} catch (error) {
console.error('下载失败:', error);
alert(`下载错误: ${error.message || '服务器连接失败'}`);
} finally {
// 恢复按钮
if (!$btn.prop('disabled')) return;
setTimeout(() => {
$btn.prop('disabled', false);
$btn.html(originalText);
}, 3000);
}
});
</script>
{% endblock %}