550 lines
23 KiB
HTML
550 lines
23 KiB
HTML
<style>
|
||
.edit {
|
||
table {
|
||
border-collapse: collapse;
|
||
thead {
|
||
text-align: center;
|
||
/*th {
|
||
background-color: #c3deff;
|
||
}*/
|
||
}
|
||
th {
|
||
vertical-align: middle;
|
||
}
|
||
}
|
||
/*input,textarea,select {
|
||
border-top: 0;
|
||
border-right: 0;
|
||
!*border-left: 2px!important;*!
|
||
border-bottom: 0;
|
||
!*background-color: #DDF3F5;*!
|
||
}*/
|
||
textarea {
|
||
width: 100%;
|
||
}
|
||
.tpl-debug>pre{
|
||
background-color: #F1F1F1;
|
||
border-top: 0;
|
||
border-right: 0;
|
||
border-bottom: 0;
|
||
}
|
||
}
|
||
</style>
|
||
<row class="qtask-list">
|
||
<div class="col-md-12" style="margin-bottom: 10px">
|
||
<h3 v-text="cfg.title"></h3>
|
||
<button @click="openDia({'x':1})" class="btn btn-primary" type="button"> 添加QTask</button>
|
||
</div>
|
||
|
||
|
||
<div class="col-md-5" style="">
|
||
<ul id="treeDemo" class="ztree" style="display: none"></ul>
|
||
<table class="table table-bordered tlist" style="width: 100%; ">
|
||
<thead>
|
||
<tr>
|
||
<th v-for="field in cfg.cols" v-text="field.label"></th>
|
||
<th>操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr v-for="row in list.rows" @click="openDia(row)" :class="{'active': row.name == _row.name}">
|
||
<td v-for="field in cfg.cols" v-title="row[field.col]" v-text="row[field.col]"></td>
|
||
<td>
|
||
<a @click="openDia(row)" href="javascript:;">编辑</a> |
|
||
<!--
|
||
<a @click="row['status']=1;qsave(row);" v-show="row.status != 1" href="javascript:;">启用</a>
|
||
<a @click="row['status']=0;qsave(row);" v-show="row.status == 1" href="javascript:;">不启用</a> |
|
||
-->
|
||
<a @click="row['status']=-1;comfirmDel(row);" href="javascript:;">删除</a>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div v-show="!row || list.rows == 0" style="text-align: center">
|
||
<img src="../res/img/none.png">
|
||
<p>暂无数据</p>
|
||
</div>
|
||
<!-- 分页 -->
|
||
<div>
|
||
<ul class="pager pull-right">
|
||
<li class="previous">
|
||
<a >共{{list.total}}条数据</a>
|
||
</li>
|
||
<li :class="['previous', {'disabled':limit.pn==1}]">
|
||
<a @click="loadList(-- limit.pn)" href="javascript:"><i class="icon icon-angle-left"></i>上一页</a>
|
||
</li>
|
||
<li :class="['next', {'disabled':limit.pn >= limit.total}]">
|
||
<a @click="loadList(limit.pn = ++limit.pn )" href="javascript:">下一页<i class="icon icon-angle-right"></i></a>
|
||
</li>
|
||
|
||
<li class="previous">
|
||
<a>到第<input v-model="limit.pn" style="width: 30px;height: 20px;margin: 0">/ {{limit.total}}页</a>
|
||
</li>
|
||
<li class="previous">
|
||
<a @click="loadList(limit.pn)" href="javascript:;">确定</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-md-7 edit" style="padding-top: 0px;">
|
||
<table v-show="editStatus==1" class="table table-bordered">
|
||
<thead>
|
||
<tr>
|
||
<th colspan="4">
|
||
<h5 class="pull-left">【任务编辑】</h5>
|
||
<!--全屏打开按钮-->
|
||
<!--<a @click="fullScreen()" href="javascript:" class="pull-right" style="margin: 5px; font-size: 18px">
|
||
<i class="icon icon-fullscreen"></i>
|
||
</a>-->
|
||
</th>
|
||
</tr>
|
||
</thead>
|
||
<tr>
|
||
<th style="width: 120px">任务名称</th>
|
||
<td>
|
||
<input v-model="row.title" class="form-control">
|
||
</td>
|
||
<th>数据平台</th>
|
||
<td>
|
||
<select v-model="row.dbid" class="form-control">
|
||
<option v-for="item in dbPlats" :value="item.dbid" v-text="item.dbname"></option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th>任务KEY</th>
|
||
<td>
|
||
<input v-model="row.name" class="form-control">
|
||
</td>
|
||
<th style="width: 120px">CataLog</th>
|
||
<td>
|
||
<select v-model="row.catalog" class="form-control">
|
||
<option v-for="item in catalogs()" :value="item" v-text="item"></option>
|
||
</select>
|
||
</td>
|
||
<!--<td colspan="3">
|
||
<div class="col-xs-6" style="padding: 0;">
|
||
<select v-model="row.dbplatid" class="form-control" style="background-color: #f2f4f9">
|
||
<option></option>
|
||
<option v-for="item in dbPlats" :value="item.key" v-text="item.name"></option>
|
||
</select>
|
||
</div>
|
||
<div class="col-xs-4">
|
||
<select v-model="row.catalog" class="form-control" style="background-color: #f2f4f9">
|
||
<option></option>
|
||
<option v-for="item in catalogs()" :value="item" v-text="item"></option>
|
||
</select>
|
||
</div>
|
||
</td>-->
|
||
</tr>
|
||
<tr>
|
||
<th>执行模板</th>
|
||
<td colspan="3" class="tpl-content">
|
||
<textarea v-model="row.content" @change="parsePara(row)" rows="6" class="pre-scrollable form-control"></textarea>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th>默认参数</th>
|
||
<td colspan="3" class="tpl-para">
|
||
<textarea rows="1" v-model="row.para" class="form-control"></textarea>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th>备注</th>
|
||
<td colspan="3" class="tpl-remark">
|
||
<textarea rows="1" v-model="row.remark" class="form-control"></textarea>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th>操作</th>
|
||
<td colspan="3">
|
||
<div class="pull-right">
|
||
<button @click="debug()" type="button" class="btn btn-primary" style="margin-right: 20px">
|
||
<i class="icon icon-bug"> 调试</i></button>
|
||
<button @click="openDia({})" type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||
<button @click="reset(row.name)" type="button" class="btn btn-default" data-dismiss="modal">重置</button>
|
||
<button @click="save()" type="button" class="btn btn-primary">
|
||
<i class="icon icon-save"> 保存</i></button>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td colspan="4"></td>
|
||
</tr>
|
||
<tr>
|
||
<th colspan="4" style="text-align: center">
|
||
调试结果
|
||
<div class="pull-right">
|
||
<button @click="copyToClipboard(debugRet)" class="btn btn-default btn-mini"
|
||
title="拷贝调试结果"><i
|
||
class="icon icon-copy"></i></button>
|
||
<button @click="debugView ='JSON'" class="btn btn-default btn-mini" title="展示JSON"><i
|
||
class="icon icon-code"></i></button>
|
||
<button @click="debugView ='TABLE'" class="btn btn-default btn-mini" title="展示表格"><i
|
||
class="icon icon-table"></i></button>
|
||
</div>
|
||
</th>
|
||
</tr>
|
||
<tr>
|
||
<td colspan="4" class="tpl-debug" style="padding: 0">
|
||
|
||
<pre class="pre-scrollable"
|
||
v-if="debugView === 'JSON' || !(debugData.header && debugData.header.length)">{{debugRet}}<p
|
||
v-if="!debugRet" class="text-muted">暂无调试信息</p></pre>
|
||
<table v-if="debugView === 'TABLE' && (debugData.header && debugData.header.length)"
|
||
style="width: 100%;overflow: auto;">
|
||
<tr>
|
||
<th v-for="item in debugData.header">{{item}}</th>
|
||
</tr>
|
||
<tr v-for="item in debugData.list">
|
||
<td v-for="i in debugData.header">{{item[i]}}</td>
|
||
</tr>
|
||
<!--<tr>
|
||
<td colspan="{{debugData.header.length}}" class="pull-right">
|
||
{{debugData.total}}
|
||
</td>
|
||
</tr>-->
|
||
</table>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<div v-show="editStatus!=1" style="text-align: center">
|
||
<img src="../res/img/none.png">
|
||
<p>暂无数据</p>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- modal-tpl -->
|
||
<div class="col-md-12">
|
||
<!-- 对话框触发按钮 -->
|
||
<!-- 对话框HTML -->
|
||
<div class="modal fade" id="myModal">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">关闭</span></button>
|
||
<h4 class="modal-title">QTask编辑</h4>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form class="form-horizontal">
|
||
<div class="form-group">
|
||
<label class="col-sm-2 required">任务名称</label>
|
||
<div class="col-md-6 col-sm-10">
|
||
<input v-model="row.title" class="form-control" placeholder="请输入 业务名称">
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="col-sm-2 required">任务标识码</label>
|
||
<div class="col-md-6 col-sm-10">
|
||
<input v-model="row.name" :disabled="row.qtaskid" :readonly="row.key" class="form-control" placeholder="请输入 任务标识码">
|
||
</div>
|
||
</div>
|
||
<div class="form-group" style="margin-bottom: 0">
|
||
<label class="col-md-2 required">执行内容</label>
|
||
<div class="col-md-10">
|
||
<textarea v-model="row.content" class="form-control layui-code" rows="5" placeholder="请输入 SQL (支持jfinal-enjoy模板语法)" > </textarea>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="para" class="col-sm-2">默认查询参数</label>
|
||
<div class="col-sm-10">
|
||
<input v-model="row.para" class="form-control" id="para" placeholder="请输入 默认查询参数格式: {k:v}">
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="para" class="col-sm-2 required">数据平台</label>
|
||
<div class="col-xs-6">
|
||
<select v-model="row.dbid" class="form-control">
|
||
<option></option>
|
||
<option v-for="item in dbPlats" :value="item.dbid" v-text="item.dbname"></option>
|
||
</select>
|
||
</div>
|
||
<div class="col-xs-4">
|
||
<select v-model="row.catalog" class="form-control">
|
||
<option></option>
|
||
<option v-for="item in catalogs()" :value="item" v-text="item"></option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="para" class="col-sm-2">备注(注释)</label>
|
||
<div class="col-sm-10">
|
||
<input v-model="row.remark" class="form-control" id="remark" placeholder="请输入 备注">
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||
<button @click="save()" type="button" class="btn btn-primary">确定</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 小对话框 -->
|
||
<!--<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#mySmModal">小对话框</button>-->
|
||
<div class="modal fade" id="mySmModal">
|
||
<div class="modal-dialog modal-sm">
|
||
<div class="modal-header">
|
||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">关闭</span></button>
|
||
<h4 class="modal-title">确认删除数据吗?</h4>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||
<button @click="del()" type="button" class="btn btn-primary">确定</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</row>
|
||
<script src="http://www.1216.top/res/layui/layui.js"></script>
|
||
<script>
|
||
//let {qtaskList, qtaskSave, qtaskDelete} = qtask
|
||
let {dbList} = plat
|
||
|
||
function beforeDrag(treeId, treeNodes) {
|
||
for (let i=0,l=treeNodes.length; i<l; i++) {
|
||
if (treeNodes[i].drag === false) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
function beforeDrop(treeId, treeNodes, targetNode, moveType) {
|
||
return targetNode ? targetNode.drop !== false : true;
|
||
}
|
||
|
||
var vm = new Vue({
|
||
el: ".qtask-list",
|
||
data: {
|
||
sysPlat: red.getData("sysPlat"),
|
||
cfg: {
|
||
title: "QTask 管理",
|
||
cols: [
|
||
{col: "qtaskid", label: "#",},
|
||
{col: "name", label: "任务标识码",},
|
||
{col: "title", label: "任务名称",},
|
||
{col: "remark", label: "备注",},
|
||
],
|
||
filters: [],
|
||
cates: ["find","update"]
|
||
},
|
||
list: {rows:[], total: 0},
|
||
limit: {pn: 1, ps: 20, total: 0},
|
||
row: {name:"",content:"", remark:"", para:"", x:""},
|
||
_row: {name:"",content:"", remark:""},
|
||
dbPlats: [],
|
||
sysPlats: [{name: "工控系统"}],
|
||
editStatus: 0,
|
||
debugRet: "",
|
||
debugData: "",
|
||
debugView: "TABLE", // 0:TABLE, 1:SQL, 3:JSON
|
||
|
||
// ZTree
|
||
setting : {
|
||
edit: {
|
||
enable: true,
|
||
showRemoveBtn: false,
|
||
showRenameBtn: false
|
||
},
|
||
data: {
|
||
simpleData: {
|
||
enable: true
|
||
}
|
||
},
|
||
callback: {
|
||
beforeDrag: beforeDrag,
|
||
beforeDrop: beforeDrop
|
||
}
|
||
}
|
||
},
|
||
watch: {
|
||
row: function (row) {
|
||
if (row.name || row.x) {
|
||
vm.editStatus = 1
|
||
} else {
|
||
vm.editStatus = 0
|
||
}
|
||
if (this.dbPlats.length === 0) {
|
||
dbList().then(res => {
|
||
this.dbPlats = res.rows;
|
||
})
|
||
}
|
||
this.debugRet = ""
|
||
this.debugData = ""
|
||
$(".tpl-content>textarea").attr("rows", this.countLines(row.content))
|
||
$(".tpl-remark>textarea").attr("rows", this.countLines(row.remark, 2, 5))
|
||
}
|
||
},
|
||
methods: {
|
||
loadList: function (pn = 1, x = '') {
|
||
let limit = this.limit.ps
|
||
let offset = (pn - 1) * limit
|
||
qtask.qtaskList({flipper: {offset, limit}}).then(res => {
|
||
this.list = res
|
||
|
||
// 如果页面初次打开,则默认打开第一条记录
|
||
if (x === 'OPEN' && res.rows.length > 0) {
|
||
vm.openDia(res.rows[0])
|
||
}
|
||
|
||
let zNodes = [
|
||
{id: 1, pId: 0, name: "qtask 任务", open: true},
|
||
/*{id: 11, pId: 1, name: "随意拖拽 1-1"},
|
||
{id: 12, pId: 1, name: "随意拖拽 1-2", open: true},*/
|
||
];
|
||
for (let i in res.rows) {
|
||
let row = res.rows[i]
|
||
zNodes.push({id: row.qtaskid, pId: "1", name: row.title + '-(' + row.name+')'})
|
||
}
|
||
|
||
$.fn.zTree.init($("#treeDemo"), this.setting, zNodes);
|
||
this.limit.total = Math.ceil(this.list.total / limit)
|
||
})
|
||
},
|
||
openDia(row) {
|
||
vm.row = red.deepClone(row);
|
||
vm._row = red.deepClone(row);
|
||
vm.editStatus = 1
|
||
/*$('#myModal').modal({moveable: true});
|
||
if (this.dbPlats.length === 0) {
|
||
dbList().then(res => {
|
||
this.dbPlats = res.rows;
|
||
})
|
||
}*/
|
||
this.parsePara(row)
|
||
},
|
||
fullScreen(row) {
|
||
$('#myModal').modal({moveable: true})
|
||
},
|
||
save() {
|
||
qtask.qtaskSave(this.row).then(res => {
|
||
red.showOk()
|
||
red.wait(1000).then(() => {
|
||
this.loadList()
|
||
// this.row = {}
|
||
// $('#myModal').modal('hide')
|
||
})
|
||
})
|
||
},
|
||
dealStatus: function (n) {
|
||
var arr = {"0":"未启用", "1":"启用", "-1":"删除",}
|
||
return arr[n+""] || "";
|
||
},
|
||
comfirmDel: function (row) {
|
||
vm.row = row;
|
||
$('#mySmModal').modal({});
|
||
},
|
||
del: function () {
|
||
qtask.qtaskDelete(this.row.qtaskid).then(res => {
|
||
$('#mySmModal').modal('hide')
|
||
this.loadList()
|
||
})
|
||
},
|
||
abc: function () {
|
||
$(".container-fixed").load("abc.html");
|
||
},
|
||
catalogs: function () {
|
||
let dbPlats = this.dbPlats;
|
||
for (i in dbPlats) {
|
||
if (dbPlats[i].dbid === this.row.dbid) {
|
||
return dbPlats[i]["catalogs"]
|
||
}
|
||
}
|
||
},
|
||
debug: function () {
|
||
qtask.qtaskDebug({task: this.row}).then(res => {
|
||
this.debugRet = res;
|
||
red.showOk("查询成功")
|
||
this.parseDebugRet(res)
|
||
})
|
||
},
|
||
countLines: function (text='', min=3, max=15) {
|
||
// 计算"\n"和"\r\n"两种换行符的数量
|
||
let line = (text.match(/\n/g) || []).length + (text.match(/\r\n/g) || []).length + 1
|
||
if (line < 3) {
|
||
line = min;
|
||
}
|
||
if (line > 15) {
|
||
line = max;
|
||
}
|
||
return line; // 最后+1是因为可能末尾没有换行符,但仍然算一行
|
||
},
|
||
reset: function () {
|
||
this.row = red.deepClone(vm._row)
|
||
},
|
||
parsePara(row) {
|
||
let sql = row.content || ''
|
||
let pattern = /#\((.*?)\)/g; // 创建一个正则表达式来查找 "#()" 内的任何内容
|
||
let match;
|
||
|
||
let para = JSON.parse(row.para)
|
||
let _para = {}
|
||
while ((match = pattern.exec(sql)) !== null) {
|
||
// console.log("提取的变量:", match[1]); // match[1] 存储的是第一个括号内捕获的内容
|
||
_para[match[1]] = para[match[1]] || ''
|
||
}
|
||
|
||
this.row.para = JSON.stringify(_para)
|
||
},
|
||
parseDebugRet(_res) {
|
||
let res = red.deepClone(_res)
|
||
if (res.list && res.list.length > 0) {
|
||
let header = []
|
||
for (let key in res.list[0]) {
|
||
header.push(key)
|
||
}
|
||
res['header'] = header
|
||
|
||
this.debugData = res
|
||
return
|
||
}
|
||
|
||
if (!res.total && res instanceof Object) {
|
||
let header = []
|
||
let _res = {}
|
||
for (let key in res) {
|
||
header.push(key)
|
||
}
|
||
// _res = {header: header, total: 1, list: [res]}
|
||
res['header'] = header
|
||
res['list'] = [res]
|
||
this.debugData = res
|
||
return
|
||
}
|
||
this.debugData = res
|
||
},
|
||
copyToClipboard(text) {
|
||
if (!navigator.clipboard) {
|
||
console.error("Clipboard API not supported.");
|
||
return;
|
||
}
|
||
let _text = text
|
||
if (typeof text !== 'string') {
|
||
_text = JSON.stringify(text)
|
||
}
|
||
|
||
navigator.clipboard.writeText(_text)
|
||
.then(() => {
|
||
red.showOk("调试结果已拷贝到剪贴板")
|
||
})
|
||
.catch(error => {
|
||
console.error("Failed to copy text:", error);
|
||
});
|
||
}
|
||
},
|
||
mounted: function () {
|
||
this.loadList(1, 'OPEN');
|
||
|
||
setTimeout(function () {
|
||
layui.use('code', function(){ //加载code模块
|
||
layui.code(/*{skin: 'notepad'}*/); //引用code方法
|
||
});
|
||
}, 500)
|
||
}
|
||
});
|
||
</script> |