|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace Bootstrap.Admin.Controllers
|
|||
ViewBag.UserName = "Admin";
|
||||
ViewBag.Password = "123789";
|
||||
}
|
||||
return User.Identity.IsAuthenticated ? (ActionResult)Redirect("~/Home/Index") : View("Login", new ModelBase());
|
||||
return User.Identity.IsAuthenticated ? (ActionResult)Redirect("~/Home/Index") : View("Login", new LoginModel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -56,8 +56,8 @@ namespace Bootstrap.Admin.Controllers
|
|||
// redirect origin url
|
||||
var originUrl = Request.Query[CookieAuthenticationDefaults.ReturnUrlParameter].FirstOrDefault() ?? "~/Home/Index";
|
||||
return Redirect(originUrl);
|
||||
}
|
||||
return View("Login", new ModelBase());
|
||||
}
|
||||
return View("Login", new LoginModel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
using Bootstrap.DataAccess;
|
||||
|
||||
namespace Bootstrap.Admin.Models
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class LoginModel : ModelBase
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public LoginModel()
|
||||
{
|
||||
ImageLibUrl = DictHelper.RetrieveImagesLibUrl();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证码图床地址
|
||||
/// </summary>
|
||||
public string ImageLibUrl { get; protected set; }
|
||||
}
|
||||
}
|
|
@ -1,219 +1,220 @@
|
|||
@model ModelBase
|
||||
@{
|
||||
ViewBag.Title = Model.Title;
|
||||
Layout = "_Layout";
|
||||
}
|
||||
@section css {
|
||||
<environment include="Development">
|
||||
<link href="~/lib/twitter-bootstrap/css/bootstrap.css" rel="stylesheet" />
|
||||
<link href="~/lib/font-awesome/css/font-awesome.css" rel="stylesheet" />
|
||||
<link href="~/lib/bootstrap-sweetalert/sweetalert.css" rel="stylesheet" />
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<link href="~/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
||||
<link href="~/lib/font-awesome/css/font-awesome.min.css" rel="stylesheet" />
|
||||
<link href="~/lib/bootstrap-sweetalert/sweetalert.min.css" rel="stylesheet" />
|
||||
</environment>
|
||||
<link href="~/lib/captcha/slidercaptcha.css" rel="stylesheet" />
|
||||
<link href="~/css/theme.css" rel="stylesheet" asp-append-version="true" />
|
||||
<link href="~/css/login.css" rel="stylesheet" asp-append-version="true" />
|
||||
<link href="~/css/login-responsive.css" rel="stylesheet" asp-append-version="true" />
|
||||
@if (!string.IsNullOrEmpty(Model.Theme))
|
||||
{
|
||||
<link href="~/css/@Model.Theme" rel="stylesheet" asp-append-version="true" />
|
||||
}
|
||||
}
|
||||
@section javascript {
|
||||
<environment include="Development">
|
||||
<script src="~/lib/twitter-bootstrap/js/bootstrap.bundle.js"></script>
|
||||
<script src="~/lib/validate/jquery.validate.js"></script>
|
||||
<script src="~/lib/validate/localization/messages_zh.js"></script>
|
||||
<script src="~/lib/bootstrap-sweetalert/sweetalert.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="~/lib/twitter-bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="~/lib/validate/jquery.validate.min.js"></script>
|
||||
<script src="~/lib/validate/localization/messages_zh.min.js"></script>
|
||||
<script src="~/lib/bootstrap-sweetalert/sweetalert.min.js"></script>
|
||||
</environment>
|
||||
<script src="~/lib/captcha/longbow.slidercaptcha.js"></script>
|
||||
<script src="~/lib/longbow/longbow.common.js"></script>
|
||||
<script src="~/lib/longbow/longbow.validate.js"></script>
|
||||
<script src="~/js/login.js" asp-append-version="true"></script>
|
||||
}
|
||||
<div class="container">
|
||||
<form id="login" method="post" class="form-signin">
|
||||
<h2 class="form-signin-heading">@Model.Title</h2>
|
||||
<div class="login-wrap" data-toggle="LgbValidate" data-valid-button="button[type='submit']">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-user"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" name="userName" class="form-control" placeholder="用户名" maxlength="16" data-required-msg="请输入用户名" value="@ViewBag.UserName" autofocus data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-lock"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="password" name="password" class="form-control" value="@ViewBag.Password" placeholder="密码" maxlength="16" data-required-msg="请输入密码" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group rememberPwd" onselectstart="return false">
|
||||
<i class="fa fa-square-o"></i>
|
||||
<span>记住密码自动登录</span>
|
||||
<input id="remember" name="remember" type="hidden" value="false" />
|
||||
</div>
|
||||
<button class="btn btn-lg btn-login btn-block" type="submit">登 陆</button>
|
||||
<div class="login-footer">
|
||||
<a href="#" data-method="register">申请账号</a>
|
||||
<a href="#" data-method="forgot">忘记密码</a>
|
||||
</div>
|
||||
<div class="slidercaptcha card">
|
||||
<div class="card-header">
|
||||
<span>请完成安全验证</span>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="card-body"><div id="captcha"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal fade" id="dialogNew" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
|
||||
<div class="modal-content" data-toggle="LgbValidate" data-valid-button="#btnSubmit" data-valid-modal="#dialogNew">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="myModalLabel">新用户注册</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="userName">登陆名称:</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-user-plus"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" id="userName" autocomplete="off" class="form-control" placeholder="登陆账号不可为空" userName="true" minlength="4" maxlength="16" remote="api/Register" data-remote-msg="此用户已存在" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="displayName">显示名称:</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-user-circle-o"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" id="displayName" class="form-control" value="" placeholder="显示名称不可为空" maxlength="20" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">密码:</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-lock"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="password" id="password" class="form-control" value="" placeholder="密码不可为空" maxlength="16" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="assurePassword">确认密码:</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-lock"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="password" id="assurePassword" class="form-control" value="" placeholder="确认密码" maxlength="16" equalTo="#password" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">申请理由:</label>
|
||||
<textarea id="description" class="form-control" placeholder="申请理由,500字以内" rows="3" maxlength="500" data-valid="true"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
<i class="fa fa-times"></i>
|
||||
<span>关闭</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary" id="btnSubmit">
|
||||
<i class="fa fa-save"></i>
|
||||
<span>提交</span>
|
||||
</button>
|
||||
<div class="slidercaptcha forgot reg card">
|
||||
<div class="card-header">
|
||||
<span>请完成安全验证</span>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="card-body"><div id="regcap"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="dialogForgot" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
|
||||
<div class="modal-content" data-toggle="LgbValidate" data-valid-button="#btnForgot" data-valid-modal="#dialogForgot">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="myModalLabelForgot">忘记密码</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="f_userName">登陆账号:</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-user-plus"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" id="f_userName" autocomplete="off" class="form-control" placeholder="登陆账号不可为空" minlength="4" maxlength="16" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="f_displayName">显示名称:</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-user-circle-o"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" id="f_displayName" class="form-control" value="" placeholder="显示名称不可为空" maxlength="20" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="f_desc">申请理由:</label>
|
||||
<textarea id="f_desc" class="form-control" placeholder="申请理由,500字以内" rows="3" maxlength="500" data-valid="true">我是用户XXX,我的手机号是XXXXXX,由于密码忘记,请将密码重置为123,登录后我自行更改,谢谢管理员</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
<i class="fa fa-times"></i>
|
||||
<span>关闭</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-danger" id="btnForgot">
|
||||
<i class="fa fa-send-o"></i>
|
||||
<span>提交</span>
|
||||
</button>
|
||||
<div class="slidercaptcha forgot card">
|
||||
<div class="card-header">
|
||||
<span>请完成安全验证</span>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="card-body"><div id="forgotcap"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@model LoginModel
|
||||
@{
|
||||
ViewBag.Title = Model.Title;
|
||||
Layout = "_Layout";
|
||||
}
|
||||
@section css {
|
||||
<environment include="Development">
|
||||
<link href="~/lib/twitter-bootstrap/css/bootstrap.css" rel="stylesheet" />
|
||||
<link href="~/lib/font-awesome/css/font-awesome.css" rel="stylesheet" />
|
||||
<link href="~/lib/bootstrap-sweetalert/sweetalert.css" rel="stylesheet" />
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<link href="~/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
||||
<link href="~/lib/font-awesome/css/font-awesome.min.css" rel="stylesheet" />
|
||||
<link href="~/lib/bootstrap-sweetalert/sweetalert.min.css" rel="stylesheet" />
|
||||
</environment>
|
||||
<link href="~/lib/captcha/slidercaptcha.css" rel="stylesheet" />
|
||||
<link href="~/css/theme.css" rel="stylesheet" asp-append-version="true" />
|
||||
<link href="~/css/login.css" rel="stylesheet" asp-append-version="true" />
|
||||
<link href="~/css/login-responsive.css" rel="stylesheet" asp-append-version="true" />
|
||||
@if (!string.IsNullOrEmpty(Model.Theme))
|
||||
{
|
||||
<link href="~/css/@Model.Theme" rel="stylesheet" asp-append-version="true" />
|
||||
}
|
||||
}
|
||||
@section javascript {
|
||||
<environment include="Development">
|
||||
<script src="~/lib/twitter-bootstrap/js/bootstrap.bundle.js"></script>
|
||||
<script src="~/lib/validate/jquery.validate.js"></script>
|
||||
<script src="~/lib/validate/localization/messages_zh.js"></script>
|
||||
<script src="~/lib/bootstrap-sweetalert/sweetalert.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="~/lib/twitter-bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="~/lib/validate/jquery.validate.min.js"></script>
|
||||
<script src="~/lib/validate/localization/messages_zh.min.js"></script>
|
||||
<script src="~/lib/bootstrap-sweetalert/sweetalert.min.js"></script>
|
||||
</environment>
|
||||
<script src="~/lib/captcha/longbow.slidercaptcha.js"></script>
|
||||
<script src="~/lib/longbow/longbow.common.js"></script>
|
||||
<script src="~/lib/longbow/longbow.validate.js"></script>
|
||||
<script src="~/js/login.js" asp-append-version="true"></script>
|
||||
}
|
||||
<div class="container">
|
||||
<input id="imgUrl" type="hidden" value="@Model.ImageLibUrl" />
|
||||
<form id="login" method="post" class="form-signin">
|
||||
<h2 class="form-signin-heading">@Model.Title</h2>
|
||||
<div class="login-wrap" data-toggle="LgbValidate" data-valid-button="button[type='submit']">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-user"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" name="userName" class="form-control" placeholder="用户名" maxlength="16" data-required-msg="请输入用户名" value="@ViewBag.UserName" autofocus data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-lock"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="password" name="password" class="form-control" value="@ViewBag.Password" placeholder="密码" maxlength="16" data-required-msg="请输入密码" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group rememberPwd" onselectstart="return false">
|
||||
<i class="fa fa-square-o"></i>
|
||||
<span>记住密码自动登录</span>
|
||||
<input id="remember" name="remember" type="hidden" value="false" />
|
||||
</div>
|
||||
<button class="btn btn-lg btn-login btn-block" type="submit">登 陆</button>
|
||||
<div class="login-footer">
|
||||
<a href="#" data-method="register">申请账号</a>
|
||||
<a href="#" data-method="forgot">忘记密码</a>
|
||||
</div>
|
||||
<div class="slidercaptcha card">
|
||||
<div class="card-header">
|
||||
<span>请完成安全验证</span>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="card-body"><div id="captcha"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal fade" id="dialogNew" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
|
||||
<div class="modal-content" data-toggle="LgbValidate" data-valid-button="#btnSubmit" data-valid-modal="#dialogNew">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="myModalLabel">新用户注册</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="userName">登陆名称:</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-user-plus"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" id="userName" autocomplete="off" class="form-control" placeholder="登陆账号不可为空" userName="true" minlength="4" maxlength="16" remote="api/Register" data-remote-msg="此用户已存在" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="displayName">显示名称:</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-user-circle-o"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" id="displayName" class="form-control" value="" placeholder="显示名称不可为空" maxlength="20" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">密码:</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-lock"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="password" id="password" class="form-control" value="" placeholder="密码不可为空" maxlength="16" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="assurePassword">确认密码:</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-lock"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="password" id="assurePassword" class="form-control" value="" placeholder="确认密码" maxlength="16" equalTo="#password" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">申请理由:</label>
|
||||
<textarea id="description" class="form-control" placeholder="申请理由,500字以内" rows="3" maxlength="500" data-valid="true"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
<i class="fa fa-times"></i>
|
||||
<span>关闭</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary" id="btnSubmit">
|
||||
<i class="fa fa-save"></i>
|
||||
<span>提交</span>
|
||||
</button>
|
||||
<div class="slidercaptcha forgot reg card">
|
||||
<div class="card-header">
|
||||
<span>请完成安全验证</span>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="card-body"><div id="regcap"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="dialogForgot" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
|
||||
<div class="modal-content" data-toggle="LgbValidate" data-valid-button="#btnForgot" data-valid-modal="#dialogForgot">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="myModalLabelForgot">忘记密码</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="f_userName">登陆账号:</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-user-plus"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" id="f_userName" autocomplete="off" class="form-control" placeholder="登陆账号不可为空" minlength="4" maxlength="16" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="f_displayName">显示名称:</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<span class="fa fa-user-circle-o"></span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" id="f_displayName" class="form-control" value="" placeholder="显示名称不可为空" maxlength="20" data-valid="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="f_desc">申请理由:</label>
|
||||
<textarea id="f_desc" class="form-control" placeholder="申请理由,500字以内" rows="3" maxlength="500" data-valid="true">我是用户XXX,我的手机号是XXXXXX,由于密码忘记,请将密码重置为123,登录后我自行更改,谢谢管理员</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
<i class="fa fa-times"></i>
|
||||
<span>关闭</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-danger" id="btnForgot">
|
||||
<i class="fa fa-send-o"></i>
|
||||
<span>提交</span>
|
||||
</button>
|
||||
<div class="slidercaptcha forgot card">
|
||||
<div class="card-header">
|
||||
<span>请完成安全验证</span>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="card-body"><div id="forgotcap"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
$(function () {
|
||||
var $imgUrl = $('#imgUrl');
|
||||
$(".container").autoCenter();
|
||||
|
||||
$("a[data-method]").on('click', function () {
|
||||
|
@ -94,8 +95,11 @@
|
|||
$('#captcha, #regcap, #forgotcap').sliderCaptcha({
|
||||
width: $.capWidth(),
|
||||
height: $.capHeight(),
|
||||
localImages: function () {
|
||||
return '../../lib/captcha/images/Pic' + Math.round(Math.random() * 4) + '.jpg';
|
||||
},
|
||||
setSrc: function () {
|
||||
return 'http://pocoafrro.bkt.clouddn.com/Pic' + Math.round(Math.random() * 136) + '.jpg';
|
||||
return $imgUrl.val() + 'Pic' + Math.round(Math.random() * 136) + '.jpg';
|
||||
},
|
||||
onSuccess: function () {
|
||||
var parent = this.$element.parents('.slidercaptcha').removeClass('d-block');
|
||||
|
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
@ -1,4 +1,4 @@
|
|||
(function ($) {
|
||||
(function ($) {
|
||||
'use strict';
|
||||
|
||||
var SliderCaptcha = function (element, options) {
|
||||
|
@ -16,11 +16,15 @@
|
|||
PI: Math.PI,
|
||||
sliderL: 42, // 滑块边长
|
||||
sliderR: 9, // 滑块半径
|
||||
offset: 5, // 容错偏差
|
||||
loadingText: '正在加载中...',
|
||||
failedText: '再试一次',
|
||||
barText: '向右滑动填充拼图',
|
||||
repeatIcon: 'fa fa-repeat',
|
||||
maxLoadCount: 3
|
||||
maxLoadCount: 3,
|
||||
localImages: function () {
|
||||
return 'images/Pic' + Math.round(Math.random() * 4) + '.jpg';
|
||||
}
|
||||
};
|
||||
|
||||
function Plugin(option) {
|
||||
|
@ -40,9 +44,9 @@
|
|||
|
||||
var _proto = SliderCaptcha.prototype;
|
||||
_proto.init = function () {
|
||||
this.initDOM()
|
||||
this.initImg()
|
||||
this.bindEvents()
|
||||
this.initDOM();
|
||||
this.initImg();
|
||||
this.bindEvents();
|
||||
};
|
||||
|
||||
_proto.initDOM = function () {
|
||||
|
@ -86,7 +90,7 @@
|
|||
Object.assign(this, {
|
||||
canvas,
|
||||
block,
|
||||
sliderContainer : $(sliderContainer),
|
||||
sliderContainer: $(sliderContainer),
|
||||
refreshIcon,
|
||||
slider,
|
||||
sliderMask,
|
||||
|
@ -127,9 +131,6 @@
|
|||
var getRandomNumberByRange = function (start, end) {
|
||||
return Math.round(Math.random() * (end - start) + start);
|
||||
};
|
||||
var localImg = function () {
|
||||
return '../images/Pic' + Math.round(Math.random() * 4) + '.jpg';
|
||||
};
|
||||
var img = new Image();
|
||||
img.crossOrigin = "Anonymous";
|
||||
var loadCount = 0;
|
||||
|
@ -158,8 +159,8 @@
|
|||
that.text.text('加载失败').addClass('text-danger');
|
||||
return;
|
||||
}
|
||||
img.src = localImg();
|
||||
}
|
||||
img.src = that.options.localImages();
|
||||
};
|
||||
img.setSrc = function () {
|
||||
var src = '';
|
||||
loadCount = 0;
|
||||
|
@ -250,7 +251,7 @@
|
|||
setTimeout(() => {
|
||||
that.text.text(that.options.failedText);
|
||||
that.reset();
|
||||
}, 1000)
|
||||
}, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -261,8 +262,8 @@
|
|||
document.addEventListener('mouseup', handleDragEnd);
|
||||
document.addEventListener('touchend', handleDragEnd);
|
||||
|
||||
document.addEventListener('mousedown', function() { return false; });
|
||||
document.addEventListener('touchstart', function() { return false; });
|
||||
document.addEventListener('mousedown', function () { return false; });
|
||||
document.addEventListener('touchstart', function () { return false; });
|
||||
};
|
||||
|
||||
_proto.verify = function () {
|
||||
|
@ -274,7 +275,7 @@
|
|||
var stddev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length);
|
||||
var left = parseInt(this.block.style.left);
|
||||
return {
|
||||
spliced: Math.abs(left - this.x) < 4,
|
||||
spliced: Math.abs(left - this.x) < this.options.offset,
|
||||
verified: stddev !== 0, // 简单验证下拖动轨迹,为零时表示Y轴上下没有波动,可能非人为操作
|
||||
}
|
||||
};
|
||||
|
|
|
@ -82,5 +82,11 @@ namespace Bootstrap.Client.DataAccess
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string RetrieveIconFolderPath() => (RetrieveDicts().FirstOrDefault(d => d.Name == "头像路径" && d.Category == "头像地址" && d.Define == 0) ?? new BootstrapDict() { Code = "~/images/uploader/" }).Code;
|
||||
|
||||
/// <summary>
|
||||
/// 获取验证码图床
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string RetrieveImagesLibUrl() => (RetrieveDicts().FirstOrDefault(d => d.Name == "验证码图床" && d.Category == "系统设置" && d.Define == 0) ?? new BootstrapDict() { Code = "https://longbow-1258823021.cos.ap-shanghai.myqcloud.com/pic/280/150/" }).Code;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,17 @@ namespace Bootstrap.Client.Models
|
|||
public NavigatorBarModel(ControllerBase controller) : base(controller.User.Identity)
|
||||
{
|
||||
Navigations = MenuHelper.RetrieveAppMenus(UserName, $"~/{controller.ControllerContext.ActionDescriptor.ControllerName}/{controller.ControllerContext.ActionDescriptor.ActionName}");
|
||||
ImageLibUrl = DictHelper.RetrieveImagesLibUrl();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IEnumerable<BootstrapMenu> Navigations { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string ImageLibUrl { get; set; }
|
||||
}
|
||||
}
|
|
@ -15,6 +15,6 @@
|
|||
<p>
|
||||
<button id="btnCaptcha" class="btn btn-success"><i class="fa fa-send-o"></i><span>点击我出现行为验证码</span></button>
|
||||
<div class="card d-none" style="padding: 10px; height: 222px;">
|
||||
<div id="captcha"></div>
|
||||
<div id="captcha" data-imageLibUrl="@Model.ImageLibUrl"></div>
|
||||
</div>
|
||||
</p>
|
|
@ -1,14 +1,19 @@
|
|||
$(function () {
|
||||
$('#captcha').sliderCaptcha({
|
||||
var $captcha = $('#captcha');
|
||||
|
||||
$captcha.sliderCaptcha({
|
||||
localImages: function () {
|
||||
return '../../lib/captcha/images/Pic' + Math.round(Math.random() * 4) + '.jpg';
|
||||
},
|
||||
setSrc: function () {
|
||||
return 'http://pocoafrro.bkt.clouddn.com/Pic' + Math.round(Math.random() * 136) + '.jpg';
|
||||
return $captcha.attr('data-imageLibUrl') + 'Pic' + Math.round(Math.random() * 136) + '.jpg';
|
||||
},
|
||||
onSuccess: function () {
|
||||
var that = this;
|
||||
setTimeout(() => {
|
||||
that.parent().removeClass('d-inline-block');
|
||||
that.sliderCaptcha('reset');
|
||||
window.location.href = "/BA/Admin/Profiles";
|
||||
$('.userinfo .dropdown-menu a:first')[0].click();
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
|
|
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 8.4 KiB |
|
@ -1,292 +1,293 @@
|
|||
(function ($) {
|
||||
'use strict';
|
||||
|
||||
var SliderCaptcha = function (element, options) {
|
||||
this.$element = $(element);
|
||||
this.options = $.extend({}, SliderCaptcha.DEFAULTS, options);
|
||||
this.$element.css({ 'position': 'relative', 'width': this.options.width + 'px', 'margin': '0 auto' });
|
||||
this.init();
|
||||
};
|
||||
|
||||
SliderCaptcha.VERSION = '1.0';
|
||||
SliderCaptcha.Author = 'argo@163.com';
|
||||
SliderCaptcha.DEFAULTS = {
|
||||
width: 280, // canvas宽度
|
||||
height: 155, // canvas高度
|
||||
PI: Math.PI,
|
||||
sliderL: 42, // 滑块边长
|
||||
sliderR: 9, // 滑块半径
|
||||
loadingText: '正在加载中...',
|
||||
failedText: '再试一次',
|
||||
barText: '向右滑动填充拼图',
|
||||
repeatIcon: 'fa fa-repeat',
|
||||
maxLoadCount: 3
|
||||
};
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this);
|
||||
var data = $this.data('lgb.SliderCaptcha');
|
||||
var options = typeof option === 'object' && option;
|
||||
|
||||
if (!data && /init|reset|verify/.test(option)) return;
|
||||
if (!data) $this.data('lgb.SliderCaptcha', data = new SliderCaptcha(this, options));
|
||||
if (typeof option === 'string') data[option]();
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.sliderCaptcha = Plugin;
|
||||
$.fn.sliderCaptcha.Constructor = SliderCaptcha;
|
||||
|
||||
var _proto = SliderCaptcha.prototype;
|
||||
_proto.init = function () {
|
||||
this.initDOM()
|
||||
this.initImg()
|
||||
this.bindEvents()
|
||||
};
|
||||
|
||||
_proto.initDOM = function () {
|
||||
var createElement = function (tagName, className) {
|
||||
var elment = document.createElement(tagName);
|
||||
elment.className = className;
|
||||
return elment;
|
||||
};
|
||||
|
||||
var createCanvas = function (width, height) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
return canvas;
|
||||
};
|
||||
|
||||
var canvas = createCanvas(this.options.width - 2, this.options.height) // 画布
|
||||
var block = canvas.cloneNode(true) // 滑块
|
||||
var sliderContainer = createElement('div', 'sliderContainer');
|
||||
var refreshIcon = createElement('i', 'refreshIcon ' + this.options.repeatIcon);
|
||||
var sliderMask = createElement('div', 'sliderMask');
|
||||
var sliderbg = createElement('div', 'sliderbg');
|
||||
var slider = createElement('div', 'slider');
|
||||
var sliderIcon = createElement('i', 'fa fa-arrow-right sliderIcon');
|
||||
var text = createElement('span', 'sliderText');
|
||||
|
||||
block.className = 'block'
|
||||
text.innerHTML = this.options.barText;
|
||||
|
||||
var el = this.$element;
|
||||
el.append($(canvas));
|
||||
el.append($(refreshIcon));
|
||||
el.append($(block));
|
||||
slider.appendChild(sliderIcon);
|
||||
sliderMask.appendChild(slider);
|
||||
sliderContainer.appendChild(sliderbg);
|
||||
sliderContainer.appendChild(sliderMask);
|
||||
sliderContainer.appendChild(text);
|
||||
el.append($(sliderContainer));
|
||||
|
||||
Object.assign(this, {
|
||||
canvas,
|
||||
block,
|
||||
sliderContainer : $(sliderContainer),
|
||||
refreshIcon,
|
||||
slider,
|
||||
sliderMask,
|
||||
sliderIcon,
|
||||
text: $(text),
|
||||
canvasCtx: canvas.getContext('2d'),
|
||||
blockCtx: block.getContext('2d')
|
||||
})
|
||||
};
|
||||
|
||||
_proto.initImg = function () {
|
||||
var that = this;
|
||||
var isIE = window.navigator.userAgent.indexOf('Trident') > -1;
|
||||
var L = this.options.sliderL + this.options.sliderR * 2 + 3; // 滑块实际边长
|
||||
var drawImg = function (ctx, operation) {
|
||||
var l = that.options.sliderL;
|
||||
var r = that.options.sliderR;
|
||||
var PI = that.options.PI;
|
||||
var x = that.x;
|
||||
var y = that.y;
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(x, y)
|
||||
ctx.arc(x + l / 2, y - r + 2, r, 0.72 * PI, 2.26 * PI)
|
||||
ctx.lineTo(x + l, y)
|
||||
ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * PI, 2.78 * PI)
|
||||
ctx.lineTo(x + l, y + l)
|
||||
ctx.lineTo(x, y + l)
|
||||
ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true)
|
||||
ctx.lineTo(x, y)
|
||||
ctx.lineWidth = 2
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)'
|
||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)'
|
||||
ctx.stroke()
|
||||
ctx[operation]()
|
||||
ctx.globalCompositeOperation = isIE ? 'xor' : 'overlay'
|
||||
}
|
||||
|
||||
var getRandomNumberByRange = function (start, end) {
|
||||
return Math.round(Math.random() * (end - start) + start);
|
||||
};
|
||||
var localImg = function () {
|
||||
return '../images/Pic' + Math.round(Math.random() * 4) + '.jpg';
|
||||
};
|
||||
var img = new Image();
|
||||
img.crossOrigin = "Anonymous";
|
||||
var loadCount = 0;
|
||||
img.onload = function () {
|
||||
// 随机创建滑块的位置
|
||||
that.x = getRandomNumberByRange(L + 10, that.options.width - (L + 10));
|
||||
that.y = getRandomNumberByRange(10 + that.options.sliderR * 2, that.options.height - (L + 10));
|
||||
drawImg(that.canvasCtx, 'fill');
|
||||
drawImg(that.blockCtx, 'clip');
|
||||
|
||||
that.canvasCtx.drawImage(img, 0, 0, that.options.width - 2, that.options.height);
|
||||
that.blockCtx.drawImage(img, 0, 0, that.options.width - 2, that.options.height);
|
||||
var y = that.y - that.options.sliderR * 2 - 1;
|
||||
var ImageData = that.blockCtx.getImageData(that.x - 3, y, L, L);
|
||||
that.block.width = L;
|
||||
that.blockCtx.putImageData(ImageData, 0, y);
|
||||
that.text.text(that.text.attr('data-text'));
|
||||
};
|
||||
img.onerror = function () {
|
||||
loadCount++;
|
||||
if (window.location.protocol === 'file:') {
|
||||
loadCount = that.options.maxLoadCount;
|
||||
console.error("can't load pic resource file from File protocal. Please try http or https");
|
||||
}
|
||||
if (loadCount >= that.options.maxLoadCount) {
|
||||
that.text.text('加载失败').addClass('text-danger');
|
||||
return;
|
||||
}
|
||||
img.src = localImg();
|
||||
}
|
||||
img.setSrc = function () {
|
||||
var src = '';
|
||||
loadCount = 0;
|
||||
that.text.removeClass('text-danger');
|
||||
if ($.isFunction(that.options.setSrc)) src = that.options.setSrc();
|
||||
if (!src || src === '') src = 'https://picsum.photos/' + that.options.width + '/' + that.options.height + '/?image=' + Math.round(Math.random() * 20);
|
||||
if (isIE) { // IE浏览器无法通过img.crossOrigin跨域,使用ajax获取图片blob然后转为dataURL显示
|
||||
var xhr = new XMLHttpRequest()
|
||||
xhr.onloadend = function (e) {
|
||||
var file = new FileReader(); // FileReader仅支持IE10+
|
||||
file.readAsDataURL(e.target.response);
|
||||
file.onloadend = function (e) {
|
||||
img.src = e.target.result;
|
||||
}
|
||||
}
|
||||
xhr.open('GET', src);
|
||||
xhr.responseType = 'blob';
|
||||
xhr.send();
|
||||
} else img.src = src;
|
||||
};
|
||||
img.setSrc();
|
||||
this.text.attr('data-text', this.options.barText);
|
||||
this.text.text(this.options.loadingText);
|
||||
this.img = img
|
||||
};
|
||||
|
||||
_proto.clean = function () {
|
||||
this.canvasCtx.clearRect(0, 0, this.options.width, this.options.height);
|
||||
this.blockCtx.clearRect(0, 0, this.options.width, this.options.height);
|
||||
this.block.width = this.options.width;
|
||||
};
|
||||
|
||||
_proto.bindEvents = function () {
|
||||
var that = this;
|
||||
this.$element.on('selectstart', function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
$(this.refreshIcon).on('click', function () {
|
||||
that.text.text(that.options.barText);
|
||||
that.reset();
|
||||
if ($.isFunction(that.options.onRefresh)) that.options.onRefresh.call(that.$element);
|
||||
});
|
||||
|
||||
var originX, originY, trail = [],
|
||||
isMouseDown = false
|
||||
|
||||
var handleDragStart = function (e) {
|
||||
if (that.text.hasClass('text-danger')) return;
|
||||
originX = e.clientX || e.touches[0].clientX;
|
||||
originY = e.clientY || e.touches[0].clientY;
|
||||
isMouseDown = true;
|
||||
};
|
||||
|
||||
var handleDragMove = function (e) {
|
||||
if (!isMouseDown) return false;
|
||||
var eventX = e.clientX || e.touches[0].clientX;
|
||||
var eventY = e.clientY || e.touches[0].clientY;
|
||||
var moveX = eventX - originX;
|
||||
var moveY = eventY - originY;
|
||||
if (moveX < 0 || moveX + 40 > that.options.width) return false;
|
||||
that.slider.style.left = (moveX - 1) + 'px';
|
||||
var blockLeft = (that.options.width - 40 - 20) / (that.options.width - 40) * moveX;
|
||||
that.block.style.left = blockLeft + 'px';
|
||||
|
||||
that.sliderContainer.addClass('sliderContainer_active');
|
||||
that.sliderMask.style.width = (moveX + 4) + 'px';
|
||||
trail.push(moveY);
|
||||
};
|
||||
|
||||
var handleDragEnd = function (e) {
|
||||
if (!isMouseDown) return false
|
||||
isMouseDown = false
|
||||
var eventX = e.clientX || e.changedTouches[0].clientX
|
||||
if (eventX == originX) return false
|
||||
that.sliderContainer.removeClass('sliderContainer_active');
|
||||
that.trail = trail
|
||||
var {
|
||||
spliced,
|
||||
verified
|
||||
} = that.verify()
|
||||
if (spliced && verified) {
|
||||
that.sliderContainer.addClass('sliderContainer_success');
|
||||
if ($.isFunction(that.options.onSuccess)) that.options.onSuccess.call(that.$element);
|
||||
} else {
|
||||
that.sliderContainer.addClass('sliderContainer_fail');
|
||||
if ($.isFunction(that.options.onFail)) that.options.onFail.call(that.$element);
|
||||
setTimeout(() => {
|
||||
that.text.text(that.options.failedText);
|
||||
that.reset();
|
||||
}, 1000)
|
||||
}
|
||||
};
|
||||
|
||||
this.slider.addEventListener('mousedown', handleDragStart);
|
||||
this.slider.addEventListener('touchstart', handleDragStart);
|
||||
document.addEventListener('mousemove', handleDragMove);
|
||||
document.addEventListener('touchmove', handleDragMove);
|
||||
document.addEventListener('mouseup', handleDragEnd);
|
||||
document.addEventListener('touchend', handleDragEnd);
|
||||
|
||||
document.addEventListener('mousedown', function() { return false; });
|
||||
document.addEventListener('touchstart', function() { return false; });
|
||||
};
|
||||
|
||||
_proto.verify = function () {
|
||||
var sum = function (x, y) { return x + y; };
|
||||
var square = function (x) { return x * x; };
|
||||
var arr = this.trail // 拖动时y轴的移动距离
|
||||
var average = arr.reduce(sum) / arr.length;
|
||||
var deviations = arr.map(function (x) { return x - average; });
|
||||
var stddev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length);
|
||||
var left = parseInt(this.block.style.left);
|
||||
return {
|
||||
spliced: Math.abs(left - this.x) < 4,
|
||||
verified: stddev !== 0, // 简单验证下拖动轨迹,为零时表示Y轴上下没有波动,可能非人为操作
|
||||
}
|
||||
};
|
||||
|
||||
_proto.reset = function () {
|
||||
this.sliderContainer.removeClass('sliderContainer_fail sliderContainer_success');
|
||||
this.slider.style.left = 0
|
||||
this.block.style.left = 0
|
||||
this.sliderMask.style.width = 0
|
||||
this.clean()
|
||||
this.text.attr('data-text', this.text.text());
|
||||
this.text.text(this.options.loadingText);
|
||||
this.img.setSrc();
|
||||
};
|
||||
(function ($) {
|
||||
'use strict';
|
||||
|
||||
var SliderCaptcha = function (element, options) {
|
||||
this.$element = $(element);
|
||||
this.options = $.extend({}, SliderCaptcha.DEFAULTS, options);
|
||||
this.$element.css({ 'position': 'relative', 'width': this.options.width + 'px', 'margin': '0 auto' });
|
||||
this.init();
|
||||
};
|
||||
|
||||
SliderCaptcha.VERSION = '1.0';
|
||||
SliderCaptcha.Author = 'argo@163.com';
|
||||
SliderCaptcha.DEFAULTS = {
|
||||
width: 280, // canvas宽度
|
||||
height: 155, // canvas高度
|
||||
PI: Math.PI,
|
||||
sliderL: 42, // 滑块边长
|
||||
sliderR: 9, // 滑块半径
|
||||
offset: 5, // 容错偏差
|
||||
loadingText: '正在加载中...',
|
||||
failedText: '再试一次',
|
||||
barText: '向右滑动填充拼图',
|
||||
repeatIcon: 'fa fa-repeat',
|
||||
maxLoadCount: 3,
|
||||
localImages: function () {
|
||||
return 'images/Pic' + Math.round(Math.random() * 4) + '.jpg';
|
||||
}
|
||||
};
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this);
|
||||
var data = $this.data('lgb.SliderCaptcha');
|
||||
var options = typeof option === 'object' && option;
|
||||
|
||||
if (!data && /init|reset|verify/.test(option)) return;
|
||||
if (!data) $this.data('lgb.SliderCaptcha', data = new SliderCaptcha(this, options));
|
||||
if (typeof option === 'string') data[option]();
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.sliderCaptcha = Plugin;
|
||||
$.fn.sliderCaptcha.Constructor = SliderCaptcha;
|
||||
|
||||
var _proto = SliderCaptcha.prototype;
|
||||
_proto.init = function () {
|
||||
this.initDOM();
|
||||
this.initImg();
|
||||
this.bindEvents();
|
||||
};
|
||||
|
||||
_proto.initDOM = function () {
|
||||
var createElement = function (tagName, className) {
|
||||
var elment = document.createElement(tagName);
|
||||
elment.className = className;
|
||||
return elment;
|
||||
};
|
||||
|
||||
var createCanvas = function (width, height) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
return canvas;
|
||||
};
|
||||
|
||||
var canvas = createCanvas(this.options.width - 2, this.options.height) // 画布
|
||||
var block = canvas.cloneNode(true) // 滑块
|
||||
var sliderContainer = createElement('div', 'sliderContainer');
|
||||
var refreshIcon = createElement('i', 'refreshIcon ' + this.options.repeatIcon);
|
||||
var sliderMask = createElement('div', 'sliderMask');
|
||||
var sliderbg = createElement('div', 'sliderbg');
|
||||
var slider = createElement('div', 'slider');
|
||||
var sliderIcon = createElement('i', 'fa fa-arrow-right sliderIcon');
|
||||
var text = createElement('span', 'sliderText');
|
||||
|
||||
block.className = 'block'
|
||||
text.innerHTML = this.options.barText;
|
||||
|
||||
var el = this.$element;
|
||||
el.append($(canvas));
|
||||
el.append($(refreshIcon));
|
||||
el.append($(block));
|
||||
slider.appendChild(sliderIcon);
|
||||
sliderMask.appendChild(slider);
|
||||
sliderContainer.appendChild(sliderbg);
|
||||
sliderContainer.appendChild(sliderMask);
|
||||
sliderContainer.appendChild(text);
|
||||
el.append($(sliderContainer));
|
||||
|
||||
Object.assign(this, {
|
||||
canvas,
|
||||
block,
|
||||
sliderContainer: $(sliderContainer),
|
||||
refreshIcon,
|
||||
slider,
|
||||
sliderMask,
|
||||
sliderIcon,
|
||||
text: $(text),
|
||||
canvasCtx: canvas.getContext('2d'),
|
||||
blockCtx: block.getContext('2d')
|
||||
})
|
||||
};
|
||||
|
||||
_proto.initImg = function () {
|
||||
var that = this;
|
||||
var isIE = window.navigator.userAgent.indexOf('Trident') > -1;
|
||||
var L = this.options.sliderL + this.options.sliderR * 2 + 3; // 滑块实际边长
|
||||
var drawImg = function (ctx, operation) {
|
||||
var l = that.options.sliderL;
|
||||
var r = that.options.sliderR;
|
||||
var PI = that.options.PI;
|
||||
var x = that.x;
|
||||
var y = that.y;
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(x, y)
|
||||
ctx.arc(x + l / 2, y - r + 2, r, 0.72 * PI, 2.26 * PI)
|
||||
ctx.lineTo(x + l, y)
|
||||
ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * PI, 2.78 * PI)
|
||||
ctx.lineTo(x + l, y + l)
|
||||
ctx.lineTo(x, y + l)
|
||||
ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true)
|
||||
ctx.lineTo(x, y)
|
||||
ctx.lineWidth = 2
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)'
|
||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)'
|
||||
ctx.stroke()
|
||||
ctx[operation]()
|
||||
ctx.globalCompositeOperation = isIE ? 'xor' : 'overlay'
|
||||
}
|
||||
|
||||
var getRandomNumberByRange = function (start, end) {
|
||||
return Math.round(Math.random() * (end - start) + start);
|
||||
};
|
||||
var img = new Image();
|
||||
img.crossOrigin = "Anonymous";
|
||||
var loadCount = 0;
|
||||
img.onload = function () {
|
||||
// 随机创建滑块的位置
|
||||
that.x = getRandomNumberByRange(L + 10, that.options.width - (L + 10));
|
||||
that.y = getRandomNumberByRange(10 + that.options.sliderR * 2, that.options.height - (L + 10));
|
||||
drawImg(that.canvasCtx, 'fill');
|
||||
drawImg(that.blockCtx, 'clip');
|
||||
|
||||
that.canvasCtx.drawImage(img, 0, 0, that.options.width - 2, that.options.height);
|
||||
that.blockCtx.drawImage(img, 0, 0, that.options.width - 2, that.options.height);
|
||||
var y = that.y - that.options.sliderR * 2 - 1;
|
||||
var ImageData = that.blockCtx.getImageData(that.x - 3, y, L, L);
|
||||
that.block.width = L;
|
||||
that.blockCtx.putImageData(ImageData, 0, y);
|
||||
that.text.text(that.text.attr('data-text'));
|
||||
};
|
||||
img.onerror = function () {
|
||||
loadCount++;
|
||||
if (window.location.protocol === 'file:') {
|
||||
loadCount = that.options.maxLoadCount;
|
||||
console.error("can't load pic resource file from File protocal. Please try http or https");
|
||||
}
|
||||
if (loadCount >= that.options.maxLoadCount) {
|
||||
that.text.text('加载失败').addClass('text-danger');
|
||||
return;
|
||||
}
|
||||
img.src = that.options.localImages();
|
||||
};
|
||||
img.setSrc = function () {
|
||||
var src = '';
|
||||
loadCount = 0;
|
||||
that.text.removeClass('text-danger');
|
||||
if ($.isFunction(that.options.setSrc)) src = that.options.setSrc();
|
||||
if (!src || src === '') src = 'https://picsum.photos/' + that.options.width + '/' + that.options.height + '/?image=' + Math.round(Math.random() * 20);
|
||||
if (isIE) { // IE浏览器无法通过img.crossOrigin跨域,使用ajax获取图片blob然后转为dataURL显示
|
||||
var xhr = new XMLHttpRequest()
|
||||
xhr.onloadend = function (e) {
|
||||
var file = new FileReader(); // FileReader仅支持IE10+
|
||||
file.readAsDataURL(e.target.response);
|
||||
file.onloadend = function (e) {
|
||||
img.src = e.target.result;
|
||||
}
|
||||
}
|
||||
xhr.open('GET', src);
|
||||
xhr.responseType = 'blob';
|
||||
xhr.send();
|
||||
} else img.src = src;
|
||||
};
|
||||
img.setSrc();
|
||||
this.text.attr('data-text', this.options.barText);
|
||||
this.text.text(this.options.loadingText);
|
||||
this.img = img
|
||||
};
|
||||
|
||||
_proto.clean = function () {
|
||||
this.canvasCtx.clearRect(0, 0, this.options.width, this.options.height);
|
||||
this.blockCtx.clearRect(0, 0, this.options.width, this.options.height);
|
||||
this.block.width = this.options.width;
|
||||
};
|
||||
|
||||
_proto.bindEvents = function () {
|
||||
var that = this;
|
||||
this.$element.on('selectstart', function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
$(this.refreshIcon).on('click', function () {
|
||||
that.text.text(that.options.barText);
|
||||
that.reset();
|
||||
if ($.isFunction(that.options.onRefresh)) that.options.onRefresh.call(that.$element);
|
||||
});
|
||||
|
||||
var originX, originY, trail = [],
|
||||
isMouseDown = false
|
||||
|
||||
var handleDragStart = function (e) {
|
||||
if (that.text.hasClass('text-danger')) return;
|
||||
originX = e.clientX || e.touches[0].clientX;
|
||||
originY = e.clientY || e.touches[0].clientY;
|
||||
isMouseDown = true;
|
||||
};
|
||||
|
||||
var handleDragMove = function (e) {
|
||||
if (!isMouseDown) return false;
|
||||
var eventX = e.clientX || e.touches[0].clientX;
|
||||
var eventY = e.clientY || e.touches[0].clientY;
|
||||
var moveX = eventX - originX;
|
||||
var moveY = eventY - originY;
|
||||
if (moveX < 0 || moveX + 40 > that.options.width) return false;
|
||||
that.slider.style.left = (moveX - 1) + 'px';
|
||||
var blockLeft = (that.options.width - 40 - 20) / (that.options.width - 40) * moveX;
|
||||
that.block.style.left = blockLeft + 'px';
|
||||
|
||||
that.sliderContainer.addClass('sliderContainer_active');
|
||||
that.sliderMask.style.width = (moveX + 4) + 'px';
|
||||
trail.push(moveY);
|
||||
};
|
||||
|
||||
var handleDragEnd = function (e) {
|
||||
if (!isMouseDown) return false
|
||||
isMouseDown = false
|
||||
var eventX = e.clientX || e.changedTouches[0].clientX
|
||||
if (eventX == originX) return false
|
||||
that.sliderContainer.removeClass('sliderContainer_active');
|
||||
that.trail = trail
|
||||
var {
|
||||
spliced,
|
||||
verified
|
||||
} = that.verify()
|
||||
if (spliced && verified) {
|
||||
that.sliderContainer.addClass('sliderContainer_success');
|
||||
if ($.isFunction(that.options.onSuccess)) that.options.onSuccess.call(that.$element);
|
||||
} else {
|
||||
that.sliderContainer.addClass('sliderContainer_fail');
|
||||
if ($.isFunction(that.options.onFail)) that.options.onFail.call(that.$element);
|
||||
setTimeout(() => {
|
||||
that.text.text(that.options.failedText);
|
||||
that.reset();
|
||||
}, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
this.slider.addEventListener('mousedown', handleDragStart);
|
||||
this.slider.addEventListener('touchstart', handleDragStart);
|
||||
document.addEventListener('mousemove', handleDragMove);
|
||||
document.addEventListener('touchmove', handleDragMove);
|
||||
document.addEventListener('mouseup', handleDragEnd);
|
||||
document.addEventListener('touchend', handleDragEnd);
|
||||
|
||||
document.addEventListener('mousedown', function () { return false; });
|
||||
document.addEventListener('touchstart', function () { return false; });
|
||||
};
|
||||
|
||||
_proto.verify = function () {
|
||||
var sum = function (x, y) { return x + y; };
|
||||
var square = function (x) { return x * x; };
|
||||
var arr = this.trail // 拖动时y轴的移动距离
|
||||
var average = arr.reduce(sum) / arr.length;
|
||||
var deviations = arr.map(function (x) { return x - average; });
|
||||
var stddev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length);
|
||||
var left = parseInt(this.block.style.left);
|
||||
return {
|
||||
spliced: Math.abs(left - this.x) < this.options.offset,
|
||||
verified: stddev !== 0, // 简单验证下拖动轨迹,为零时表示Y轴上下没有波动,可能非人为操作
|
||||
}
|
||||
};
|
||||
|
||||
_proto.reset = function () {
|
||||
this.sliderContainer.removeClass('sliderContainer_fail sliderContainer_success');
|
||||
this.slider.style.left = 0
|
||||
this.block.style.left = 0
|
||||
this.sliderMask.style.width = 0
|
||||
this.clean()
|
||||
this.text.attr('data-text', this.text.text());
|
||||
this.text.text(this.options.loadingText);
|
||||
this.img.setSrc();
|
||||
};
|
||||
})(jQuery);
|
|
@ -1,180 +1,186 @@
|
|||
using Bootstrap.Security;
|
||||
using Bootstrap.Security.DataAccess;
|
||||
using Longbow;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Bootstrap.DataAccess
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class Dict : BootstrapDict
|
||||
{
|
||||
/// <summary>
|
||||
/// 删除字典中的数据
|
||||
/// </summary>
|
||||
/// <param name="value">需要删除的IDs</param>
|
||||
/// <returns></returns>
|
||||
public virtual bool Delete(IEnumerable<string> value)
|
||||
{
|
||||
if (!value.Any()) return true;
|
||||
var ids = string.Join(",", value);
|
||||
string sql = $"where ID in ({ids})";
|
||||
DbManager.Create().Delete<BootstrapDict>(sql);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存新建/更新的字典信息
|
||||
/// </summary>
|
||||
/// <param name="dict"></param>
|
||||
/// <returns></returns>
|
||||
public virtual bool Save(BootstrapDict dict)
|
||||
{
|
||||
if (dict.Category.Length > 50) dict.Category = dict.Category.Substring(0, 50);
|
||||
if (dict.Name.Length > 50) dict.Name = dict.Name.Substring(0, 50);
|
||||
if (dict.Code.Length > 50) dict.Code = dict.Code.Substring(0, 50);
|
||||
|
||||
DbManager.Create().Save(dict);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存网站个性化设置
|
||||
/// </summary>
|
||||
/// <param name="dict"></param>
|
||||
/// <returns></returns>
|
||||
public virtual bool SaveSettings(BootstrapDict dict)
|
||||
{
|
||||
DbManager.Create().Update<BootstrapDict>("set Code = @Code where Category = @Category and Name = @Name", dict);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取字典分类名称
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<string> RetrieveCategories() => DictHelper.RetrieveDicts().OrderBy(d => d.Category).Select(d => d.Category).Distinct();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual string RetrieveWebTitle() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "网站标题" && d.Category == "网站设置" && d.Define == 0) ?? new BootstrapDict() { Code = "后台管理系统" }).Code;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual string RetrieveWebFooter() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "网站页脚" && d.Category == "网站设置" && d.Define == 0) ?? new BootstrapDict() { Code = "2016 © 通用后台管理系统" }).Code;
|
||||
|
||||
/// <summary>
|
||||
/// 获得系统中配置的可以使用的网站样式
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<BootstrapDict> RetrieveThemes() => DictHelper.RetrieveDicts().Where(d => d.Category == "网站样式");
|
||||
|
||||
/// <summary>
|
||||
/// 获得网站设置中的当前样式
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual string RetrieveActiveTheme()
|
||||
{
|
||||
var theme = DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "使用样式" && d.Category == "当前样式" && d.Define == 0);
|
||||
return theme == null ? string.Empty : (theme.Code.Equals("site.css", StringComparison.OrdinalIgnoreCase) ? string.Empty : theme.Code);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取头像路径
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual string RetrieveIconFolderPath() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "头像路径" && d.Category == "头像地址" && d.Define == 0) ?? new BootstrapDict { Code = "~/images/uploader/" }).Code;
|
||||
|
||||
/// <summary>
|
||||
/// 获得默认的前台首页地址,默认为~/Home/Index
|
||||
/// </summary>
|
||||
/// <param name="appCode"></param>
|
||||
/// <returns></returns>
|
||||
public virtual string RetrieveHomeUrl(string appCode)
|
||||
{
|
||||
// https://gitee.com/LongbowEnterprise/dashboard/issues?id=IS0WK
|
||||
var url = "~/Home/Index";
|
||||
var dicts = DictHelper.RetrieveDicts();
|
||||
if (appCode != "0")
|
||||
{
|
||||
var appUrl = dicts.FirstOrDefault(d => d.Name.Equals(appCode, StringComparison.OrdinalIgnoreCase) && d.Category == "应用首页" && d.Define == 0)?.Code;
|
||||
if (!string.IsNullOrEmpty(appUrl))
|
||||
{
|
||||
url = appUrl;
|
||||
return url;
|
||||
}
|
||||
}
|
||||
var defaultUrl = dicts.FirstOrDefault(d => d.Name == "前台首页" && d.Category == "网站设置" && d.Define == 0)?.Code;
|
||||
if (!string.IsNullOrEmpty(defaultUrl)) url = defaultUrl;
|
||||
return url;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<KeyValuePair<string, string>> RetrieveApps() => DictHelper.RetrieveDicts().Where(d => d.Category == "应用程序" && d.Define == 0).Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).OrderBy(d => d.Key);
|
||||
|
||||
/// <summary>
|
||||
/// 通过数据库获得所有字典表配置信息,缓存Key=DictHelper-RetrieveDicts
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<BootstrapDict> RetrieveDicts() => DbHelper.RetrieveDicts();
|
||||
|
||||
/// <summary>
|
||||
/// 程序异常时长 默认1月
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int RetrieveExceptionsLogPeriod() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "程序异常保留时长" && d.Define == 0)?.Code, 1);
|
||||
|
||||
/// <summary>
|
||||
/// 操作日志时长 默认12月
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int RetrieveLogsPeriod() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "操作日志保留时长" && d.Define == 0)?.Code, 12);
|
||||
|
||||
/// <summary>
|
||||
/// 登录日志时长 默认12月
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int RetrieveLoginLogsPeriod() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "登录日志保留时长" && d.Define == 0)?.Code, 12);
|
||||
|
||||
/// <summary>
|
||||
/// Cookie保存时长 默认7天
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int RetrieveCookieExpiresPeriod() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "Cookie保留时长" && d.Define == 0)?.Code, 7);
|
||||
|
||||
/// <summary>
|
||||
/// 获得 IP地理位置
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string RetrieveLocaleIPSvr() => DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "IP地理位置接口" && d.Define == 0)?.Code;
|
||||
|
||||
/// <summary>
|
||||
/// 获得 项目是否获取登录地点 默认为false
|
||||
/// </summary>
|
||||
/// <param name="ipSvr">服务提供名称</param>
|
||||
/// <returns></returns>
|
||||
public string RetrieveLocaleIPSvrUrl(string ipSvr) => DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == ipSvr && d.Define == 0)?.Code;
|
||||
|
||||
/// <summary>
|
||||
/// 获得 访问日志保留时长 默认为1个月
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int RetrieveAccessLogPeriod() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "访问日志保留时长" && d.Define == 0)?.Code, 1);
|
||||
|
||||
/// <summary>
|
||||
/// 获得 是否为演示系统 默认为 false 不是演示系统
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool RetrieveSystemModel() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "演示系统" && d.Define == 0)?.Code, "0") == "1";
|
||||
}
|
||||
}
|
||||
using Bootstrap.Security;
|
||||
using Bootstrap.Security.DataAccess;
|
||||
using Longbow;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Bootstrap.DataAccess
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class Dict : BootstrapDict
|
||||
{
|
||||
/// <summary>
|
||||
/// 删除字典中的数据
|
||||
/// </summary>
|
||||
/// <param name="value">需要删除的IDs</param>
|
||||
/// <returns></returns>
|
||||
public virtual bool Delete(IEnumerable<string> value)
|
||||
{
|
||||
if (!value.Any()) return true;
|
||||
var ids = string.Join(",", value);
|
||||
string sql = $"where ID in ({ids})";
|
||||
DbManager.Create().Delete<BootstrapDict>(sql);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存新建/更新的字典信息
|
||||
/// </summary>
|
||||
/// <param name="dict"></param>
|
||||
/// <returns></returns>
|
||||
public virtual bool Save(BootstrapDict dict)
|
||||
{
|
||||
if (dict.Category.Length > 50) dict.Category = dict.Category.Substring(0, 50);
|
||||
if (dict.Name.Length > 50) dict.Name = dict.Name.Substring(0, 50);
|
||||
if (dict.Code.Length > 50) dict.Code = dict.Code.Substring(0, 50);
|
||||
|
||||
DbManager.Create().Save(dict);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存网站个性化设置
|
||||
/// </summary>
|
||||
/// <param name="dict"></param>
|
||||
/// <returns></returns>
|
||||
public virtual bool SaveSettings(BootstrapDict dict)
|
||||
{
|
||||
DbManager.Create().Update<BootstrapDict>("set Code = @Code where Category = @Category and Name = @Name", dict);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取字典分类名称
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<string> RetrieveCategories() => DictHelper.RetrieveDicts().OrderBy(d => d.Category).Select(d => d.Category).Distinct();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual string RetrieveWebTitle() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "网站标题" && d.Category == "网站设置" && d.Define == 0) ?? new BootstrapDict() { Code = "后台管理系统" }).Code;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual string RetrieveWebFooter() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "网站页脚" && d.Category == "网站设置" && d.Define == 0) ?? new BootstrapDict() { Code = "2016 © 通用后台管理系统" }).Code;
|
||||
|
||||
/// <summary>
|
||||
/// 获得系统中配置的可以使用的网站样式
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<BootstrapDict> RetrieveThemes() => DictHelper.RetrieveDicts().Where(d => d.Category == "网站样式");
|
||||
|
||||
/// <summary>
|
||||
/// 获得网站设置中的当前样式
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual string RetrieveActiveTheme()
|
||||
{
|
||||
var theme = DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "使用样式" && d.Category == "当前样式" && d.Define == 0);
|
||||
return theme == null ? string.Empty : (theme.Code.Equals("site.css", StringComparison.OrdinalIgnoreCase) ? string.Empty : theme.Code);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取头像路径
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual string RetrieveIconFolderPath() => (DictHelper.RetrieveDicts().FirstOrDefault(d => d.Name == "头像路径" && d.Category == "头像地址" && d.Define == 0) ?? new BootstrapDict { Code = "~/images/uploader/" }).Code;
|
||||
|
||||
/// <summary>
|
||||
/// 获得默认的前台首页地址,默认为~/Home/Index
|
||||
/// </summary>
|
||||
/// <param name="appCode"></param>
|
||||
/// <returns></returns>
|
||||
public virtual string RetrieveHomeUrl(string appCode)
|
||||
{
|
||||
// https://gitee.com/LongbowEnterprise/dashboard/issues?id=IS0WK
|
||||
var url = "~/Home/Index";
|
||||
var dicts = DictHelper.RetrieveDicts();
|
||||
if (appCode != "0")
|
||||
{
|
||||
var appUrl = dicts.FirstOrDefault(d => d.Name.Equals(appCode, StringComparison.OrdinalIgnoreCase) && d.Category == "应用首页" && d.Define == 0)?.Code;
|
||||
if (!string.IsNullOrEmpty(appUrl))
|
||||
{
|
||||
url = appUrl;
|
||||
return url;
|
||||
}
|
||||
}
|
||||
var defaultUrl = dicts.FirstOrDefault(d => d.Name == "前台首页" && d.Category == "网站设置" && d.Define == 0)?.Code;
|
||||
if (!string.IsNullOrEmpty(defaultUrl)) url = defaultUrl;
|
||||
return url;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<KeyValuePair<string, string>> RetrieveApps() => DictHelper.RetrieveDicts().Where(d => d.Category == "应用程序" && d.Define == 0).Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).OrderBy(d => d.Key);
|
||||
|
||||
/// <summary>
|
||||
/// 通过数据库获得所有字典表配置信息,缓存Key=DictHelper-RetrieveDicts
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<BootstrapDict> RetrieveDicts() => DbHelper.RetrieveDicts();
|
||||
|
||||
/// <summary>
|
||||
/// 程序异常时长 默认1月
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int RetrieveExceptionsLogPeriod() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "程序异常保留时长" && d.Define == 0)?.Code, 1);
|
||||
|
||||
/// <summary>
|
||||
/// 操作日志时长 默认12月
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int RetrieveLogsPeriod() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "操作日志保留时长" && d.Define == 0)?.Code, 12);
|
||||
|
||||
/// <summary>
|
||||
/// 登录日志时长 默认12月
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int RetrieveLoginLogsPeriod() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "登录日志保留时长" && d.Define == 0)?.Code, 12);
|
||||
|
||||
/// <summary>
|
||||
/// Cookie保存时长 默认7天
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int RetrieveCookieExpiresPeriod() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "Cookie保留时长" && d.Define == 0)?.Code, 7);
|
||||
|
||||
/// <summary>
|
||||
/// 获得 IP地理位置
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string RetrieveLocaleIPSvr() => DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "IP地理位置接口" && d.Define == 0)?.Code;
|
||||
|
||||
/// <summary>
|
||||
/// 获得 项目是否获取登录地点 默认为false
|
||||
/// </summary>
|
||||
/// <param name="ipSvr">服务提供名称</param>
|
||||
/// <returns></returns>
|
||||
public string RetrieveLocaleIPSvrUrl(string ipSvr) => DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == ipSvr && d.Define == 0)?.Code;
|
||||
|
||||
/// <summary>
|
||||
/// 获得 访问日志保留时长 默认为1个月
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int RetrieveAccessLogPeriod() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "访问日志保留时长" && d.Define == 0)?.Code, 1);
|
||||
|
||||
/// <summary>
|
||||
/// 获得 是否为演示系统 默认为 false 不是演示系统
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool RetrieveSystemModel() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "演示系统" && d.Define == 0)?.Code, "0") == "1";
|
||||
|
||||
/// <summary>
|
||||
/// 获得 验证码图床地址
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string RetrieveImagesLibUrl() => LgbConvert.ReadValue(DictHelper.RetrieveDicts().FirstOrDefault(d => d.Category == "系统设置" && d.Name == "验证码图床" && d.Define == 0)?.Code, "https://longbow-1258823021.cos.ap-shanghai.myqcloud.com/pic/280/150/");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -200,5 +200,11 @@ namespace Bootstrap.DataAccess
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool RetrieveSystemModel() => DbContextManager.Create<Dict>().RetrieveSystemModel();
|
||||
|
||||
/// <summary>
|
||||
/// 获得验证码图床地址
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string RetrieveImagesLibUrl() => DbContextManager.Create<Dict>().RetrieveImagesLibUrl();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ INSERT [dbo].[Dicts] ([Category], [Name], [Code], [Define]) VALUES (N'系统设
|
|||
INSERT [dbo].[Dicts] ([Category], [Name], [Code], [Define]) VALUES (N'系统设置', N'BaiDuIPSvr', 'http://api.map.baidu.com/location/ip?ak=6lvVPMDlm2gjLpU0aiqPsHXi2OiwGQRj&ip=', 0)
|
||||
INSERT [dbo].[Dicts] ([Category], [Name], [Code], [Define]) VALUES (N'系统设置', N'JuheIPSvr', 'http://apis.juhe.cn/ip/ipNew?key=f57102d1b9fadd3f4a1c29072d0c0206&ip=', 0)
|
||||
INSERT [dbo].[Dicts] ([Category], [Name], [Code], [Define]) VALUES (N'系统设置', N'演示系统', '0', 0)
|
||||
INSERT [dbo].[Dicts] ([Category], [Name], [Code], [Define]) VALUES (N'系统设置', N'验证码图床', 'https://longbow-1258823021.cos.ap-shanghai.myqcloud.com/pic/280/150/', 0)
|
||||
|
||||
DELETE FROM Navigations Where Category = N'0'
|
||||
INSERT [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, N'后台管理', 10, N'fa fa-gear', N'~/Admin/Index', N'0')
|
||||
|
|
|
@ -341,5 +341,12 @@
|
|||
"Name": "演示系统",
|
||||
"Code": "0",
|
||||
"Define": NumberInt(0)
|
||||
},
|
||||
{
|
||||
"_id": ObjectId("5bd6c73d5fa31256f77e4a49"),
|
||||
"Category": "系统设置",
|
||||
"Name": "验证码图床",
|
||||
"Code": "https://longbow-1258823021.cos.ap-shanghai.myqcloud.com/pic/280/150/",
|
||||
"Define": NumberInt(0)
|
||||
}
|
||||
]
|
|
@ -41,6 +41,7 @@ INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统设置', 'IP地
|
|||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统设置', 'BaiDuIPSvr', 'http://api.map.baidu.com/location/ip?ak=6lvVPMDlm2gjLpU0aiqPsHXi2OiwGQRj&ip=', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统设置', 'JuheIPSvr', 'http://apis.juhe.cn/ip/ipNew?key=f57102d1b9fadd3f4a1c29072d0c0206&ip=', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统设置', '演示系统', '0', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统设置', '验证码图床', 'https://longbow-1258823021.cos.ap-shanghai.myqcloud.com/pic/280/150/', 0);
|
||||
|
||||
DELETE FROM Navigations Where Category = '0';
|
||||
INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category) VALUES (0, '后台管理', 10, 'fa fa-gear', '~/Admin/Index', '0');
|
||||
|
|
|
@ -40,6 +40,7 @@ INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统设置', 'IP地
|
|||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统设置', 'BaiDuIPSvr', 'http://api.map.baidu.com/location/ip?ak=6lvVPMDlm2gjLpU0aiqPsHXi2OiwGQRj&ip=', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统设置', 'JuheIPSvr', 'http://apis.juhe.cn/ip/ipNew?key=f57102d1b9fadd3f4a1c29072d0c0206&ip=', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统设置', '演示系统', '0', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统设置', '验证码图床', 'https://longbow-1258823021.cos.ap-shanghai.myqcloud.com/pic/280/150/', 0);
|
||||
|
||||
DELETE FROM Navigations Where Category = '0';
|
||||
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '后台管理', 10, 'fa fa-gear', '~/Admin/Index', '0');
|
||||
|
|
|
@ -39,6 +39,7 @@ INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('系统设置
|
|||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('系统设置', 'BaiDuIPSvr', 'http://api.map.baidu.com/location/ip?ak=6lvVPMDlm2gjLpU0aiqPsHXi2OiwGQRj&ip=', 0);
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('系统设置', 'JuheIPSvr', 'http://apis.juhe.cn/ip/ipNew?key=f57102d1b9fadd3f4a1c29072d0c0206&ip=', 0);
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('系统设置', '演示系统', '0', 0);
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('系统设置', '验证码图床', 'https://longbow-1258823021.cos.ap-shanghai.myqcloud.com/pic/280/150/', 0);
|
||||
|
||||
DELETE FROM Navigations Where Category = '0';
|
||||
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, '后台管理', 10, 'fa fa-gear', '~/Admin/Index', '0');
|
||||
|
|