Files
meta-kit/root/qtask/list.html
绝尘 36a30ba2b3 新增:1、qtask-debug结果渲染为表格
2、mdict 存贮到MySQL, meta 业务预览支持字典渲染验证
     3、其他交互优化
2024-04-05 00:30:11 +08:00

550 lines
23 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>