最近工作中有个开发主站的需求,做为一个前端零基础的小白,在开发过程中踩了很多坑,走了很多弯路,这里记录一下遇到的问题与解决方法。( 前端:Layui 后端:ASP.NET)
一、笔记
1.使用Layui需要项目中引用相关资源
<!-- 引入 layui.css -->
<link href="../../layuiadmin/layui/css/layui.css" rel="stylesheet">
<!-- 引入 layui.js -->
<script src="../../layuiadmin/layui/layui.js"></script>
2.添加界面时需要后台添加显示接口
3.通过lay-herf调用webapi接口打开相应的界面
<a lay-href="" lay-tips="主页" lay-direction="2">
<a lay-href="Home/MonitoringPageOne">其他界面</a>
4.在config.js中进行全局配置
5.通过dom操作实现js与html交互
1.通过 id 查找 HTML 元素:
var x=document.getElementById("intro");
2.通过标签名查找 HTML 元素
var x=document.getElementById("main");
var y=x.getElementsByTagName("p");
3.通过类名找到 HTML 元素
var x=document.getElementsByClassName("intro");
6.获取后端的数据
$.get("/Monitoring/GetAllStatus", function (r) {
if (r === undefined || r === null) {
return;
}
}
var data = { Line: dev, Action: fun };
$.post("/Monitoring/PostClient", data, function (s) {
if (s==1) {
alert("设置成功!");
}
else{
alert("设置失败!");
}
});
二、问题与感悟
1. 选则框无法显示样式
<div class="layui-form layui-row layui-col-space16">
<div class="layui-col-md6">
<select>
<option value="">请选择</option>
<option value="AAA">选项 A</option>
<option value="BBB">选项 B</option>
<option value="CCC">选项 C</option>
</select>
</div>
</div>
使用上述代码后运行始终无法显示样式,但其他如文本框、复选框的都能正常显示,百思不得其解,最后使用如下代码解决。
layui.use('form', function () {
var form = layui.form; //只有执行了这一步,部分表单元素才会自动修饰成功
form.render();
});
2. 前端调用post接口时产生的跨域问题
这里我需要实现主站去调用其他软件接口的需求,不可避免的产生跨域问题,用postman调用接口没问题,但使用前端一直提示跨域缺少设置头。前端测试代码如下
网上找了很多方法都无法解决,一筹莫展之际想到了仿照代理服务器方法,于是采用一个比较巧妙的技巧:
通过本域前端调本域后台,本域后台调跨域接口,接收到的数据再由后台传给前端,所有就不存在前端跨域问题了。问题果然解决了!!!测试代码如下
前端代码:
function SetPLC() {
//获取选择框的数值
var dev = $("#formDev option:selected");
var fun = $("#formFun option:selected");
console.log("plc=", dev.text(), dev.val());
console.log("plc=", fun.text(), fun.val());
var data = { Line: dev, Action: fun };
//调用自己的后台接口
$.post("/Monitoring/PostClient", data, function (s) {
if (s==1) {
alert("设置成功!");
}
else{
alert("设置失败!");
}
});
}
后端代码:
先依赖注入
private readonly IHttpClientFactory httpClientFactory;
public MonitoringController(IHttpClientFactory _httpClientFactory)
{
httpClientFactory= _httpClientFactory;
}
本域的后台接口调用跨域的后台接口
/// <summary>
/// 带参数post接口调用
/// </summary>
/// <param name="addr">地址</param>
/// <param name="data">数据</param>
/// <returns></returns>
[Public]
[HttpPost]
public async Task<string> PostClient(PlcActionData data)
{
try
{
if(data==null)
{
return "0";
}
var addr = "http://199.999.99.999:8100/Line/SetPlcAction";
var httpClient = httpClientFactory.CreateClient();
var reqjson = new StringContent(
JsonSerializer.Serialize(data),
Encoding.UTF8,
"Application/Json"
);
using var httpres = await httpClient.PostAsync(addr, reqjson);
var readstr = await httpres.Content.ReadAsStringAsync();
return readstr;
}
catch (Exception ex)
{
return "0";
}
}
}
成功解决!nice!
3.弹窗功能
废话不多说,直接上代码
<div id="弹框" style="display: none;">
这是一个隐藏的弹框
</div>
function showTrayMessage(device) {
var m='#'+device;
layer.open({
type: 1, // page 层类型
area: ['500px', '300px'],
title: '当前托盘',
shade: false, // 不显示遮罩
shadeClose: true, // 点击遮罩区域,关闭弹层
maxmin: true, // 允许全屏最小化
anim: 0, // 0-6 的动画形式,-1 不开启
//content: '<div style="padding: 32px;">一个普通的页面层,传入了自定义的 HTML</div>'
content: $(m), // 捕获的元素
});
};
单击界面上的文字调用弹窗方法
<a href="javascript:showTrayMessage('弹框')">
<h3 class="layadmin-title">
<strong>点我弹框</strong>
</h3>
</a>
4.获取当前选定的日期
前端html的日期选择框和js渲染
<div class="layui-form layui-row layui-col-space16">
<br />
<br />
<div class="layui-inline">
<label class="layui-form-label" style="font-size:20px;">选择日期</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" id="ID-laydate-demo" placeholder="实时日期">
</div>
<br>
<br>
<div style="padding-bottom: 20px; padding-left:300px">
<button class="layui-btn layuiadmin-btn-useradmin" data-type="batchdel" onclick="SetDateTime()">确定</button>
</div>
</div>
</div>
layui.use(function () {
var laydate = layui.laydate;
// 渲染
laydate.render({
elem: '#ID-laydate-demo'
});
});
点击按钮上传日期的js方法 ,通过jquery获取input输入框的值
function SetDateTime()
{
var time = $('#ID-laydate-demo').val();
var data = {time};
console.log("time=", data);
$.post("/Monitoring/SetShowTime", data, function (s) {
if (s == 1) {
alert("设置指定日期成功!");
}
else {
alert("设置实时日期成功!");
}
});
}
后台接收前端的日期
[Public]
[HttpPost]
public int SetShowTime([FromBody]string time)
{
Logger.Info($"请求设置大屏展示时间为:{time}");
if (time!=null&&time!="")
{
RuningTest.isRunning=true;
RuningTest.today = Convert.ToDateTime(time);
return 1;
}
else
{
RuningTest.isRunning = false;
return 0;
}
}
5.多次调用定时器问题
在开发前端时遇到了一个奇怪的现象,我需要写一个轮询获取数据的界面 ,所以需要开一个定时,但是我退出这个界面时定时器没有被清除,重开打开界面后定时器又多调了一个,导致有多个定时器同时执行。
解决问题的思路还是和上面一样,前端解决不了的就放在后端解决。获取当前定时器的id,在把值传给后端。
function StartInterval() {
timerId = setInterval(GetTrayMessage, 5000);
console.log("定时器ID:",timerId);
var data = { timerId };
$.post("/Monitoring/MonitoringTimerId", data, function (s) {
if (s === undefined || s === null) {
return;
}
if (s!=-1) {
clearInterval(s);
}
});
}
StartInterval();
后端拿到id后储存起来,等下次再获取id后进行一个对比,返回旧的id由前端清除
[Public]
[HttpPost]
public int MonitoringTimerId([FromBody] string timerId)
{
Logger.Info($"获取定时器id值为:{timerId}");
var id = int.Parse(timerId);
var oldId = RuningTest.timerId;
if (RuningTest.timerId != id)
{
RuningTest.timerId = id;
Logger.Info($"删除原来定时器id值为:{oldId}");
return oldId;
}
return -1;
}