开源模块化前端 UI 框架
由职业前端倾情打造,面向全层次的前后端开发者,易上手开源免费的 Web UI 组件库
非常适合开发后台管理系统。
它和VFP碰撞的火花,该是什么样的呢?
经过猫猫的试用,极简快速开发,很适合个人和小团队开发,非常适合和猫猫的祺佑三层开发框架配合使用,一前一后,配合丝滑。
来看看完成的效果图
开箱即用的感觉非常好。
layui框架下载地址
https://layui.dev/
前端页面 contact.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 引入 layui.css -->
<link rel="stylesheet" href="layui/css/layui.css">
<!-- 引入 layui.js -->
<script src="layui/layui.js"></script>
<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
</script>
</head>
<body>
<!-- 搜索栏 -->
<div class="layui">
<div class="layui-row">
<div class="layui-col-md5">
<i class="layui-icon layui-icon-search"></i>
请输入:
<div class="layui-inline">
<input type="text" class="layui-input" id="txttj">
</div>
<button id="btncx" type="button" class="layui-btn layui-btn-normal">
<i class="layui-icon layui-icon-search"></i>
查询
</button>
<button id="btn_add" type="button" class="layui-btn">新增</button>
</div>
</div>
</div>
<table id="demo" lay-filter="test"></table>
<div id="page1"></div>
<script>
var row; //用于父子页面交换
var serverurl = "http://127.0.0.1:801/"
layui.use(['laydate', 'laypage', 'jquery', 'table'], function() {
var laydate = layui.laydate,laypage = layui.laypage,$ = layui.$,layer = layui.layer,table = layui.table;
$("#btncx").click(function() {
select()
})
//绑定新增按钮的点击事件
$('#btn_add').click(function() {
row = null;
open('新增');
});
//加载表格
initTable();
//1.初始化数据表格
function initTable() {
//表格加载
var url = serverurl + "ctl_contact.fsp?proc=getlist";
//第一个实例
var tableIns = table.render({
elem: '#demo'
//,height: 500
,
height: 'full',
url: url //数据接口
,
page: true //开启分页
,
cols: [
[ //表头
{
field: 'id',
title: 'ID',
width: 80,
sort: true,
fixed: 'left'
}, {
field: 'lxr1',
title: '联系人',
width: 120
}, {
field: 'lxr1tel',
title: '电话',
width: 200
}
// ,{field: 'lxr2', title: '联系人1', width:120}
// ,{field: 'lxr2tel', title: '电话2', width:200}
, {
field: 'memo',
title: '备注',
width: 200
}, {
field: 'ctime',
title: '创建时间',
width: 177,
sort: true
}, {
fixed: 'right',
width: 200,
align: 'center',
toolbar: '#barDemo'
} //这里的toolbar值是模板元素的选择器
]
],
where: {
tj: ""
},
parseData: function(res) { //res 即为原始返回的数据
console.log(res);
return {
"code": res.errno, //解析接口状态
"msg": res.errmsg, //解析提示文本
"count": res.total, //解析数据长度
"data": res.rows //解析数据列表
};
},
});
//工具条事件
table.on('tool(test)', function(obj) { //注:tool 是工具条事件名,test 是 table 原始容器的属性 lay-filter="对应的值"
console.log(obj);
var data = obj.data; //获得当前行数据
var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)
var tr = obj.tr; //获得当前行 tr 的 DOM 对象(如果有的话)
if (layEvent === 'del') { //删除
layer.confirm('真的删除行么', function(index) {
//向服务端发送删除指令
$.post(serverurl + "ctl_contact.fsp?proc=del", JSON.stringify(data),
function(rs) {
console.log(rs);
if (rs.errno == 0) {
obj.del(); //删除对应行(tr)的DOM结构,并更新缓存
layer.close(index);
} else {
layer.msg(rs.errmsg, function() {});
}
}, 'json');
});
} else if (layEvent === 'edit') { //编辑
//do something
row = obj.data; //将这张表中的数据赋给row这个变量
open("编辑")
}
});
}
//2.点击查询
function select() {
table.reload("demo",{
where: { //设定异步数据接口的额外参数,任意设
tj: $("#txttj").val()
},
page: {
curr: 1 //重新从第 1 页开始
}
});
}
//3.对话框操作
function open(title) {
layer.open({
type: 2, //layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)
title: title,
area: ['660px', '340px'], //宽高
skin: 'layui-layer-rim', //样式类名
content: 'contact_edit.html', //编辑页面
btn: ['保存', '关闭'],
yes: function(index, layero) {
//调用子页面中提供的getData方法,快速获取子页面的form表单数据
let data = $(layero).find("iframe")[0].contentWindow.getData(); //父调子
console.log(data);
$.post(serverurl + "ctl_contact.fsp?proc=save", JSON.stringify(data),
function(rs) {
console.log(rs);
if (rs.errno == 0) {
//关闭对话框
layer.closeAll();
//调用查询方法刷新数据
select();
} else {
layer.msg(rs.errmsg, function() {});
}
}, 'json');
},
btn2: function(index, layero) {
layer.closeAll();
},
});
}
});
</script>
</body>
</html>
前端页面contact_edit.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 引入 layui.css -->
<link rel="stylesheet" href="layui/css/layui.css">
<!-- 引入 layui.js -->
<script src="layui/layui.js"></script>
<style>
.layui-form-select dl{
max-height:150px;
}
</style>
</head>
<body>
<div style="padding:10px;">
<form class="layui-form layui-form-pane" lay-filter="user">
<input type="hidden" name="id"/>
<div class="layui-form-item">
<label class="layui-form-label">联系人</label>
<div class="layui-input-block">
<input type="text" id="lxr1" name="lxr1" autocomplete="off" placeholder="请输入联系人" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">联系电话</label>
<div class="layui-input-block">
<input type="text" name="lxr1tel" lay-verify="required" placeholder="请输入联系电话" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">备注</label>
<div class="layui-input-block">
<input type="memo" name="memo" placeholder="请输入备注" autocomplete="off" class="layui-input">
</div>
</div>
</form>
</div>
<script>
var myform;
layui.use(['layer','form','jquery'],function(){
let layer=layui.layer,form=layui.form, $=layui.jquery;
myform=form;
initData();
function initData(){
console.log(parent.row);
if(null!=parent.row){//子调父
//点击编辑按钮的时候
//$.extend({}, parent.row || {}) 的作用是创建一个新的对象,并将 parent.row 中的键值对复制到该新对象中,达到给表单赋值的目的
form.val('user',$.extend({}, parent.row||{}));//将父页面传递的行数据赋值到名为 'user' 的表单中
}
}
});
function getData(){
//<form class="layui-form layui-form-pane" lay-filter="user">
//取 user from中的值
return myform.val('user');
}
</script>
</body>
</html>
后端ctl_contact.prg 数据库是mysql,mssql的TSQL语句有点点不同。
Define Class ctl_contact As Session
Procedure getlist
Do setenv
ctj=HttpQueryParams2("tj")
cpageno=HttpQueryParams2("page")
cpagesize=HttpQueryParams2("limit")
cpagesize=Iif(Empty(cpagesize),"0",cpagesize)
TEXT TO lcSQLcmd1 NOSHOW TEXTMERGE
select COUNT(*) from contact WHERE 1=1
ENDTEXT
cwhere=""
oDBSQLhelper=Newobject("MSSQLHelper","MSSQLHelper.prg")
nPageno=Int((Val(cpageno)-1)*Val(cpagesize))
TEXT TO lcSQLcmd NOSHOW TEXTMERGE
select * from contact WHERE 1=1
ENDTEXT
If !Empty(ctj)
cwhere=Textmerge(" and (lxr1 like '%<<ctj>>%' or lxr1tel like '%<<ctj>>%' or lxr2 like '%<<ctj>>%' or lxr2tel like '%<<ctj>>%')")
lcSQLcmd = lcSQLcmd + cwhere
lcSQLcmd1 = lcSQLcmd1 + cwhere
Endif
lcSQLCmd = lcSQLCmd + Textmerge(" limit <<nPageno>>,<<cpagesize>> ")
uCount=oDBSQLhelper.GetSingle(lcSQLCmd1)
If Isnull(uCount) And !Empty(oDBSQLhelper.errmsg)
Error oDBSQLhelper.errmsg
Endif
If oDBSQLhelper.SQLQuery(lcSQLCmd,"devdata")<0
Error oDBSQLhelper.errmsg
Endif
Return cursortojson("devdata",Val(uCount))
Endproc
Procedure Save
cPostData=HttpGetPostData()
If Empty(cPostData)
Error "数据为空"
Endif
odal=Newobject("Dal_contact","Dal_contact.prg")
If !odal.parsejson(cPostData,"",0,"id")
Error odal.msg
Endif
If !odal.Save()
Error odal.msg
Endif
Return cursortojson(odal.Alias)
Endproc
Procedure del
cPostData=HttpGetPostData()
If Empty(cPostData)
Error "数据为空"
Endif
odal=Newobject("Dal_contact","Dal_contact.prg")
If !odal.parsejson(cPostData,"",0,"id")
Error odal.msg
Endif
Delete All
If !odal.Save()
Error odal.msg
Endif
Return [{"errno":0,"errmsg":"ok"}]
Endproc
Enddefine
运行测试,代码极少,完美。