This commit is contained in:
landaiqing 2023-06-09 01:59:08 +08:00
commit 23b265e957
37 changed files with 2087 additions and 0 deletions

29
.gitignore vendored Normal file
View File

@ -0,0 +1,29 @@
### IntelliJ IDEA ###
out/
!**/src/main/**/out/
!**/src/test/**/out/
.idea
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

24
Guestbook.iml Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="web" name="Web">
<configuration>
<descriptors>
<deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/web/WEB-INF/web.xml" />
</descriptors>
<webroots>
<root url="file://$MODULE_DIR$/web" relative="/" />
</webroots>
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="libs" level="project" />
</component>
</module>

Binary file not shown.

BIN
libs/fastjson-1.2.79.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
libs/servlet-api.jar Normal file

Binary file not shown.

View File

@ -0,0 +1,42 @@
package com.landaiqing.dao;
import com.landaiqing.entity.AdminUserEntity;
import com.landaiqing.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class AdminUserDao {
private AdminUserEntity adminUserEntity=new AdminUserEntity();
/**
* 管理员登录
* */
public AdminUserEntity login(String userName, String userPwd) {
ResultSet resultSet = null;
PreparedStatement preparedStatement = null;
Connection connection = null;
try {
connection = JdbcUtils.getConnection();
String loginSql = "select * from admin where adminUserName=? and adminPassword=?;";
preparedStatement = connection.prepareStatement(loginSql);
preparedStatement.setString(1, userName);
preparedStatement.setString(2, userPwd);
resultSet = preparedStatement.executeQuery();
if (!resultSet.next()) { // 查询不到用户数据
return null;
}
// 将db中数据 返回给客户端 查询到数据
Integer id = resultSet.getInt(1);
String dbUserName = resultSet.getString(2);
String dbUserPwd = resultSet.getString(3);
AdminUserEntity adminUserEntity = new AdminUserEntity(dbUserName, dbUserPwd);
return adminUserEntity;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
JdbcUtils.closeConnection(resultSet, preparedStatement, connection);
}
}
}

View File

@ -0,0 +1,57 @@
package com.landaiqing.entity;
public class AdminUserEntity {
/**
*CREATE TABLE `admin-user` (
* `adminId` int NOT NULL AUTO_INCREMENT COMMENT 'ID',
* `adminUserName` varchar(25) NOT NULL COMMENT '管理员账号',
* `adminPassword` varchar(255) DEFAULT NULL COMMENT '管理员密码',
* PRIMARY KEY (`adminId`) USING BTREE
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
*/
private Integer adminId;
private String adminUserName;
private String adminPassword;
public Integer getAdminId() {
return adminId;
}
public void setAdminId(Integer adminId) {
this.adminId = adminId;
}
public String getAdminUserName() {
return adminUserName;
}
public void setAdminUserName(String adminUserName) {
this.adminUserName = adminUserName;
}
public String getAdminPassword() {
return adminPassword;
}
public void setAdminPassword(String adminPassword) {
this.adminPassword = adminPassword;
}
public AdminUserEntity(Integer adminId, String adminUserName, String adminPassword) {
this.adminId = adminId;
this.adminUserName = adminUserName;
this.adminPassword = adminPassword;
}
public AdminUserEntity(String adminUserName, String adminPassword) {
this.adminUserName = adminUserName;
this.adminPassword = adminPassword;
}
public AdminUserEntity(){
}
}

View File

@ -0,0 +1,48 @@
//package com.landaiqing.filter;
//
//
//import jakarta.servlet.*;
//import jakarta.servlet.annotation.WebFilter;
//import jakarta.servlet.http.HttpServletRequest;
//import jakarta.servlet.http.HttpServletResponse;
//import jakarta.servlet.http.HttpSession;
//
//import java.io.IOException;
//
///**
// * 过滤器
// */
//@WebFilter("/*")// 过滤器所有的请求
//public class UserSessionFilter implements Filter {
// private String[] excludeUrls = new String[]{"/login", "/register", "/VerifycodeServlet"};
//
// @Override
// public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// // 从session获取到用户的会话信息 判断用户是否登录过
// HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
// HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
// String contextPath = httpServletRequest.getContextPath();
// // 定义一个数组 哪些 请求是需要排除的
// for (int i = 0; i < excludeUrls.length; i++) {
// String excludeUrl = contextPath + excludeUrls[i];
// String requestURI = httpServletRequest.getRequestURI();
// if (excludeUrl.equals(requestURI)) {
// // 放行请求
// filterChain.doFilter(httpServletRequest, httpServletResponse);
// return;
// }
// }
// // 排除请求
// HttpSession session = httpServletRequest.getSession();
// Object user = session.getAttribute("user");
// if (user == null) {
// // 当前用户没有登录或者登录会话失效
// // 重定向到登录页面
// httpServletResponse.sendRedirect(contextPath+"/login");
// return;
// }
// // 用户已经登录了 正常放行请求
// filterChain.doFilter(httpServletRequest, httpServletResponse);
// }
//}

View File

@ -0,0 +1,15 @@
package com.landaiqing.service;
import com.landaiqing.dao.AdminUserDao;
import com.landaiqing.entity.AdminUserEntity;
public class AdminUserService {
private AdminUserDao adminUserDao=new AdminUserDao();
/**
* 管理员登录
* */
public AdminUserEntity login(String userName, String userPwd) {
return adminUserDao.login(userName,userPwd);
}
}

View File

@ -0,0 +1,80 @@
package com.landaiqing.servlet;
import com.landaiqing.entity.AdminUserEntity;
import com.landaiqing.service.AdminUserService;
import com.landaiqing.utils.RandomValidateCode;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
/**
* 管理员登录
*/
@WebServlet("/login")
public class AdminLoginServlet extends HttpServlet {
private AdminUserService adminUserService = new AdminUserService();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 转发login页面
req.getRequestDispatcher("login.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 点击登录的时候 获取到用户的参数
String userName = req.getParameter("username");
if (StringUtils.isEmpty(userName)) {
//转发到错误页面
req.setAttribute("errorMsg", "用户名称不能够是为空!");
req.getRequestDispatcher("error.jsp").forward(req, resp);
return;
}
String userPwd = req.getParameter("password");
// 参数验证
if (StringUtils.isEmpty(userPwd)) {
//转发到错误页面
req.setAttribute("errorMsg", "userPwd不能够是为空!");
req.getRequestDispatcher("error.jsp").forward(req, resp);
return;
}
String userCode = req.getParameter("code"); // 用户输入的图形验证码
// 从session中获取图形验证码
HttpSession session = req.getSession();
String sessionCode = (String) session.getAttribute(RandomValidateCode.RANDOMVALIDATECODE);
if (!sessionCode.equalsIgnoreCase(userCode)) {
req.setAttribute("errorMsg", "图形验证码不正确,请重新输入!");
req.getRequestDispatcher("error.jsp").forward(req, resp);
return;
}
// 在调用业务逻辑层
AdminUserEntity adminUserEntity = adminUserService.login(userName, userPwd);
if (adminUserEntity == null) {
// 用户名称或者密码错误!
req.setAttribute("errorMsg", "用户名称或者是密码错误!");
req.getRequestDispatcher("error.jsp").forward(req, resp);
return;
}
// 判断用户是否记住密码
String rememberPassword = req.getParameter("remember");
if ("on".equals(rememberPassword)) {
// 如果有记住密码则 将密码保存在cookie中
Cookie userNameCookie = new Cookie("userName", userName);
Cookie userPwdCookie = new Cookie("userPwd", userPwd);
resp.addCookie(userNameCookie);
resp.addCookie(userPwdCookie);
}
// 能够db中查询到对象 登录成功了 将用户数据存放在session中
session = req.getSession();
session.setAttribute("user", adminUserEntity);
// 在转发到首页重定向到首页
// req.getRequestDispatcher("index.jsp").forward(req, resp);
resp.sendRedirect("./System/index.jsp");
}
}

View File

@ -0,0 +1,39 @@
package com.landaiqing.servlet;
import com.landaiqing.utils.RandomValidateCode;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 前台验证码处点击刷新,发送到该servlet的请求,
* 该servlet调用生成验证码的工具类返回一个图像验证码
*/
@WebServlet(name = "VerifycodeServlet", urlPatterns = "/VerifycodeServlet")
public class VerifycodeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("image/jpeg");//设置相应类型,告诉浏览器输出的内容为图片
response.setHeader("Pragma", "No-cache");//设置响应头信息告诉浏览器不要缓存此内容
//做浏览器兼容
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expire", 0);
RandomValidateCode randomValidateCode = new RandomValidateCode();
try {
randomValidateCode.getRandcode(request, response);//输出图片方法
} catch (Exception e) {
e.printStackTrace();
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

View File

@ -0,0 +1,132 @@
package com.landaiqing.utils;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JdbcUtils {
private JdbcUtils() {
}
/**
* 2.定义工具类 需要 声明 变量
*/
private static String driverClass;
private static String url;
private static String user;
private static String password;
/**
*3.使用静态代码快 来给我们声明好 jdbc变量赋值读取config.properties
*/
static {
try {
// 1.读取config.properties IO 路径 相对路径
InputStream resourceAsStream = JdbcUtils.class.getClassLoader().
getResourceAsStream("config.properties");
// 2.赋值给我们声明好的变量
Properties properties = new Properties();
properties.load(resourceAsStream);
driverClass = properties.getProperty("driverClass");
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
// 3.注册驱动类
Class.forName(driverClass);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 4.封装连接方法
*/
public static Connection getConnection() throws SQLException {
Connection connection = DriverManager.getConnection(url, user, password);
return connection;
}
/**
* 5.封装释放连接方法 (重载)
*/
public static void closeConnection(ResultSet resultSet, Statement statement, Connection connection) {
// 1.查询 释放连接 resultSet statement connection
try {
if (resultSet != null)
resultSet.close();
if (statement != null)
statement.close();
if (connection != null)
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 增删改---释放jdbc资源
*
* @param statement
* @param connection
*/
public static void closeConnection(Statement statement, Connection connection) {
// 1.查询 释放连接 resultSet statement connection
closeConnection(null, statement, connection);
}
/**
* 开启事务
*
* @param connection
* @throws SQLException
*/
public static void beginTransaction(Connection connection) throws SQLException {
connection.setAutoCommit(false);
}
/**
* 提交事务
*
* @param connection
* @throws SQLException
*/
public static void commitTransaction(Connection connection) throws SQLException {
connection.commit();
}
/**
* 回滚事务
*
* @param connection
*/
public static void rollBackTransaction(Connection connection) {
if (connection != null) {
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 关闭事务
*
* @param connection
*/
public static void endTransaction(Connection connection) {
if (connection != null) {
try {
connection.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,105 @@
package com.landaiqing.utils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* 工具类,生成随机验证码
*/
public class RandomValidateCode {
public static final String RANDOMVALIDATECODE = "RandomValidateCode";// 放到session中的key
private Random random = new Random();
private String randString = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生的字符串
private int width = 100;// 图片宽度
private int height = 26;// 图片高度
private int lineSize = 40;// 干扰线数量
private int stringNum = 4;// 随机产生的字符数量
/**
* 获得字体
*/
private Font getFont() {
return new Font("Fixedsys", Font.CENTER_BASELINE, 18);
}
/**
* 获得颜色
*/
private Color getRandColor(int fc, int bc) {
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 255;
int r = fc + random.nextInt(bc - fc - 16);
int g = fc + random.nextInt(bc - fc - 14);
int b = fc + random.nextInt(bc - fc - 18);
return new Color(r, g, b);
}
/**
* 生成随机图片
*/
public void getRandcode(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
// BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
Graphics g = image.getGraphics();// 产生Image对象的Graphics对象,该对象可以在图像上进行各种绘制操作
g.fillRect(0, 0, width, height);
g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));
g.setColor(getRandColor(110, 133));
// 绘制干扰线
for (int i = 0; i <= lineSize; i++) {
drowLine(g);
}
// 绘制随机字符
String randomString = "";
for (int i = 1; i <= stringNum; i++) {
randomString = drowString(g, randomString, i);
}
session.removeAttribute(RANDOMVALIDATECODE);
session.setAttribute(RANDOMVALIDATECODE, randomString);
g.dispose();
try {
ImageIO.write(image, "JPEG", response.getOutputStream());// 将内存中的图片通过流动形式输出到客户端
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 绘制字符串
*/
private String drowString(Graphics g, String randomString, int i) {
g.setFont(getFont());
g.setColor(new Color(random.nextInt(101), random.nextInt(111), random.nextInt(121)));
String rand = getRandomString(random.nextInt(randString.length()));
randomString += rand;
g.translate(random.nextInt(3), random.nextInt(3));
g.drawString(rand, 13 * i, 16);
return randomString;
}
/**
* 绘制干扰线
*/
private void drowLine(Graphics g) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(13);
int yl = random.nextInt(15);
g.drawLine(x, y, x + xl, y + yl);
}
/**
* 获取随机的字符
*/
public String getRandomString(int num) {
return String.valueOf(randString.charAt(num));
}
}

4
src/config.properties Normal file
View File

@ -0,0 +1,4 @@
driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/webguestbook?serverTimezone=GMT%2B8
user=root
password=1611

140
web/System/index.jsp Normal file
View File

@ -0,0 +1,140 @@
<%--
Created by IntelliJ IDEA.
User: LDQ
Date: 2023/6/8
Time: 19:48
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>留言本管理</title>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<!-- 引入 layui.css -->
<link href="//unpkg.com/layui@2.8.0/dist/css/layui.css" rel="stylesheet">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<%-- <script type="text/javascript" src="./static/layui/layui.js"></script>--%>
<%-- <link rel="stylesheet" type="text/css" href="./static/layui/css/layui.css">--%>
</head>
<body>
<div class="layui-layout layui-layout-admin">
<div class="layui-header">
<div class="layui-logo layui-hide-xs layui-bg-black">layout demo</div>
<!-- 头部区域可配合layui 已有的水平导航) -->
<ul class="layui-nav layui-layout-left">
<!-- 移动端显示 -->
<li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-header-event="menuLeft">
<i class="layui-icon layui-icon-spread-left"></i>
</li>
<li class="layui-nav-item layui-hide-xs"><a href="javascript:;">nav 1</a></li>
<li class="layui-nav-item layui-hide-xs"><a href="javascript:;">nav 2</a></li>
<li class="layui-nav-item layui-hide-xs"><a href="javascript:;">nav 3</a></li>
<li class="layui-nav-item">
<a href="javascript:;">nav groups</a>
<dl class="layui-nav-child">
<dd><a href="javascript:;">menu 11</a></dd>
<dd><a href="javascript:;">menu 22</a></dd>
<dd><a href="javascript:;">menu 33</a></dd>
</dl>
</li>
</ul>
<ul class="layui-nav layui-layout-right">
<li class="layui-nav-item layui-hide layui-show-sm-inline-block">
<a href="javascript:;">
<img src="https://unpkg.com/outeres@0.0.10/img/layui/icon-v2.png" class="layui-nav-img">
tester
</a>
<dl class="layui-nav-child">
<dd><a href="javascript:;">Your Profile</a></dd>
<dd><a href="javascript:;">Settings</a></dd>
<dd><a href="javascript:;">Sign out</a></dd>
</dl>
</li>
<li class="layui-nav-item" lay-header-event="menuRight" lay-unselect>
<a href="javascript:;">
<i class="layui-icon layui-icon-more-vertical"></i>
</a>
</li>
</ul>
</div>
<div class="layui-side layui-bg-black">
<div class="layui-side-scroll">
<!-- 左侧导航区域可配合layui已有的垂直导航 -->
<ul class="layui-nav layui-nav-tree" lay-filter="test">
<li class="layui-nav-item layui-nav-itemed">
<a class="" href="javascript:;">menu group 1</a>
<dl class="layui-nav-child">
<dd><a href="javascript:;">menu 1</a></dd>
<dd><a href="javascript:;">menu 2</a></dd>
<dd><a href="javascript:;">menu 3</a></dd>
<dd><a href="javascript:;">the links</a></dd>
</dl>
</li>
<li class="layui-nav-item">
<a href="javascript:;">menu group 2</a>
<dl class="layui-nav-child">
<dd><a href="javascript:;">list 1</a></dd>
<dd><a href="javascript:;">list 2</a></dd>
<dd><a href="javascript:;">超链接</a></dd>
</dl>
</li>
<li class="layui-nav-item"><a href="javascript:;">click menu item</a></li>
<li class="layui-nav-item"><a href="javascript:;">the links</a></li>
</ul>
</div>
</div>
<div class="layui-body">
<!-- 内容主体区域 -->
<div style="padding: 15px;">
<blockquote class="layui-elem-quote layui-text">
Layui 框体布局内容主体区域
</blockquote>
<div class="layui-card layui-panel">
<div class="layui-card-header">
下面是充数内容,为的是出现滚动条
</div>
<div class="layui-card-body">
充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>充数内容<br>你还真滑到了底部呀
</div>
</div>
<br><br>
</div>
</div>
<div class="layui-footer">
<!-- 底部固定区域 -->
底部固定区域
</div>
</div>
<script src="/cdn.staticfile.org/layui/2.8.0/layui.js"></script>
<script>
//JS
layui.use(['element', 'layer', 'util'], function(){
var element = layui.element;
var layer = layui.layer;
var util = layui.util;
var $ = layui.$;
//头部事件
util.event('lay-header-event', {
menuLeft: function(othis){ // 左侧菜单事件
layer.msg('展开左侧菜单的操作', {icon: 0});
},
menuRight: function(){ // 右侧菜单事件
layer.open({
type: 1
,title: '更多'
,content: '<div style="padding: 15px;">处理右侧面板的操作</div>'
,area: ['260px', '100%']
,offset: 'rt' //右上角
,anim: 'slideLeft'
,shadeClose: true
,scrollbar: false
});
}
});
});
</script>
</body>
</html>

6
web/WEB-INF/web.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
</web-app>

16
web/error.jsp Normal file
View File

@ -0,0 +1,16 @@
<%--
Created by IntelliJ IDEA.
User: LDQ
Date: 2023/6/9
Time: 1:32
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${errorMsg}
</body>
</html>

450
web/index.jsp Normal file
View File

@ -0,0 +1,450 @@
<%--
Created by IntelliJ IDEA.
User: landaiqing
Date: 2023/6/8
Time: 19:20
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<html>
<head>
<title>留言本</title>
<%-- Lay-ui组件库--%>
<%-- <script type="text/javascript" src="./static/layui/layui.js"></script>--%>
<%-- &lt;%&ndash; Lay-ui样式&ndash;%&gt;--%>
<%-- <link rel="stylesheet" type="text/css" href="./static/layui/css/layui.css">--%>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<!-- 引入 layui.css -->
<link href="//unpkg.com/layui@2.8.0/dist/css/layui.css" rel="stylesheet">
<!-- 引入 layui.js -->
<script src="//unpkg.com/layui@2.8.0/dist/layui.js">
// <link rel="stylesheet" href="./static/css/index.css" type="text/css">
// <script language=JavaScript type="text/javascript" src="static/js/index.js"></script>
<style type="text/css">
@IMPORT url("./static/css/index.css");
</style>
</head>
<body>
<div class="main">
<div class="header">
<div style="display: flex;flex-direction: row;flex-wrap: nowrap;align-items: center;">
<div style="width: 570px;height: 45px;">
<span style="font-size: 2rem;font-weight: 700;font-family: FZShuTi;color:coral;">留 &nbsp;&nbsp;言&nbsp;&nbsp; 本</span>
</div>
<button type="button" class="layui-btn layui-btn-warm layui-btn-radius" lay-on="wrap">
<i class="layui-icon layui-icon-edit"></i>
发布留言
</button>
<!-- <button type="button" class="layui-btn layui-btn-radius" lay-on="admin">
<i class="layui-icon layui-icon-set-fill"></i>
管理
</button> -->
<div>
<ul class="layui-nav" style="background: transparent;">
<li class="layui-nav-item" lay-unselect>
<a href="javascript:;">
<img src="./static/img/touxiang.png" class="layui-nav-img">
</a>
<dl class="layui-nav-child">
<button type="button" class="layui-btn layui-btn-radius" lay-on="admin">
<i class="layui-icon layui-icon-set-fill"></i>
管理
</button>
</dl>
</li>
</ul>
</div>
</div>
</div>
<blockquote class="layui-elem-quote layui-text">
留言列表
</blockquote>
<!-- 管理员登陆 -->
<div class="layui-form" id="adminform" lay-filter="filter-test-layer" style="margin: 16px;display: none;">
<form action="/Guestbook_war_exploded/login" method="post">
<div class="demo-login-container">
<div class="layui-form-item">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-username"></i>
</div>
<input type="text" name="username" value="" lay-verify="required" placeholder="用户名"
lay-reqtext="请填写用户名" autocomplete="off" class="layui-input" lay-affix="clear">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-password"></i>
</div>
<input type="password" name="password" value="" lay-verify="required" placeholder="密 码"
lay-reqtext="请填写密码" autocomplete="off" class="layui-input" lay-affix="eye">
</div>
</div>
<div class="layui-form-item">
<div class="layui-row">
<div class="layui-col-xs7">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-vercode"></i>
</div>
<input type="text" name="code" value="" lay-verify="required" placeholder="验证码"
lay-reqtext="请填写验证码" autocomplete="off" class="layui-input" lay-affix="clear">
</div>
</div>
<div class="layui-col-xs5">
<div style="margin-left: 10px;">
<img src=VerifycodeServlet
onclick="this.src='VerifycodeServlet?'+ new Date().getTime();">
</div>
</div>
</div>
</div>
<div class="layui-form-item">
<input type="checkbox" name="remember" lay-skin="primary" title="记住密码">
</div>
<%-- <div class="layui-form-item">--%>
<%-- <button class="layui-btn layui-btn-fluid" lay-submit lay-filter="demo-login">登录</button>--%>
<%-- </div>--%>
<input type="submit" value="注册"/>
</div>
</form>
</div>
<!-- 发布留言的主体 -->
<div class="wrap" id="warp" style="display: none;">
<div class="userIfo">
<div class="layui-panel">
<div style="padding: 32px;" class="panel">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-username"></i>
</div>
<input type="text" placeholder="昵称" class="layui-input">
</div>
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-login-qq"></i>
</div>
<input type="text" placeholder="QQ" class="layui-input">
</div>
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-email"></i>
</div>
<input type="text" placeholder="Email" class="layui-input">
</div>
</div>
</div>
</div>
<div class="layui-panel">
<div class="wrap-head">
<div class="head-logo">
<img src="./static/img/留言.png" style="height: 20px;width: 20px;" />
</div>
<div class="head-txt">
<a class="title-txt"
href="javascript:void(0)">111111111111111111111111111&nbsp;&nbsp;&nbsp;热门</a>
</div>
</div>
<div class="main-txt">
<textarea name="" rows="" cols="" class="main-area"></textarea>
</div>
<div class="warp-footer">
<div class="warp-icon-cont">
<ul>
<li><img src="./static/img/发表情.png" alt="" />
<a href="javascript:void(0)">表情</a>
</li>
<li><img src="./static/img/图片_填充.png" alt="" />
<a href="javascript:void(0)">图片</a>
</li>
<li><img src="./static/img/视频_填充.png" alt="" />
<a href="javascript:void(0)">视频</a>
</li>
<li><img src="./static/img/话题选中.png" alt="" />
<a href="javascript:void(0)">话题</a>
</li>
<li><img src="./static/img/文章.png" alt="" />
<a href="javascript:void(0)">文章</a>
</li>
</ul>
</div>
<div class="warp-footer-btns">
<div class="release-btn">
<a href="javascript:void(0)">发布</a>
</div>
</div>
</div>
</div>
</div>
<!-- 显示留言的主体 -->
<div class="show">
<div class="show-content">
<div class="show-name">
<div class="avtors"><img src="./static/img/touxiang.png" alt="" style="width: 40px;height: 40px;border-radius: 50%;"></div>
<span style="margin-left: 10px;font-size: 1rem;">Xx</span>
</div>
<div class="show-txt">
<p class="">这是内容111111111111111111111111111111111111111111111111111111111</p>
</div>
<div class="show-time">2018年10月24日</div>
<!-- <button type="button" class="layui-btn layui-btn-xs" lay-on="wrap">
<i class="layui-icon layui-icon-release"></i> 回复
</button> -->
<div class="layui-panel">
<div class="comments">
<div class="comment-wrap">
<div class="photo">
<div class="avatar" style="background-image: url('./static/img/touxiang.png')"></div>
</div>
<div class="comment-block">
<form action="">
<textarea name="" id="" cols="30" rows="3" placeholder="Say somthing..." style="resize:none"></textarea>
<button type="button" class="layui-btn layui-btn-xs">
<i class="layui-icon layui-icon-release"></i> 回复
</button>
</form>
</div>
</div>
<div class="comment-wrap">
<div class="photo">
<div class="avatar" style="background-image: url('./static/img/touxiang.png')"></div>
</div>
<div class="comment-block">
<p class="comment-text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto temporibus iste nostrum dolorem natus recusandae incidunt voluptatum. Eligendi voluptatum ducimus architecto tempore, quaerat explicabo veniam fuga corporis totam reprehenderit
quasi sapiente modi tempora at perspiciatis mollitia, dolores voluptate. Cumque, corrupti?</p>
<div class="bottom-comment">
<div class="comment-date">23.5 2014</div>
<ul class="comment-actions">
<li class="complain">Complain</li>
<li class="reply">Reply</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="show-close">x</div>
</div>
</div>
</div>
<script>
layui.use(function () {
var $ = layui.$;
var layer = layui.layer;
var util = layui.util;
var form = layui.form;
util.on('lay-on', {
'wrap': function () {
layer.open({
type: 1,
resize: true,
title: '发表留言',
shade: false, // 不显示遮罩
content: $('#warp'), // 捕获的元素
end: function () {
// layer.msg('关闭后的回调', {icon:6});
}
});
},
'admin': function () {
layer.open({
type: 1,
area: '350px',
resize: false,
shadeClose: true,
title: '管理员登录',
content: $('#adminform'),
}, )
}
})
})
// 匿名函数包裹,防止外界操作的修改
$(function () {
// 还能输入的字得个数
var able_count = 140;
// 是否可以发布留言
var release_able = false;
// 右上角文字
var $title_txt = $('.title-txt');
// 留言框
var $main_area = $('.main-area');
// 发布按钮
var $release_btn = $('.release-btn');
// 输入框获取焦点
$main_area.focus(function () {
console.log("获取焦点");
$(this).parent().addClass('outline');
$title_txt.addClass('title');
if (able_count >= 0) {
$title_txt.html("还可以输入" + able_count + "个字");
} else {
$title_txt.html("你以超出" + (-able_count) + "个字");
}
})
// 输入框失去焦点
$main_area.blur(function () {
console.log("失去焦点");
$(this).parent().removeClass('outline');
$title_txt.removeClass('title');
$title_txt.html("111");
})
// 输入框文本修改
$main_area.on('input', function () {
console.log("文本修改");
// 剩余可输入的字个数
able_count = 140 - $main_area.val().length;
// console.log(able_count);
// 根据可输入字的个数决定右上角文本的提示 与 是否能发布的状态
if (able_count >= 0 && able_count <= 140) {
$title_txt.html("还可以输入" + able_count + "个字");
if (able_count != 140) {
release_able = true;
} else {
release_able = false;
}
} else {
$title_txt.html("你以超出" + (-able_count) + "个字");
release_able = false;
}
// 根据发布状态决定发布按钮的样式
if (release_able) {
$release_btn.css({
backgroundColor: "orange",
borderColor: "orange"
})
} else {
$release_btn.css({
backgroundColor: "#ffc09f",
borderColor: "#ffc09f"
})
}
})
// 发布事件
$release_btn.click(function () {
console.log("发布");
if (release_able) {
console.log('可以发布');
// 创建show对象的各个部位
var $showContent = $('<div class="show-content"></div>'),
$showName = $('<div class="show-name"></div>'),
$showTxt = $('<div class="show-txt"></div>'),
$showTime = $('<div class="show-time"></div>'),
$showClose = $('<div class="show-close"></div>'),
$showP = $('<p class=""></p>');
var date = new Date();
// 设置,对象结构内内容
$showName.text("XxXx");
$showP.text($main_area.val());
$showTime.text(date);
$showClose.text("x");
// 添加进入主结构
$showTxt.append($showP);
$showContent.append($showName);
$showContent.append($showTxt);
$showContent.append($showTime);
$showContent.append($showClose);
// 向所有匹配元素内部的开始处插入内容
$('.show').prepend($showContent);
// 添加动画
// 位置从输入框处下移
$showContent.css({
top: '-150px'
})
$showContent.animate({
top: 0
}, 200)
// 删除事件
$showClose.click(function () {
// 显示插入的索引位置
// console.log($(this).parent().index());
// console.log($showContent.index());
// 删除操作为顺便
// $showContent.remove();
// 使用删除动画,创建效果
$showContent.animate({
height: 0
}, 200, function () {
// 动画结束后将自身从dom中移除
$showContent.remove();
})
})
// 发布成功后收尾工作
$main_area.val(""); //输入框清空
able_count = 140; //输入框可输入内容数重置
release_able = false;
$release_btn.css({
backgroundColor: '#ffc09f',
borderColor: '#ffc09f'
}) //按钮点击事件重置
}
})
})
</script>
</body>
</html>

351
web/static/css/index.css Normal file
View File

@ -0,0 +1,351 @@
body, ul {
margin: 0;
padding: 0;
}
body{
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
}
ul {
list-style: none;
}
/* main */
.main {
width: 800px;
height: 100%;
/* background-color: #eb7350; */
display: flex;
flex-direction: column;
}
/* header */
.header{
width: 100%;
height: 50px;
/* background-color: #ddd; */
display: flex;
flex-direction: row-reverse;
flex-wrap: nowrap;
/* align-items: center; */
/* justify-content: flex-end; */
}
.userIfo {
display: flex;
margin-top: 20px;
}
.panel{
display: flex;
flex-direction: row;
justify-content: space-between;
}
.layui-panel {
background:transparent;
}
.admin {
width: 350px;
height: 500px;
}
/* 管理员登陆 */
.demo-login-container{width: 320px; margin: 21px auto 0;}
.demo-login-other .layui-icon{position: relative; display: inline-block; margin: 0 2px; top: 2px; font-size: 26px;}
/*最外层*/
.wrap {
width: 700px;
height: 325px;
margin: 20px auto;
border-radius: 4px;
/* border: 1px solid #ddd; */
padding: 0 10px;
}
.wrap-head {
width: 100%;
height: 24px;
padding-top: 4px;
overflow: hidden;
}
.head-logo {
width: 40%;
float: left;
}
.head-logo img {
width: 30px;
height: 30px;
}
.head-txt {
padding: 4px 0;
width: 60%;
float: right;
}
.head-txt a {
font-size: 12px;
color: #eb7350;
text-decoration: none;
}
.title-txt.title {
text-align: right;
color: black;
display: block;
width: 100%;
}
/*内层设计,输入框*/
.main-txt {
border: 1px solid #ccc;
width: 98%;
height: 68px;
margin: 4px 0 0;
padding: 5px;
box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.15) inset;
}
.main-txt textarea {
border: none;
width: 100%;
height: 66px;
outline: none;
resize: none;
color: #333;
}
.main-txt.outline {
outline: 2px orange solid;
}
/*下层设计*/
.warp-footer {
width: 100%;
height: 40px;
margin: 6px 0;
overflow: hidden;
}
.warp-icon-cont {
width: 65%;
float: left;
margin-top: 10px;
}
.warp-icon-cont ul li {
display: inline-block;
margin-right: 15px;
cursor: pointer;
}
.warp-icon-cont a {
font-size: 12px;
color: #333;
text-decoration: none;
height: 20px;
margin-left: 5px;
display: block;
width: 25px;
float: right;
line-height: 20px;
}
.warp-icon-cont a:hover {
color: #eb7350;
}
.warp-icon-cont img {
width: 20px;
height: 20px;
}
.warp-footer-btns {
width: 35%;
float: right;
overflow: hidden;
margin-top: 3px;
}
.release-btn {
width: 80px;
height: 28px;
float: right;
background-color: #ffc09f;
border: 4px solid #fbbd9e;
cursor: pointer;
border-radius: 2px;
}
.release-btn a {
display: block;
color: #fff;
width: 80px;
height: 28px;
line-height: 28px;
text-align: center;
text-decoration: none;
font-size: 15px;
}
/*后期添加的留言框*/
.show {
width: 800px;
/* margin: 20px auto; */
}
.show-content {
width: 775px;
border: 1px solid #ccc;
border-radius: 4px;
margin-bottom: 10px;
padding: 10px;
position: relative;
overflow: hidden;
}
.show-name {
width: 100%;
text-align: left;
font-size: 14px;
color: #333;
font-weight: bold;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
}
.show-txt {
width: 100%;
color: #444;
font-size: 14px;
margin-top: 10px;
}
.show-txt p {
width: 100%;
word-wrap: break-word;
}
.show-time {
font-size: 12px;
color: #808080;
margin-top: 10px;
}
.show-close {
position: absolute;
top: 10px;
right: 10px;
font-size: 12px;
color: #ccc;
cursor: pointer;
transition: .5s;
}
.show-close:hover {
color: red;
}
/* html,
body {
background-color: #f0f2fa;
font-family: "PT Sans", "Helvetica Neue", "Helvetica", "Roboto", "Arial", sans-serif;
color: #555f77;
-webkit-font-smoothing: antialiased;
} */
input,
textarea {
outline: none;
border: none;
display: block;
margin: 0;
padding: 0;
-webkit-font-smoothing: antialiased;
font-family: "PT Sans", "Helvetica Neue", "Helvetica", "Roboto", "Arial", sans-serif;
font-size: 1rem;
color: #555f77;
}
input::-webkit-input-placeholder,
textarea::-webkit-input-placeholder {
color: #ced2db;
}
input::-moz-placeholder,
textarea::-moz-placeholder {
color: #ced2db;
}
input:-moz-placeholder,
textarea:-moz-placeholder {
color: #ced2db;
}
input:-ms-input-placeholder,
textarea:-ms-input-placeholder {
color: #ced2db;
}
p {
line-height: 1.3125rem;
}
.comments {
margin: 2.5rem auto 0;
max-width: 60.75rem;
padding: 0 1.25rem;
}
.comment-wrap {
margin-bottom: 1.25rem;
display: table;
width: 100%;
min-height: 5.3125rem;
}
.photo {
padding-top: 0.625rem;
display: table-cell;
width: 3.5rem;
}
.photo .avatar {
height: 2.25rem;
width: 2.25rem;
border-radius: 50%;
background-size: contain;
}
.comment-block {
padding: 1rem;
background-color: #fff;
display: table-cell;
vertical-align: top;
border-radius: 0.1875rem;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.08);
}
.comment-block textarea {
width: 100%;
max-width: 100%;
}
.comment-text {
margin-bottom: 1.25rem;
}
.bottom-comment {
color: #acb4c2;
font-size: 0.875rem;
}
.comment-date {
float: left;
}
.comment-actions {
float: right;
}
.comment-actions li {
display: inline;
}
.comment-actions li.complain {
padding-right: 0.625rem;
border-right: 1px solid #e1e5eb;
}
.comment-actions li.reply {
padding-left: 0.625rem;
}

BIN
web/static/img/touxiang.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
web/static/img/文章.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
web/static/img/留言.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

142
web/static/js/index.js Normal file
View File

@ -0,0 +1,142 @@
// 匿名函数包裹,防止外界操作的修改
$(function () {
// 还能输入的字得个数
var able_count = 140;
// 是否可以发布留言
var release_able = false;
// 右上角文字
var $title_txt = $('.title-txt');
// 留言框
var $main_area = $('.main-area');
// 发布按钮
var $release_btn = $('.release-btn');
// 输入框获取焦点
$main_area.focus(function () {
console.log("获取焦点");
$(this).parent().addClass('outline');
$title_txt.addClass('title');
if (able_count >= 0) {
$title_txt.html("还可以输入" + able_count + "个字");
} else {
$title_txt.html("你以超出" + (-able_count) + "个字");
}
})
// 输入框失去焦点
$main_area.blur(function () {
console.log("失去焦点");
$(this).parent().removeClass('outline');
$title_txt.removeClass('title');
$title_txt.html("111");
})
// 输入框文本修改
$main_area.on('input', function () {
console.log("文本修改");
// 剩余可输入的字个数
able_count = 140 - $main_area.val().length;
// console.log(able_count);
// 根据可输入字的个数决定右上角文本的提示 与 是否能发布的状态
if (able_count >= 0 && able_count <= 140) {
$title_txt.html("还可以输入" + able_count + "个字");
if (able_count != 140) {
release_able = true;
} else {
release_able = false;
}
} else {
$title_txt.html("你以超出" + (-able_count) + "个字");
release_able = false;
}
// 根据发布状态决定发布按钮的样式
if (release_able) {
$release_btn.css({
backgroundColor: "orange",
borderColor: "orange"
})
} else {
$release_btn.css({
backgroundColor: "#ffc09f",
borderColor: "#ffc09f"
})
}
})
// 发布事件
$release_btn.click(function () {
console.log("发布");
if (release_able) {
console.log('可以发布');
// 创建show对象的各个部位
var $showContent = $('<div class="show-content"></div>'),
$showName = $('<div class="show-name"></div>'),
$showTxt = $('<div class="show-txt"></div>'),
$showTime = $('<div class="show-time"></div>'),
$showClose = $('<div class="show-close"></div>'),
$showP = $('<p class=""></p>');
var date = new Date();
// 设置,对象结构内内容
$showName.text("XxXx");
$showP.text($main_area.val());
$showTime.text(date);
$showClose.text("x");
// 添加进入主结构
$showTxt.append($showP);
$showContent.append($showName);
$showContent.append($showTxt);
$showContent.append($showTime);
$showContent.append($showClose);
// 向所有匹配元素内部的开始处插入内容
$('.show').prepend($showContent);
// 添加动画
// 位置从输入框处下移
$showContent.css({
top: '-150px'
})
$showContent.animate({
top: 0
}, 200)
// 删除事件
$showClose.click(function () {
// 显示插入的索引位置
// console.log($(this).parent().index());
// console.log($showContent.index());
// 删除操作为顺便
// $showContent.remove();
// 使用删除动画,创建效果
$showContent.animate({
height: 0
}, 200, function () {
// 动画结束后将自身从dom中移除
$showContent.remove();
})
})
// 发布成功后收尾工作
$main_area.val(""); //输入框清空
able_count = 140; //输入框可输入内容数重置
release_able = false;
$release_btn.css({
backgroundColor: '#ffc09f',
borderColor: '#ffc09f'
}) //按钮点击事件重置
}
})
})

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long