master
commit
76cdec07b7
@ -0,0 +1,29 @@
|
||||
# Compiled class file
|
||||
*.class
|
||||
classes/
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
target/
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
*.iml
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
.idea/
|
||||
.settings/
|
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : 127.0.0.1
|
||||
Source Server Type : MySQL
|
||||
Source Server Version : 50644
|
||||
Source Host : localhost:3306
|
||||
Source Schema : health
|
||||
|
||||
Target Server Type : MySQL
|
||||
Target Server Version : 50644
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 03/05/2020 15:46:09
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for t_body_info
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `t_body_info`;
|
||||
CREATE TABLE `t_body_info` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`creator` int(11) NULL DEFAULT NULL COMMENT '创建id',
|
||||
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
|
||||
`updater` int(11) NULL DEFAULT NULL COMMENT '修改id',
|
||||
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
|
||||
`low_blood_pressure` int(10) NULL DEFAULT NULL COMMENT '舒张压',
|
||||
`high_blood_pressure` int(10) NULL DEFAULT NULL COMMENT '收缩压',
|
||||
`heart_rate` int(10) NULL DEFAULT NULL COMMENT '心率',
|
||||
`temperature` double(10, 2) NULL DEFAULT NULL COMMENT '体温',
|
||||
`appetite` int(11) NULL DEFAULT NULL COMMENT '食欲',
|
||||
`weight` double(10, 2) NULL DEFAULT NULL COMMENT '体重',
|
||||
`number_of_step` bigint(20) NULL DEFAULT NULL COMMENT '步数',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = '身体信息表' ROW_FORMAT = Compact;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for t_health_config
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `t_health_config`;
|
||||
CREATE TABLE `t_health_config` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`creator` int(11) NULL DEFAULT NULL COMMENT '创建人id',
|
||||
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
|
||||
`updater` int(11) NULL DEFAULT NULL COMMENT '修改人',
|
||||
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
|
||||
`min_low_blood_pressure` int(10) NULL DEFAULT NULL COMMENT '最小低血压',
|
||||
`max_low_blood_pressure` int(10) NULL DEFAULT NULL COMMENT '最高低血压',
|
||||
`min_high_blood_pressure` int(10) NULL DEFAULT NULL COMMENT '最小高血压',
|
||||
`max_high_blood_pressure` int(10) NULL DEFAULT NULL COMMENT '最大高血压',
|
||||
`min_heart_rate` int(10) NULL DEFAULT NULL COMMENT '最小心率',
|
||||
`max_heart_rate` int(10) NULL DEFAULT NULL COMMENT '最大心率',
|
||||
`min_temperature` double(10, 2) NULL DEFAULT NULL COMMENT '最低体温',
|
||||
`max_temperature` double(10, 2) NULL DEFAULT NULL COMMENT '最高体温',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = '健康信息配置表' ROW_FORMAT = Compact;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for t_user
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `t_user`;
|
||||
CREATE TABLE `t_user` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`creator` int(11) NULL DEFAULT NULL COMMENT '创建人',
|
||||
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
|
||||
`updater` int(11) NULL DEFAULT NULL COMMENT '修改人',
|
||||
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
|
||||
`nick_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '用户昵称',
|
||||
`user_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '登录账户',
|
||||
`password` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '登录密码',
|
||||
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '邮箱',
|
||||
`head_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '头像',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `user_name`(`user_name`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = '用户表' ROW_FORMAT = Compact;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
@ -0,0 +1,141 @@
|
||||
package top.beansprout.health.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import top.beansprout.health.constant.SysConstant;
|
||||
import top.beansprout.health.model.vo.RequestVo;
|
||||
import top.beansprout.health.model.vo.RequestVo.RequestVoBuilder;
|
||||
import top.beansprout.health.model.vo.UserLoginVo;
|
||||
import top.beansprout.health.util.JsonUtils;
|
||||
import top.beansprout.health.util.PublicUtils;
|
||||
|
||||
/**
|
||||
* <p>Title: CrossXssFilter</p>
|
||||
* <p>Description: 对用户输入的表单信息进行检测过滤</p>
|
||||
*
|
||||
* @author beansprout
|
||||
* @version 1.0
|
||||
* @date 2020/3/22 22:47
|
||||
*/
|
||||
@Slf4j
|
||||
public class CrossXssFilter implements Filter {
|
||||
|
||||
/** 忽略资源地址 **/
|
||||
private final String[] ignores = new String[] { "/druid", "/static" };
|
||||
/** 忽略页面地址 **/
|
||||
private final String[] filtrationViews = new String[] { "/login", "/user/login", "/register", "/user/register",
|
||||
"/logout", "/user/logout" };
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
final HttpServletRequest request = init(servletRequest);
|
||||
if (!isRequestValid(request)) {
|
||||
chain.doFilter(servletRequest, servletResponse);
|
||||
return;
|
||||
}
|
||||
servletRequest.setCharacterEncoding("UTF-8");
|
||||
servletResponse.setContentType("text/html;charset=utf-8");
|
||||
// sql,xss过滤
|
||||
log.info("URI:{}", request.getRequestURI());
|
||||
log.info("METHOD:{}", request.getMethod());
|
||||
log.info("ParameterMap:{}", JsonUtils.toJson(request.getParameterMap()));
|
||||
if (isOauthValid(request)) {
|
||||
// 获取身份
|
||||
final Object user = request.getSession().getAttribute(SysConstant.INIT_FIELD_USER_VO);
|
||||
if (PublicUtils.isBlank(user)) {
|
||||
final HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
if ((request.getHeader("x-requested-with") != null)
|
||||
&& "XMLHttpRequest".equals(request.getHeader("x-requested-with"))) {
|
||||
// ajax请求
|
||||
response.setHeader("sessionstatus", "timeout");
|
||||
response.setStatus(403);
|
||||
response.addHeader("loginPath", "login");
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
// 页面请求
|
||||
response.setHeader("X-Frame-Options", "DENY");
|
||||
response.sendRedirect("login");
|
||||
return;
|
||||
}
|
||||
}
|
||||
final XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper(request);
|
||||
chain.doFilter(xssHttpServletRequestWrapper, servletResponse);
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
private HttpServletRequest init(ServletRequest servletRequest) {
|
||||
final HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
|
||||
final String basePath = PublicUtils.join(request.getScheme(), "://", request.getServerName(),
|
||||
":" + request.getServerPort(), request.getContextPath(), "/");
|
||||
|
||||
final RequestVoBuilder requestVo = RequestVo.builder().basePath(basePath);
|
||||
final Object userStr = request.getSession().getAttribute(SysConstant.INIT_FIELD_USER_VO);
|
||||
if (PublicUtils.isNotBlank(userStr)) {
|
||||
requestVo.user((UserLoginVo) userStr);
|
||||
}
|
||||
request.setAttribute(SysConstant.INIT_FIELD_REQUEST_VO, JsonUtils.toJson(requestVo.build()));
|
||||
return request;
|
||||
}
|
||||
|
||||
/** 校验合法地址请求 **/
|
||||
private boolean isRequestValid(HttpServletRequest request) {
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(request.getRequestURL().toString());
|
||||
} catch (final URISyntaxException ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (uri.getHost() == null)
|
||||
return false;
|
||||
if (!uri.getScheme().equalsIgnoreCase("http") && !uri.getScheme().equalsIgnoreCase("https"))
|
||||
return false;
|
||||
// 忽略指定地址
|
||||
final String path = StringUtils.removeStart(uri.getPath(), request.getContextPath());
|
||||
for (final String ignore : ignores) {
|
||||
if (path.startsWith(ignore))
|
||||
return false;
|
||||
}
|
||||
// 忽略swagger的根路径
|
||||
if (path.equalsIgnoreCase("/"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** 是否校验合法身份请求 **/
|
||||
private boolean isOauthValid(HttpServletRequest request) {
|
||||
// 忽略指定地址
|
||||
final String path = StringUtils.removeStart(request.getRequestURI(), request.getContextPath());
|
||||
for (final String filtrationView : filtrationViews) {
|
||||
if (path.startsWith(filtrationView))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package top.beansprout.health.config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import top.beansprout.health.model.vo.R;
|
||||
|
||||
/**
|
||||
* <p>Title: ExceptionManager</p>
|
||||
* <p>Description: </p>
|
||||
* @author cyy
|
||||
* @date 2020年4月28日
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class ExceptionManager {
|
||||
|
||||
@ResponseBody
|
||||
@ExceptionHandler({ BindException.class, MethodArgumentNotValidException.class })
|
||||
public R handleException(Exception e) {
|
||||
List<FieldError> fieldErrs = null;
|
||||
if (e instanceof BindException) {
|
||||
fieldErrs = ((BindException) e).getBindingResult().getFieldErrors();
|
||||
}
|
||||
if (e instanceof MethodArgumentNotValidException) {
|
||||
fieldErrs = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors();
|
||||
}
|
||||
Object r = e.getMessage();
|
||||
if (fieldErrs != null) {
|
||||
for (final FieldError err : fieldErrs) {
|
||||
r = err.getDefaultMessage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return R.budil().result(false).message(r.toString()).data(r);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,556 @@
|
||||
package top.beansprout.health.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* <p>Title: HTMLWrapper</p>
|
||||
* <p>Description: HTML内容过滤</p>
|
||||
* HTML filtering utility for protecting against XSS (Cross Site Scripting).
|
||||
*
|
||||
* This code is licensed LGPLv3
|
||||
*
|
||||
* This code is a Java port of the original work in PHP by Cal Hendersen.
|
||||
* http://code.iamcal.com/php/lib_filter/
|
||||
*
|
||||
* The trickiest part of the translation was handling the differences in regex handling
|
||||
* between PHP and Java. These resources were helpful in the process:
|
||||
*
|
||||
* http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html
|
||||
* http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php
|
||||
* http://www.regular-expressions.info/modifiers.html
|
||||
*
|
||||
* A note on naming conventions: instance variables are prefixed with a "v"; global
|
||||
* constants are in all caps.
|
||||
*
|
||||
* Sample use:
|
||||
* String input = ...
|
||||
* String clean = new HTMLWrapper().filter( input );
|
||||
*
|
||||
* The class is not thread safe. Create a new instance if in doubt.
|
||||
*
|
||||
* If you find bugs or have suggestions on improvement (especially regarding
|
||||
* performance), please contact us. The latest version of this
|
||||
* source, and our contact details, can be found at http://xss-html-filter.sf.net
|
||||
*
|
||||
* @author beansprout
|
||||
* @date 2020/3/22 23:06
|
||||
* @version 1.0
|
||||
*/
|
||||
@Slf4j
|
||||
public final class HTMLWrapper {
|
||||
|
||||
private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
|
||||
private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
|
||||
private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
|
||||
private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
|
||||
private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
|
||||
private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
|
||||
private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
|
||||
private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
|
||||
private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
|
||||
private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
|
||||
private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
|
||||
private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
|
||||
private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
|
||||
private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
|
||||
private static final Pattern P_END_ARROW = Pattern.compile("^>");
|
||||
private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
|
||||
private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
|
||||
private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
|
||||
private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
|
||||
private static final Pattern P_AMP = Pattern.compile("&");
|
||||
private static final Pattern P_QUOTE = Pattern.compile("<");
|
||||
private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
|
||||
private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
|
||||
private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
|
||||
|
||||
// @xxx could grow large... maybe use sesat's ReferenceMap
|
||||
private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<String, Pattern>();
|
||||
private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<String, Pattern>();
|
||||
|
||||
/**
|
||||
* set of allowed html elements, along with allowed attributes for each element
|
||||
**/
|
||||
private final Map<String, List<String>> vAllowed;
|
||||
/**
|
||||
* counts of open tags for each (allowable) html element
|
||||
**/
|
||||
private final Map<String, Integer> vTagCounts = new HashMap<String, Integer>();
|
||||
|
||||
/**
|
||||
* html elements which must always be self-closing (e.g. "<img />")
|
||||
**/
|
||||
private final String[] vSelfClosingTags;
|
||||
/**
|
||||
* html elements which must always have separate opening and closing tags (e.g. "<b></b>")
|
||||
**/
|
||||
private final String[] vNeedClosingTags;
|
||||
/**
|
||||
* set of disallowed html elements
|
||||
**/
|
||||
private final String[] vDisallowed;
|
||||
/**
|
||||
* attributes which should be checked for valid protocols
|
||||
**/
|
||||
private final String[] vProtocolAtts;
|
||||
/**
|
||||
* allowed protocols
|
||||
**/
|
||||
private final String[] vAllowedProtocols;
|
||||
/**
|
||||
* tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />")
|
||||
**/
|
||||
private final String[] vRemoveBlanks;
|
||||
/**
|
||||
* entities allowed within html markup
|
||||
**/
|
||||
private final String[] vAllowedEntities;
|
||||
/**
|
||||
* flag determining whether comments are allowed in input String.
|
||||
*/
|
||||
private final boolean stripComment;
|
||||
private final boolean encodeQuotes;
|
||||
private boolean vDebug = false;
|
||||
/**
|
||||
* flag determining whether to try to make tags when presented with "unbalanced"
|
||||
* angle brackets (e.g. "<b text </b>" becomes "<b> text </b>"). If set to false,
|
||||
* unbalanced angle brackets will be html escaped.
|
||||
*/
|
||||
private final boolean alwaysMakeTags;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public HTMLWrapper() {
|
||||
vAllowed = new HashMap<>();
|
||||
|
||||
final ArrayList<String> a_atts = new ArrayList<String>();
|
||||
a_atts.add("href");
|
||||
a_atts.add("target");
|
||||
vAllowed.put("a", a_atts);
|
||||
|
||||
final ArrayList<String> img_atts = new ArrayList<String>();
|
||||
img_atts.add("src");
|
||||
img_atts.add("width");
|
||||
img_atts.add("height");
|
||||
img_atts.add("alt");
|
||||
vAllowed.put("img", img_atts);
|
||||
|
||||
final ArrayList<String> no_atts = new ArrayList<String>();
|
||||
vAllowed.put("b", no_atts);
|
||||
vAllowed.put("strong", no_atts);
|
||||
vAllowed.put("i", no_atts);
|
||||
vAllowed.put("em", no_atts);
|
||||
|
||||
vSelfClosingTags = new String[]{"img"};
|
||||
vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"};
|
||||
vDisallowed = new String[]{};
|
||||
vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp.
|
||||
vProtocolAtts = new String[]{"src", "href"};
|
||||
vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"};
|
||||
vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"};
|
||||
stripComment = true;
|
||||
encodeQuotes = true;
|
||||
alwaysMakeTags = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set debug flag to true. Otherwise use default settings. See the default constructor.
|
||||
*
|
||||
* @param debug turn debug on with a true argument
|
||||
*/
|
||||
public HTMLWrapper(final boolean debug) {
|
||||
this();
|
||||
vDebug = debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map-parameter configurable constructor.
|
||||
*
|
||||
* @param conf map containing configuration. keys match field names.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public HTMLWrapper(final Map<String, Object> conf) {
|
||||
|
||||
assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
|
||||
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
|
||||
assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
|
||||
assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
|
||||
assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
|
||||
assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
|
||||
assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
|
||||
assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
|
||||
|
||||
vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
|
||||
vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
|
||||
vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
|
||||
vDisallowed = (String[]) conf.get("vDisallowed");
|
||||
vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
|
||||
vProtocolAtts = (String[]) conf.get("vProtocolAtts");
|
||||
vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
|
||||
vAllowedEntities = (String[]) conf.get("vAllowedEntities");
|
||||
stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
|
||||
encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
|
||||
alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
vTagCounts.clear();
|
||||
}
|
||||
|
||||
private void debug(final String msg) {
|
||||
if (vDebug) {
|
||||
log.info(msg);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// my versions of some PHP library functions
|
||||
public static String chr(final int decimal) {
|
||||
return String.valueOf((char) decimal);
|
||||
}
|
||||
|
||||
public static String htmlSpecialChars(final String s) {
|
||||
String result = s;
|
||||
result = regexReplace(P_AMP, "&", result);
|
||||
result = regexReplace(P_QUOTE, """, result);
|
||||
result = regexReplace(P_LEFT_ARROW, "<", result);
|
||||
result = regexReplace(P_RIGHT_ARROW, ">", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* given a user submitted input String, filter out any invalid or restricted
|
||||
* html.
|
||||
*
|
||||
* @param input text (i.e. submitted by a user) than may contain html
|
||||
* @return "clean" version of input, with only valid, whitelisted html elements allowed
|
||||
*/
|
||||
public String filter(final String input) {
|
||||
reset();
|
||||
String s = input;
|
||||
|
||||
debug("************************************************");
|
||||
debug(" INPUT: " + input);
|
||||
|
||||
s = escapeComments(s);
|
||||
debug(" escapeComments: " + s);
|
||||
|
||||
s = balanceHTML(s);
|
||||
debug(" balanceHTML: " + s);
|
||||
|
||||
s = checkTags(s);
|
||||
debug(" checkTags: " + s);
|
||||
|
||||
s = processRemoveBlanks(s);
|
||||
debug("processRemoveBlanks: " + s);
|
||||
|
||||
s = validateEntities(s);
|
||||
debug(" validateEntites: " + s);
|
||||
|
||||
debug("************************************************\n\n");
|
||||
return s;
|
||||
}
|
||||
|
||||
public boolean isAlwaysMakeTags() {
|
||||
return alwaysMakeTags;
|
||||
}
|
||||
|
||||
public boolean isStripComments() {
|
||||
return stripComment;
|
||||
}
|
||||
|
||||
private String escapeComments(final String s) {
|
||||
final Matcher m = P_COMMENTS.matcher(s);
|
||||
final StringBuffer buf = new StringBuffer();
|
||||
if (m.find()) {
|
||||
final String match = m.group(1); //(.*?)
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String balanceHTML(String s) {
|
||||
if (alwaysMakeTags) {
|
||||
//
|
||||
// try and form html
|
||||
//
|
||||
s = regexReplace(P_END_ARROW, "", s);
|
||||
s = regexReplace(P_BODY_TO_END, "<$1>", s);
|
||||
s = regexReplace(P_XML_CONTENT, "$1<$2", s);
|
||||
|
||||
} else {
|
||||
//
|
||||
// escape stray brackets
|
||||
//
|
||||
s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s);
|
||||
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s);
|
||||
|
||||
//
|
||||
// the last regexp causes '<>' entities to appear
|
||||
// (we need to do a lookahead assertion so that the last bracket can
|
||||
// be used in the next pass of the regexp)
|
||||
//
|
||||
s = regexReplace(P_BOTH_ARROWS, "", s);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private String checkTags(String s) {
|
||||
final Matcher m = P_TAGS.matcher(s);
|
||||
|
||||
final StringBuffer buf = new StringBuffer();
|
||||
while (m.find()) {
|
||||
String replaceStr = m.group(1);
|
||||
replaceStr = processTag(replaceStr);
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
|
||||
s = buf.toString();
|
||||
|
||||
// these get tallied in processTag
|
||||
// (remember to reset before subsequent calls to filter method)
|
||||
for (final String key : vTagCounts.keySet()) {
|
||||
for (int ii = 0; ii < vTagCounts.get(key); ii++) {
|
||||
s += "</" + key + ">";
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private String processRemoveBlanks(final String s) {
|
||||
String result = s;
|
||||
for (final String tag : vRemoveBlanks) {
|
||||
if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) {
|
||||
P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
|
||||
}
|
||||
result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
|
||||
if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) {
|
||||
P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
|
||||
}
|
||||
result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) {
|
||||
final Matcher m = regex_pattern.matcher(s);
|
||||
return m.replaceAll(replacement);
|
||||
}
|
||||
|
||||
private String processTag(final String s) {
|
||||
// ending tags
|
||||
Matcher m = P_END_TAG.matcher(s);
|
||||
if (m.find()) {
|
||||
final String name = m.group(1).toLowerCase();
|
||||
if (allowed(name)) {
|
||||
if (!inArray(name, vSelfClosingTags)) {
|
||||
if (vTagCounts.containsKey(name)) {
|
||||
vTagCounts.put(name, vTagCounts.get(name) - 1);
|
||||
return "</" + name + ">";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// starting tags
|
||||
m = P_START_TAG.matcher(s);
|
||||
if (m.find()) {
|
||||
final String name = m.group(1).toLowerCase();
|
||||
final String body = m.group(2);
|
||||
String ending = m.group(3);
|
||||
|
||||
//debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
|
||||
if (allowed(name)) {
|
||||
String params = "";
|
||||
|
||||
final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
|
||||
final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
|
||||
final List<String> paramNames = new ArrayList<String>();
|
||||
final List<String> paramValues = new ArrayList<String>();
|
||||
while (m2.find()) {
|
||||
paramNames.add(m2.group(1)); //([a-z0-9]+)
|
||||
paramValues.add(m2.group(3)); //(.*?)
|
||||
}
|
||||
while (m3.find()) {
|
||||
paramNames.add(m3.group(1)); //([a-z0-9]+)
|
||||
paramValues.add(m3.group(3)); //([^\"\\s']+)
|
||||
}
|
||||
|
||||
String paramName, paramValue;
|
||||
for (int ii = 0; ii < paramNames.size(); ii++) {
|
||||
paramName = paramNames.get(ii).toLowerCase();
|
||||
paramValue = paramValues.get(ii);
|
||||
|
||||
// debug( "paramName='" + paramName + "'" );
|
||||
// debug( "paramValue='" + paramValue + "'" );
|
||||
// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
|
||||
|
||||
if (allowedAttribute(name, paramName)) {
|
||||
if (inArray(paramName, vProtocolAtts)) {
|
||||
paramValue = processParamProtocol(paramValue);
|
||||
}
|
||||
params += " " + paramName + "=\"" + paramValue + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
if (inArray(name, vSelfClosingTags)) {
|
||||
ending = " /";
|
||||
}
|
||||
|
||||
if (inArray(name, vNeedClosingTags)) {
|
||||
ending = "";
|
||||
}
|
||||
|
||||
if ((ending == null) || (ending.length() < 1)) {
|
||||
if (vTagCounts.containsKey(name)) {
|
||||
vTagCounts.put(name, vTagCounts.get(name) + 1);
|
||||
} else {
|
||||
vTagCounts.put(name, 1);
|
||||
}
|
||||
} else {
|
||||
ending = " /";
|
||||
}
|
||||
return "<" + name + params + ending + ">";
|
||||
} else
|
||||
return "";
|
||||
}
|
||||
|
||||
// comments
|
||||
m = P_COMMENT.matcher(s);
|
||||
if (!stripComment && m.find())
|
||||
return "<" + m.group() + ">";
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private String processParamProtocol(String s) {
|
||||
s = decodeEntities(s);
|
||||
final Matcher m = P_PROTOCOL.matcher(s);
|
||||
if (m.find()) {
|
||||
final String protocol = m.group(1);
|
||||
if (!inArray(protocol, vAllowedProtocols)) {
|
||||
// bad protocol, turn into local anchor link instead
|
||||
s = "#" + s.substring(protocol.length() + 1, s.length());
|
||||
if (s.startsWith("#//")) {
|
||||
s = "#" + s.substring(3, s.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private String decodeEntities(String s) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
||||
Matcher m = P_ENTITY.matcher(s);
|
||||
while (m.find()) {
|
||||
final String match = m.group(1);
|
||||
final int decimal = Integer.decode(match).intValue();
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
s = buf.toString();
|
||||
|
||||
buf = new StringBuffer();
|
||||
m = P_ENTITY_UNICODE.matcher(s);
|
||||
while (m.find()) {
|
||||
final String match = m.group(1);
|
||||
final int decimal = Integer.valueOf(match, 16).intValue();
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
s = buf.toString();
|
||||
|
||||
buf = new StringBuffer();
|
||||
m = P_ENCODE.matcher(s);
|
||||
while (m.find()) {
|
||||
final String match = m.group(1);
|
||||
final int decimal = Integer.valueOf(match, 16).intValue();
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
s = buf.toString();
|
||||
|
||||
s = validateEntities(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
private String validateEntities(final String s) {
|
||||
final StringBuffer buf = new StringBuffer();
|
||||
|
||||
// validate entities throughout the string
|
||||
final Matcher m = P_VALID_ENTITIES.matcher(s);
|
||||
while (m.find()) {
|
||||
final String one = m.group(1); //([^&;]*)
|
||||
final String two = m.group(2); //(?=(;|&|$))
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
|
||||
return encodeQuotes(buf.toString());
|
||||
}
|
||||
|
||||
private String encodeQuotes(final String s) {
|
||||
if (encodeQuotes) {
|
||||
final StringBuffer buf = new StringBuffer();
|
||||
final Matcher m = P_VALID_QUOTES.matcher(s);
|
||||
while (m.find()) {
|
||||
final String one = m.group(1); //(>|^)
|
||||
final String two = m.group(2); //([^<]+?)
|
||||
final String three = m.group(3); //(<|$)
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, """, two) + three));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
return buf.toString();
|
||||
} else
|
||||
return s;
|
||||
}
|
||||
|
||||
private String checkEntity(final String preamble, final String term) {
|
||||
|
||||
return ";".equals(term) && isValidEntity(preamble)
|
||||
? '&' + preamble
|
||||
: "&" + preamble;
|
||||
}
|
||||
|
||||
private boolean isValidEntity(final String entity) {
|
||||
return inArray(entity, vAllowedEntities);
|
||||
}
|
||||
|
||||
private static boolean inArray(final String s, final String[] array) {
|
||||
for (final String item : array) {
|
||||
if ((item != null) && item.equals(s))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean allowed(final String name) {
|
||||
return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
|
||||
}
|
||||
|
||||
private boolean allowedAttribute(final String name, final String paramName) {
|
||||
return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package top.beansprout.health.config;
|
||||
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
public class TaskExecutorConfig implements AsyncConfigurer { // 1
|
||||
|
||||
@Override
|
||||
public Executor getAsyncExecutor() { // 2
|
||||
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
|
||||
taskExecutor.setCorePoolSize(10);
|
||||
taskExecutor.setMaxPoolSize(15);
|
||||
taskExecutor.setQueueCapacity(25);
|
||||
taskExecutor.initialize();
|
||||
return taskExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
||||
return new SimpleAsyncUncaughtExceptionHandler();
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package top.beansprout.health.constant;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import top.beansprout.health.model.vo.RequestVo;
|
||||
import top.beansprout.health.util.JsonUtils;
|
||||
import top.beansprout.health.util.PublicUtils;
|
||||
|
||||
/**
|
||||
* <p>Title: SysConstant</p>
|
||||
* <p>Description: 系统常量</p>
|
||||
* @author cyy
|
||||
* @date 2020年4月23日
|
||||
*/
|
||||
public class SysConstant {
|
||||
|
||||
public static final String CHARACHER = "UTF-8";
|
||||
|
||||
public static final String INIT_FIELD_REQUEST_IP = "ip";
|
||||
public static final String INIT_FIELD_REQUEST_REQUEST_ID = "requestId";
|
||||
public static final String INIT_FIELD_REQUEST_USER_AGENT = "userAgent";
|
||||
public static final String INIT_FIELD_REQUEST_BASE_PATH = "basePath";
|
||||
public static final String INIT_FIELD_REQUEST_VO = "requestVo";
|
||||
public static final String INIT_FIELD_USER_VO = "user";
|
||||
|
||||
/** 获取初始化数据 **/
|
||||
public static RequestVo getRequestVo(HttpServletRequest request) {
|
||||
return JsonUtils.toObj(PublicUtils.getAttribute(request, INIT_FIELD_REQUEST_VO), RequestVo.class);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package top.beansprout.health.controller;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import top.beansprout.health.constant.SysConstant;
|
||||
import top.beansprout.health.model.vo.BusinessException;
|
||||
import top.beansprout.health.model.vo.UserLoginVo;
|
||||
import top.beansprout.health.util.PublicUtils;
|
||||
|
||||
/**
|
||||
* <p> Title: BaseController </p>
|
||||
* <p> Description: 基本信息处理</p>
|
||||
*
|
||||
* @Auther: cyy
|
||||
* @Date: 2020年4月27日 上午12:36:51
|
||||
* @Version: 1.0.0
|
||||
*/
|
||||
public class BaseController {
|
||||
|
||||
@Autowired
|
||||
private HttpServletRequest request;
|
||||
|
||||
public UserLoginVo getUserInfo() {
|
||||
final Object userObject = request.getSession().getAttribute(SysConstant.INIT_FIELD_USER_VO);
|
||||
if (PublicUtils.isNotBlank(userObject))
|
||||
return (UserLoginVo) userObject;
|
||||
throw new BusinessException("login", "身份信息已过期,请重新登录");
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return getUserInfo().getId();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package top.beansprout.health.controller;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import top.beansprout.health.model.dto.BodyInfoQuery;
|
||||
import top.beansprout.health.model.dto.BodyInfoSaveDto;
|
||||
import top.beansprout.health.model.vo.R;
|
||||
import top.beansprout.health.service.HealthService;
|
||||
|
||||
/**
|
||||
* <p>Title: HealthController</p>
|
||||
* <p>Description: 健康管理接口</p>
|
||||
*
|
||||
* @author cyy
|
||||
* @date 2020年4月27日
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/health")
|
||||
public class HealthController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private HealthService healthService;
|
||||
|
||||
// 保存身体信息
|
||||
@ResponseBody
|
||||
@PostMapping("/saveBodyInfo")
|
||||
public R saveBodyInfo(@RequestBody @Valid BodyInfoSaveDto bodyInfoSaveDto) {
|
||||
healthService.saveBodyInfo(getUserId(), bodyInfoSaveDto);
|
||||
return R.okAsAjax();
|
||||
}
|
||||
|
||||
// 身体信息列表
|
||||
@ResponseBody
|
||||
@GetMapping("/bodyInfoList")
|
||||
public R bodyInfoList(@Valid BodyInfoQuery bodyInfoQuery) {
|
||||
return R.okAsAjax(healthService.bodyInfoList(getUserId(), bodyInfoQuery));
|
||||
}
|
||||
|
||||
// 删除身体信息
|
||||
@ResponseBody
|
||||
@DeleteMapping("/{id}")
|
||||
public R saveBodyInfo(@PathVariable int id) {
|
||||
healthService.deleteBodyInfo(getUserId(), id);
|
||||
return R.okAsAjax();
|
||||
}
|
||||
|
||||
// 获取身体信息
|
||||
@ResponseBody
|
||||
@GetMapping("/{id}")
|
||||
public R getBodyInfo(@PathVariable int id) {
|
||||
return R.okAsAjax(healthService.getBodyInfo(getUserId(), id));
|
||||
}
|
||||
|
||||
// 身体信息统计
|
||||
@ResponseBody
|
||||
@GetMapping("/bodyInfoStatistics")
|
||||
public R bodyInfoStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date) {
|
||||
return R.okAsAjax(healthService.getBodyStatistics(getUserId(), date));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package top.beansprout.health.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import top.beansprout.health.model.dto.BodyInfoSaveDto;
|
||||
import top.beansprout.health.model.dto.UserUpdateInfoDto;
|
||||
import top.beansprout.health.model.entity.TBodyInfo;
|
||||
import top.beansprout.health.model.vo.R;
|
||||
import top.beansprout.health.service.HealthService;
|
||||
import top.beansprout.health.util.MailUtils;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Title: MailController</p>
|
||||
* <p>Description: 发送邮箱接口</p>
|
||||
*
|
||||
* @author ateenliu
|
||||
* @date 2022年4月6日
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/mail")
|
||||
public class MailController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private HealthService healthService;
|
||||
|
||||
@ResponseBody
|
||||
@PostMapping(value = "/verification")
|
||||
public R sendVerificationMail(@Valid String email) {
|
||||
MailUtils mailUtils = new MailUtils();
|
||||
String verificationCode = mailUtils.createVertifyCode();
|
||||
String mailSubject = "个人健康管理平台验证码";
|
||||
String mailBody = "欢迎使用个人健康管理平台,您的邮箱验证码为:"+verificationCode;
|
||||
if(mailUtils.sendingMimeMail(email,mailSubject,mailBody))
|
||||
{
|
||||
System.out.println("邮件发送成功!");
|
||||
return R.okAsAjax(verificationCode);
|
||||
}
|
||||
else {
|
||||
System.out.println("邮件发送失败!");
|
||||
return R.okAsAjax();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@PostMapping(value = "/recentPush")
|
||||
public R recentPushMail(){
|
||||
if(getUserInfo().getEmail()==null)
|
||||
return R.ofAsAjax(true,"暂未绑定邮箱","");
|
||||
|
||||
List<TBodyInfo> tBodyInfoList = healthService.recentBodyInfoList(getUserId());
|
||||
TBodyInfo t = new TBodyInfo();
|
||||
MailUtils mailUtils = new MailUtils();
|
||||
String mailSubject = "近期健康报告";
|
||||
StringBuilder content = new StringBuilder("<html><head></head><body><h2>您的近期报告如下:</h2>");
|
||||
content.append("<table border=\"1\">");
|
||||
content.append("<tr><th>打卡时间</th><th>收缩压</th><th>舒张压</th>" +
|
||||
"<th>心率</th><th>体温</th><th>食欲</th><th>体重</th><th>步数</th></tr>");
|
||||
for(int i=0;i<tBodyInfoList.size();i++){
|
||||
t = tBodyInfoList.get(i);
|
||||
content.append("<tr><td>"+t.getCreateTime()+"</td>"+ "<td>"+t.getHighBloodPressure()+"</td>"
|
||||
+ "<td>"+t.getLowBloodPressure()+"</td>"+ "<td>"+t.getHeartRate()+"</td>"
|
||||
+ "<td>"+t.getTemperature()+"度</td>"+ "<td>"+t.getAppetiteDes(t.getAppetite())+"</td>"
|
||||
+ "<td>"+t.getWeight()+"kg</td>"+ "<td>"+t.getNumberOfStep()+"步</td></tr>");
|
||||
}
|
||||
content.append("</table>");
|
||||
content.append("</body></html>");
|
||||
|
||||
|
||||
if(mailUtils.sendingMimeMail(getUserInfo().getEmail(), mailSubject,content.toString()))
|
||||
{
|
||||
System.out.println("邮件发送成功!");
|
||||
return R.okAsAjax();
|
||||
}
|
||||
else {
|
||||
System.out.println("邮件发送失败!");
|
||||
return R.okAsAjax();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package top.beansprout.health.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
/**
|
||||
* <p> Title: PageController </p>
|
||||
* <p> Description: 页面管理</p>
|
||||
*
|
||||
* @Auther: cyy
|
||||
* @Date: 2020年4月23日 下午11:15:18
|
||||
* @Version: 1.0.0
|
||||
*/
|
||||
@Controller
|
||||
public class PageController {
|
||||
|
||||
// 根页面
|
||||
@GetMapping("/")
|
||||
public String rootView() {
|
||||
return "redirect:/login";
|
||||
}
|
||||
|
||||
// 登录页面
|
||||
@GetMapping("/login")
|
||||
public String loginView() {
|
||||
return "../../index";
|
||||
}
|
||||
|
||||
// 注册页面
|
||||
@GetMapping("/register")
|
||||
public String registerView() {
|
||||
return "register";
|
||||
}
|
||||
|
||||
// 主页面
|
||||
@GetMapping("/home")
|
||||
public String homeView() {
|
||||
return "home";
|
||||
}
|
||||
|
||||
// 用户信息页面
|
||||
@GetMapping("/userInfo")
|
||||
public String userInfoView() {
|
||||
return "userInfo";
|
||||
}
|
||||
|
||||
// 用户信息页面
|
||||
@GetMapping("/updatePassword")
|
||||
public String updatePasswordView() {
|
||||
return "updatePassword";
|
||||
}
|
||||
|
||||
// 用户身体信息录入页面
|
||||
@GetMapping("/bodyInfoInput")
|
||||
public String bodyInfoInputView() {
|
||||
return "bodyInfoInput";
|
||||
}
|
||||
|
||||
// 用户身体信息列表页面
|
||||
@GetMapping("/bodyInofList")
|
||||
public String bodyInofListView() {
|
||||
return "bodyInofList";
|
||||
}
|
||||
|
||||
// 用户身体信息统计页面
|
||||
@GetMapping("/bodyInofStatistics")
|
||||
public String bodyInofStatisticsView() {
|
||||
return "bodyInofStatistics";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package top.beansprout.health.controller;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import top.beansprout.health.model.dto.UserLoginDto;
|
||||
import top.beansprout.health.model.dto.UserRegisterDto;
|
||||
import top.beansprout.health.model.dto.UserUpdateInfoDto;
|
||||
import top.beansprout.health.model.dto.UserUpdatePasswordDto;
|
||||
import top.beansprout.health.model.vo.R;
|
||||
import top.beansprout.health.service.UserService;
|
||||
|
||||
/**
|
||||
* <p>Title: UserController</p>
|
||||
* <p>Description: 用户管理接口</p>
|
||||
*
|
||||
* @author cyy
|
||||
* @date 2020年4月23日
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/user")
|
||||
public class UserController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
// 登录
|
||||
@ResponseBody
|
||||
@PostMapping("/login")
|
||||
public R login(@Valid UserLoginDto userLoginDto) {
|
||||
return R.okAsAjax(userService.login(userLoginDto));
|
||||
}
|
||||
|
||||
// 注册
|
||||
@ResponseBody
|
||||
@PostMapping("/register")
|
||||
public R register(@Valid UserRegisterDto userRegisterDto) {
|
||||
userService.register(userRegisterDto);
|
||||
return R.okAsAjax();
|
||||
}
|
||||
|
||||
// 登出
|
||||
@GetMapping("/logout")
|
||||
public String logout(HttpServletRequest request) {
|
||||
userService.logout(request);
|
||||
return "redirect:/login?target=redirect";
|
||||
}
|
||||
|
||||
// 修改密码
|
||||
@ResponseBody
|
||||
@PutMapping("/updatePassword")
|
||||
public R updatePassword(HttpServletRequest request, @RequestBody @Valid UserUpdatePasswordDto updatePasswordDto) {
|
||||
userService.updatePassword(request, getUserId(), updatePasswordDto);
|
||||
return R.okAsAjax();
|
||||
}
|
||||
|
||||
// 修改用户信息
|
||||
@ResponseBody
|
||||
@PostMapping(value = "/updateUserInfo", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public R updateUserInfo(@Valid UserUpdateInfoDto userUpdateInfoDto) {
|
||||
return R.okAsAjax(userService.updateUserInfo(getUserId(), userUpdateInfoDto));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package top.beansprout.health.mapper;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import top.beansprout.health.model.entity.TBodyInfo;
|
||||
|
||||
/**
|
||||
* <p>Title: TBodyInfoMapper</p>
|
||||
* <p>Description: 身体健康操作</p>
|
||||
*
|
||||
* @author cyy
|
||||
* @date 2020年4月27日
|
||||
*/
|
||||
public interface TBodyInfoMapper {
|
||||
|
||||
@Insert("INSERT INTO t_body_info (creator, create_time, updater, update_time, low_blood_pressure, "
|
||||
+ "high_blood_pressure, heart_rate, temperature, appetite, weight, number_of_step) VALUE "
|
||||
+ "( #{creator},NOW(),#{updater},NOW(),#{lowBloodPressure},#{highBloodPressure},"
|
||||
+ "#{heartRate},#{temperature},#{appetite},#{weight},#{numberOfStep} )")
|
||||
int insertByOne(TBodyInfo bodyInfo);
|
||||
|
||||
@Select("SELECT COUNT(*) FROM t_body_info WHERE creator = #{creator} AND create_time >= CURDATE() AND create_time <= CONCAT(CURDATE(), '23:59:59')")
|
||||
int countByOneAsToDay(@Param("creator") int userId);
|
||||
|
||||
List<TBodyInfo> selectByUserId(@Param("creator") int userId, @Param("minDate") Date minDate,
|
||||
@Param("maxDate") Date maxDate);
|
||||
|
||||
@Delete("DELETE FROM t_body_info WHERE id = #{id} AND creator = #{creator}")
|
||||
int deleteByOne(@Param("id") int id, @Param("creator") int userId);
|
||||
|
||||
@Select("SELECT * FROM t_body_info WHERE id = #{id} AND creator = #{creator}")
|
||||
TBodyInfo selectByUserOne(@Param("id") int id, @Param("creator") int userId);
|
||||
|
||||
@Select("SELECT * FROM t_body_info WHERE creator = #{creator} LIMIT 7 ")
|
||||
List<TBodyInfo> selectRecentByUserId(@Param("creator") int userId);
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package top.beansprout.health.mapper;
|
||||
|
||||
/**
|
||||
* <p>Title: THealthConfigMapper</p>
|
||||
* <p>Description: 健康配置操作</p>
|
||||
*
|
||||
* @author cyy
|
||||
* @date 2020年4月27日
|
||||
*/
|
||||
public interface THealthConfigMapper {
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package top.beansprout.health.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
|
||||
import top.beansprout.health.model.entity.TUser;
|
||||
|
||||
/**
|
||||
* <p> Title: TUserMapper </p>
|
||||
* <p> Description: 用户数据操作</p>
|
||||
*
|
||||
* @Auther: cyy
|
||||
* @Date: 2020年4月23日 下午9:24:05
|
||||
* @Version: 1.0.0
|
||||
*/
|
||||
public interface TUserMapper {
|
||||
|
||||
@Select("SELECT * FROM t_user WHERE user_name = #{userName}")
|
||||
TUser selectByUserName(@Param("userName") String userName);
|
||||
|
||||
@Select("SELECT * FROM t_user WHERE id = #{userId}")
|
||||
TUser selectById(@Param("userId") int id);
|
||||
|
||||
@Insert("INSERT INTO t_user (creator, create_time, updater, update_time, nick_name, user_name, password, head_url) "
|
||||
+ "VALUE (0, NOW(), 0, NOW(), #{userName}, #{userName}, #{password}, #{headUrl})")
|
||||
int insertByOne(TUser tUser);
|
||||
|
||||
@Update("UPDATE t_user SET updater = #{id}, update_time = NOW(), password = #{password} WHERE id = #{id}")
|
||||
int updateByOne(TUser tUser);
|
||||
|
||||
@Update("UPDATE t_user SET updater = #{id}, update_time = NOW(), nick_name = #{nickName}, email = #{email}, head_url = #{headUrl} WHERE id = #{id}")
|
||||
int updateByUserInfoOne(TUser tUser);
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package top.beansprout.health.model.dto;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: BodyInfoQuery</p>
|
||||
* <p>Description: 身体信息查询</p>
|
||||
*
|
||||
* @author cyy
|
||||
* @date 2020年4月27日
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class BodyInfoQuery extends PageDto {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date minDate;
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date maxDate;
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package top.beansprout.health.model.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: BodyInfoSaveDto</p>
|
||||
* <p>Description: 身体信息保存</p>
|
||||
*
|
||||
* @author cyy
|
||||
* @date 2020年4月27日
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class BodyInfoSaveDto implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 80577054311531170L;
|
||||
|
||||
@NotNull(message = "低血压不能为空")
|
||||
@Range(min = 0, max = 200, message = "低血压只能在0到200之间")
|
||||
private Integer lowBloodPressure;
|
||||
@NotNull(message = "高血压不能为空")
|
||||
@Range(min = 0, max = 200, message = "高血压只能在0到200之间")
|
||||
private Integer highBloodPressure;
|
||||
@NotNull(message = "心率不能为空")
|
||||
@Range(min = 40, max = 200, message = "心率只能在40到200之间")
|
||||
private Integer heartRate;
|
||||
@NotNull(message = "体温不能为空")
|
||||
@Range(min = 33, max = 45, message = "体温只能在33到45之间")
|
||||
private Double temperature;
|
||||
@NotNull(message = "食欲不能为空")
|
||||
@Range(min = 1, max = 6, message = "食欲只能在1到6之间")
|
||||
private Integer appetite;
|
||||
@NotNull(message = "体重不能为空")
|
||||
@Range(min = 0, max = 200, message = "体重只能在33到40之间")
|
||||
private Double weight;
|
||||
// 步数
|
||||
private int numberOfStep;
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package top.beansprout.health.model.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: PageDto</p>
|
||||
* <p>Description: 列表请求</p>
|
||||
*
|
||||
* @author beansprout
|
||||
* @version 1.0
|
||||
* @date 2020/3/22 22:32
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class PageDto implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1796187511693230421L;
|
||||
|
||||
@Min(value = 1, message = "当前页最小页码为1")
|
||||
private int page = 1;
|
||||
|
||||
@Min(value = 1, message = "每页展示条数最小为1")
|
||||
@Max(value = 100, message = "每页展示条数最大为100")
|
||||
private int pageSize = 10;
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package top.beansprout.health.model.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p> Title: UserLoginDto </p>
|
||||
* <p> Description: 用户登录</p>
|
||||
*
|
||||
* @Auther: cyy
|
||||
* @Date: 2020年4月25日 下午8:11:06
|
||||
* @Version: 1.0.0
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class UserLoginDto implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6865880222397602631L;
|
||||
|
||||
@NotBlank(message = "账户不能为空")
|
||||
@Length(max = 20, message = "账户不能超过20位")
|
||||
private String userName;
|
||||
@NotBlank(message = "密码不能为空")
|
||||
@Length(max = 20, message = "密码不能超过20位")
|
||||
private String passWord;
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package top.beansprout.health.model.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p> Title: UserRegisterDto </p>
|
||||
* <p> Description: 用户注册</p>
|
||||
*
|
||||
* @Auther: cyy
|
||||
* @Date: 2020年4月26日 上午12:54:09
|
||||
* @Version: 1.0.0
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class UserRegisterDto implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -4003225859721099921L;
|
||||
|
||||
@NotBlank(message = "用户名或姓名不能为空")
|
||||
@Length(min = 2, max = 10, message = "用户名或姓名必须在2~10位之间")
|
||||
private String userName;
|
||||
@NotBlank(message = "密码不能为空")
|
||||
@Length(min = 6, max = 10, message = "密码必须在6~10位之间")
|
||||
private String passWord;
|
||||
@NotBlank(message = "确认密码不能为空")
|
||||
@Length(min = 6, max = 10, message = "确认密码必须在6~10位之间")
|
||||
private String confirmPassWord;
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package top.beansprout.health.model.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: UserUpdateInfoDto</p>
|
||||
* <p>Description: 用户信息修改</p>
|
||||
*
|
||||
* @author cyy
|
||||
* @date 2020年4月30日
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class UserUpdateInfoDto implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7815632813092576575L;
|
||||
|
||||
// 昵称
|
||||
@NotBlank(message = "昵称不能为空")
|
||||
@Length(min = 2, max = 10, message = "昵称只能为2~10个字符")
|
||||
private String nickName;
|
||||
// 邮件
|
||||
@Email(message = "邮箱格式不正确")
|
||||
private String email;
|
||||
// 头像
|
||||
@NotNull(message = "头像不能为空")
|
||||
private MultipartFile headUrl;
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package top.beansprout.health.model.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p> Title: UserUpdatePasswordDto </p>
|
||||
* <p> Description: 用户修改密码</p>
|
||||
*
|
||||
* @Auther: cyy
|
||||
* @Date: 2020年4月27日 上午12:32:39
|
||||
* @Version: 1.0.0
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class UserUpdatePasswordDto implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8674837059264557849L;
|
||||
|
||||
@NotBlank(message = "密码不能为空")
|
||||
@Length(min = 6, max = 10, message = "密码必须在6~10位之间")
|
||||
private String passWord;
|
||||
@NotBlank(message = "确认密码不能为空")
|
||||
@Length(min = 6, max = 10, message = "确认密码必须在6~10位之间")
|
||||
private String confirmPassWord;
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package top.beansprout.health.model.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: BaseEntity</p>
|
||||
* <p>Description: 实体类对象的父类-公共字段</p>
|
||||
*
|
||||
* @author beansprout
|
||||
* @version 1.0
|
||||
* @date 2020/3/22 16:50
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public abstract class BaseEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4402927657355642335L;
|
||||
|
||||
private int id;
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package top.beansprout.health.model.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: BaseUpdateEntity</p>
|
||||
* <p>Description: 实体类插入对象的父类-公共字段</p>
|
||||
*
|
||||
* @author beansprout
|
||||
* @version 1.0
|
||||
* @date 2020/3/23 23:52
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public abstract class BaseInsertEntity extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = -7314584145079382702L;
|
||||
|
||||
private Long creator;// 创建人id
|
||||
private Date createTime;// 创建时间
|
||||
|
||||
public void init(long userId) {
|
||||
this.creator = userId;
|
||||
this.createTime = new Date();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package top.beansprout.health.model.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: BaseUpdateEntity</p>
|
||||
* <p>Description: 实体类用户对象的父类-公共字段</p>
|
||||
*
|
||||
* @author beansprout
|
||||
* @version 1.0
|
||||
* @date 2020/3/23 23:52
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public abstract class BaseUpdateEntity extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1620758104430484420L;
|
||||
|
||||
private int creator;// 创建人id
|
||||
private Date createTime;// 创建时间
|
||||
private int updater;// 更新者id
|
||||
private Date updateTime;// 更新时间
|
||||
|
||||
public void init(int userId) {
|
||||
this.creator = userId;
|
||||
this.createTime = new Date();
|
||||
this.update(userId);
|
||||
}
|
||||
|
||||
public void update(int userId) {
|
||||
this.updater = userId;
|
||||
this.updateTime = new Date();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package top.beansprout.health.model.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>Title: TBodyInfo</p>
|
||||
* <p>Description: 身体信息表</p>
|
||||
* @author cyy
|
||||
* @date 2020年4月27日
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class TBodyInfo extends BaseUpdateEntity {
|
||||
|
||||
private static final long serialVersionUID = -7707228772072459981L;
|
||||
|
||||
// 打开时间
|
||||
private Date createTime;
|
||||
|
||||
// 舒张压
|
||||
private int lowBloodPressure;
|
||||
// 收缩压
|
||||
private int highBloodPressure;
|
||||
// 心率
|
||||
private int heartRate;
|
||||
// 体温
|
||||
private double temperature;
|
||||
// 食欲
|
||||
private int appetite;
|
||||
// 体重
|
||||
private double weight;
|
||||
// 步数
|
||||
private int numberOfStep;
|
||||
|
||||
public String getAppetiteDes(int appetite){
|
||||
switch (appetite){
|
||||
case 1:
|
||||
return "非常差";
|
||||
case 2:
|
||||
return "差";
|
||||
case 3:
|
||||
return "一般";
|
||||
case 4:
|
||||
return "良好";
|
||||
case 5:
|
||||
return "很好";
|
||||
case 6:
|
||||
return "非常好";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package top.beansprout.health.model.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: THealthConfig</p>
|
||||
* <p>Description: 健康信息配置表</p>
|
||||
* @author cyy
|
||||
* @date 2020年4月27日
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class THealthConfig extends BaseUpdateEntity {
|
||||
|
||||
private static final long serialVersionUID = 6928075281678415808L;
|
||||
|
||||
// 最小低血压
|
||||
private int minLowBloodPressure;
|
||||
// 最大低血压
|
||||
private int maxLowBloodPressure;
|
||||
// 最小高血压
|
||||
private int minHighBloodPressure;
|
||||
// 最大高血压
|
||||
private int maxHighBloodPressure;
|
||||
// 最小心率
|
||||
private int minHeartRate;
|
||||
// 最大心率
|
||||
private int maxHeartRate;
|
||||
// 最小体温
|
||||
private double minTemperature;
|
||||
// 最大体温
|
||||
private double maxTemperature;
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package top.beansprout.health.model.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: TUser</p>
|
||||
* <p>Description: 用户表</p>
|
||||
*
|
||||
* @author beansprout
|
||||
* @date 2020年4月22日
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class TUser extends BaseUpdateEntity {
|
||||
|
||||
private static final long serialVersionUID = 7849174171033853904L;
|
||||
|
||||
// 用户名
|
||||
private String nickName;
|
||||
// 账户
|
||||
private String userName;
|
||||
// 密码
|
||||
private String password;
|
||||
// 邮箱
|
||||
private String email;
|
||||
// 头像
|
||||
private String headUrl;
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package top.beansprout.health.model.vo;
|
||||
|
||||
import javax.mail.Authenticator;
|
||||
import javax.mail.PasswordAuthentication;
|
||||
|
||||
/**
|
||||
* <p>Title: AuthVo</p>
|
||||
* <p>Description: 发送邮箱用户</p>
|
||||
*
|
||||
* @author ateenliu
|
||||
* @date 2022年4月6日
|
||||
*/
|
||||
|
||||
public class AuthVo extends Authenticator {
|
||||
private String username = "";
|
||||
private String password = "";
|
||||
|
||||
public AuthVo(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
public PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package top.beansprout.health.model.vo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: BodyInfoDetailVo</p>
|
||||
* <p>Description: 身体信息详情</p>
|
||||
*
|
||||
* @author cyy
|
||||
* @date 2020年4月28日
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class BodyInfoDetailVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -2831120593213278473L;
|
||||
|
||||
// id
|
||||
private int id;
|
||||
// 打卡时间
|
||||
private Date createTime;
|
||||
|
||||
// 舒张压
|
||||
private int lowBloodPressure;
|
||||
// 舒张压状态
|
||||
private int lowBloodPressureStatus;
|
||||
// 舒张压描述
|
||||
private String lowBloodPressureDesc;
|
||||
|
||||
// 收缩压
|
||||
private int highBloodPressure;
|
||||
// 收缩压状态
|
||||
private int highBloodPressureStatus;
|
||||
// 收缩压描述
|
||||
private String highBloodPressureDesc;
|
||||
|
||||
// 血压
|
||||
private String bloodPressureDesc;
|
||||
|
||||
// 心率
|
||||
private int heartRate;
|
||||
// 心率状态
|
||||
private int heartRateStatus;
|
||||
// 心率描述
|
||||
private String heartRateDesc;
|
||||
|
||||
// 体温
|
||||
private double temperature;
|
||||
// 体温状态
|
||||
private int temperatureStatus;
|
||||
// 体温描述
|
||||
private String temperatureDesc;
|
||||
|
||||
// 食欲
|
||||
private int appetite;
|
||||
// 体重
|
||||
private double weight;
|
||||
// 步数
|
||||
private int numberOfStep;
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package top.beansprout.health.model.vo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p> Title: BodyInfoStatisticsVo </p>
|
||||
* <p> Description: 健康信息统计</p>
|
||||
*
|
||||
* @Auther: cyy
|
||||
* @Date: 2020年4月28日 下午11:32:05
|
||||
* @Version: 1.0.0
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BodyInfoStatisticsVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8627681890953284164L;
|
||||
|
||||
// 类别名字
|
||||
private List<String> typeNames;
|
||||
// 类别数据
|
||||
private List<BodyInfoVo> bodyInfoVos;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class BodyInfoVo {
|
||||
// 类别名
|
||||
private String typeName;
|
||||
// 数据
|
||||
private List<Object> datas;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package top.beansprout.health.model.vo;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* <p>Title: BusinessException</p>
|
||||
* <p>Description: 业务异常</p>
|
||||
* @author cyy
|
||||
* @date 2020年4月23日
|
||||
*/
|
||||
@Getter
|
||||
public class BusinessException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -5846808029174051527L;
|
||||
|
||||
private final R r;
|
||||
|
||||
public BusinessException() {
|
||||
r = R.budil().result(false).message("系统异常");
|
||||
}
|
||||
|
||||
public BusinessException(String message) {
|
||||
r = R.budil().result(false).message(message);
|
||||
}
|
||||
|
||||
public BusinessException(String path, String message) {
|
||||
r = R.budil().result(false).message(message).path(path);
|
||||
}
|
||||
|
||||
public BusinessException(String message, Object data) {
|
||||
r = R.budil().result(false).message(message).data(data);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package top.beansprout.health.model.vo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: PageVo</p>
|
||||
* <p>Description: 列表返回</p>
|
||||
*
|
||||
* @author beansprout
|
||||
* @version 1.0
|
||||
* @date 2020/3/22 22:15
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class PageVo<T extends Object> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7039024431017840683L;
|
||||
|
||||
// 当前页
|
||||
private long page;
|
||||
// 每页展示数量
|
||||
private long pageSize;
|
||||
// 是否是第一页true第一
|
||||
private boolean first = false;
|
||||
// 是否是最后一页true最后
|
||||
private boolean last = false;
|
||||
// 总页数
|
||||
private int totalPages;
|
||||
// 总数据条数
|
||||
private int totalElements;
|
||||
// 当前页数据条数
|
||||
private int numberOfElements;
|
||||
// 数据集
|
||||
private List<?> content;
|
||||
|
||||
public PageVo(int page, int pageSize, int totalElements, List<T> content) {
|
||||
this.pageSize = pageSize;
|
||||
this.totalElements = totalElements;
|
||||
this.page = page <= 0 ? 1 : page;
|
||||
this.totalPages = totalElements == 0 ? 0
|
||||
: (totalElements % pageSize) == 0 ? totalElements / pageSize : (totalElements / pageSize) + 1;
|
||||
this.first = page == 1 ? true : false;
|
||||
this.last = ((page == this.totalPages) || (content.size() < 1)) ? true : false;
|
||||
this.content = content;
|
||||
this.numberOfElements = this.content.size();
|
||||
}
|
||||
|
||||
public PageVo(PageInfo<T> pageInfo) {
|
||||
this.page = pageInfo.getPageNum();
|
||||
this.pageSize = pageInfo.getPageSize();
|
||||
this.totalElements = (int) pageInfo.getTotal();
|
||||
this.totalPages = pageInfo.getPages();
|
||||
this.first = page == 1 ? true : false;
|
||||
this.content = pageInfo.getList();
|
||||
this.last = ((page == this.totalPages) || (content.size() < 1)) ? true : false;
|
||||
this.numberOfElements = this.content.size();
|
||||
}
|
||||
|
||||
public static <T> PageVo<T> of(int page, int pageSize, int totalElements, List<T> content) {
|
||||
return new PageVo<T>(page, pageSize, totalElements, content);
|
||||
}
|
||||
|
||||
public static <T> PageVo<T> of(PageInfo<T> pageInfo) {
|
||||
return new PageVo<T>(pageInfo);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
package top.beansprout.health.model.vo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import top.beansprout.health.constant.SysConstant;
|
||||
|
||||
/**
|
||||
* <p>Title: R</p>
|
||||
* <p>Description: 返回结果</p>
|
||||
* @author cyy
|
||||
* @date 2020年4月23日
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class R extends HashMap<String, Object> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -7261945562236369523L;
|
||||
|
||||
public static final String FIELD_RESULT = "result";
|
||||
public static final String FIELD_MESSAGE = "message";
|
||||
public static final String FIELD_DATA = "data";
|
||||
public static final String FIELD_PATH = "path";
|
||||
|
||||
public static final String FAILED_FIELD_REQUEST_ID = SysConstant.INIT_FIELD_REQUEST_REQUEST_ID;
|
||||
public static final String FAILED_FIELD_TIME_STAMP = "timestamp";
|
||||
public static final String FAILED_FIELD_PATH = "path";
|
||||
public static final String FAILED_FIELD_ERROR = "error";
|
||||
public static final String FAILED_FIELD_ERRORS = "errors";
|
||||
|
||||
// 结果
|
||||
private boolean result;
|
||||
// 描述
|
||||
private String message;
|
||||
// 数据
|
||||
private Object data;
|
||||
// 页面
|
||||
private String path;
|
||||
|
||||
public static R budil() {
|
||||
return new R();
|
||||
}
|
||||
|
||||
public R result(boolean result) {
|
||||
this.put(FIELD_RESULT, result);
|
||||
this.result = result;
|
||||
return this;
|
||||
}
|
||||
|
||||
public R message(String message) {
|
||||
this.put(FIELD_MESSAGE, message);
|
||||
this.message = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public R data(Object data) {
|
||||
this.put(FIELD_DATA, data);
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public R path(String path) {
|
||||
this.put(FIELD_PATH, path);
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static ModelAndView ok() {
|
||||
return of("/", null);
|
||||
}
|
||||
|
||||
public static R okAsAjax() {
|
||||
return okAsAjax(null);
|
||||
}
|
||||
|
||||
public static ModelAndView ok(Map<String, Object> data) {
|
||||
return of("/", data);
|
||||
}
|
||||
|
||||
public static R okAsAjax(Object data) {
|
||||
return ofAsAjax(true, "成功", data);
|
||||
}
|
||||
|
||||
public static ModelAndView failed() {
|
||||
return of("/500", null);
|
||||
}
|
||||
|
||||
public static ModelAndView failed(Map<String, Object> data) {
|
||||
return of("/500", data);
|
||||
}
|
||||
|
||||
public static ModelAndView failed(String path, Map<String, Object> data) {
|
||||
return of(path, data);
|
||||
}
|
||||
|
||||
public static ModelAndView of(String path, Map<String, Object> data) {
|
||||
final ModelAndView modelAndView = new ModelAndView(path, data);
|
||||
return modelAndView;
|
||||
}
|
||||
|
||||
public static R ofAsAjax(boolean result, String message, Object data) {
|
||||
return budil().result(result).message(message).data(data);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package top.beansprout.health.model.vo;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: RequestVo</p>
|
||||
* <p>Description: 请求数据</p>
|
||||
* @author cyy
|
||||
* @date 2020年4月23日
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RequestVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -2460516900904070899L;
|
||||
|
||||
// 基本项目地址
|
||||
private String basePath;
|
||||
// 用户信息
|
||||
private UserLoginVo user;
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package top.beansprout.health.model.vo;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>Title: UserInfoVo</p>
|
||||
* <p>Description: 用户信息</p>
|
||||
*
|
||||
* @author cyy
|
||||
* @date 2020年4月30日
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UserInfoVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8389631895704876733L;
|
||||
|
||||
// 用户id
|
||||
private int id;
|
||||
// 用户名
|
||||
private String nickName;
|
||||
// 账户
|
||||
private String userName;
|
||||
// 邮箱
|
||||
private String email;
|
||||
// 头像
|
||||
private String headUrl;
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package top.beansprout.health.model.vo;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p> Title: UserLoginVo </p>
|
||||
* <p> Description: </p>
|
||||
*
|
||||
* @Auther: cyy
|
||||
* @Date: 2020年4月25日 下午8:49:19
|
||||
* @Version: 1.0.0
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class UserLoginVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -7027379021523096696L;
|
||||
|
||||
// 用户id
|
||||
private int id;
|
||||
// 用户名
|
||||
private String nickName;
|
||||
// 账户
|
||||
private String userName;
|
||||
// 邮箱
|
||||
private String email;
|
||||
// 头像
|
||||
private String headUrl;
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package top.beansprout.health.service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import top.beansprout.health.model.dto.BodyInfoQuery;
|
||||
import top.beansprout.health.model.dto.BodyInfoSaveDto;
|
||||
import top.beansprout.health.model.entity.TBodyInfo;
|
||||
import top.beansprout.health.model.vo.BodyInfoDetailVo;
|
||||
import top.beansprout.health.model.vo.BodyInfoStatisticsVo;
|
||||
import top.beansprout.health.model.vo.PageVo;
|
||||
|
||||
/**
|
||||
* <p>Title: HealthService</p>
|
||||
* <p>Description: 健康业务接口</p>
|
||||
*
|
||||
* @author cyy
|
||||
* @date 2020年4月27日
|
||||
*/
|
||||
public interface HealthService {
|
||||
|
||||
/** 保存身体信息 **/
|
||||
void saveBodyInfo(int userId, BodyInfoSaveDto bodyInfoSaveDto);
|
||||
|
||||
/** 获取身体信息列表 **/
|
||||
PageVo<TBodyInfo> bodyInfoList(int userId, BodyInfoQuery bodyInfoQuery);
|
||||
|
||||
/** 删除身体信息 **/
|
||||
void deleteBodyInfo(int userId, int id);
|
||||
|
||||
/** 获取身体信息 **/
|
||||
BodyInfoDetailVo getBodyInfo(int userId, int id);
|
||||
|
||||
/** 获取身体信息统计 **/
|
||||
BodyInfoStatisticsVo getBodyStatistics(int userId, Date date);
|
||||
|
||||
/** 获取惊奇身体信息统计 **/
|
||||
List<TBodyInfo> recentBodyInfoList(int userId);
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package top.beansprout.health.service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import top.beansprout.health.model.dto.UserLoginDto;
|
||||
import top.beansprout.health.model.dto.UserRegisterDto;
|
||||
import top.beansprout.health.model.dto.UserUpdateInfoDto;
|
||||
import top.beansprout.health.model.dto.UserUpdatePasswordDto;
|
||||
import top.beansprout.health.model.vo.UserInfoVo;
|
||||
import top.beansprout.health.model.vo.UserLoginVo;
|
||||
|
||||
/**
|
||||
* <p> Title: UserService </p>
|
||||
* <p> Description: 用户业务接口</p>
|
||||
*
|
||||
* @Auther: cyy
|
||||
* @Date: 2020年4月25日 下午8:01:14
|
||||
* @Version: 1.0.0
|
||||
*/
|
||||
public interface UserService {
|
||||
|
||||
/** 登录逻辑 **/
|
||||
UserLoginVo login(UserLoginDto userLoginDto);
|
||||
|
||||
/** 注册逻辑 **/
|
||||
void register(UserRegisterDto userRegisterDto);
|
||||
|
||||
/** 登出 **/
|
||||
void logout(HttpServletRequest request);
|
||||
|
||||
/** 修改密码 **/
|
||||
void updatePassword(HttpServletRequest request, int userId, UserUpdatePasswordDto updatePasswordDto);
|
||||
|
||||
/** 修改用户信息 **/
|
||||
UserInfoVo updateUserInfo(int userId, UserUpdateInfoDto userUpdateInfoDto);
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package top.beansprout.health.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* <p>Title: CollectionUtils</p>
|
||||
* <p>Description: 集合工具类</p>
|
||||
*
|
||||
* @author beansprout
|
||||
* @version 1.0
|
||||
* @date 2020/3/19 22:37
|
||||
*/
|
||||
public class CollectionUtils {
|
||||
|
||||
/** 判断集合是否为null或者size=0 **/
|
||||
public static <T> boolean isEmpty(Collection<T> coll) {
|
||||
return CollectionUtils.isEmpty(coll);
|
||||
}
|
||||
|
||||
public static <T> boolean isNotEmpty(Collection<T> coll) {
|
||||
return !isEmpty(coll);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Iterable映射成列表
|
||||
*
|
||||
* @param src
|
||||
* @param mapper
|
||||
* @return
|
||||
*/
|
||||
public static <T, R> List<R> map(final Iterable<T> src, final Function<? super T, ? extends R> mapper) {
|
||||
final List<R> r = new ArrayList<>();
|
||||
for (final T t : src) {
|
||||
r.add(mapper.apply(t));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数组转集合
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public static <T extends Object> List<T> arrayToList(T... key) {
|
||||
return Arrays.asList(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* element 转换成指定集合
|
||||
*
|
||||
* @param sourceCollection 源集合
|
||||
* @param collectionFactory 目标集合
|
||||
* @return DEST
|
||||
*/
|
||||
public static <T, SOURCETYPE extends Collection<T>, DEST extends Collection<T>> DEST
|
||||
transformElements(SOURCETYPE sourceCollection, Supplier<DEST> collectionFactory) {
|
||||
final DEST dest = collectionFactory.get();
|
||||
sourceCollection.forEach(t -> {
|
||||
dest.add(t);
|
||||
});
|
||||
return dest;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package top.beansprout.health.util;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
/**
|
||||
* <p>Title: PublicUtils</p>
|
||||
* <p>Description: 公共方法</p>
|
||||
*
|
||||
* @author beansprout
|
||||
* @version 1.0
|
||||
* @date 2020/3/22 17:41
|
||||
*/
|
||||
public class PublicUtils {
|
||||
|
||||
/**
|
||||
* 为空
|
||||
* @param obj
|
||||
* @return
|
||||
*/
|
||||
public static boolean isBlank(Object obj) {
|
||||
if (obj == null)
|
||||
return true;
|
||||
if (obj instanceof String)
|
||||
return ((String) obj).trim().equals("");
|
||||
if (obj instanceof CharSequence)
|
||||
return ((CharSequence) obj).length() == 0;
|
||||
if (obj instanceof Object[])
|
||||
return ((Object[]) obj).length == 0;
|
||||
if (obj instanceof Collection)
|
||||
return ((Collection<?>) obj).isEmpty();
|
||||
if (obj instanceof Map)
|
||||
return ((Map<?, ?>) obj).isEmpty();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 不为空
|
||||
* @param obj
|
||||
* @return
|
||||
*/
|
||||
public static boolean isNotBlank(Object obj) {
|
||||
return !isBlank(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机指定长度的数字+字母字符串
|
||||
* @param leng
|
||||
* @return
|
||||
*/
|
||||
public static String randomString(int leng) {
|
||||
return RandomStringUtils.randomAlphanumeric(leng);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接字符串
|
||||
* @param values
|
||||
* @return
|
||||
*/
|
||||
public static String join(Object ...values) {
|
||||
if (values.length <= 0) return "";
|
||||
final StringBuilder stringBuilder = new StringBuilder();
|
||||
for (final Object value : values) {
|
||||
stringBuilder.append(value);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64加密
|
||||
* @param value 原文
|
||||
* @return
|
||||
*/
|
||||
public static String encryptBase64(String value) {
|
||||
if (isBlank(value)) return null;
|
||||
final byte[] encode = Base64.getEncoder().encode(value.getBytes());
|
||||
return new String(encode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64解密
|
||||
* @param encrypt 密文
|
||||
* @return
|
||||
*/
|
||||
public static String decryptBase64(String encrypt) {
|
||||
if (isBlank(encrypt)) return null;
|
||||
final byte[] decode = Base64.getDecoder().decode(encrypt);
|
||||
return new String(decode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求域参数
|
||||
* @param request
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public static String getAttribute(HttpServletRequest request, String key) {
|
||||
return getAttribute(request, key, String.class);
|
||||
}
|
||||
|
||||
public static <T> T getAttribute(HttpServletRequest request, String key, Class<T> requiredType) {
|
||||
if ((request == null) || isBlank(key)) return null;
|
||||
final Object value = request.getAttribute(key);
|
||||
return isBlank(value) ? null : castValue(value, requiredType);
|
||||
}
|
||||
|
||||
/** Object类型转换 **/
|
||||
private static <T> T castValue(Object value, Class<T> requiredType) {
|
||||
if ((requiredType == Date.class) && (value instanceof Long)) {
|
||||
value = new Date((Long)value);
|
||||
}
|
||||
|
||||
if (value instanceof Integer) {
|
||||
final int intValue = (Integer)value;
|
||||
if (requiredType == Long.class) {
|
||||
value = (long)intValue;
|
||||
} else if ((requiredType == Short.class) && (-32768 <= intValue) && (intValue <= 32767)) {
|
||||
value = (short)intValue;
|
||||
} else if ((requiredType == Byte.class) && (-128 <= intValue) && (intValue <= 127)) {
|
||||
value = (byte)intValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!requiredType.isInstance(value))
|
||||
throw new RuntimeException(
|
||||
"Expected value to be of type: " + requiredType + ", but was " + value.getClass());
|
||||
else
|
||||
return requiredType.cast(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bean字段值复制
|
||||
* @param source 源
|
||||
* @param target 目标
|
||||
* @return 目标
|
||||
*/
|
||||
public static <T extends Object>T copyBean(T source, T target) {
|
||||
if (isBlank(source) && isBlank(target)) return null;
|
||||
BeanUtils.copyProperties(source, target);
|
||||
return target;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
jdbc.driver=com.mysql.cj.jdbc.Driver
|
||||
jdbc.url=jdbc:mysql://localhost:3306/health?useUnicode=true&characterEncoding=UTF-8
|
||||
jdbc.username=health
|
||||
jdbc.password=health
|
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="top.beansprout.health.mapper.TBodyInfoMapper">
|
||||
<resultMap id="BaseResultMap"
|
||||
type="top.beansprout.health.model.entity.TBodyInfo">
|
||||
<id column="id" property="id" jdbcType="INTEGER"/>
|
||||
<result column="creator" property="creator" jdbcType="INTEGER" javaType="int"/>
|
||||
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="updater" property="updater" jdbcType="INTEGER" javaType="int"/>
|
||||
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectByUserId" resultType="top.beansprout.health.model.entity.TBodyInfo">
|
||||
SELECT * FROM t_body_info
|
||||
<where>
|
||||
creator = #{ creator }
|
||||
<if test="minDate != null">
|
||||
AND create_time>=#{minDate}
|
||||
</if>
|
||||
<if test="maxDate != null">
|
||||
<![CDATA[ AND create_time<=#{maxDate} ]]>
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY create_time DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="top.beansprout.health.mapper.THealthConfigMapper">
|
||||
<resultMap id="BaseResultMap"
|
||||
type="top.beansprout.health.model.entity.THealthConfig">
|
||||
<id column="id" property="id" jdbcType="INTEGER"/>
|
||||
<result column="creator" property="creator" jdbcType="INTEGER" javaType="int"/>
|
||||
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="updater" property="updater" jdbcType="INTEGER" javaType="int"/>
|
||||
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
|
||||
</resultMap>
|
||||
</mapper>
|
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="top.beansprout.health.mapper.TUserMapper">
|
||||
<resultMap id="BaseResultMap"
|
||||
type="top.beansprout.health.model.entity.TUser">
|
||||
<id column="id" property="id" jdbcType="INTEGER"/>
|
||||
<result column="creator" property="creator" jdbcType="INTEGER" javaType="int"/>
|
||||
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="updater" property="updater" jdbcType="INTEGER" javaType="int"/>
|
||||
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="nick_name" property="nickName" jdbcType="VARCHAR" javaType="string"/>
|
||||
<result column="user_name" property="userName" jdbcType="VARCHAR" javaType="string"/>
|
||||
<result column="password" property="password" jdbcType="VARCHAR" javaType="string"/>
|
||||
<result column="email" property="email" jdbcType="VARCHAR" javaType="string"/>
|
||||
<result column="head_url" property="headUrl" jdbcType="VARCHAR" javaType="string"/>
|
||||
</resultMap>
|
||||
</mapper>
|
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE configuration
|
||||
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-config.dtd">
|
||||
<configuration>
|
||||
<!-- 配置全局属性 -->
|
||||
<settings>
|
||||
<!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->
|
||||
<setting name="useGeneratedKeys" value="true" />
|
||||
<!-- 使用列别名替换列名 默认:true -->
|
||||
<setting name="useColumnLabel" value="true" />
|
||||
<!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
|
||||
<setting name="mapUnderscoreToCamelCase" value="true" />
|
||||
</settings>
|
||||
<!-- 默认已经配置分页工具 -->
|
||||
</configuration>
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:task="http://www.springframework.org/schema/task"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/task
|
||||
http://www.springframework.org/schema/task/spring-task-3.2.xsd">
|
||||
|
||||
<!-- 引入其他的xml文件 -->
|
||||
<import resource="classpath:/spring/spring-dao.xml"/>
|
||||
<import resource="classpath:/spring/spring-service.xml"/>
|
||||
|
||||
<context:component-scan
|
||||
base-package="top.beansprout.health.config" />
|
||||
|
||||
<!-- 定时器 -->
|
||||
<!-- <task:annotation-driven/> -->
|
||||
<!-- <context:component-scan base-package="top.beansprout.health.tasks"/> -->
|
||||
|
||||
</beans>
|
@ -0,0 +1,71 @@
|
||||
<%--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--%>
|
||||
<%@ page session="false" trimDirectiveWhitespaces="true" %>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>401 Unauthorized</title>
|
||||
<style type="text/css">
|
||||
<!--
|
||||
BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;font-size:12px;}
|
||||
H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;}
|
||||
PRE, TT {border: 1px dotted #525D76}
|
||||
A {color : black;}A.name {color : black;}
|
||||
-->
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>401 Unauthorized</h1>
|
||||
<p>
|
||||
You are not authorized to view this page. If you have not changed
|
||||
any configuration files, please examine the file
|
||||
<tt>conf/tomcat-users.xml</tt> in your installation. That
|
||||
file must contain the credentials to let you use this webapp.
|
||||
</p>
|
||||
<p>
|
||||
For example, to add the <tt>admin-gui</tt> role to a user named
|
||||
<tt>tomcat</tt> with a password of <tt>s3cret</tt>, add the following to the
|
||||
config file listed above.
|
||||
</p>
|
||||
<pre>
|
||||
<role rolename="admin-gui"/>
|
||||
<user username="tomcat" password="s3cret" roles="admin-gui"/>
|
||||
</pre>
|
||||
<p>
|
||||
Note that for Tomcat 7 onwards, the roles required to use the host manager
|
||||
application were changed from the single <tt>admin</tt> role to the
|
||||
following two roles. You will need to assign the role(s) required for
|
||||
the functionality you wish to access.
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>admin-gui</tt> - allows access to the HTML GUI</li>
|
||||
<li><tt>admin-script</tt> - allows access to the text interface</li>
|
||||
</ul>
|
||||
<p>
|
||||
The HTML interface is protected against CSRF but the text interface is not.
|
||||
To maintain the CSRF protection:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Users with the <tt>admin-gui</tt> role should not be granted the
|
||||
<tt>admin-script</tt> role.</li>
|
||||
<li>If the text interface is accessed through a browser (e.g. for testing
|
||||
since this interface is intended for tools not humans) then the browser
|
||||
must be closed afterwards to terminate the session.</li>
|
||||
</ul>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -0,0 +1,90 @@
|
||||
<%--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--%>
|
||||
<%@ page session="false" trimDirectiveWhitespaces="true" %>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>403 Access Denied</title>
|
||||
<style type="text/css">
|
||||
<!--
|
||||
BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;font-size:12px;}
|
||||
H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;}
|
||||
PRE, TT {border: 1px dotted #525D76}
|
||||
A {color : black;}A.name {color : black;}
|
||||
-->
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>403 Access Denied</h1>
|
||||
<p>
|
||||
You are not authorized to view this page.
|
||||
</p>
|
||||
<p>
|
||||
By default the Host Manager is only accessible from a browser running on the
|
||||
same machine as Tomcat. If you wish to modify this restriction, you'll need
|
||||
to edit the Host Manager's <tt>context.xml</tt> file.
|
||||
</p>
|
||||
<p>
|
||||
If you have already configured the Host Manager application to allow access
|
||||
and you have used your browsers back button, used a saved book-mark or
|
||||
similar then you may have triggered the cross-site request forgery (CSRF)
|
||||
protection that has been enabled for the HTML interface of the Host Manager
|
||||
application. You will need to reset this protection by returning to the
|
||||
<a href="<%=request.getContextPath()%>/html">main Host Manager page</a>.
|
||||
Once you return to this page, you will be able to continue using the Host
|
||||
Manager application's HTML interface normally. If you continue to see this
|
||||
access denied message, check that you have the necessary permissions to
|
||||
access this application.
|
||||
</p>
|
||||
<p> If you have not changed
|
||||
any configuration files, please examine the file
|
||||
<tt>conf/tomcat-users.xml</tt> in your installation. That
|
||||
file must contain the credentials to let you use this webapp.
|
||||
</p>
|
||||
<p>
|
||||
For example, to add the <tt>admin-gui</tt> role to a user named
|
||||
<tt>tomcat</tt> with a password of <tt>s3cret</tt>, add the following to the
|
||||
config file listed above.
|
||||
</p>
|
||||
<pre>
|
||||
<role rolename="admin-gui"/>
|
||||
<user username="tomcat" password="s3cret" roles="admin-gui"/>
|
||||
</pre>
|
||||
<p>
|
||||
Note that for Tomcat 7 onwards, the roles required to use the host manager
|
||||
application were changed from the single <tt>admin</tt> role to the
|
||||
following two roles. You will need to assign the role(s) required for
|
||||
the functionality you wish to access.
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>admin-gui</tt> - allows access to the HTML GUI</li>
|
||||
<li><tt>admin-script</tt> - allows access to the text interface</li>
|
||||
</ul>
|
||||
<p>
|
||||
The HTML interface is protected against CSRF but the text interface is not.
|
||||
To maintain the CSRF protection:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Users with the <tt>admin-gui</tt> role should not be granted the
|
||||
<tt>admin-script</tt> role.</li>
|
||||
<li>If the text interface is accessed through a browser (e.g. for testing
|
||||
since this interface is intended for tools not humans) then the browser
|
||||
must be closed afterwards to terminate the session.</li>
|
||||
</ul>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -0,0 +1,60 @@
|
||||
<jsp:include page="../view/base.jsp" />
|
||||
<html>
|
||||
<head>
|
||||
<title>404 Not found</title>
|
||||
<style type="text/css">
|
||||
<!--
|
||||
BODY {
|
||||
font-family: Tahoma, Arial, sans-serif;
|
||||
color: black;
|
||||
background-color: white;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
H1 {
|
||||
font-family: Tahoma, Arial, sans-serif;
|
||||
color: white;
|
||||
background-color: #525D76;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
PRE, TT {
|
||||
border: 1px dotted #525D76
|
||||
}
|
||||
|
||||
A {
|
||||
color: black;
|
||||
}
|
||||
|
||||
A.name {
|
||||
color: black;
|
||||
}
|
||||
-->
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>404 Not found</h1>
|
||||
<p>
|
||||
The page you tried to access (<%=request.getAttribute("javax.servlet.error.request_uri")%>)
|
||||
${ baseurl }
|
||||
does not exist.
|
||||
</p>
|
||||
<p>The Host Manager application has been re-structured for Tomcat 7
|
||||
onwards and some URLs have changed. All URLs used to access the
|
||||
Manager application should now start with one of the following
|
||||
options:</p>
|
||||
<ul>
|
||||
<li><%=request.getContextPath()%>/html for the HTML GUI</li>
|
||||
<li><%=request.getContextPath()%>/text for the text interface</li>
|
||||
</ul>
|
||||
<p>
|
||||
Note that the URL for the text interface has changed from "<%=request.getContextPath()%>"
|
||||
to "<%=request.getContextPath()%>/text".
|
||||
</p>
|
||||
<p>You probably need to adjust the URL you are using to access the
|
||||
Host Manager application. However, there is always a chance you have
|
||||
found a bug in the Host Manager application. If you are sure you have
|
||||
found a bug, and that the bug has not already been reported, please
|
||||
report it to the Apache Tomcat team.</p>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,12 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>错误页面</title>
|
||||
</head>
|
||||
<body>
|
||||
<% System.out.print(request.getAttribute("message")); %>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,215 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<%@include file="base.jsp"%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>身体信息录入</title>
|
||||
<script type="text/javascript" src="static/js/common-css.js"></script>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Poppins:300,400,700">
|
||||
<style type="text/css">
|
||||
.bg-white {
|
||||
padding-left: 20px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.bg-white .input-material {
|
||||
padding-left: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="col-lg-6 bg-white">
|
||||
<div class="form d-flex align-items-center">
|
||||
<div class="content">
|
||||
<div class="form-group">
|
||||
<span>昵称</span> <input id="body-nickname" class="input-material" type="text" name="nickName" disabled="disabled"
|
||||
value="${ user.nickName }">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span>舒张压</span> <input id="body-low-blood-pressure" class="input-material" type="text" oninput="value=value.replace(/[^\d]/g,'')"
|
||||
name="lowBloodPressure" placeholder="请输入舒张压">
|
||||
<div class="invalid-feedback">舒张压必须在0~200之间</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span>收缩压</span> <input id="body-high-blood-pressure" class="input-material" type="text" oninput="value=value.replace(/[^\d]/g,'')"
|
||||
name="highBloodPressure" placeholder="请输入收缩压">
|
||||
<div class="invalid-feedback">收缩压必须在0~200之间</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span>心率</span> <input id="body-heart-rate" class="input-material" type="text" oninput="value=value.replace(/[^\d]/g,'')"
|
||||
name="heartRate" placeholder="请输入心率">
|
||||
<div class="invalid-feedback">心率必须在40~200之间</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span>体温</span> <input id="body-temperature" class="input-material" type="text" onkeyup="clearNoNum(this)"
|
||||
oninput="value=value.replace(/[^\d.]/g,'')" name="temperature" placeholder="请输入体温">
|
||||
<div class="invalid-feedback">体温必须在33~45度之间</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span>食欲</span> <select id="body-appetite" class="input-material form-control" name="appetite">
|
||||
<option>-请选择-</option>
|
||||
<option value="1">非常差</option>
|
||||
<option value="2">差</option>
|
||||
<option value="3">一般</option>
|
||||
<option value="4">良好</option>
|
||||
<option value="5">很多</option>
|
||||
<option value="6">非常多</option>
|
||||
</select>
|
||||
<div class="invalid-feedback">请选择食欲</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span>体重KG</span> <input id="body-weight" class="input-material" type="text" onkeyup="clearNoNum(this)" oninput="value=value.replace(/[^\d.]/g,'')"
|
||||
name="weight" placeholder="请输入体重">
|
||||
<div class="invalid-feedback">体重必须在0~200之间</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span>步数</span> <input id="body-number-of-step" class="input-material" type="text" oninput="value=value.replace(/[^\d]/g,'')"
|
||||
name=numberOfStep placeholder="请输入步数">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button id="submit" type="button" name="submit" class="btn btn-primary">打卡</button>
|
||||
<button id="reset" type="reset" name="reset" class="btn btn-primary" style="margin-left: 40px">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="static/js/common-js.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
/*错误class form-control is-invalid
|
||||
正确class form-control is-valid*/
|
||||
var flaglowBloodPressure = false;
|
||||
var flagHighBloodPressure = false;
|
||||
var flagHeartRate = false;
|
||||
var flagTemperature = false;
|
||||
var flagAppetite = false;
|
||||
var flagWeight = false;
|
||||
var lowBloodPressure, highBloodPressure, heartRate, temperature, appetite, weight;
|
||||
$("#body-low-blood-pressure").change(function() {
|
||||
lowBloodPressure = $(this).val();
|
||||
if (lowBloodPressure < 0 || lowBloodPressure > 200) {
|
||||
$(this).removeClass("form-control is-valid").addClass("form-control is-invalid");
|
||||
flaglowBloodPressure = false;
|
||||
} else {
|
||||
$(this).removeClass("form-control is-invalid").addClass("form-control is-valid");
|
||||
flaglowBloodPressure = true;
|
||||
}
|
||||
})
|
||||
$("#body-high-blood-pressure").change(function() {
|
||||
highBloodPressure = $(this).val();
|
||||
if (highBloodPressure < 0 || highBloodPressure > 200) {
|
||||
$(this).removeClass("form-control is-valid").addClass("form-control is-invalid");
|
||||
flagHighBloodPressure = false;
|
||||
} else {
|
||||
$(this).removeClass("form-control is-invalid").addClass("form-control is-valid");
|
||||
flagHighBloodPressure = true;
|
||||
}
|
||||
})
|
||||
$("#body-heart-rate").change(function() {
|
||||
heartRate = $(this).val();
|
||||
if (heartRate < 40 || heartRate > 200) {
|
||||
$(this).removeClass("form-control is-valid").addClass("form-control is-invalid");
|
||||
flagHeartRate = false;
|
||||
} else {
|
||||
$(this).removeClass("form-control is-invalid").addClass("form-control is-valid");
|
||||
flagHeartRate = true;
|
||||
}
|
||||
})
|
||||
$("#body-temperature").change(function() {
|
||||
temperature = $(this).val();
|
||||
if (temperature < 33 || temperature > 45) {
|
||||
$(this).removeClass("form-control is-valid").addClass("form-control is-invalid");
|
||||
flagTemperature = false;
|
||||
} else {
|
||||
$(this).removeClass("form-control is-invalid").addClass("form-control is-valid");
|
||||
flagTemperature = true;
|
||||
}
|
||||
})
|
||||
$("#body-appetite").change(function() {
|
||||
appetite = $(this).val();
|
||||
if (!appetite || appetite == '-请选择-') {
|
||||
$(this).removeClass("form-control is-valid").addClass("form-control is-invalid");
|
||||
flagAppetite = false;
|
||||
} else {
|
||||
$(this).removeClass("form-control is-invalid").addClass("form-control is-valid");
|
||||
flagAppetite = true;
|
||||
}
|
||||
})
|
||||
$("#body-weight").change(function() {
|
||||
weight = $(this).val();
|
||||
if (!weight || weight <0 || weight > 200) {
|
||||
$(this).removeClass("form-control is-valid").addClass("form-control is-invalid");
|
||||
flagWeight = false;
|
||||
} else {
|
||||
$(this).removeClass("form-control is-invalid").addClass("form-control is-valid");
|
||||
flagWeight = true;
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
$("#submit").click(function() {
|
||||
if (flaglowBloodPressure && flagHighBloodPressure && flagHeartRate && flagTemperature && flagAppetite && flagWeight) {
|
||||
$.ajax({
|
||||
url: "${baseurl}/health/saveBodyInfo",
|
||||
type: 'POST',
|
||||
dataType: "json",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
'lowBloodPressure': lowBloodPressure,
|
||||
'highBloodPressure': highBloodPressure,
|
||||
'heartRate': heartRate,
|
||||
'temperature': temperature,
|
||||
'appetite': appetite,
|
||||
'weight': weight,
|
||||
'numberOfStep': $("#body-number-of-step").val()
|
||||
}),
|
||||
success: function(data) {
|
||||
alert(data.message)
|
||||
if (data.result == true) {
|
||||
$("input").each(function() {
|
||||
$(this).removeClass("form-control is-invalid").val("");
|
||||
});
|
||||
$("#body-appetite").removeClass("is-valid is-invalid").val("-请选择-");
|
||||
$("#body-nickname").val('${user.nickName}');
|
||||
} else {
|
||||
if (data.path) {
|
||||
top.location.href=data.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (!flaglowBloodPressure) {
|
||||
$("#body-low-blood-pressure").addClass("form-control is-invalid");
|
||||
}
|
||||
if (!flagHighBloodPressure) {
|
||||
$("#body-high-blood-pressure").addClass("form-control is-invalid");
|
||||
}
|
||||
if (!flagHeartRate) {
|
||||
$("#body-heart-rate").addClass("form-control is-invalid");
|
||||
}
|
||||
if (!flagTemperature) {
|
||||
$("#body-temperature").addClass("form-control is-invalid");
|
||||
}
|
||||
if (!flagAppetite) {
|
||||
$("#body-appetite").addClass("form-control is-invalid");
|
||||
}
|
||||
if (!flagWeight) {
|
||||
$("#body-weight").addClass("form-control is-invalid");
|
||||
}
|
||||
}
|
||||
})
|
||||
// 重置
|
||||
$("#reset").click(function() {
|
||||
$("input").each(function() {
|
||||
$(this).removeClass("form-control is-invalid").val("");
|
||||
});
|
||||
$("#body-appetite").removeClass("is-valid is-invalid").val("-请选择-");
|
||||
$("#body-nickname").val('${user.nickName}');
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,234 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<%@include file="base.jsp" %>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>用户身体信息列表</title>
|
||||
<script src="static/js/common-css.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="static/css/util/bootstrap-datetimepicker.min.css">
|
||||
<script src="static/js/common-js.js"></script>
|
||||
<script type="text/javascript" src="static/js/util/bootstrap-datetimepicker.min.js" charset="UTF-8"></script>
|
||||
<script type="text/javascript" src="static/js/util/bootstrap-datetimepicker.zh-CN.js" charset="UTF-8"></script>
|
||||
|
||||
<style type="text/css">
|
||||
div.search {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
div.search label {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
div.search .time {
|
||||
display: inline-block;
|
||||
width: 200px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
div.search button {
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
.body-list tr th {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.body-list tbody tr td {
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.body-list tfoot span {
|
||||
border: 1px solid #ececec;
|
||||
width: 15px;
|
||||
padding-left: 10px;
|
||||
padding-right: 16px;
|
||||
text-align: center;
|
||||
line-height: 25px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="body-list">
|
||||
<div class="search">
|
||||
<label>打卡时间 </label>
|
||||
<input type="text" class="form-control time" id="min-expireTime"> ~
|
||||
<input type="text" class="form-control time" id="max-expireTime">
|
||||
<button type="button" onclick="search(this)" class="btn btn-primary">搜索</button>
|
||||
<button type="button" onclick="list(1, 10)" class="btn btn-info">刷新</button>
|
||||
</div>
|
||||
<table class="table table-bordered table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>序号</th>
|
||||
<th>打卡时间</th>
|
||||
<th>收缩压</th>
|
||||
<th>舒张压</th>
|
||||
<th>心率</th>
|
||||
<th>体温</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="body"></tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td id="dataInfo" colspan="6" style="text-align: right; border-right: 0px; line-height: 28px;">1/2</td>
|
||||
<td id="pageInfo" style="text-align: center; border-left: 0px;">
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- JavaScript files-->
|
||||
<script>
|
||||
|
||||
//中文包 解决日期组件乱码问题
|
||||
(function($){
|
||||
$.fn.datetimepicker.dates['zh-CN'] = {
|
||||
days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
|
||||
daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
|
||||
daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"],
|
||||
months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
||||
monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
||||
today: "今天",
|
||||
suffix: [],
|
||||
meridiem: ["上午", "下午"]
|
||||
};
|
||||
}(jQuery));
|
||||
|
||||
var pageSize = 10;
|
||||
$(function() {
|
||||
$(".time").datetimepicker({
|
||||
language: "zh-CN",
|
||||
format: "yyyy-mm-dd", //显示格式
|
||||
minView: "month", //设置只显示到月份
|
||||
initialDate: new Date(), //初始化当前日期
|
||||
autoclose: true, //选中自动关闭
|
||||
todayBtn: true, //显示今日按钮
|
||||
clearBtn: true,
|
||||
pickerPosition: "bottom-left"
|
||||
});
|
||||
|
||||
$("#min-expireTime").on('change', function(ev) {
|
||||
var startDate = $('#min-expireTime').val();
|
||||
$("#max-expireTime").datetimepicker('setStartDate', startDate);
|
||||
$("#min-expireTime").datetimepicker('hide');
|
||||
});
|
||||
$("#max-expireTime").on('change', function(ev) {
|
||||
var startDate = $('#max-expireTime').val();
|
||||
$("#min-expireTime").datetimepicker('setReturnDate', startDate);
|
||||
$("#max-expireTime").datetimepicker('hide');
|
||||
});
|
||||
|
||||
list(1, pageSize);
|
||||
})
|
||||
|
||||
function list(page, pageSize, minDate, maxDate) {
|
||||
$.ajax({
|
||||
url: "${baseurl}/health/bodyInfoList?page=" + page + "&pageSize=" + pageSize + (minDate ? ("&minDate=" + minDate) :
|
||||
'') + (maxDate ? ("&maxDate=" + maxDate) : ''),
|
||||
type: 'GET',
|
||||
success: function(data) {
|
||||
if (data.result == false) {
|
||||
alert(data.message)
|
||||
return;
|
||||
}
|
||||
var content = "";
|
||||
const list = data.data.content;
|
||||
const page = data.data.page;
|
||||
const totalPage = data.data.totalPages;
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
content += "<tr>" +
|
||||
"<td target=" + list[i].id + ">" + ((page - 1) * pageSize + i + 1) + "</td>" +
|
||||
"<td>" + dateFormat('YYYY-mm-dd HH:MM', new Date(list[i].createTime)) + "</td>" +
|
||||
"<td>" + list[i].lowBloodPressure + "</td>" +
|
||||
"<td>" + list[i].highBloodPressure + "</td>" +
|
||||
"<td>" + list[i].heartRate + "</td>" +
|
||||
"<td>" + list[i].temperature + "</td>" +
|
||||
"<td><button onclick='detailBodyInfo(" + list[i].id + ")' type='button' class='btn btn-info'>详情</button> " +
|
||||
"<button onclick='deleteBodyInfo(" + list[i].id + ", " + page + ", " + data.data.numberOfElements + ", " +
|
||||
totalPage + ")' type='button' class='btn btn-danger'>删除</button></td>" +
|
||||
"</tr>";
|
||||
}
|
||||
$("#body").empty().append(content);
|
||||
$("#dataInfo").text("共" + data.data.totalElements + "条 " + data.data.page + "/" + data.data.totalPages + "页");
|
||||
$("#pageInfo").html('<a href="#" onclick="pagelist(1, ' + totalPage + ', 0)"><span>|«</span></a>' +
|
||||
' <a href="#" onclick="pagelist(' + page + ', ' + totalPage + ', -1)"><span>«</span></a>' +
|
||||
' <a href="#" onclick="pagelist(' + page + ', ' + totalPage + ', 1)"><span>»</span></a>' +
|
||||
' <a href="#" onclick="pagelist(' + totalPage + ', ' + totalPage + ', 0)"><span>»|</span></a>');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function pagelist(page, totalPage, criticality) {
|
||||
const newPage = page + criticality;
|
||||
if (newPage < 1) {
|
||||
return;
|
||||
}
|
||||
if (newPage > totalPage) {
|
||||
return;
|
||||
}
|
||||
list(newPage, pageSize);
|
||||
}
|
||||
|
||||
function deleteBodyInfo(id, page, numberOfElements, totalPage) {
|
||||
$.ajax({
|
||||
url: "${baseurl}/health/" + id,
|
||||
type: 'DELETE',
|
||||
success: function(data) {
|
||||
alert(data.message)
|
||||
// 当前页临界值处理
|
||||
if (numberOfElements == 1) {
|
||||
if (totalPage > 1 && page > 1) {
|
||||
page = page - 1;
|
||||
}
|
||||
}
|
||||
list(page, pageSize);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function search(e) {
|
||||
const minDate = $("#min-expireTime").val();
|
||||
const maxDate = $("#max-expireTime").val();
|
||||
list(1, pageSize, minDate, maxDate);
|
||||
}
|
||||
|
||||
function detailBodyInfo(id) {
|
||||
const parent = window.parent;
|
||||
parent.$('#model_in').val(id);
|
||||
parent.$('#myModal').modal('show');
|
||||
|
||||
$.ajax({
|
||||
url: "${baseurl}/health/" + id,
|
||||
type: 'GET',
|
||||
success: function(data) {
|
||||
if (data.result == true) {
|
||||
parent.$("#body-low-blood-pressure").val(data.data.lowBloodPressure);
|
||||
parent.$("#body-low-blood-pressure-desc").text(data.data.lowBloodPressureDesc);
|
||||
parent.$("#body-high-blood-pressure").val(data.data.highBloodPressure);
|
||||
parent.$("#body-high-blood-pressure-desc").text(data.data.highBloodPressureDesc);
|
||||
parent.$("#body-heart-rate").val(data.data.heartRate);
|
||||
parent.$("#body-heart-rate-desc").text(data.data.heartRateDesc);
|
||||
parent.$("#body-temperature").val(data.data.temperature);
|
||||
parent.$("#body-temperature-desc").text(data.data.temperatureDesc);
|
||||
parent.$("#body-appetite").val(data.data.appetite);
|
||||
parent.$("#body-weight").val(data.data.weight);
|
||||
parent.$("#body-number-of-step").val(data.data.numberOfStep);
|
||||
parent.$("#body-blog-pressure").text(data.data.bloodPressureDesc);
|
||||
} else {
|
||||
alert(data.message)
|
||||
if (data.path) {
|
||||
top.location.href = data.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,175 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<%@include file="base.jsp" %>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>用户身体信息统计</title>
|
||||
<script src="static/js/common-css.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="static/css/util/bootstrap-datetimepicker.min.css">
|
||||
<style type="text/css">
|
||||
.bar {
|
||||
padding-right: 40px;
|
||||
z-index: 1000;
|
||||
}
|
||||
.bar label {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.bar #min-expireTime {
|
||||
display: inline-block;
|
||||
width: 200px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
.bar .btn-primary {
|
||||
margin-top: -5px;
|
||||
}
|
||||
.bar .btn-info {
|
||||
float: right;
|
||||
}
|
||||
#container {
|
||||
margin-top: 35px;
|
||||
padding: 5px;
|
||||
position: absolute;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="bar">
|
||||
<label>时间 </label>
|
||||
<input type="text" class="form-control time" id="min-expireTime">
|
||||
<button type="button" onclick="search(this)" class="btn btn-primary">搜索</button>
|
||||
<button type="button" onclick="init()" class="btn btn-info">刷新</button>
|
||||
<button type="button" onclick="mailPush()" class="btn btn-info">近期推送</button>
|
||||
</div>
|
||||
<div id="container"></div>
|
||||
<script src="static/js/common-js.js"></script>
|
||||
<script type="text/javascript" src="static/js/util/bootstrap-datetimepicker.min.js"></script>
|
||||
<script type="text/javascript" src="static/js/util/bootstrap-datetimepicker.zh-CN.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-gl/dist/echarts-gl.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-stat/dist/ecStat.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
//中文包 解决日期组件乱码问题
|
||||
(function($){
|
||||
$.fn.datetimepicker.dates['zh-CN'] = {
|
||||
days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
|
||||
daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
|
||||
daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"],
|
||||
months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
||||
monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
||||
today: "今天",
|
||||
suffix: [],
|
||||
meridiem: ["上午", "下午"]
|
||||
};
|
||||
}(jQuery));
|
||||
|
||||
|
||||
$(".time").datetimepicker({
|
||||
language: "zh-CN",
|
||||
format: "yyyy-mm-dd", //显示格式
|
||||
minView: "month", //设置只显示到月份
|
||||
initialDate: new Date(), //初始化当前日期
|
||||
autoclose: true, //选中自动关闭
|
||||
todayBtn: true, //显示今日按钮
|
||||
clearBtn: true,
|
||||
pickerPosition: "bottom-left",
|
||||
endDate: new Date()
|
||||
});
|
||||
|
||||
function mailPush(){
|
||||
$.ajax({
|
||||
url: "${baseurl}/mail/recentPush" ,
|
||||
type: 'POST',
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: function(data){
|
||||
alert(data.message);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function search(e) {
|
||||
const minDate = $("#min-expireTime").val();
|
||||
init(minDate);
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
function init(date) {
|
||||
$.ajax({
|
||||
url: "${baseurl}/health/bodyInfoStatistics?" + (date ? ("date=" + date) : ''),
|
||||
type: 'GET',
|
||||
success: function(data) {
|
||||
if (data.result == true) {
|
||||
let option = {
|
||||
title: {
|
||||
text: '健康信息图'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'cross',
|
||||
label: {
|
||||
backgroundColor: '#6a7985'
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: data.data.typeNames,
|
||||
selected: { "步数": false }
|
||||
},
|
||||
toolbox: {
|
||||
feature: {
|
||||
saveAsImage: {}
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [{
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
||||
}],
|
||||
yAxis: [{
|
||||
type: 'value'
|
||||
}]
|
||||
};
|
||||
|
||||
const bodyInfos = data.data.bodyInfoVos;
|
||||
let series = [];
|
||||
for (var i = 0; i < bodyInfos.length; i++) {
|
||||
series.push({
|
||||
name: bodyInfos[i].typeName,
|
||||
type: 'line',
|
||||
stack: '总量',
|
||||
areaStyle: {},
|
||||
data: bodyInfos[i].datas
|
||||
});
|
||||
}
|
||||
option["series"] = series;
|
||||
|
||||
if (option && typeof option === "object") {
|
||||
echarts.init(document.getElementById("container")).setOption(option, true);
|
||||
}
|
||||
} else {
|
||||
alert(data.message)
|
||||
if (data.path) {
|
||||
top.location.href = data.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,150 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<%@include file="base.jsp" %>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>注册</title>
|
||||
<script src="static/js/common-css.js"></script>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Poppins:300,400,700">
|
||||
<link rel="stylesheet" href="static/css/login.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="page login-page">
|
||||
<div class="container d-flex align-items-center">
|
||||
<div class="form-holder has-shadow">
|
||||
<div class="row">
|
||||
<!-- Logo & Information Panel-->
|
||||
<div class="col-lg-6">
|
||||
<div class="info d-flex align-items-center">
|
||||
<div class="content">
|
||||
<div class="logo">
|
||||
<h1>欢迎注册</h1>
|
||||
</div>
|
||||
<p>个人健康信息管理系统</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Form Panel -->
|
||||
<div class="col-lg-6 bg-white">
|
||||
<div class="form d-flex align-items-center">
|
||||
<div class="content">
|
||||
<div class="form-group">
|
||||
<input id="register-username" class="input-material" type="text" name="registerUsername" placeholder="请输入用户名/姓名">
|
||||
<div class="invalid-feedback">
|
||||
用户名必须在2~10位之间
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input id="register-password" class="input-material" type="password" name="registerPassword" placeholder="请输入密码">
|
||||
<div class="invalid-feedback">
|
||||
密码必须在6~10位之间
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input id="register-passwords" class="input-material" type="password" name="registerPasswords" placeholder="确认密码">
|
||||
<div class="invalid-feedback">
|
||||
两次密码必须相同 且在6~10位之间
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button id="regbtn" type="button" name="registerSubmit" class="btn btn-primary">注册</button>
|
||||
</div>
|
||||
<small>已有账号?</small><a href="login" class="signup"> 登录</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- JavaScript files-->
|
||||
<script src="static/js/common-js.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
/*错误class form-control is-invalid
|
||||
正确class form-control is-valid*/
|
||||
var flagName = false;
|
||||
var flagPas = false;
|
||||
var flagPass = false;
|
||||
/*验证用户名*/
|
||||
var name, passWord, passWords;
|
||||
$("#register-username").change(function() {
|
||||
name = $("#register-username").val();
|
||||
if (name.length < 2 || name.length > 10) {
|
||||
$("#register-username").removeClass("form-control is-valid")
|
||||
$("#register-username").addClass("form-control is-invalid");
|
||||
flagName = false;
|
||||
} else {
|
||||
$("#register-username").removeClass("form-control is-invalid")
|
||||
$("#register-username").addClass("form-control is-valid");
|
||||
flagName = true;
|
||||
}
|
||||
})
|
||||
/*验证密码*/
|
||||
$("#register-password").change(function() {
|
||||
passWord = $("#register-password").val();
|
||||
if (passWord.length < 6 || passWord.length > 18) {
|
||||
$("#register-password").removeClass("form-control is-valid")
|
||||
$("#register-password").addClass("form-control is-invalid");
|
||||
flagPas = false;
|
||||
} else {
|
||||
$("#register-password").removeClass("form-control is-invalid")
|
||||
$("#register-password").addClass("form-control is-valid");
|
||||
flagPas = true;
|
||||
}
|
||||
})
|
||||
/*验证确认密码*/
|
||||
$("#register-passwords").change(function() {
|
||||
passWords = $("#register-passwords").val();
|
||||
if ((passWord != passWords) || (passWords.length < 6 || passWords.length > 18)) {
|
||||
$("#register-passwords").removeClass("form-control is-valid")
|
||||
$("#register-passwords").addClass("form-control is-invalid");
|
||||
flagPass = false;
|
||||
} else {
|
||||
$("#register-passwords").removeClass("form-control is-invalid")
|
||||
$("#register-passwords").addClass("form-control is-valid");
|
||||
flagPass = true;
|
||||
}
|
||||
})
|
||||
|
||||
$("#regbtn").click(function() {
|
||||
if (flagName && flagPas && flagPass) {
|
||||
$.ajax({
|
||||
url: "${baseurl}/user/register",
|
||||
type: 'POST',
|
||||
data: {
|
||||
'userName': name,
|
||||
'passWord': passWord,
|
||||
'confirmPassWord': passWords
|
||||
},
|
||||
success: function(data) {
|
||||
alert(data.message)
|
||||
if (data.result == true) {
|
||||
localStorage.setItem("userName", name);
|
||||
$("#register-username").val("");
|
||||
$("#register-username").removeClass("is-valid");
|
||||
$("#register-password").val("");
|
||||
$("#register-password").removeClass("is-valid");
|
||||
$("#register-passwords").val("");
|
||||
$("#register-passwords").removeClass("is-valid");
|
||||
window.location.href = 'login';
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (!flagName) {
|
||||
$("#register-username").addClass("form-control is-invalid");
|
||||
}
|
||||
if (!flagPas) {
|
||||
$("#register-password").addClass("form-control is-invalid");
|
||||
}
|
||||
if (!flagPass) {
|
||||
$("#register-passwords").addClass("form-control is-invalid");
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,55 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>头部</title>
|
||||
<script src="static/js/common-css.js"></script>
|
||||
<script type="text/javascript" src="static/js/common-js.js"></script>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
|
||||
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
|
||||
|
||||
<style type="text/css">
|
||||
div.container {
|
||||
background: #0088ff;
|
||||
height: 60px;
|
||||
max-width: 100%;
|
||||
}
|
||||
div.container h3 {
|
||||
float: left;
|
||||
margin-top: 10px;
|
||||
margin-left: 10%;
|
||||
}
|
||||
div.container h3 a {
|
||||
color: #ffffff;
|
||||
}
|
||||
div.container h3 a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
div.container .dropdown {
|
||||
float: right;
|
||||
margin-top: 5px;
|
||||
margin-right: 5%;
|
||||
}
|
||||
div.container span img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 40px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h3><a href="home">个人健康信息管理</a></h3>
|
||||
<div class="dropdown">
|
||||
<span class="dropdown-toggle" data-toggle="dropdown"><img src="${ user.headUrl }" /></span>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="#" onclick="ifram_info('userInfo')">个人信息</a>
|
||||
<a id="logout" class="dropdown-item" href="user/logout">退出登录</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,120 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<%@include file="base.jsp"%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>修改密码</title>
|
||||
<script type="text/javascript" src="static/js/common-css.js"></script>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Poppins:300,400,700">
|
||||
<style type="text/css">
|
||||
.bg-white {
|
||||
padding-left: 20px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.bg-white .input-material {
|
||||
padding-left: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="col-lg-6 bg-white">
|
||||
<div class="form d-flex align-items-center">
|
||||
<div class="content">
|
||||
<div class="form-group">
|
||||
<input id="register-username" class="input-material" type="text" name="userName" placeholder="请输入用户名" disabled="disabled"
|
||||
value="${ user.userName }">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input id="register-password" class="input-material" type="password" name="passWord" placeholder="请输入密码">
|
||||
<div class="invalid-feedback">
|
||||
密码必须在6~10位之间
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input id="register-passwords" class="input-material" type="password" name="confirmPassWord" placeholder="确认密码">
|
||||
<div class="invalid-feedback">
|
||||
两次密码必须相同 且在6~10位之间
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button id="regbtn" type="button" name="registerSubmit" class="btn btn-primary">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="static/js/common-js.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
/*错误class form-control is-invalid
|
||||
正确class form-control is-valid*/
|
||||
var flagPas = false;
|
||||
var flagPass = false;
|
||||
var passWord, passWords;
|
||||
/*验证密码*/
|
||||
$("#register-password").change(function() {
|
||||
passWord = $("#register-password").val();
|
||||
if (passWord.length < 6 || passWord.length > 18) {
|
||||
$("#register-password").removeClass("form-control is-valid")
|
||||
$("#register-password").addClass("form-control is-invalid");
|
||||
flagPas = false;
|
||||
} else {
|
||||
$("#register-password").removeClass("form-control is-invalid")
|
||||
$("#register-password").addClass("form-control is-valid");
|
||||
flagPas = true;
|
||||
}
|
||||
})
|
||||
/*验证确认密码*/
|
||||
$("#register-passwords").change(function() {
|
||||
passWords = $("#register-passwords").val();
|
||||
if ((passWord != passWords) || (passWords.length < 6 || passWords.length > 18)) {
|
||||
$("#register-passwords").removeClass("form-control is-valid")
|
||||
$("#register-passwords").addClass("form-control is-invalid");
|
||||
flagPass = false;
|
||||
} else {
|
||||
$("#register-passwords").removeClass("form-control is-invalid")
|
||||
$("#register-passwords").addClass("form-control is-valid");
|
||||
flagPass = true;
|
||||
}
|
||||
})
|
||||
|
||||
$("#regbtn").click(function() {
|
||||
if (flagPas && flagPass) {
|
||||
$.ajax({
|
||||
url: "${baseurl}/user/updatePassword",
|
||||
type: 'PUT',
|
||||
dataType: "json",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
'passWord': passWord,
|
||||
'confirmPassWord': passWords
|
||||
}),
|
||||
success: function(data) {
|
||||
alert(data.message)
|
||||
if (data.result == true) {
|
||||
localStorage.removeItem("passWord");
|
||||
localStorage.removeItem("check1");
|
||||
localStorage.removeItem("user");
|
||||
$("#register-password").val("");
|
||||
$("#register-password").removeClass("is-valid");
|
||||
$("#register-passwords").val("");
|
||||
$("#register-passwords").removeClass("is-valid");
|
||||
top.location.href = 'login';
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (!flagPas) {
|
||||
$("#register-password").addClass("form-control is-invalid");
|
||||
}
|
||||
if (!flagPass) {
|
||||
$("#register-passwords").addClass("form-control is-invalid");
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,200 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<%@include file="base.jsp"%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>用户信息</title>
|
||||
<script type="text/javascript" src="static/js/common-css.js"></script>
|
||||
<style type="text/css">
|
||||
#form_content {
|
||||
text-align: center;
|
||||
padding: 20px 0px 20px 35%;
|
||||
}
|
||||
.content {
|
||||
width: 100%;
|
||||
padding: 20px 0px;
|
||||
}
|
||||
.content .form-group span {
|
||||
display: inline-block;
|
||||
line-height: 30px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
.content .form-group input {
|
||||
width: 250px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
.content .form-group input#body-headUrl {
|
||||
font-size: 10px;
|
||||
border-bottom: none;
|
||||
}
|
||||
.btn_clar {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="form_content">
|
||||
<div class="col-lg-6 bg-white">
|
||||
<div class="form d-flex align-items-center">
|
||||
<div class="content">
|
||||
<div class="form-group">
|
||||
<span>昵称</span> <input id="body-nickname" class="input-material" type="text" name="nickName" disabled="disabled"
|
||||
value="${ user.nickName }">
|
||||
<div class="invalid-feedback">昵称必须在2~10之间</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span>账号</span> <input id="body-userName" class="input-material" type="text" name="userName" disabled="disabled"
|
||||
value="${ user.userName }">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span>邮箱</span> <input id="body-email" class="input-material" type="email" name="email" disabled="disabled"
|
||||
value="${ user.email }">
|
||||
<div class="invalid-feedback">邮箱不能为空</div>
|
||||
<button id="verification" type="button" name="verification"
|
||||
class="btn btn_clar" style="position: fixed;" >验证码</button>
|
||||
<button id="already-verification" type="button" name="already-verification"
|
||||
class="btn btn_clar" style="position: fixed;">已发送</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span>验证</span> <input id="body-email-verification" class="input-material" type="text" name="email-verification" disabled="disabled"
|
||||
value="">
|
||||
<div class="invalid-feedback">验证码不能为空</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span>头像</span> <input id="body-headUrl" class="input-material" type="file" name="headUrl" disabled="disabled"
|
||||
value="${ user.headUrl }">
|
||||
<div class="invalid-feedback">请选择头像文件</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button id="update" type="button" name="update" class="btn btn-primary">修改信息</button>
|
||||
<button id="submit" type="button" name="submit" class="btn btn-primary btn_clar">确认修改</button>
|
||||
<button id="reset"type="reset" name="reset" class="btn btn-primary btn_clar" style="margin-left: 40px">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="static/js/common-js.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
/*错误class form-control is-invalid
|
||||
正确class form-control is-valid*/
|
||||
var nickName = '${user.nickName}';
|
||||
var flagNickName = nickName;
|
||||
var flagHeadUrl = false;
|
||||
var headUrl ;
|
||||
var verificationTrueCode;
|
||||
$("#body-nickname").change(function() {
|
||||
nickName = $(this).val();
|
||||
console.log(nickName)
|
||||
if (nickName.length < 2 || nickName.length > 10) {
|
||||
$(this).removeClass("form-control is-valid").addClass("form-control is-invalid").css("display", "inline-block");
|
||||
flagNickName = false;
|
||||
} else {
|
||||
$(this).removeClass("form-control is-invalid").addClass("form-control is-valid").css("display", "inline-block");
|
||||
flagNickName = true;
|
||||
}
|
||||
})
|
||||
$("#body-headUrl").change(function() {
|
||||
headUrl = $(this).val();
|
||||
if (!headUrl) {
|
||||
$(this).removeClass("form-control is-valid").addClass("form-control is-invalid").css("display", "inline-block");
|
||||
flagHeadUrl = false;
|
||||
} else {
|
||||
$(this).removeClass("form-control is-invalid").addClass("form-control is-valid").css("display", "inline-block");
|
||||
flagHeadUrl = true;
|
||||
}
|
||||
})
|
||||
|
||||
$("#verification").click(function() {
|
||||
var fromData = new FormData();
|
||||
fromData.append('email',$("#body-email").val());
|
||||
$.ajax({
|
||||
url: "${baseurl}/mail/verification",
|
||||
type: 'POST',
|
||||
data: fromData,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: function(data) {
|
||||
alert(data.message)
|
||||
if (data.result == true) {
|
||||
verificationTrueCode = data.data;
|
||||
$("#verification").addClass("btn_clar");
|
||||
$("#already-verification").removeClass("btn_clar");
|
||||
} else {
|
||||
if (data.path) {
|
||||
top.location.href=data.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
$("#update").click(function() {
|
||||
$("#body-nickname").removeAttr("disabled", 'none');
|
||||
$("#body-email").removeAttr("disabled", 'none');
|
||||
$("#body-headUrl").removeAttr("disabled", 'none');
|
||||
$("#body-email-verification").removeAttr("disabled",'none');
|
||||
$("#submit").removeClass("btn_clar");
|
||||
$("#reset").removeClass("btn_clar");
|
||||
$("#verification").removeClass("btn_clar");
|
||||
$(this).addClass("btn_clar");
|
||||
});
|
||||
|
||||
$("#submit").click(function() {
|
||||
var verificationCode = $('#body-email-verification').val()
|
||||
if(verificationCode==verificationTrueCode){
|
||||
if (flagNickName && flagHeadUrl) {
|
||||
const oFiles = document.getElementById("body-headUrl").files;
|
||||
var fromData = new FormData();
|
||||
fromData.append('nickName', nickName);
|
||||
fromData.append('headUrl', oFiles[0]);
|
||||
fromData.append('email', $("#body-email").val());
|
||||
$.ajax({
|
||||
url: "${baseurl}/user/updateUserInfo",
|
||||
type: 'POST',
|
||||
data: fromData,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: function(data) {
|
||||
alert(data.message)
|
||||
if (data.result == true) {
|
||||
localStorage.setItem("user", JSON.stringify(data.data));
|
||||
location.href='userInfo';
|
||||
window.parent.$(".dropdown-toggle img").attr('src', data.data.headUrl);
|
||||
} else {
|
||||
if (data.path) {
|
||||
top.location.href=data.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (!flagNickName) {
|
||||
$("#body-nickname").addClass("form-control is-invalid").css("display", "inline-block");
|
||||
}
|
||||
if (!flagHeadUrl) {
|
||||
$("#body-headUrl").addClass("form-control is-invalid").css("display", "inline-block");
|
||||
}
|
||||
}
|
||||
}else {
|
||||
alert("验证码错误!")
|
||||
}
|
||||
})
|
||||
// 重置
|
||||
$("#reset").click(function() {
|
||||
$("input").each(function() {
|
||||
$(this).removeClass("form-control is-invalid").val("");
|
||||
});
|
||||
$("#body-nickname").val('${user.nickName}');
|
||||
$("#body-userName").val('${user.userName}');
|
||||
$("#body-email").val('${user.email}');
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app version="3.1"
|
||||
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_3_1.xsd">
|
||||
|
||||
<display-name>个人健康信息管理</display-name>
|
||||
|
||||
<!--spring上下文配置文件路径 -->
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>classpath:spring/spring.xml</param-value>
|
||||
</context-param>
|
||||
<!--Web监听器 -->
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<filter>
|
||||
<filter-name>crossXssFilter</filter-name>
|
||||
<filter-class>top.beansprout.health.config.CrossXssFilter</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>crossXssFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!--注册字符集过滤器:解决中文乱码问题 -->
|
||||
<filter>
|
||||
<filter-name>characterEncodingFilter</filter-name>
|
||||
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
|
||||
<!--指定字符集 -->
|
||||
<init-param>
|
||||
<param-name>encoding</param-name>
|
||||
<param-value>UTF-8</param-value>
|
||||
</init-param>
|
||||
<!--指定强制指定的字符集 -->
|
||||
<init-param>
|
||||
<param-name>forceEncoding</param-name>
|
||||
<param-value>true</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>characterEncodingFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!--注册中央处理器 -->
|
||||
<servlet>
|
||||
<servlet-name>dispatcher</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<!--制定SpringMVC的配置文件 -->
|
||||
<init-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>classpath:spring/spring-mvc.xml</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>dispatcher</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
<error-page>
|
||||
<exception-type>java.lang.Exception</exception-type>
|
||||
<location>/WEB-INF/error/500.jsp</location>
|
||||
</error-page>
|
||||
<error-page>
|
||||
<error-code>401</error-code>
|
||||
<location>/WEB-INF/error/401.jsp</location>
|
||||
</error-page>
|
||||
<error-page>
|
||||
<error-code>403</error-code>
|
||||
<location>/WEB-INF/error/403.jsp</location>
|
||||
</error-page>
|
||||
<error-page>
|
||||
<error-code>404</error-code>
|
||||
<location>/WEB-INF/error/404.jsp</location>
|
||||
</error-page>
|
||||
<error-page>
|
||||
<error-code>405</error-code>
|
||||
<location>/WEB-INF/error/404.jsp</location>
|
||||
</error-page>
|
||||
|
||||
</web-app>
|
@ -0,0 +1,128 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<%@include file="WEB-INF/view/base.jsp"%>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>登录</title>
|
||||
<script src="static/js/common-css.js"></script>
|
||||
<link rel="stylesheet" href="static/css/login.css">
|
||||
<script type="text/javascript">
|
||||
// 防止退出登录后又页面回退带来的问题
|
||||
const referer = '<%=request.getHeader("Referer")%>';
|
||||
const target = '<%=request.getParameter("target")%>';
|
||||
function getreferer() {
|
||||
if ((!target || target == 'null') && referer && referer.indexOf("/home") != -1) {
|
||||
top.location.href = 'login';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="getreferer()">
|
||||
<div class="page login-page">
|
||||
<div class="container d-flex align-items-center">
|
||||
<div class="form-holder has-shadow">
|
||||
<div class="row">
|
||||
<!-- Logo & Information Panel-->
|
||||
<div class="col-lg-6">
|
||||
<div class="info d-flex align-items-center">
|
||||
<div class="content">
|
||||
<div class="logo">
|
||||
<h1>欢迎登录</h1>
|
||||
</div>
|
||||
<p>个人健康信息管理系统</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Form Panel -->
|
||||
<div class="col-lg-6 bg-white">
|
||||
<div class="form d-flex align-items-center">
|
||||
<div class="content">
|
||||
<form class="form-validate" id="loginFrom">
|
||||
<div class="form-group">
|
||||
<input id="login-username" type="text" name="userName" required data-msg="请输入用户名" placeholder="用户名" value=""
|
||||
class="input-material">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input id="login-password" type="password" name="passWord" required data-msg="请输入密码" placeholder="密码" class="input-material">
|
||||
</div>
|
||||
<button id="login" class="btn btn-primary">登录</button>
|
||||
<div style="margin-top: -40px;">
|
||||
<!-- <input type="checkbox" id="check1"/> <span>记住密码</span>
|
||||
<input type="checkbox" id="check2"/> <span>自动登录</span> -->
|
||||
<div class="custom-control custom-checkbox " style="float: right;">
|
||||
<input type="checkbox" class="custom-control-input" id="check2"> <label class="custom-control-label" for="check2">自动登录</label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox " style="float: right;">
|
||||
<input type="checkbox" class="custom-control-input" id="check1"> <label class="custom-control-label" for="check1">记住密码 </label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<br /> <small>没有账号?</small><a href="register" class="signup"> 注册</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- JavaScript files-->
|
||||
<script src="static/js/common-js.js"></script>
|
||||
<script src="static/js/util/jquery.validate.min.js"></script>
|
||||
<script src="static/js/login.js"></script>
|
||||
<!--表单验证-->
|
||||
<!-- Main File-->
|
||||
<script>
|
||||
$(window).load(function() {
|
||||
/*判断上次是否勾选记住密码和自动登录*/
|
||||
var check1s = localStorage.getItem("check1");
|
||||
var check2s = sessionStorage.getItem("check2");
|
||||
var oldName = localStorage.getItem("userName");
|
||||
var oldPass = localStorage.getItem("passWord");
|
||||
if (check1s == "true") {
|
||||
$("#login-username").val(oldName);
|
||||
$("#login-password").val(oldPass);
|
||||
$("#check1").prop('checked', true);
|
||||
} else {
|
||||
$("#login-username").val('');
|
||||
$("#login-password").val('');
|
||||
$("#check1").prop('checked', false);
|
||||
}
|
||||
if (check2s == "true") {
|
||||
$("#check2").prop('checked', true);
|
||||
$("#loginFrom").submit();
|
||||
} else {
|
||||
$("#check2").prop('checked', false);
|
||||
}
|
||||
});
|
||||
$("#loginFrom").submit(function(e) {
|
||||
var userName = $("#login-username").val();
|
||||
var passWord = $("#login-password").val();
|
||||
$.ajax({
|
||||
url: "${baseurl}/user/login",
|
||||
type: 'POST',
|
||||
data: {
|
||||
'userName': userName,
|
||||
'passWord': passWord
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.result == true) {
|
||||
localStorage.setItem("user", JSON.stringify(data.data))
|
||||
localStorage.setItem("userName", userName);
|
||||
localStorage.setItem("passWord", passWord);
|
||||
var check1 = $("#check1").prop('checked');
|
||||
var check2 = $('#check2').prop('checked');
|
||||
localStorage.setItem("check1", check1);
|
||||
sessionStorage.setItem("check2", check2);
|
||||
window.location.href = 'home';
|
||||
} else {
|
||||
alert(data.message)
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* ==========================================================
|
||||
* LOGIN PAGE
|
||||
* ==========================================================
|
||||
*/
|
||||
.login-page {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.login-page::before {
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
z-index: -1;
|
||||
background: url(../imgs/login.jpg);
|
||||
background-size: cover;
|
||||
-webkit-filter: blur(10px);
|
||||
filter: blur(10px);
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.login-page .container {
|
||||
min-height: 100vh;
|
||||
z-index: 999;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.login-page .form-holder {
|
||||
width: 100%;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.login-page .form-holder .info,
|
||||
.login-page .form-holder .form {
|
||||
min-height: 70vh;
|
||||
padding: 40px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.login-page .form-holder div[class*='col-'] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.login-page .form-holder .info {
|
||||
background: rgba(121, 106, 238, 0.9);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.login-page .form-holder .info h1 {
|
||||
font-size: 2.5em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.login-page .form-holder .info p {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.login-page .form-holder .form .form-group {
|
||||
position: relative;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.login-page .form-holder .form .content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.login-page .form-holder .form form {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.login-page .form-holder .form #login,
|
||||
.login-page .form-holder .form #register {
|
||||
margin-bottom: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.login-page .form-holder .form a.forgot-pass,
|
||||
.login-page .form-holder .form a.signup {
|
||||
font-size: 0.9em;
|
||||
color: #85b4f2;
|
||||
}
|
||||
|
||||
.login-page .form-holder .form small {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.login-page .form-holder .form .terms-conditions label {
|
||||
cursor: pointer;
|
||||
color: #aaa;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.login-page .copyrights {
|
||||
width: 100%;
|
||||
z-index: 9999;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.login-page .info,
|
||||
.login-page .form {
|
||||
min-height: auto !important;
|
||||
}
|
||||
|
||||
.login-page .info {
|
||||
padding-top: 100px !important;
|
||||
padding-bottom: 100px !important;
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,13 @@
|
||||
/* 移动端设置 */
|
||||
document.write('<meta charset="UTF-8">');
|
||||
document.write('<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">');
|
||||
document.write('<meta http-equiv="X-UA-Compatible" content="IE=edge">');
|
||||
/* 移动端兼容 */
|
||||
document.write('<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">');
|
||||
/* 搜索引擎优化 */
|
||||
document.write('<meta name="description" content="个人健康信息管理">');
|
||||
document.write('<meta name="robots" content="all,follow">');
|
||||
|
||||
document.write('<link type="text/css" rel="stylesheet" href="static/css/base.css" />');
|
||||
/* 最新版本的 Bootstrap 核心 CSS 文件 */
|
||||
document.write('<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/4.2.1/css/bootstrap.min.css">');
|
@ -0,0 +1,43 @@
|
||||
/* bootstrap */
|
||||
document.write('<script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>');
|
||||
document.write('<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>');
|
||||
document.write('<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>');
|
||||
|
||||
// input浮点数处理
|
||||
function clearNoNum(obj){
|
||||
obj.value = obj.value.replace(/[^\d.]/g,""); //清除“数字”和“.”以外的字符
|
||||
obj.value = obj.value.replace(/\.{2,}/g,"."); //只保留第一个. 清除多余的
|
||||
obj.value = obj.value.replace(".","$#$").replace(/\./g,"").replace("$#$",".");
|
||||
obj.value = obj.value.replace(/^(\-)*(\d+)\.(\d).*$/,'$1$2.$3');//只能输入两个小数
|
||||
//如果没有小数点,不能为类似 01、02的金额
|
||||
if(obj.value.indexOf(".")< 0 && obj.value !=""){
|
||||
obj.value= parseFloat(obj.value);
|
||||
}
|
||||
//如果有小数点,不能为类似 1.10的金额
|
||||
if(obj.value.indexOf(".")> 0 && obj.value.indexOf("0")>2){
|
||||
obj.value= parseFloat(obj.value);
|
||||
}
|
||||
//如果有小数点,不能为类似 0.00的金额
|
||||
if(obj.value.indexOf(".")> 0 && obj.value.lastIndexOf("0")>1){
|
||||
obj.value= parseFloat(obj.value);
|
||||
}
|
||||
}
|
||||
function dateFormat(fmt, date) {
|
||||
let ret;
|
||||
const opt = {
|
||||
"Y+": date.getFullYear().toString(), // 年
|
||||
"m+": (date.getMonth() + 1).toString(), // 月
|
||||
"d+": date.getDate().toString(), // 日
|
||||
"H+": date.getHours().toString(), // 时
|
||||
"M+": date.getMinutes().toString(), // 分
|
||||
"S+": date.getSeconds().toString() // 秒
|
||||
// 有其他格式化字符需求可以继续添加,必须转化成字符串
|
||||
};
|
||||
for (let k in opt) {
|
||||
ret = new RegExp("(" + k + ")").exec(fmt);
|
||||
if (ret) {
|
||||
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
|
||||
};
|
||||
};
|
||||
return fmt;
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
$(document).ready(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
// ------------------------------------------------------- //
|
||||
// Search Box
|
||||
// ------------------------------------------------------ //
|
||||
$('#search').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$('.search-box').fadeIn();
|
||||
});
|
||||
$('.dismiss').on('click', function () {
|
||||
$('.search-box').fadeOut();
|
||||
});
|
||||
|
||||
// ------------------------------------------------------- //
|
||||
// Card Close
|
||||
// ------------------------------------------------------ //
|
||||
$('.card-close a.remove').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$(this).parents('.card').fadeOut();
|
||||
});
|
||||
|
||||
// ------------------------------------------------------- //
|
||||
// Tooltips init
|
||||
// ------------------------------------------------------ //
|
||||
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
|
||||
|
||||
// ------------------------------------------------------- //
|
||||
// Adding fade effect to dropdowns
|
||||
// ------------------------------------------------------ //
|
||||
$('.dropdown').on('show.bs.dropdown', function () {
|
||||
$(this).find('.dropdown-menu').first().stop(true, true).fadeIn();
|
||||
});
|
||||
$('.dropdown').on('hide.bs.dropdown', function () {
|
||||
$(this).find('.dropdown-menu').first().stop(true, true).fadeOut();
|
||||
});
|
||||
|
||||
|
||||
// ------------------------------------------------------- //
|
||||
// Sidebar Functionality
|
||||
// ------------------------------------------------------ //
|
||||
$('#toggle-btn').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$(this).toggleClass('active');
|
||||
|
||||
$('.side-navbar').toggleClass('shrinked');
|
||||
$('.content-inner').toggleClass('active');
|
||||
$(document).trigger('sidebarChanged');
|
||||
|
||||
if ($(window).outerWidth() > 1183) {
|
||||
if ($('#toggle-btn').hasClass('active')) {
|
||||
$('.navbar-header .brand-small').hide();
|
||||
$('.navbar-header .brand-big').show();
|
||||
} else {
|
||||
$('.navbar-header .brand-small').show();
|
||||
$('.navbar-header .brand-big').hide();
|
||||
}
|
||||
}
|
||||
|
||||
if ($(window).outerWidth() < 1183) {
|
||||
$('.navbar-header .brand-small').show();
|
||||
}
|
||||
});
|
||||
|
||||
// ------------------------------------------------------- //
|
||||
// Universal Form Validation
|
||||
// ------------------------------------------------------ //
|
||||
|
||||
$('.form-validate').each(function() {
|
||||
$(this).validate({
|
||||
errorElement: "div",
|
||||
errorClass: 'is-invalid',
|
||||
validClass: 'is-valid',
|
||||
ignore: ':hidden:not(.summernote, .checkbox-template, .form-control-custom),.note-editable.card-block',
|
||||
errorPlacement: function (error, element) {
|
||||
// Add the `invalid-feedback` class to the error element
|
||||
error.addClass("invalid-feedback");
|
||||
if (element.prop("type") === "checkbox") {
|
||||
error.insertAfter(element.siblings("label"));
|
||||
}
|
||||
else {
|
||||
error.insertAfter(element);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// ------------------------------------------------------- //
|
||||
// Material Inputs
|
||||
// ------------------------------------------------------ //
|
||||
|
||||
var materialInputs = $('input.input-material');
|
||||
|
||||
// activate labels for prefilled values
|
||||
materialInputs.filter(function() { return $(this).val() !== ""; }).siblings('.label-material').addClass('active');
|
||||
|
||||
// move label on focus
|
||||
materialInputs.on('focus', function () {
|
||||
$(this).siblings('.label-material').addClass('active');
|
||||
});
|
||||
|
||||
// remove/keep label on blur
|
||||
materialInputs.on('blur', function () {
|
||||
$(this).siblings('.label-material').removeClass('active');
|
||||
|
||||
if ($(this).val() !== '') {
|
||||
$(this).siblings('.label-material').addClass('active');
|
||||
} else {
|
||||
$(this).siblings('.label-material').removeClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
// ------------------------------------------------------- //
|
||||
// Footer
|
||||
// ------------------------------------------------------ //
|
||||
|
||||
var contentInner = $('.content-inner');
|
||||
|
||||
$(document).on('sidebarChanged', function () {
|
||||
adjustFooter();
|
||||
});
|
||||
|
||||
$(window).on('resize', function () {
|
||||
adjustFooter();
|
||||
})
|
||||
|
||||
function adjustFooter() {
|
||||
var footerBlockHeight = $('.main-footer').outerHeight();
|
||||
contentInner.css('padding-bottom', footerBlockHeight + 'px');
|
||||
}
|
||||
|
||||
// ------------------------------------------------------- //
|
||||
// External links to new window
|
||||
// ------------------------------------------------------ //
|
||||
$('.external').on('click', function (e) {
|
||||
|
||||
e.preventDefault();
|
||||
window.open($(this).attr("href"));
|
||||
});
|
||||
|
||||
// ------------------------------------------------------ //
|
||||
// For demo purposes, can be deleted
|
||||
// ------------------------------------------------------ //
|
||||
|
||||
var stylesheet = $('link#theme-stylesheet');
|
||||
$("<link id='new-stylesheet' rel='stylesheet'>").insertAfter(stylesheet);
|
||||
var alternateColour = $('link#new-stylesheet');
|
||||
|
||||
if ($.cookie("theme_csspath")) {
|
||||
alternateColour.attr("href", $.cookie("theme_csspath"));
|
||||
}
|
||||
|
||||
$("#colour").change(function () {
|
||||
|
||||
if ($(this).val() !== '') {
|
||||
|
||||
var theme_csspath = 'css/style.' + $(this).val() + '.css';
|
||||
|
||||
alternateColour.attr("href", theme_csspath);
|
||||
|
||||
$.cookie("theme_csspath", theme_csspath, {
|
||||
expires: 365,
|
||||
path: document.URL.substr(0, document.URL.lastIndexOf('/'))
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Simplified Chinese translation for bootstrap-datetimepicker
|
||||
* Yuan Cheung <advanimal@gmail.com>
|
||||
*/
|
||||
;(function($){
|
||||
$.fn.datetimepicker.dates['zh-CN'] = {
|
||||
days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
|
||||
daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
|
||||
daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"],
|
||||
months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
||||
monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
||||
today: "今天",
|
||||
suffix: [],
|
||||
meridiem: ["上午", "下午"]
|
||||
};
|
||||
}(jQuery));
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,10 @@
|
||||
#版本1.0.0为gitee开源版本修改了数据库为本地数据库之后的版本
|
||||
功能:每日健康打开、历史打卡记录、健康周报、登陆注册、头像上传、修改资料和修改密码等。
|
||||
|
||||
#版本1.0.1修复了时间组件显示乱码问题
|
||||
|
||||
#版本1.0.2修复了头像未上传成功的问题
|
||||
|
||||
#版本2.0.2增加了默认头像,增加了邮箱认证功能,增加了近期推送功能
|
||||
|
||||
#版本2.0.3修复了近期推送邮箱未绑定没有提示的问题
|
Loading…
Reference in new issue