完善程序异常模块,增加查看服务器日志功能
This commit is contained in:
parent
1be3ff60d7
commit
605b0e4e3f
|
@ -0,0 +1 @@
|
||||||
|
请不要删除此目录
|
|
@ -101,6 +101,7 @@
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Content Include="App_Data\ErrorLog\Readme.txt" />
|
||||||
<Content Include="Content\css\admin-responsive.css" />
|
<Content Include="Content\css\admin-responsive.css" />
|
||||||
<Content Include="Content\css\admin.css" />
|
<Content Include="Content\css\admin.css" />
|
||||||
<Content Include="Content\css\blue.css" />
|
<Content Include="Content\css\blue.css" />
|
||||||
|
@ -294,7 +295,6 @@
|
||||||
<Content Include="Views\Home\Register.cshtml" />
|
<Content Include="Views\Home\Register.cshtml" />
|
||||||
<Content Include="Views\Admin\Notifications.cshtml" />
|
<Content Include="Views\Admin\Notifications.cshtml" />
|
||||||
<Content Include="Views\Admin\Infos.cshtml" />
|
<Content Include="Views\Admin\Infos.cshtml" />
|
||||||
<Content Include="Views\Admin\Excep.cshtml" />
|
|
||||||
<Content Include="Views\Admin\Exceptions.cshtml" />
|
<Content Include="Views\Admin\Exceptions.cshtml" />
|
||||||
<Content Include="Views\Admin\Messages.cshtml" />
|
<Content Include="Views\Admin\Messages.cshtml" />
|
||||||
<None Include="Web.Debug.config">
|
<None Include="Web.Debug.config">
|
||||||
|
@ -304,9 +304,7 @@
|
||||||
<DependentUpon>Web.config</DependentUpon>
|
<DependentUpon>Web.config</DependentUpon>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup />
|
||||||
<Folder Include="App_Data\" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Bootstrap.DataAccess\Bootstrap.DataAccess.csproj">
|
<ProjectReference Include="..\Bootstrap.DataAccess\Bootstrap.DataAccess.csproj">
|
||||||
<Project>{af16ca71-b8c6-4f51-b38c-0c0300fdebd7}</Project>
|
<Project>{af16ca71-b8c6-4f51-b38c-0c0300fdebd7}</Project>
|
||||||
|
|
|
@ -96,7 +96,7 @@
|
||||||
right: 16px;
|
right: 16px;
|
||||||
top: 62px;
|
top: 62px;
|
||||||
bottom: 80px;
|
bottom: 80px;
|
||||||
overflow-y: scroll;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-content .modal-footer {
|
.icon-content .modal-footer {
|
||||||
|
|
|
@ -246,7 +246,7 @@
|
||||||
var htmlTemplate = '<div class="form-group checkbox col-lg-3 col-xs-4"><label class="tooltips" data-placement="top" data-original-title="{3}" title="{3}"><input type="checkbox" value="{0}" {2}/>{1}</label></div>';
|
var htmlTemplate = '<div class="form-group checkbox col-lg-3 col-xs-4"><label class="tooltips" data-placement="top" data-original-title="{3}" title="{3}"><input type="checkbox" value="{0}" {2}/>{1}</label></div>';
|
||||||
|
|
||||||
var processData = function (options) {
|
var processData = function (options) {
|
||||||
var data = $.extend({ data: { type: "" }, remote: true, method: "POST", Id: "", url: this.url, title: this.title, html: this.html }, options);
|
var data = $.extend({ data: { type: "" }, remote: true, method: "POST", Id: "", url: this.url, title: this.title, html: this.html, swal: true }, options);
|
||||||
|
|
||||||
if (data.remote) {
|
if (data.remote) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
@ -275,14 +275,14 @@
|
||||||
else if ($.isPlainObject(data.callback) && data.callback.modal !== undefined) {
|
else if ($.isPlainObject(data.callback) && data.callback.modal !== undefined) {
|
||||||
$("#" + data.callback.modal).modal('hide');
|
$("#" + data.callback.modal).modal('hide');
|
||||||
}
|
}
|
||||||
if (data.remote) {
|
if (data.swal) {
|
||||||
if (result) { swal("成功", data.title, "success"); }
|
if (result) { swal("成功", data.title, "success"); }
|
||||||
else { swal("失败", data.title, "error"); }
|
else { swal("失败", data.title, "error"); }
|
||||||
}
|
}
|
||||||
if ($.isFunction(data.callback)) data.callback(result);
|
if ($.isFunction(data.callback)) data.callback(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Role
|
// Roles
|
||||||
Role = {
|
Role = {
|
||||||
url: '../api/Roles/',
|
url: '../api/Roles/',
|
||||||
title: "授权角色",
|
title: "授权角色",
|
||||||
|
@ -354,7 +354,8 @@
|
||||||
Group.saveGroupsByRoleId = function (roleId, groupIds, callback) {
|
Group.saveGroupsByRoleId = function (roleId, groupIds, callback) {
|
||||||
processData.call(this, { Id: roleId, callback: callback, method: "PUT", data: { type: "role", groupIds: groupIds } });
|
processData.call(this, { Id: roleId, callback: callback, method: "PUT", data: { type: "role", groupIds: groupIds } });
|
||||||
};
|
};
|
||||||
//Menus
|
|
||||||
|
// Menus
|
||||||
Menu = {
|
Menu = {
|
||||||
url: '../api/Menus/',
|
url: '../api/Menus/',
|
||||||
title: "授权菜单",
|
title: "授权菜单",
|
||||||
|
@ -387,6 +388,7 @@
|
||||||
Menu.saveMenusByRoleId = function (roleId, menuIds, callback) {
|
Menu.saveMenusByRoleId = function (roleId, menuIds, callback) {
|
||||||
processData.call(this, { Id: roleId, callback: callback, method: "PUT", data: { type: "role", menuIds: menuIds } });
|
processData.call(this, { Id: roleId, callback: callback, method: "PUT", data: { type: "role", menuIds: menuIds } });
|
||||||
};
|
};
|
||||||
|
|
||||||
//Profiles
|
//Profiles
|
||||||
Profiles = {
|
Profiles = {
|
||||||
url: '../api/Profiles/',
|
url: '../api/Profiles/',
|
||||||
|
@ -395,4 +397,21 @@
|
||||||
Profiles.saveWebSite = function (options) {
|
Profiles.saveWebSite = function (options) {
|
||||||
processData.call(this, { data: options });
|
processData.call(this, { data: options });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exceptions
|
||||||
|
Exceptions = {
|
||||||
|
url: '../api/Exceptions/',
|
||||||
|
title: "程序异常日志",
|
||||||
|
html: function (result) {
|
||||||
|
return result.map(function (ele) {
|
||||||
|
return $.format('<div class="form-group col-lg-3 col-md-3 col-sm-4 col-xs-6"><a href="#">{0}</a></div>', ele);
|
||||||
|
}).join('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Exceptions.getFiles = function (callback) {
|
||||||
|
processData.call(this, { Id: "", callback: callback });
|
||||||
|
}
|
||||||
|
Exceptions.getFileByName = function (fileName, callback) {
|
||||||
|
processData.call(this, { Id: "", callback: callback, method: "PUT", swal: false, data: { "": fileName } });
|
||||||
|
}
|
||||||
})(jQuery);
|
})(jQuery);
|
|
@ -113,18 +113,6 @@ namespace Bootstrap.Admin.Controllers
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ActionResult Excep()
|
|
||||||
{
|
|
||||||
using (System.IO.StreamReader reader = new System.IO.StreamReader(Server.MapPath("~/App_Data/ErrorLog/Error2016-11-11.log")))
|
|
||||||
{
|
|
||||||
ViewBag.Content = new MvcHtmlString(reader.ReadToEnd().Replace("\r\n", "</br>"));
|
|
||||||
}
|
|
||||||
return View();
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public ActionResult Exceptions()
|
public ActionResult Exceptions()
|
||||||
{
|
{
|
||||||
var v = new NavigatorBarModel("~/Admin/Exceptions");
|
var v = new NavigatorBarModel("~/Admin/Exceptions");
|
||||||
|
|
|
@ -1,20 +1,48 @@
|
||||||
using Bootstrap.Admin.Models;
|
using Bootstrap.Admin.Models;
|
||||||
using Bootstrap.DataAccess;
|
using Bootstrap.DataAccess;
|
||||||
using System.Web.Http;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
namespace Bootstrap.Admin.Controllers
|
using System.Linq;
|
||||||
{
|
using System.Web;
|
||||||
public class ExceptionsController : ApiController
|
using System.Web.Http;
|
||||||
{
|
|
||||||
/// <summary>
|
namespace Bootstrap.Admin.Controllers
|
||||||
/// 显示所有异常
|
{
|
||||||
/// </summary>
|
public class ExceptionsController : ApiController
|
||||||
/// <param name="id"></param>
|
{
|
||||||
/// <returns></returns>
|
/// <summary>
|
||||||
[HttpGet]
|
/// 显示所有异常
|
||||||
public QueryData<Exceptions> Get([FromUri]QueryExceptionOption value)
|
/// </summary>
|
||||||
{
|
/// <param name="id"></param>
|
||||||
return value.RetrieveData();
|
/// <returns></returns>
|
||||||
}
|
[HttpGet]
|
||||||
}
|
public QueryData<Exceptions> Get([FromUri]QueryExceptionOption value)
|
||||||
}
|
{
|
||||||
|
return value.RetrieveData();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public IEnumerable<string> Post()
|
||||||
|
{
|
||||||
|
var filePath = HttpContext.Current.Server.MapPath("~/App_Data/ErrorLog");
|
||||||
|
return Directory.GetFiles(filePath).Select(f => Path.GetFileNameWithoutExtension(f)).OrderByDescending(s => s);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPut]
|
||||||
|
public dynamic Put([FromBody]string fileName)
|
||||||
|
{
|
||||||
|
var logName = HttpContext.Current.Server.MapPath(string.Format("~/App_Data/ErrorLog/{0}.log", fileName));
|
||||||
|
if (!File.Exists(logName)) return new { content = string.Empty };
|
||||||
|
using (StreamReader reader = new StreamReader(logName))
|
||||||
|
{
|
||||||
|
return new { content = reader.ReadToEnd().Replace("\r\n", "</br>") };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,42 +1,53 @@
|
||||||
$(function () {
|
$(function () {
|
||||||
var bsa = new BootstrapAdmin({
|
var $dialog = $('#dialogNew');
|
||||||
url: '../api/Exceptions',
|
var $dataForm = $('#dataForm');
|
||||||
dataEntity: new DataEntity({
|
var $dataFormDetail = $('#dataFormDetail');
|
||||||
map: {
|
var $errorList = $('#errorList');
|
||||||
ID: "ID",
|
var $errorDetail = $('#errorDetail');
|
||||||
AppDomainName: "appDomainName",
|
var $errorDetailTitle = $('#myDetailModalLabel');
|
||||||
ErrorPage: "errorPage",
|
|
||||||
UserID: "userId",
|
$('table').smartTable({
|
||||||
UserIp: "userIp",
|
url: '../api/Exceptions',
|
||||||
Message: "message",
|
sortName: 'ErrorPage',
|
||||||
StackTrace: "stackTrace",
|
queryParams: function (params) { return $.extend(params, { OperateTimeStart: $("#txt_operate_start").val(), OperateTimeEnd: $("#txt_operate_end").val() }); },
|
||||||
LogTime:"logTime"
|
columns: [{ checkbox: true },
|
||||||
}
|
{ title: "请求网址", field: "ErrorPage", sortable: false },
|
||||||
}),
|
{ title: "用户名", field: "UserID", sortable: false },
|
||||||
})
|
{ title: "IP", field: "UserIp", sortable: false },
|
||||||
$('table').smartTable({
|
{ title: "错误", field: "Message", sortable: false },
|
||||||
url: '../api/Exceptions', //请求后台的URL(*)
|
{
|
||||||
sortName: 'AppDomainName',
|
title: "异常捕获时间", field: "LogTime", sortable: true, formatter: function (value, row, index) {
|
||||||
queryParams: function (params) { return $.extend(params, { OperateTimeStart: $("#txt_operate_start").val(), OperateTimeEnd: $("#txt_operate_end").val() }); }, //传递参数(*)
|
return new Date(value).format("yyyy-MM-dd HH:mm:ss");
|
||||||
columns: [{ checkbox: true },
|
}
|
||||||
{ title: "APP域名", field: "AppDomainName", sortable: true },
|
}
|
||||||
{ title: "错误页", field: "ErrorPage", sortable: false },
|
]
|
||||||
{
|
});
|
||||||
title: "用户名", field: "UserID", sortable: false,
|
|
||||||
},
|
$('input[type="datetime"]').parent().datetimepicker({
|
||||||
{ title: "用户IP", field: "UserIp", sortable: false },
|
locale: "zh-cn",
|
||||||
{ title: "备注", field: "Message", sortable: false },
|
format: "YYYY-MM-DD"
|
||||||
{ title: "栈记录", field: "StackTrace", sortable: false },
|
});
|
||||||
{ title: "异常捕获时间", field: "LogTime", sortable: false,
|
|
||||||
formatter: function (value, row, index) {
|
$('#btn_view').on('click', function (row) {
|
||||||
return value.substring(0, 19).replace("T", " ");
|
Exceptions.getFiles(function (data) {
|
||||||
}
|
$dataForm.children('div').html(data);
|
||||||
}
|
});
|
||||||
]
|
$dialog.modal('show');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('input[type="datetime"]').parent().datetimepicker({
|
$dialog.on('click', 'a', function () {
|
||||||
locale: "zh-cn",
|
var fileName = $(this).text();
|
||||||
format: "YYYY-MM-DD"
|
$errorDetailTitle.text(fileName);
|
||||||
});
|
$errorList.hide();
|
||||||
|
$errorDetail.show();
|
||||||
|
$dataFormDetail.html('<div class="text-center"><i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i></div>');
|
||||||
|
Exceptions.getFileByName(fileName, function (data) {
|
||||||
|
$dataFormDetail.html(data.content);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$errorDetail.on('click', 'button', function () {
|
||||||
|
$errorDetail.hide();
|
||||||
|
$errorList.show();
|
||||||
|
});
|
||||||
});
|
});
|
|
@ -1,5 +0,0 @@
|
||||||
@{
|
|
||||||
ViewBag.Title = "Excep";
|
|
||||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
|
||||||
}
|
|
||||||
<div>@ViewBag.Content</div>
|
|
|
@ -1,62 +1,108 @@
|
||||||
@model NavigatorBarModel
|
@model NavigatorBarModel
|
||||||
@{
|
@{
|
||||||
ViewBag.Title = "程序异常";
|
ViewBag.Title = "程序异常";
|
||||||
Layout = "~/Views/Shared/_Admin.cshtml";
|
Layout = "~/Views/Shared/_Admin.cshtml";
|
||||||
}
|
}
|
||||||
@section css {
|
@section css {
|
||||||
<link href="~/Content/css/bootstrap-table.css" rel="stylesheet" />
|
<link href="~/Content/css/bootstrap-table.css" rel="stylesheet" />
|
||||||
<link href="~/Content/css/bootstrap-datetimepicker.css" rel="stylesheet" />
|
<link href="~/Content/css/bootstrap-datetimepicker.css" rel="stylesheet" />
|
||||||
}
|
<link href="~/Content/css/fa.css" rel="stylesheet" />
|
||||||
@section Javascript {
|
}
|
||||||
<script src="~/content/js/bootstrap-table.js"></script>
|
@section Javascript {
|
||||||
<script src="~/content/js/bootstrap-table-zh-CN.js"></script>
|
<script src="~/content/js/bootstrap-table.js"></script>
|
||||||
<script src="~/Content/js/moment-with-locales.js"></script>
|
<script src="~/content/js/bootstrap-table-zh-CN.js"></script>
|
||||||
<script src="~/Content/js/bootstrap-datetimepicker.js"></script>
|
<script src="~/Content/js/moment-with-locales.js"></script>
|
||||||
<script src="~/content/js/longbow.dataentity.js"></script>
|
<script src="~/Content/js/bootstrap-datetimepicker.js"></script>
|
||||||
<script src="~/scripts/Exceptions.js"></script>
|
<script src="~/content/js/longbow.dataentity.js"></script>
|
||||||
}
|
<script src="~/scripts/Exceptions.js"></script>
|
||||||
@section header {
|
}
|
||||||
@Html.Partial("Header", Model)
|
@section header {
|
||||||
}
|
@Html.Partial("Header", Model)
|
||||||
@section navigator {
|
}
|
||||||
@Html.Partial("Navigator", Model)
|
@section navigator {
|
||||||
}
|
@Html.Partial("Navigator", Model)
|
||||||
<div class="panel panel-default">
|
}
|
||||||
<div class="panel-heading">查询条件</div>
|
<div class="panel panel-default">
|
||||||
<div class="panel-body">
|
<div class="panel-heading">查询条件</div>
|
||||||
<form class="form-inline" role="form">
|
<div class="panel-body">
|
||||||
<div class="row">
|
<form class="form-inline" role="form">
|
||||||
<div class="form-group col-xs-12 col-sm-6 col-md-5 col-lg-5">
|
<div class="row">
|
||||||
<label class="control-label" for="txt_operate_start">起始时间</label>
|
<div class="form-group col-xs-12 col-sm-6 col-md-5 col-lg-5">
|
||||||
<div class="input-group date">
|
<label class="control-label" for="txt_operate_start">起始时间</label>
|
||||||
<input type="datetime" class="form-control" id="txt_operate_start" />
|
<div class="input-group date">
|
||||||
<span class="input-group-btn">
|
<input type="datetime" class="form-control" id="txt_operate_start" />
|
||||||
<button class="btn btn-default" type="button"><i class="fa fa-calendar" aria-hidden="true"></i></button>
|
<span class="input-group-btn">
|
||||||
</span>
|
<button class="btn btn-default" type="button"><i class="fa fa-calendar" aria-hidden="true"></i></button>
|
||||||
</div>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-xs-12 col-sm-6 col-md-5 col-lg-5">
|
</div>
|
||||||
<label class="control-label" for="txt_operate_end">终止时间</label>
|
<div class="form-group col-xs-12 col-sm-6 col-md-5 col-lg-5">
|
||||||
<div class="input-group input-append date form_datetime">
|
<label class="control-label" for="txt_operate_end">终止时间</label>
|
||||||
<input type="datetime" class="form-control" id="txt_operate_start" />
|
<div class="input-group input-append date form_datetime">
|
||||||
<span class="input-group-btn">
|
<input type="datetime" class="form-control" id="txt_operate_start" />
|
||||||
<button class="btn btn-default" type="button"><i class="fa fa-calendar" aria-hidden="true"></i></button>
|
<span class="input-group-btn">
|
||||||
</span>
|
<button class="btn btn-default" type="button"><i class="fa fa-calendar" aria-hidden="true"></i></button>
|
||||||
</div>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
|
</div>
|
||||||
<label class="sr-only"></label>
|
<div class="form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
|
||||||
<button type="button" id="btn_query" class="btn btn-primary form-control"><span class="glyphicon glyphicon-search" aria-hidden="true"></span>查询</button>
|
<label class="sr-only"></label>
|
||||||
</div>
|
<button type="button" id="btn_query" class="btn btn-primary form-control"><span class="glyphicon glyphicon-search" aria-hidden="true"></span>查询</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
<div class="toolbar btn-group dropdown">
|
||||||
</div>
|
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button"><i class="fa fa-gear"></i></button>
|
||||||
</div>
|
<div class="dropdown-menu">
|
||||||
<div class="panel panel-default">
|
<a id="tb_view" href="#" title="查看明细"><i class="fa fa-file-text-o"></i></a>
|
||||||
<div class="panel-heading">
|
</div>
|
||||||
查询结果
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
</form>
|
||||||
<table></table>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div id="toolbar" class="btn-group">
|
||||||
|
<button id="btn_view" type="button" class="btn btn-danger">
|
||||||
|
<span class="fa fa-file-text-o" aria-hidden="true"></span>服务器日志
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
查询结果
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<table></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@section modal {
|
||||||
|
<div class="modal fade" id="dialogNew" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||||
|
<div id="errorList" class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title" id="myModalLabel">程序异常日志窗口</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form class="form-inline" id="dataForm" name="dataForm" role="form"><div class="row"></div></form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||||
|
关闭
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="errorDetail" class="modal-content icon-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title" id="myDetailModalLabel">程序异常日志窗口</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div id="dataFormDetail"><div class="text-center"><i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i></div></div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default">
|
||||||
|
关闭
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue