加入前端框架;编写登录界面;

This commit is contained in:
Saturneric 2020-02-22 21:41:16 +08:00
parent 1d01b41f62
commit 1737b3bbc5
15 changed files with 490 additions and 132 deletions

26
pom.xml
View File

@ -126,6 +126,18 @@
<version>3.14</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.61</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.71.android</version>
</dependency>
</dependencies>
<build>
@ -141,4 +153,18 @@
</plugins>
</build>
<repositories>
<repository>
<id>AlibabaMaven</id>
<name>Maven Aliyun Mirror</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

View File

@ -0,0 +1,8 @@
package com.codesdream.ase.component.datamanager;
import org.springframework.stereotype.Component;
// 解析request请求,获得对应的Java对象
@Component
public class DataGetObjectFromRequest {
}

View File

@ -0,0 +1,49 @@
package com.codesdream.ase.component.datamanager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
/**
* 处理JSON相关数据
*/
@Component
public class JSONParameter {
// 提取Request中的JSON数据
public JSONObject getJSONByRequest(HttpServletRequest request){
JSONObject jsonParam = null;
try {
// 获取输入流
BufferedReader streamReader =
new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
// 写入数据到 String Builder
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = streamReader.readLine()) != null) {
sb.append(line);
}
jsonParam = JSONObject.parseObject(sb.toString());
} catch (Exception e) {
e.printStackTrace();
}
return jsonParam;
}
// 根据JSON对象构造JSON字符串用于返回-0=
public String getJSONString(JSONObject json){
return json.toJSONString();
}
// 根据Java对象构造JSON字符串用于返回
public String getJSONString(Object object){
return JSON.toJSONString(object);
}
}

View File

@ -0,0 +1,20 @@
package com.codesdream.ase.component.datamanager;
import lombok.Data;
import java.util.Date;
// 服务端返回的JSON对象模板
@Data
public class RespondJSONBaseObject {
String status = "fail";
Date time = new Date();
public RespondJSONBaseObject(){
}
public RespondJSONBaseObject(String status){
this.status = status;
}
}

View File

@ -0,0 +1,10 @@
package com.codesdream.ase.component.permission;
import lombok.Data;
@Data
public class UserLoginChecker {
private String checkType;
private String username;
private String password;
}

View File

@ -0,0 +1,15 @@
package com.codesdream.ase.component.permission;
import com.codesdream.ase.component.datamanager.RespondJSONBaseObject;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class UserLoginCheckerRespond extends RespondJSONBaseObject {
boolean userExist = false;
public UserLoginCheckerRespond(){
super("success");
}
}

View File

@ -54,6 +54,12 @@ public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/assets/**", "/register/**", "/forget/**", "/not_found/**", "/error/**");
.antMatchers(
"/assets/**",
"/register/**",
"/forget/**",
"/not_found/**",
"/error/**",
"/login/**");
}
}

View File

@ -1,17 +1,70 @@
package com.codesdream.ase.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.codesdream.ase.component.datamanager.JSONParameter;
import com.codesdream.ase.component.datamanager.RespondJSONBaseObject;
import com.codesdream.ase.component.permission.ASEUsernameEncoder;
import com.codesdream.ase.component.permission.UserLoginChecker;
import com.codesdream.ase.component.permission.UserLoginCheckerRespond;
import com.codesdream.ase.service.IUserService;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.sun.org.apache.xpath.internal.operations.Bool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
* 登录界面控制器类
*/
@Slf4j
@Controller
public class LoginController {
@Resource
private JSONParameter jsonParameter;
@Resource
private IUserService userService;
@Resource
private ASEUsernameEncoder usernameEncoder;
@RequestMapping(value = "/login")
String printLogin(Model model) {
return "login";
}
@RequestMapping(value = "/login/check", method = RequestMethod.POST)
@ResponseBody
String checkLogin(HttpServletRequest request){
log.info("Get Login Check Request");
JSONObject json = jsonParameter.getJSONByRequest(request);
UserLoginChecker loginChecker = json.toJavaObject(UserLoginChecker.class);
// 检查类型
if(loginChecker.getCheckType().equals("UsernameExistChecker")){
// 计算用户名
String user = usernameEncoder.encode(loginChecker.getUsername()) ;
// 查询用户名存在状态
boolean existStatus = userService.checkIfUserExists(user).getKey();
// 构造返回对象
UserLoginCheckerRespond respond = new UserLoginCheckerRespond();
respond.setUserExist(existStatus);
return jsonParameter.getJSONString(respond);
}
else {
// 返回失败对象
return jsonParameter.getJSONString(new RespondJSONBaseObject());
}
}
}

View File

@ -69,6 +69,9 @@ public class RegisterController {
// 返回登录界面
return "login";
}
else{
throw new RuntimeException("Retry Password Not Correct");
}
}

View File

@ -0,0 +1,26 @@
.parent{;
height: 100%;
padding: 100px 0 0;
ox-sizing: border-box;
position: relative;
}
.middle-container{
height: 420px;
width: 320px;
margin-left: auto;
margin-right: auto;
}
.line-display{
display: inline-block;
}
.link-block{
height: 20px;
width: 80px;
}
.left-block{
margin-right:0;
}

View File

@ -0,0 +1,171 @@
// 快速打印信息
function ase_debug_log_info(message){
const head = "[ASE JQuery Framework] INFO: ";
console.log(head + message)
}
// 快速打印错误信息
function ase_debug_log_error(message){
const head = "[ASE JQuery Framework] Error ";
console.error(head + message)
}
function ase_create_random_id() {
return (Math.random()*10000000).toString(16).substr(0,4)
+'-'+(new Date()).getTime()
+'-'+Math.random().toString().substr(2,5);
}
// 获得一个HTML标签
function ase_tag_getter(tag, id){
return $(tag+"#"+id);
}
// 获得一个input标签的内容
function ase_input_content_getter(id){
return ase_tag_getter("input", id).val();
}
// 在某个标签的内部追加一个标签
function ase_tag_append(tag, id, tag_append) {
ase_tag_getter(tag, id).append(tag_append);
}
// 在某个标签的后面追加一个标签
function ase_tag_after(tag, id, tag_append) {
ase_tag_getter(tag, id).after(tag_append);
}
// 获得一个div标签
function ase_div_getter(id){
return ase_tag_getter("div", id);
}
// 在某个div内部追加一个标签
function ase_div_append(id, tag_append) {
ase_tag_append("div", id, tag_append);
}
// 修改标签的某个属性
function ase_modify_attr(tag, attr_name, attr_value) {
tag.attr(attr_name, attr_value);
}
// 修改标签的data-notify属性
function ase_add_attr_data_notify(tag, value) {
ase_modify_attr(tag, 'data-notify', value);
}
// 修改标签的data-notify-position属性
function ase_add_attr_data_notify_position(tag, position) {
ase_modify_attr(tag, 'data-notify-position', position);
}
// 给标签添加显示值
function ase_add_show_text(tag, text) {
tag.html(text);
}
// 创建一个标签
function ase_create_tag(tag, id) {
const new_tag = $("<" + tag + ">" + "</" + tag + ">");
if(id !== undefined) {
ase_modify_attr(new_tag, 'id', id);
}
return new_tag;
}
// 给标签指定css属性
function ase_add_attr_style(tag, value) {
ase_modify_attr(tag, 'style', value);
}
// 给标签指定class属性
function ase_add_attr_class(tag, value) {
ase_modify_attr(tag, 'class', value);
}
// 给标签指定class属性
function ase_add_attr_role(tag, value) {
ase_modify_attr(tag, 'role', value);
}
// 获得一个提示气泡
function ase_notification_getter() {
const notification = ase_create_tag("div", ase_create_random_id());
const close_button = ase_create_tag('button');
const icon_span = ase_create_tag('span');
const title_span = ase_create_tag('span');
const message_span = ase_create_tag('span');
notification.append(close_button);
notification.append(icon_span);
notification.append(title_span);
notification.append(message_span);
ase_add_attr_data_notify(notification, 'container');
ase_add_attr_data_notify_position(notification, 'top-right');
ase_add_attr_role(notification, 'alert');
ase_add_attr_class(notification, 'col-10 col-xs-11 col-sm-4 alert alert-danger');
ase_add_attr_style(notification, 'display: inline-block; ' +
'margin: 0px auto; ' +
'padding-left: 65px; ' +
'position: fixed; ' +
'transition: all 0.5s ease-in-out 0s; ' +
'z-index: 1031; ' +
'top: 254px; ' +
'right: 20px;');
ase_add_attr_data_notify(close_button, 'dismiss');
ase_add_attr_data_notify(icon_span, 'icon');
ase_add_attr_data_notify(title_span, 'title');
ase_add_attr_data_notify(message_span, 'message');
}
// 快速给服务器以POST方法传递对象
function ase_post_object(url, object, callback){
if(!callback.hasOwnProperty("success")){
ase_debug_log_info("Function Callback NULL")
callback.success = function (result) {
}
}
if(!callback.hasOwnProperty("error")){
ase_debug_log_info("the error callback is null")
callback.error = function (result) {
ase_debug_log_info("Post Request Error Occurred");
};
}
// 对成功调用返回进行装饰
callback.success = request_success_callback_decorator(callback.success);
$.ajax({
type: "POST",
dataType: "json",
url: url ,
data: JSON.stringify(object),
success: callback.success,
error : callback.error,
});
}
// 对成功返回的回调函数进行装饰
function request_success_callback_decorator(callback){
return function (result) {
if(result.status === "failed"){
ase_system_status_checker(result)
}
else callback(result);
}
}
// 对服务器返回的状态进行检查
function ase_system_status_checker(result) {
ase_debug_log_error("Request Failed.");
ase_debug_log_error(result);
}

View File

@ -0,0 +1,43 @@
$(document).ready(function () {
// 当自动查询用户名是否有效
$("input#username").on("input",function () {
let studentId = $("input#username").val();
if(studentId.length === 10) {
check_username();
}
else if(studentId.length > 10){
}
});
});
function check_username(){
const checker = {
"checkType": "UsernameExistChecker",
"username": $("input#username").val(),
"password":"",
};
ase_post_object("/login/check", checker, {
success: function (result) {
console.log(result);
const usernameGroup = $("div#username-group");
if(result.userExist === true) {
if(usernameGroup.hasClass("has-error")){
usernameGroup.removeClass("has-error");
}
if(!usernameGroup.hasClass("has-success")){
usernameGroup.addClass("has-success");
}
}
else{
if(usernameGroup.hasClass("has-success")){
usernameGroup.removeClass("has-success");
}
if(!usernameGroup.hasClass("has-error")){
usernameGroup.addClass("has-error");
}
}
}
});
}

View File

@ -317,8 +317,6 @@
<td><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">职务</font></font></td>
<td style="background-color: #FFFFFF"><font style="vertical-align: inherit;"><font style="vertical-align: inherit;"></font></font></td>
</tr>

View File

@ -1,10 +1,10 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<html lang="zh-cn"
xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<body>
<div th:fragment="head">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Atlantis Lite - Bootstrap 4 Admin Dashboard</title>
<meta content='width=device-width, initial-scale=1.0, shrink-to-fit=no' name='viewport' />
<link rel="icon" th:href="@{/assets/img/icon.ico}" type="image/x-icon"/>
@ -24,9 +24,11 @@
<link rel="stylesheet" th:href="@{/assets/css/bootstrap.min.css}">
<link rel="stylesheet" th:href="@{/assets/css/atlantis.min.css}">
<!-- CSS Just for demo purpose, don't include it in your project -->
<link rel="stylesheet" th:href="@{/assets/css/demo.css}">
<!-- Custom CSS File -->
<link rel="stylesheet" th:href="@{/assets/css/custom.css}">
</div>
<div th:fragment="js">
<!-- Core JS Files -->
<script th:src="@{/assets/js/core/jquery.3.2.1.min.js}"></script>
@ -66,103 +68,9 @@
<!-- Atlantis JS -->
<script th:src="@{/assets/js/atlantis.min.js}"></script>
<!-- Atlantis DEMO methods, don't include it in your project! -->
<script th:src="@{/assets/js/setting-demo.js}"></script>
<script th:src="@{/assets/js/demo.js}"></script>
<script>
Circles.create({
id:'circles-1',
radius:45,
value:60,
maxValue:100,
width:7,
text: 5,
colors:['#f1f1f1', '#FF9E27'],
duration:400,
wrpClass:'circles-wrp',
textClass:'circles-text',
styleWrapper:true,
styleText:true
})
<!-- ASE JS -->
<script th:src="@{/assets/js/ase/ase-jquery-framework.js}"></script>
Circles.create({
id:'circles-2',
radius:45,
value:70,
maxValue:100,
width:7,
text: 36,
colors:['#f1f1f1', '#2BB930'],
duration:400,
wrpClass:'circles-wrp',
textClass:'circles-text',
styleWrapper:true,
styleText:true
})
Circles.create({
id:'circles-3',
radius:45,
value:40,
maxValue:100,
width:7,
text: 12,
colors:['#f1f1f1', '#F25961'],
duration:400,
wrpClass:'circles-wrp',
textClass:'circles-text',
styleWrapper:true,
styleText:true
})
var totalIncomeChart = document.getElementById('totalIncomeChart').getContext('2d');
var mytotalIncomeChart = new Chart(totalIncomeChart, {
type: 'bar',
data: {
labels: ["S", "M", "T", "W", "T", "F", "S", "S", "M", "T"],
datasets : [{
label: "Total Income",
backgroundColor: '#ff9e27',
borderColor: 'rgb(23, 125, 255)',
data: [6, 4, 9, 5, 4, 6, 4, 3, 8, 10],
}],
},
options: {
responsive: true,
maintainAspectRatio: false,
legend: {
display: false,
},
scales: {
yAxes: [{
ticks: {
display: false //this will remove only the label
},
gridLines : {
drawBorder: false,
display : false
}
}],
xAxes : [ {
gridLines : {
drawBorder: false,
display : false
}
}]
},
}
});
$('#lineChart').sparkline([105,103,123,100,95,105,115], {
type: 'line',
height: '70',
width: '100%',
lineWidth: '2',
lineColor: '#ffa534',
fillColor: 'rgba(255, 165, 52, .14)'
});
</script>
</div>
<div th:fragment="main-header">
<div class="main-header">

View File

@ -2,42 +2,64 @@
<html lang="en"
xmlns:th="http://www.thymeleaf.org">
<head>
<div th:include="layout::head"></div>
<th:block th:include="layout::head"></th:block>
<title>全员育人系统登录</title>
<!-- JavaScript -->
<th:block th:include="layout::js"></th:block>
<script th:src="@{/assets/js/ase/ase-login.js}"></script>
</head>
<body>
<div th:fragment="content">
<div class="wrapper">
<div class="row" style="height: 15%"></div>
<div class="row" style="height: 70%">
<div class="col-md-3 ml-auto mr-auto">
<div class="card">
<div class="parent">
<div class="middle-container card">
<div class="card-header">
<h4 class="card-title">登录</h4>
</div>
<form action="/login" method="post">
<form id="login-form" action="/login" method="post">
<div class="card-body">
<div class="form-group">
<div id="username-group" class="form-group">
<label for="username">学号</label>
<div class="input-icon">
<span class="input-icon-addon">
<i class="fa fa-user"></i>
</span>
<input type="text" class="form-control" id="username" name="username" placeholder="这里输入学号" required>
</div>
</div>
<div class="form-group">
<label for="password">密码</label>
<div class="input-icon">
<span class="input-icon-addon">
<i class="fa fa-key"></i>
</span>
<input type="password" class="form-control" id="password" name="password" placeholder="这里输入密码" required>
</div>
</div>
</div>
<div class="card-action">
<button type="submit" class="btn btn-primary btn-block"><b>登录</b></button>
<div class="form-check" align="right">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" value="">
<span class="form-check-sign">记住密码</span>
</label>
</div>
</div>
</form>
<button onclick="check_username()" class="btn btn-primary btn-block"><b>检查</b></button>
<div class="line-display">
<a class="btn-link" th:href="@{/forget}"><b>忘记密码</b></a>
&nbsp;&nbsp;&nbsp;
<a class="btn-link" th:href="@{/register}"><b>注册账号</b></a>
</div>
</div>
</div>
<div th:include="layout::custom-template"></div>
</div>
</div>
<div th:include="layout::js"></div>
</body>
</html>