Commit 11d480f6 by tangyi

优化登录

parent b24c210c
...@@ -21,4 +21,4 @@ intellij/ ...@@ -21,4 +21,4 @@ intellij/
atlassian-ide-plugin.xml atlassian-ide-plugin.xml
!etc/eclipse/.checkstyle !etc/eclipse/.checkstyle
.checkstyle .checkstyle
docs/deploy/dev.env .dev.env
\ No newline at end of file \ No newline at end of file
...@@ -96,6 +96,11 @@ public class ApiMsg { ...@@ -96,6 +96,11 @@ public class ApiMsg {
public static final int KEY_ACCESS = 404; public static final int KEY_ACCESS = 404;
/** /**
* 认证
*/
public static final int KEY_AUTHENTICATION = 405;
/**
* code和提示内容的对应关系 * code和提示内容的对应关系
*/ */
private static final Map<Integer, String> CODE_MAP = new HashMap<>(); private static final Map<Integer, String> CODE_MAP = new HashMap<>();
......
package com.github.tangyi.common.security.config; package com.github.tangyi.common.security.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tangyi.common.security.handler.CustomAccessDeniedHandler;
import com.github.tangyi.common.security.mobile.MobileSecurityConfigurer; import com.github.tangyi.common.security.mobile.MobileSecurityConfigurer;
import com.github.tangyi.common.security.properties.FilterIgnorePropertiesConfig; import com.github.tangyi.common.security.properties.FilterIgnorePropertiesConfig;
import com.github.tangyi.common.security.wx.WxSecurityConfigurer; import com.github.tangyi.common.security.wx.WxSecurityConfigurer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
import org.springframework.security.web.access.AccessDeniedHandler;
/** /**
* 资源服务器配置 * 资源服务器配置
...@@ -38,16 +43,23 @@ public class CustomResourceServerConfig extends ResourceServerConfigurerAdapter ...@@ -38,16 +43,23 @@ public class CustomResourceServerConfig extends ResourceServerConfigurerAdapter
*/ */
private final WxSecurityConfigurer wxSecurityConfigurer; private final WxSecurityConfigurer wxSecurityConfigurer;
private final ObjectMapper objectMapper;
@Autowired @Autowired
public CustomResourceServerConfig(FilterIgnorePropertiesConfig filterIgnorePropertiesConfig, MobileSecurityConfigurer mobileSecurityConfigurer, WxSecurityConfigurer wxSecurityConfigurer) { public CustomResourceServerConfig(FilterIgnorePropertiesConfig filterIgnorePropertiesConfig,
MobileSecurityConfigurer mobileSecurityConfigurer,
WxSecurityConfigurer wxSecurityConfigurer,
ObjectMapper objectMapper) {
this.filterIgnorePropertiesConfig = filterIgnorePropertiesConfig; this.filterIgnorePropertiesConfig = filterIgnorePropertiesConfig;
this.mobileSecurityConfigurer = mobileSecurityConfigurer; this.mobileSecurityConfigurer = mobileSecurityConfigurer;
this.wxSecurityConfigurer = wxSecurityConfigurer; this.wxSecurityConfigurer = wxSecurityConfigurer;
this.objectMapper = objectMapper;
} }
@Override @Override
public void configure(ResourceServerSecurityConfigurer resources) { public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID).stateless(false); resources.resourceId(RESOURCE_ID).stateless(false);
resources.accessDeniedHandler(accessDeniedHandler());
} }
@Override @Override
...@@ -65,4 +77,10 @@ public class CustomResourceServerConfig extends ResourceServerConfigurerAdapter ...@@ -65,4 +77,10 @@ public class CustomResourceServerConfig extends ResourceServerConfigurerAdapter
// 微信登录 // 微信登录
http.apply(wxSecurityConfigurer); http.apply(wxSecurityConfigurer);
} }
@Bean
@ConditionalOnMissingBean(AccessDeniedHandler.class)
public AccessDeniedHandler accessDeniedHandler() {
return new CustomAccessDeniedHandler(objectMapper);
}
} }
package com.github.tangyi.common.security.exception;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.github.tangyi.common.security.serializer.CustomOauthExceptionSerializer;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
/**
* 自定义OauthException
*
* @author tangyi
* @date 2020/2/29 14:12
*/
@JsonSerialize(using = CustomOauthExceptionSerializer.class)
public class CustomOauthException extends OAuth2Exception {
public CustomOauthException(String msg) {
super(msg);
}
}
package com.github.tangyi.common.security.handler;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* 自定义AccessDeniedHandler
*
* @author tangyi
* @date 2020-02-29 15:39
*/
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
private final ObjectMapper objectMapper;
public CustomAccessDeniedHandler(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
response.setContentType("application/json;charset=UTF-8");
Map<String, Object> map = new HashMap<>();
map.put("code", 400);
map.put("msg", e.getMessage());
map.put("data", e.getMessage());
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write(objectMapper.writeValueAsString(map));
}
}
package com.github.tangyi.common.security.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.github.tangyi.common.security.exception.CustomOauthException;
import java.io.IOException;
import java.util.Map;
/**
* 自定义OauthException Serializer,定制异常返回结果
*
* @author tangyi
* @date 2020/2/29 14:12
*/
public class CustomOauthExceptionSerializer extends StdSerializer<CustomOauthException> {
public CustomOauthExceptionSerializer() {
super(CustomOauthException.class);
}
@Override
public void serialize(CustomOauthException e, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeNumberField("code", e.getHttpErrorCode());
jsonGenerator.writeStringField("msg", e.getMessage());
jsonGenerator.writeObjectField("data", e.getOAuth2ErrorCode());
if (e.getAdditionalInformation() != null) {
for (Map.Entry<String, String> entry : e.getAdditionalInformation().entrySet()) {
jsonGenerator.writeStringField(entry.getKey(), entry.getValue());
}
}
jsonGenerator.writeEndObject();
}
}
...@@ -91,12 +91,11 @@ ignore: ...@@ -91,12 +91,11 @@ ignore:
- /actuator/** - /actuator/**
- /hystrix.sender - /hystrix.sender
- /v1/sms/** - /v1/sms/**
- /v1/user/findUserByIdentifier/** - /v1/user/anonymousUser/**
- /v1/tenant/findTenantByTenantCode/** - /v1/tenant/anonymousUser/**
- /v1/user/checkExist/** - /v1/user/checkExist/**
- /v1/user/updatePassword - /v1/user/updatePassword
- /v1/menu/findMenuByRole/** - /v1/menu/anonymousUser/**
- /v1/menu/findAllMenu
- /v1/code/** - /v1/code/**
- /v1/attachment/download - /v1/attachment/download
- /v1/log/** - /v1/log/**
......
...@@ -119,12 +119,9 @@ ignore: ...@@ -119,12 +119,9 @@ ignore:
- /actuator/** - /actuator/**
- /hystrix.sender - /hystrix.sender
- /v1/sms/** - /v1/sms/**
- /v1/user/findUserByIdentifier/** - /v1/user/anonymousUser/**
- /v1/tenant/findTenantByTenantCode/** - /v1/tenant/anonymousUser/**
- /v1/menu/findMenuByRole/** - /v1/menu/anonymousUser/**
- /v1/menu/findAllMenu
- /v1/user/checkExist/**
- /v1/user/updatePassword
- /v1/code/** - /v1/code/**
- /v1/attachment/download - /v1/attachment/download
- /v1/log/** - /v1/log/**
......
...@@ -110,8 +110,7 @@ swagger: ...@@ -110,8 +110,7 @@ swagger:
preview: preview:
ignores: ignores:
- api/auth # 授权服务 - api/auth # 授权服务
- register - anonymousUser
- checkExist
- updateInfo - updateInfo
- updateAvatar - updateAvatar
- attachment - attachment
......
...@@ -153,13 +153,9 @@ ignore: ...@@ -153,13 +153,9 @@ ignore:
- /hystrix.sender - /hystrix.sender
- /v1/sms/** - /v1/sms/**
- /v1/mobile/** - /v1/mobile/**
- /v1/user/findUserByIdentifier/** - /v1/user/anonymousUser/**
- /v1/tenant/findTenantByTenantCode/** - /v1/tenant/anonymousUser/**
- /v1/menu/findMenuByRole/** - /v1/menu/anonymousUser/**
- /v1/menu/findAllMenu
- /v1/user/register
- /v1/user/checkExist/**
- /v1/user/updatePassword
- /v1/code/** - /v1/code/**
- /v1/attachment/download - /v1/attachment/download
- /v1/log/** - /v1/log/**
......
/*
Navicat Premium Data Transfer
Source Server : 腾讯云-上海
Source Server Type : MySQL
Source Server Version : 50644
Source Host : 118.25.138.130:3306
Source Schema : dev_microservice_user
Target Server Type : MySQL
Target Server Version : 50644
File Encoding : 65001
Date: 23/02/2020 16:29:29
*/
SET NAMES utf8mb4; SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; SET FOREIGN_KEY_CHECKS = 0;
......
docs/images/image_web_record.png

196 KB | W: | H:

docs/images/image_web_record.png

131 KB | W: | H:

docs/images/image_web_record.png
docs/images/image_web_record.png
docs/images/image_web_record.png
docs/images/image_web_record.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -50,7 +50,7 @@ export function updateObjInfo (obj) { ...@@ -50,7 +50,7 @@ export function updateObjInfo (obj) {
export function updatePassword (obj) { export function updatePassword (obj) {
return request({ return request({
url: baseUserUrl + 'updatePassword', url: baseUserUrl + 'anonymousUser/updatePassword',
method: 'put', method: 'put',
data: obj data: obj
}) })
...@@ -86,7 +86,7 @@ export function exportObj (obj) { ...@@ -86,7 +86,7 @@ export function exportObj (obj) {
// 重置密码 // 重置密码
export function resetPassword (obj) { export function resetPassword (obj) {
return request({ return request({
url: baseUserUrl + 'resetPassword', url: baseUserUrl + 'anonymousUser/resetPassword',
method: 'put', method: 'put',
data: obj data: obj
}) })
......
...@@ -5,5 +5,8 @@ export default { ...@@ -5,5 +5,8 @@ export default {
'403': '当前操作没有权限', '403': '当前操作没有权限',
'400': '用户名不存在或密码错误', '400': '用户名不存在或密码错误',
'500': '服务器内部错误,请反馈给管理员', '500': '服务器内部错误,请反馈给管理员',
'4015': '服务不可用',
'4020': '验证码错误',
'4026': '验证码已过期,请重新获取',
'default': '系统未知错误,请反馈给管理员' 'default': '系统未知错误,请反馈给管理员'
} }
...@@ -13,7 +13,7 @@ function hasPermission (roles, permissionRoles) { ...@@ -13,7 +13,7 @@ function hasPermission (roles, permissionRoles) {
return roles.some(role => permissionRoles.indexOf(role) >= 0) return roles.some(role => permissionRoles.indexOf(role) >= 0)
} }
const whiteList = ['/login', '/auth-redirect', '/404', '/401', '/lock']// no redirect whitelist const whiteList = ['/login', '/auth-redirect', '/404', '/401', '/500', '/lock']// no redirect whitelist
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
NProgress.start() // start progress bar NProgress.start() // start progress bar
......
import axios from 'axios' import axios from 'axios'
import store from '../store' import store from '../store'
import router from './index'
import { getToken, setToken, getRefreshToken, getTenantCode } from '@/utils/auth' import { getToken, setToken, getRefreshToken, getTenantCode } from '@/utils/auth'
import { isNotEmpty, isSuccess } from '@/utils/util' import { isNotEmpty, isSuccess } from '@/utils/util'
import { refreshToken } from '@/api/admin/login' import { refreshToken } from '@/api/admin/login'
...@@ -39,7 +40,9 @@ axios.interceptors.response.use(data => { ...@@ -39,7 +40,9 @@ axios.interceptors.response.use(data => {
NProgress.done() NProgress.done()
// 请求失败,弹出提示信息 // 请求失败,弹出提示信息
if (!isSuccess(data.data)) { if (!isSuccess(data.data)) {
Message({ message: data.data.msg, type: 'error' }) const { code, msg } = data.data
const errMsg = errorCode[String(code)] || msg || errorCode['default']
Message({ message: errMsg, type: 'error' })
} }
return data return data
}, error => { }, error => {
...@@ -67,11 +70,22 @@ axios.interceptors.response.use(data => { ...@@ -67,11 +70,22 @@ axios.interceptors.response.use(data => {
}) })
} else if (error.response.status === 423) { } else if (error.response.status === 423) {
Message({ message: '演示环境不能操作', type: 'warning' }) Message({ message: '演示环境不能操作', type: 'warning' })
} else if (error.response.status === 404) {
// 跳转到404页面
router.replace({
path: '404',
query: { redirect: router.currentRoute.fullPath }
})
} else if (error.response.status === 500) {
// 500提示页面
router.replace({
path: '500',
query: { redirect: router.currentRoute.fullPath }
})
} else { } else {
// 其它错误则弹出提示 // 其它错误则弹出提示
const { code, data } = error.response.data const { code, msg } = error.response.data
const errMsg = data || errorCode[code] || errorCode['default'] const errMsg = errorCode[String(code)] || msg || errorCode['default']
// TODO 跳转到对应的404、500提示页面
Message({ message: errMsg, type: 'error' }) Message({ message: errMsg, type: 'error' })
} }
} }
......
...@@ -47,6 +47,19 @@ export const constantRouterMap = [ ...@@ -47,6 +47,19 @@ export const constantRouterMap = [
hidden: true hidden: true
}, },
{ {
path: '/500',
component: Layout,
children: [
{
path: '',
component: () => import('@/views/errorPage/500'),
name: '500',
title: '500'
}
],
hidden: true
},
{
path: '/404', path: '/404',
component: Layout, component: Layout,
children: [ children: [
......
<template>
<div class="wscn-http500-container">
<div class="wscn-http500">
<div class="bullshit">
<div class="bullshit__oops">500</div>
<div class="bullshit__headline">{{ message }}</div>
<div class="bullshit__info">服务器内部错误,请联系管理员</div>
<a href="" class="bullshit__return-home">返回首页</a>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Page500',
computed: {
message () {
return '服务器内部错误......'
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.wscn-http500-container{
transform: translate(-50%,-50%);
position: absolute;
top: 40%;
left: 50%;
}
.wscn-http500 {
position: relative;
width: 1200px;
padding: 0 50px;
overflow: hidden;
.pic-500 {
position: relative;
float: left;
width: 600px;
overflow: hidden;
&__parent {
width: 100%;
}
&__child {
position: absolute;
&.left {
width: 80px;
top: 17px;
left: 220px;
opacity: 0;
animation-name: cloudLeft;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
}
&.mid {
width: 46px;
top: 10px;
left: 420px;
opacity: 0;
animation-name: cloudMid;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1.2s;
}
&.right {
width: 62px;
top: 100px;
left: 500px;
opacity: 0;
animation-name: cloudRight;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
}
@keyframes cloudLeft {
0% {
top: 17px;
left: 220px;
opacity: 0;
}
20% {
top: 33px;
left: 188px;
opacity: 1;
}
80% {
top: 81px;
left: 92px;
opacity: 1;
}
100% {
top: 97px;
left: 60px;
opacity: 0;
}
}
@keyframes cloudMid {
0% {
top: 10px;
left: 420px;
opacity: 0;
}
20% {
top: 40px;
left: 360px;
opacity: 1;
}
70% {
top: 130px;
left: 180px;
opacity: 1;
}
100% {
top: 160px;
left: 120px;
opacity: 0;
}
}
@keyframes cloudRight {
0% {
top: 100px;
left: 500px;
opacity: 0;
}
20% {
top: 120px;
left: 460px;
opacity: 1;
}
80% {
top: 180px;
left: 340px;
opacity: 1;
}
100% {
top: 200px;
left: 300px;
opacity: 0;
}
}
}
}
.bullshit {
position: relative;
float: left;
width: 300px;
padding: 30px 0;
overflow: hidden;
&__oops {
font-size: 32px;
font-weight: bold;
line-height: 40px;
color: #1482f0;
opacity: 0;
margin-bottom: 20px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
&__headline {
font-size: 20px;
line-height: 24px;
color: #222;
font-weight: bold;
opacity: 0;
margin-bottom: 10px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.1s;
animation-fill-mode: forwards;
}
&__info {
font-size: 13px;
line-height: 21px;
color: grey;
opacity: 0;
margin-bottom: 30px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.2s;
animation-fill-mode: forwards;
}
&__return-home {
display: block;
float: left;
width: 110px;
height: 36px;
background: #1482f0;
border-radius: 100px;
text-align: center;
color: #ffffff;
opacity: 0;
font-size: 14px;
line-height: 36px;
cursor: pointer;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.3s;
animation-fill-mode: forwards;
}
@keyframes slideUp {
0% {
transform: translateY(60px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
}
}
</style>
...@@ -30,12 +30,12 @@ ...@@ -30,12 +30,12 @@
<span>{{ scope.row.score }}</span> <span>{{ scope.row.score }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.subject.modifyDate')" property="updateTime" width="150"> <el-table-column :label="$t('table.modifyDate')" property="updateTime" width="150">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.modifyDate | fmtDate('yyyy-MM-dd hh:mm') }}</span> <span>{{ scope.row.modifyDate | fmtDate('yyyy-MM-dd hh:mm') }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.subject.modifier')" property="modifier" width="120"> <el-table-column :label="$t('table.modifier')" property="modifier" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.modifier }}</span> <span>{{ scope.row.modifier }}</span>
</template> </template>
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
<span>{{ scope.row.loginTime | fmtDate('yyyy-MM-dd hh:mm') }}</span> <span>{{ scope.row.loginTime | fmtDate('yyyy-MM-dd hh:mm') }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.actions')" class-name="status-col"> <el-table-column :label="$t('table.actions')" class-name="status-col" width="300">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-if="user_btn_edit" type="primary" size="mini" @click="handleUpdate(scope.row)">{{ $t('table.edit') }}</el-button> <el-button v-if="user_btn_edit" type="primary" size="mini" @click="handleUpdate(scope.row)">{{ $t('table.edit') }}</el-button>
<el-button v-if="user_btn_edit" type="warning" size="mini" @click="handleResetPassword(scope.row)">{{ $t('table.resetPassword') }}</el-button> <el-button v-if="user_btn_edit" type="warning" size="mini" @click="handleResetPassword(scope.row)">{{ $t('table.resetPassword') }}</el-button>
......
...@@ -38,7 +38,7 @@ export function loginBySocial (social, code) { ...@@ -38,7 +38,7 @@ export function loginBySocial (social, code) {
export function registerByUsername (identifier, email, credential, code, randomStr) { export function registerByUsername (identifier, email, credential, code, randomStr) {
return request({ return request({
url: '/api/user/v1/user/register', url: '/api/user/v1/user/anonymousUser/register',
method: 'post', method: 'post',
params: {identifier, email, credential, randomStr, code}, params: {identifier, email, credential, randomStr, code},
data: {identifier, email, credential} data: {identifier, email, credential}
......
...@@ -50,7 +50,7 @@ export function updateObjInfo (obj) { ...@@ -50,7 +50,7 @@ export function updateObjInfo (obj) {
export function updatePassword (obj) { export function updatePassword (obj) {
return request({ return request({
url: baseUserUrl + 'updatePassword', url: baseUserUrl + 'anonymousUser/updatePassword',
method: 'put', method: 'put',
data: obj data: obj
}) })
...@@ -74,7 +74,7 @@ export function delAllObj (obj) { ...@@ -74,7 +74,7 @@ export function delAllObj (obj) {
export function checkExist (username, tenantCode) { export function checkExist (username, tenantCode) {
return request({ return request({
url: baseUserUrl + 'checkExist/' + username, url: baseUserUrl + 'anonymousUser/checkExist/' + username,
method: 'get', method: 'get',
params: { tenantCode, identityType: 1 } params: { tenantCode, identityType: 1 }
}) })
......
...@@ -40,3 +40,11 @@ export function getCurrentTime () { ...@@ -40,3 +40,11 @@ export function getCurrentTime () {
method: 'get' method: 'get'
}) })
} }
// 查询成绩详情
export function examRecordDetails (id) {
return request({
url: baseExamRecordUrl + id + '/details',
method: 'get'
})
}
...@@ -5,5 +5,8 @@ export default { ...@@ -5,5 +5,8 @@ export default {
'403': '当前操作没有权限', '403': '当前操作没有权限',
'400': '用户名不存在或密码错误', '400': '用户名不存在或密码错误',
'500': '服务器内部错误,请反馈给管理员', '500': '服务器内部错误,请反馈给管理员',
'4015': '服务不可用',
'4020': '验证码错误',
'4026': '验证码已过期,请重新获取',
'default': '系统未知错误,请反馈给管理员' 'default': '系统未知错误,请反馈给管理员'
} }
import { formatDate, commonFilter, isNotEmpty } from '../utils/util'
import { statusType, examType, subjectType, subjectTypeTag } from '../utils/constant'
/**
* 日期格式化
* @param date
* @param format
* @returns {*}
*/
export function fmtDate (date, format) {
if (!isNotEmpty(date)) {
return ''
}
return formatDate(new Date(date), format)
}
/**
* 通用状态
* @param status
* @returns {*}
*/
export function statusTypeFilter (status) {
return statusType[status]
}
/**
* 截取指定长度
* @param str
* @param length
* @returns {string}
*/
export function simpleStrFilter (str, length) {
if (length === undefined) {
length = 20
}
return commonFilter(str, length)
}
/**
* 考试类型
* @param type
* @returns {*}
*/
export function examTypeFilter (type) {
return examType[type]
}
/**
* 发布类型
* @param status
* @returns {string}
*/
export function publicStatusFilter (status) {
return parseInt(status) === 0 ? '已发布' : '草稿'
}
/**
* 题目类型
* @param type
* @returns {*}
*/
export function subjectTypeFilter (type) {
return subjectType[type]
}
/**
* 题目标签
* @param type
* @returns {*}
*/
export function subjectTypeTagFilter (type) {
return subjectTypeTag[type]
}
/**
* 考试提交状态
* @param type
* @returns {*}
*/
export function submitStatusFilter (type) {
const typeMap = {
0: '待批改',
1: '已批改',
2: '待批改',
3: '统计完成'
}
return typeMap[type]
}
/**
* success状态
* @param status, 自动传入
* @param expectStatus
* @returns {string}
*/
export function simpleTagStatusFilter (status, expectStatus) {
return status === expectStatus ? 'success' : 'warning'
}
...@@ -8,11 +8,16 @@ import store from './store' ...@@ -8,11 +8,16 @@ import store from './store'
import './permission' // 权限控制 import './permission' // 权限控制
import 'element-ui/lib/theme-chalk/index.css' import 'element-ui/lib/theme-chalk/index.css'
import './icons' // icon import './icons' // icon
import * as filters from './filters' // global filters
Vue.config.productionTip = false Vue.config.productionTip = false
Vue.use(ElementUI) Vue.use(ElementUI)
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
})
/* eslint-disable no-new */ /* eslint-disable no-new */
new Vue({ new Vue({
el: '#app', el: '#app',
......
import axios from 'axios' import axios from 'axios'
import store from '../store' import store from '../store'
import router from './index'
import { getToken, setToken, getRefreshToken, getTenantCode } from '@/utils/auth' import { getToken, setToken, getRefreshToken, getTenantCode } from '@/utils/auth'
import { isNotEmpty, isSuccess } from '@/utils/util' import { isNotEmpty, isSuccess } from '@/utils/util'
import { refreshToken } from '@/api/admin/login' import { refreshToken } from '@/api/admin/login'
...@@ -39,7 +40,9 @@ axios.interceptors.response.use(data => { ...@@ -39,7 +40,9 @@ axios.interceptors.response.use(data => {
NProgress.done() NProgress.done()
// 请求失败,弹出提示信息 // 请求失败,弹出提示信息
if (!isSuccess(data.data)) { if (!isSuccess(data.data)) {
Message({ message: data.data.msg, type: 'error' }) const { code, msg } = data.data
const errMsg = errorCode[String(code)] || msg || errorCode['default']
Message({ message: errMsg, type: 'error' })
} }
return data return data
}, error => { }, error => {
...@@ -67,11 +70,16 @@ axios.interceptors.response.use(data => { ...@@ -67,11 +70,16 @@ axios.interceptors.response.use(data => {
}) })
} else if (error.response.status === 423) { } else if (error.response.status === 423) {
Message({ message: '演示环境不能操作', type: 'warning' }) Message({ message: '演示环境不能操作', type: 'warning' })
} else if (error.response.status === 404) {
// 跳转到404页面
router.replace({
path: '404',
query: { redirect: router.currentRoute.fullPath }
})
} else { } else {
// 其它错误则弹出提示 // 其它错误则弹出提示
const { code, data } = error.response.data const { code, msg } = error.response.data
const errMsg = data || errorCode[code] || errorCode['default'] const errMsg = errorCode[String(code)] || msg || errorCode['default']
// TODO 跳转到对应的404、500提示页面
Message({ message: errMsg, type: 'error' }) Message({ message: errMsg, type: 'error' })
} }
} }
......
export const dialogStatusConstant = {
create: 'create',
update: 'update'
}
export const statusType = {
0: 'success',
1: 'warning'
}
// 考试类型
export const examType = {
0: '正式考试',
1: '模拟考试',
2: '在线练习'
}
// 题目类型
export const subjectType = {
0: '单选题',
2: '判断题',
1: '简答题',
3: '多选题'
}
export const subjectTypeTag = {
0: 'success',
1: 'info',
2: 'warning',
3: 'default'
}
...@@ -284,3 +284,27 @@ export const cropStr = (str, len) => { ...@@ -284,3 +284,27 @@ export const cropStr = (str, len) => {
} }
return result return result
} }
/**
* 截取指定长度
* @param str
* @param length
* @returns {string}
*/
export const commonFilter = (str, length) => {
if (str.length > length) {
return str.substring(0, length) + '...'
}
return str
}
/**
* 新建状态
*/
export const isCreate = (status) => {
return status === 'create'
}
export const trimComma = (str) => {
return str.replace(new RegExp('^,*|,*$', 'gm'), '')
}
...@@ -17,22 +17,17 @@ ...@@ -17,22 +17,17 @@
</el-table-column> </el-table-column>
<el-table-column label="考试类型" min-width="90" align="center"> <el-table-column label="考试类型" min-width="90" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.type | typeFilter }}</span> <span>{{ scope.row.type | examTypeFilter }}</span>
</template>
</el-table-column>
<el-table-column label="所属课程" min-width="90" align="center">
<template slot-scope="scope">
<span>{{ scope.row.type | typeFilter }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="考试时间" sortable prop="start_time" min-width="90" align="center"> <el-table-column label="考试时间" sortable prop="start_time" min-width="90" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.startTime | timeFilter }}</span> <span>{{ scope.row.startTime | fmtDate('yyyy-MM-dd hh:mm') }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="状态" min-width="90" align="center"> <el-table-column label="状态" min-width="90" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.submitStatus | submitStatusTypeFilter">{{ scope.row.submitStatus | submitStatusFilter }}</el-tag> <el-tag :type="scope.row.submitStatus | simpleTagStatusFilter(3)">{{ scope.row.submitStatus | submitStatusFilter }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="成绩" sortable prop="score" align="center" width="120px"> <el-table-column label="成绩" sortable prop="score" align="center" width="120px">
...@@ -43,7 +38,6 @@ ...@@ -43,7 +38,6 @@
<el-table-column label="操作" align="center"> <el-table-column label="操作" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="success" size="mini" @click="handleDetail(scope.row)" :disabled="scope.row.submitStatus !== 3">成绩详情</el-button> <el-button type="success" size="mini" @click="handleDetail(scope.row)" :disabled="scope.row.submitStatus !== 3">成绩详情</el-button>
<el-button type="danger" size="mini" @click="incorrectAnswer(scope.row)" :disabled="scope.row.submitStatus !== 3">查看错题</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -52,73 +46,19 @@ ...@@ -52,73 +46,19 @@
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<!-- 成绩详情 -->
<el-dialog :visible.sync="dialogDetailVisible" title="成绩详情">
<el-row>
<el-col :span="24">
<div slot="header" class="score-gray-box-title">
<span>考试成绩</span>
</div>
<div class="score">
<h4>成绩: <span type="success">{{ tempScore.score }}</span></h4>
<h4>正确题数: <span type="success">{{ tempScore.correctNumber }}</span></h4>
<h4>错误题数: <span type="success">{{ tempScore.inCorrectNumber }}</span></h4>
<h4>开始时间: <span type="success">{{ tempScore.startTime | timeFilter }}</span></h4>
<h4>结束时间: <span type="success">{{ tempScore.endTime | timeFilter }}</span></h4>
</div>
</el-col>
</el-row>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from 'vuex' import { mapState } from 'vuex'
import { fetchList } from '@/api/exam/examRecord' import { fetchList } from '@/api/exam/examRecord'
import store from '@/store' import store from '@/store'
import { formatDate, cropStr } from '@/utils/util'
export default { export default {
filters: {
typeFilter (type) {
const typeMap = {
0: '正式考试',
1: '模拟考试',
2: '在线练习'
}
return typeMap[type]
},
submitStatusFilter (type) {
const typeMap = {
0: '未提交',
1: '已提交',
2: '待批改',
3: '批改完成'
}
return typeMap[type]
},
submitStatusTypeFilter (status) {
const statusMap = {
0: 'warning',
1: 'warning',
2: 'warning',
3: 'success'
}
return statusMap[status]
},
timeFilter (time) {
return formatDate(new Date(time), 'yyyy-MM-dd hh:mm')
},
examinationNameFilter (name) {
return cropStr(name, 8)
}
},
data () { data () {
return { return {
examRecodeList: [], examRecodeList: [],
total: 0, total: 0,
listLoading: true, listLoading: true,
dialogDetailVisible: false,
tableKey: 0, tableKey: 0,
listQuery: { listQuery: {
pageNum: 1, pageNum: 1,
...@@ -172,11 +112,6 @@ export default { ...@@ -172,11 +112,6 @@ export default {
}, },
// 查看成绩详情 // 查看成绩详情
handleDetail (row) { handleDetail (row) {
this.tempScore = row
this.dialogDetailVisible = true
},
// 查看错题
incorrectAnswer (row) {
store.dispatch('SetIncorrectRecord', { id: row.id }).then(() => { store.dispatch('SetIncorrectRecord', { id: row.id }).then(() => {
this.$router.push({ name: 'incorrect' }) this.$router.push({ name: 'incorrect' })
}).catch((error) => { }).catch((error) => {
......
<template> <template>
<div class="app-container"> <div class="app-container">
<el-row> <el-card>
<el-col :span="20" :offset="2"> <spinner-loading v-if="listLoading"/>
<div class="subject-content" v-for="(tempIncorrectAnswer, index) in list" :key="tempIncorrectAnswer.id"> <el-row>
<div class="subject-content-option"> <el-col :span="20" :offset="2">
<div class="subject-title"> <el-divider>成绩详情</el-divider>
<span class="subject-title-number">{{index + 1}} .</span> </el-col>
{{tempIncorrectAnswer.subject.subjectName}}{{tempIncorrectAnswer.subject.score}}分) </el-row>
<el-row>
<el-col :span="20" :offset="2">
<el-row>
<el-col :span="8">
<label class="el-form-item__label">考试名称: {{ examRecordDetail.examinationName }}</label>
</el-col>
<el-col :span="8">
<label class="el-form-item__label">考生姓名: {{ examRecordDetail.userName }}</label>
</el-col>
<el-col :span="8">
<label class="el-form-item__label">总得分: {{ examRecordDetail.score }}</label>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<label class="el-form-item__label">开始时间: {{ examRecordDetail.startTime | fmtDate('yyyy-MM-dd hh:mm') }}</label>
</el-col>
<el-col :span="8">
<label class="el-form-item__label">结束时间: {{ examRecordDetail.endTime | fmtDate('yyyy-MM-dd hh:mm') }}</label>
</el-col>
<el-col :span="8">
<label class="el-form-item__label">耗时: {{ examRecordDetail.duration }}</label>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<label class="el-form-item__label">评卷人: 系统自动评分</label>
</el-col>
<el-col :span="8">
<label class="el-form-item__label">正确题数: </label><el-tag type="success" size="small" effect="dark">{{ examRecordDetail.correctNumber }}</el-tag>
</el-col>
<el-col :span="8">
<label class="el-form-item__label">错误题数: </label><el-tag type="danger" size="small" effect="dark">{{ examRecordDetail.inCorrectNumber }}</el-tag>
</el-col>
</el-row>
</el-col>
</el-row>
<el-row>
<el-col :span="20" :offset="2">
<el-divider>错题列表</el-divider>
</el-col>
</el-row>
<el-row>
<el-col :span="20" :offset="2">
<div class="subject-content" v-for="(tempIncorrectAnswer, index) in list" :key="tempIncorrectAnswer.id">
<div class="subject-content-option">
<div class="subject-title">
<span class="subject-title-number">{{index + 1}} .</span>
{{tempIncorrectAnswer.subject.subjectName}}{{tempIncorrectAnswer.subject.score}}分)
</div>
<!-- 选择题 -->
<div>
<ul class="subject-options" v-for="option in tempIncorrectAnswer.subject.options" :key="option.id">
<li class="subject-option" :class="getClass(option.right)">
<label><span class="subject-option-prefix">{{ option.optionName }}&nbsp;</span><span v-html="option.optionContent" class="subject-option-prefix"></span></label>
</li>
</ul>
</div>
</div> </div>
<!-- 选择题 --> <!-- 简答题 -->
<div> <div v-if="tempIncorrectAnswer.subject.type === 1">
<ul class="subject-options" v-for="option in tempIncorrectAnswer.subject.options" :key="option.id"> <p>
<li class="subject-option" :class="getClass(option.right)"> <span v-html="tempIncorrectAnswer.subject.answer.answer"></span>
<label><span class="subject-option-prefix">{{ option.optionName }}&nbsp;</span><span v-html="option.optionContent" class="subject-option-prefix"></span></label> </p>
</li>
</ul>
</div> </div>
</div> <p class="subject-content-answer">
<!-- 简答题 --> 参考答案:{{tempIncorrectAnswer.subject.answer.answer}}
<div v-if="tempIncorrectAnswer.subject.type === 1"> </p>
<p> <p class="subject-content-analysis">
<span v-html="tempIncorrectAnswer.subject.answer"></span> 解析:{{tempIncorrectAnswer.subject.analysis}}
</p> </p>
</div> </div>
<p class="subject-content-answer"> <div class="pagination-container">
参考答案:{{tempIncorrectAnswer.subject.answer.answer}} <el-pagination v-show="total > 0" :current-page="listQuery.pageNum" :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" :total="total" background layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" @current-change="handleCurrentChange"/>
</p> </div>
<p class="subject-content-analysis"> </el-col>
解析:{{tempIncorrectAnswer.subject.analysis}} </el-row>
</p> </el-card>
</div>
<div class="pagination-container">
<el-pagination v-show="total > 0" :current-page="listQuery.pageNum" :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" :total="total" background layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" @current-change="handleCurrentChange"/>
</div>
</el-col>
</el-row>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from 'vuex' import { mapState } from 'vuex'
import { getAnswerListInfo } from '@/api/exam/answer' import { getAnswerListInfo } from '@/api/exam/answer'
import { examRecordDetails } from '@/api/exam/examRecord'
import { notifyFail } from '@/utils/util' import { notifyFail } from '@/utils/util'
import { answerType } from '@/const/constant' import { answerType } from '@/const/constant'
import SpinnerLoading from '@/components/SpinnerLoading'
export default { export default {
name: 'Incorrect',
components: {
SpinnerLoading
},
data () { data () {
return { return {
total: 0,
listLoading: true, listLoading: true,
total: 0,
tableKey: 0, tableKey: 0,
list: [], list: [],
listQuery: { listQuery: {
...@@ -56,6 +112,17 @@ export default { ...@@ -56,6 +112,17 @@ export default {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
answerType: 1 answerType: 1
},
examRecordDetail: {
correctNumber: 0,
endTime: 0,
duration: '',
examinationName: '',
inCorrectNumber: 0,
score: 0,
startTime: 0,
submitStatus: 0,
totalScore: 0
} }
} }
}, },
...@@ -67,16 +134,20 @@ export default { ...@@ -67,16 +134,20 @@ export default {
}) })
}, },
created () { created () {
this.getList() this.getRecordDetail()
}, },
methods: { methods: {
getList () { getRecordDetail () {
getAnswerListInfo(this.incorrectRecord.id, this.listQuery).then(response => { this.listLoading = true
this.list = response.data.list examRecordDetails(this.incorrectRecord.id).then(response => {
this.total = response.data.total this.examRecordDetail = response.data.data
this.listLoading = false getAnswerListInfo(this.incorrectRecord.id, this.listQuery).then(response => {
}).catch(() => { this.list = response.data.list
notifyFail(this, '加载错题失败') this.total = response.data.total
this.listLoading = false
}).catch(() => {
notifyFail(this, '加载错题失败')
})
}) })
}, },
handleSizeChange (val) { handleSizeChange (val) {
......
...@@ -2,17 +2,24 @@ package com.github.tangyi.auth.config; ...@@ -2,17 +2,24 @@ package com.github.tangyi.auth.config;
import com.github.tangyi.auth.security.CustomTokenConverter; import com.github.tangyi.auth.security.CustomTokenConverter;
import com.github.tangyi.common.security.core.ClientDetailsServiceImpl; import com.github.tangyi.common.security.core.ClientDetailsServiceImpl;
import com.github.tangyi.common.security.exception.CustomOauthException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.bootstrap.encrypt.KeyProperties; import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory; import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
...@@ -107,7 +114,9 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf ...@@ -107,7 +114,9 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
// 将token存储到redis // 将token存储到redis
.tokenStore(tokenStore()) .tokenStore(tokenStore())
// token增强 // token增强
.tokenEnhancer(jwtTokenEnhancer()); .tokenEnhancer(jwtTokenEnhancer())
// 异常转换
.exceptionTranslator(webResponseExceptionTranslator());
} }
/** /**
...@@ -125,5 +134,22 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf ...@@ -125,5 +134,22 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
.checkTokenAccess("isAuthenticated()") .checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients(); .allowFormAuthenticationForClients();
} }
@Bean
@Lazy
public WebResponseExceptionTranslator<OAuth2Exception> webResponseExceptionTranslator() {
return new DefaultWebResponseExceptionTranslator() {
@Override
public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
if (e instanceof OAuth2Exception) {
OAuth2Exception exception = (OAuth2Exception) e;
// 转换返回结果
return ResponseEntity.status(exception.getHttpErrorCode()).body(new CustomOauthException(e.getMessage()));
} else {
throw e;
}
}
};
}
} }
...@@ -64,6 +64,7 @@ public class LoginSuccessListener implements ApplicationListener<CustomAuthentic ...@@ -64,6 +64,7 @@ public class LoginSuccessListener implements ApplicationListener<CustomAuthentic
logInfo.setServiceId(ServiceConstant.AUTH_SERVICE); logInfo.setServiceId(ServiceConstant.AUTH_SERVICE);
// 记录日志和登录时间 // 记录日志和登录时间
UserDto userDto = new UserDto(); UserDto userDto = new UserDto();
userDto.setId(customUserDetails.getId());
userDto.setIdentifier(username); userDto.setIdentifier(username);
userDto.setLoginTime(DateUtils.asDate(LocalDateTime.now())); userDto.setLoginTime(DateUtils.asDate(LocalDateTime.now()));
saveLoginInfo(logInfo, userDto); saveLoginInfo(logInfo, userDto);
...@@ -82,7 +83,7 @@ public class LoginSuccessListener implements ApplicationListener<CustomAuthentic ...@@ -82,7 +83,7 @@ public class LoginSuccessListener implements ApplicationListener<CustomAuthentic
public void saveLoginInfo(Log logInfo, UserDto userDto) { public void saveLoginInfo(Log logInfo, UserDto userDto) {
try { try {
userServiceClient.saveLog(logInfo); userServiceClient.saveLog(logInfo);
//userServiceClient.updateUser(userDto); userServiceClient.updateLoginInfo(userDto);
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
} }
......
...@@ -24,6 +24,11 @@ public class CustomUserDetails extends User { ...@@ -24,6 +24,11 @@ public class CustomUserDetails extends User {
private String tenantCode; private String tenantCode;
/** /**
* id
*/
private Long id;
/**
* 开始授权时间 * 开始授权时间
*/ */
private long start; private long start;
...@@ -44,9 +49,10 @@ public class CustomUserDetails extends User { ...@@ -44,9 +49,10 @@ public class CustomUserDetails extends User {
* @param start start * @param start start
* @param loginType loginType * @param loginType loginType
*/ */
public CustomUserDetails(String username, String password, boolean enabled, Collection<? extends GrantedAuthority> authorities, String tenantCode, long start, LoginTypeEnum loginType) { public CustomUserDetails(String username, String password, boolean enabled, Collection<? extends GrantedAuthority> authorities, String tenantCode, Long id, long start, LoginTypeEnum loginType) {
super(username, password, enabled, true, true, true, authorities); super(username, password, enabled, true, true, true, authorities);
this.tenantCode = tenantCode; this.tenantCode = tenantCode;
this.id = id;
this.start = start; this.start = start;
this.loginType = loginType; this.loginType = loginType;
} }
......
...@@ -43,7 +43,7 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails ...@@ -43,7 +43,7 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
if (authentication.getCredentials() == null) { if (authentication.getCredentials() == null) {
log.debug("Authentication failed: password is blank"); log.debug("Authentication failed: password is blank");
throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "密码为空.")); throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "密码为空"));
} }
// 获取密码 // 获取密码
String presentedPassword = authentication.getCredentials().toString(); String presentedPassword = authentication.getCredentials().toString();
...@@ -51,7 +51,7 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails ...@@ -51,7 +51,7 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails
if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) { if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
log.debug("Authentication failed: invalid password"); log.debug("Authentication failed: invalid password");
publisher.publishEvent(new CustomAuthenticationFailureEvent(authentication, userDetails)); publisher.publishEvent(new CustomAuthenticationFailureEvent(authentication, userDetails));
throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "密码错误.")); throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "用户名或密码错误"));
} }
publisher.publishEvent(new CustomAuthenticationSuccessEvent(authentication, userDetails)); publisher.publishEvent(new CustomAuthenticationSuccessEvent(authentication, userDetails));
} }
...@@ -77,16 +77,14 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails ...@@ -77,16 +77,14 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails
try { try {
// 加载用户信息 // 加载用户信息
loadedUser = this.userDetailsService.loadUserByIdentifierAndTenantCode(TenantContextHolder.getTenantCode(), authentication.getPrincipal().toString()); loadedUser = this.userDetailsService.loadUserByIdentifierAndTenantCode(TenantContextHolder.getTenantCode(), authentication.getPrincipal().toString());
} catch (TenantNotFoundException tenantNotFound) {
throw new InternalAuthenticationServiceException(tenantNotFound.getMessage(), tenantNotFound);
} catch (UsernameNotFoundException notFound) { } catch (UsernameNotFoundException notFound) {
if (authentication.getCredentials() != null) { if (authentication.getCredentials() != null) {
String presentedPassword = authentication.getCredentials().toString(); String presentedPassword = authentication.getCredentials().toString();
passwordEncoder.matches(presentedPassword, userNotFoundEncodedPassword); passwordEncoder.matches(presentedPassword, userNotFoundEncodedPassword);
} }
throw notFound; throw notFound;
} catch (Exception repositoryProblem) { } catch (Exception tenantNotFound) {
throw new InternalAuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem); throw new InternalAuthenticationServiceException(tenantNotFound.getMessage(), tenantNotFound);
} }
if (loadedUser == null) { if (loadedUser == null) {
throw new InternalAuthenticationServiceException("get user information failed"); throw new InternalAuthenticationServiceException("get user information failed");
......
...@@ -63,7 +63,7 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService { ...@@ -63,7 +63,7 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
UserVo userVo = userVoResponseBean.getData(); UserVo userVo = userVoResponseBean.getData();
if (userVo == null) if (userVo == null)
throw new UsernameNotFoundException("user does not exist"); throw new UsernameNotFoundException("user does not exist");
return new CustomUserDetails(username, userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), start, LoginTypeEnum.PWD); return new CustomUserDetails(username, userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), userVo.getId(), start, LoginTypeEnum.PWD);
} }
/** /**
...@@ -103,7 +103,7 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService { ...@@ -103,7 +103,7 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
throw new ServiceException(GET_USER_INFO_FAIL + userVoResponseBean.getMsg()); throw new ServiceException(GET_USER_INFO_FAIL + userVoResponseBean.getMsg());
userVo = userVoResponseBean.getData(); userVo = userVoResponseBean.getData();
} }
return new CustomUserDetails(userVo.getIdentifier(), userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), start, LoginTypeEnum.SMS); return new CustomUserDetails(userVo.getIdentifier(), userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), userVo.getId(), start, LoginTypeEnum.SMS);
} }
/** /**
...@@ -149,7 +149,7 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService { ...@@ -149,7 +149,7 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
throw new ServiceException(GET_USER_INFO_FAIL + userVoResponseBean.getMsg()); throw new ServiceException(GET_USER_INFO_FAIL + userVoResponseBean.getMsg());
userVo = userVoResponseBean.getData(); userVo = userVoResponseBean.getData();
} }
return new CustomUserDetails(userVo.getIdentifier(), userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), start, LoginTypeEnum.WECHAT); return new CustomUserDetails(userVo.getIdentifier(), userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), userVo.getId(), start, LoginTypeEnum.WECHAT);
} }
/** /**
......
...@@ -6,6 +6,7 @@ import com.github.tangyi.exam.api.dto.SubjectDto; ...@@ -6,6 +6,7 @@ import com.github.tangyi.exam.api.dto.SubjectDto;
import com.github.tangyi.exam.api.module.Answer; import com.github.tangyi.exam.api.module.Answer;
import com.github.tangyi.exam.enums.SubjectTypeEnum; import com.github.tangyi.exam.enums.SubjectTypeEnum;
import com.github.tangyi.exam.handler.AbstractAnswerHandler; import com.github.tangyi.exam.handler.AbstractAnswerHandler;
import com.github.tangyi.exam.utils.AnswerHandlerUtil;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
...@@ -41,8 +42,8 @@ public class MultipleChoicesAnswerHandler extends AbstractAnswerHandler { ...@@ -41,8 +42,8 @@ public class MultipleChoicesAnswerHandler extends AbstractAnswerHandler {
String userAnswer = answer.getAnswer(); String userAnswer = answer.getAnswer();
String correctAnswer = subject.getAnswer().getAnswer(); String correctAnswer = subject.getAnswer().getAnswer();
if (StringUtils.isNotBlank(userAnswer) && StringUtils.isNotBlank(correctAnswer)) { if (StringUtils.isNotBlank(userAnswer) && StringUtils.isNotBlank(correctAnswer)) {
String[] userAnswers = userAnswer.split(CommonConstant.COMMA); String[] userAnswers = AnswerHandlerUtil.replaceComma(userAnswer).split(CommonConstant.COMMA);
String[] correctAnswers = correctAnswer.split(CommonConstant.COMMA); String[] correctAnswers = AnswerHandlerUtil.replaceComma(correctAnswer).split(CommonConstant.COMMA);
subject.getOptions().forEach(option -> { subject.getOptions().forEach(option -> {
if (ArrayUtils.contains(correctAnswers, option.getOptionName())) { if (ArrayUtils.contains(correctAnswers, option.getOptionName())) {
option.setRight(ArrayUtils.contains(userAnswers, option.getOptionName()) ? TRUE : FALSE); option.setRight(ArrayUtils.contains(userAnswers, option.getOptionName()) ? TRUE : FALSE);
...@@ -53,7 +54,7 @@ public class MultipleChoicesAnswerHandler extends AbstractAnswerHandler { ...@@ -53,7 +54,7 @@ public class MultipleChoicesAnswerHandler extends AbstractAnswerHandler {
@Override @Override
public boolean judgeRight(Answer answer, SubjectDto subject) { public boolean judgeRight(Answer answer, SubjectDto subject) {
String[] correctAnswers = subject.getAnswer().getAnswer().split(CommonConstant.COMMA); String[] correctAnswers = AnswerHandlerUtil.replaceComma(subject.getAnswer().getAnswer()).split(CommonConstant.COMMA);
for (String as : answer.getAnswer().split(CommonConstant.COMMA)) { for (String as : answer.getAnswer().split(CommonConstant.COMMA)) {
if (!ArrayUtils.contains(correctAnswers, as)) { if (!ArrayUtils.contains(correctAnswers, as)) {
return false; return false;
......
...@@ -35,7 +35,7 @@ public interface UserServiceClient { ...@@ -35,7 +35,7 @@ public interface UserServiceClient {
* @author tangyi * @author tangyi
* @date 2019/03/17 12:14 * @date 2019/03/17 12:14
*/ */
@GetMapping("/v1/user/findUserByIdentifier/{identifier}") @GetMapping("/v1/user/anonymousUser/findUserByIdentifier/{identifier}")
ResponseBean<UserVo> findUserByIdentifier(@PathVariable("identifier") String identifier, @RequestParam("tenantCode") String tenantCode); ResponseBean<UserVo> findUserByIdentifier(@PathVariable("identifier") String identifier, @RequestParam("tenantCode") String tenantCode);
/** /**
...@@ -48,7 +48,7 @@ public interface UserServiceClient { ...@@ -48,7 +48,7 @@ public interface UserServiceClient {
* @author tangyi * @author tangyi
* @date 2019/07/06 14:14:11 * @date 2019/07/06 14:14:11
*/ */
@GetMapping("/v1/user/findUserByIdentifier/{identifier}") @GetMapping("/v1/user/anonymousUser/findUserByIdentifier/{identifier}")
ResponseBean<UserVo> findUserByIdentifier(@PathVariable("identifier") String identifier, @RequestParam(value = "identityType", required = false) Integer identityType, @RequestParam("tenantCode") String tenantCode); ResponseBean<UserVo> findUserByIdentifier(@PathVariable("identifier") String identifier, @RequestParam(value = "identityType", required = false) Integer identityType, @RequestParam("tenantCode") String tenantCode);
...@@ -131,7 +131,7 @@ public interface UserServiceClient { ...@@ -131,7 +131,7 @@ public interface UserServiceClient {
* @author tangyi * @author tangyi
* @date 2019/04/08 20:42 * @date 2019/04/08 20:42
*/ */
@GetMapping("/v1/menu/findMenuByRole/{role}") @GetMapping("/v1/menu/anonymousUser/findMenuByRole/{role}")
ResponseBean<List<Menu>> findMenuByRole(@PathVariable("role") String role, @RequestParam("tenantCode") String tenantCode); ResponseBean<List<Menu>> findMenuByRole(@PathVariable("role") String role, @RequestParam("tenantCode") String tenantCode);
/** /**
...@@ -142,7 +142,7 @@ public interface UserServiceClient { ...@@ -142,7 +142,7 @@ public interface UserServiceClient {
* @author tangyi * @author tangyi
* @date 2019/04/26 11:48 * @date 2019/04/26 11:48
*/ */
@GetMapping("/v1/menu/findAllMenu") @GetMapping("/v1/menu/anonymousUser/findAllMenu")
ResponseBean<List<Menu>> findAllMenu(@RequestParam("tenantCode") String tenantCode); ResponseBean<List<Menu>> findAllMenu(@RequestParam("tenantCode") String tenantCode);
/** /**
...@@ -153,7 +153,7 @@ public interface UserServiceClient { ...@@ -153,7 +153,7 @@ public interface UserServiceClient {
* @author tangyi * @author tangyi
* @date 2019/05/26 10:21 * @date 2019/05/26 10:21
*/ */
@GetMapping("/v1/tenant/findTenantByTenantCode/{tenantCode}") @GetMapping("/v1/tenant/anonymousUser/findTenantByTenantCode/{tenantCode}")
ResponseBean<Tenant> findTenantByTenantCode(@PathVariable("tenantCode") String tenantCode); ResponseBean<Tenant> findTenantByTenantCode(@PathVariable("tenantCode") String tenantCode);
/** /**
...@@ -176,17 +176,17 @@ public interface UserServiceClient { ...@@ -176,17 +176,17 @@ public interface UserServiceClient {
* @author tangyi * @author tangyi
* @date 2019/07/05 20:57:31 * @date 2019/07/05 20:57:31
*/ */
@PostMapping("/v1/user/register") @PostMapping("/v1/user/anonymousUser/register")
ResponseBean<Boolean> registerUser(@RequestBody UserDto userDto); ResponseBean<Boolean> registerUser(@RequestBody UserDto userDto);
/** /**
* 更新用户 * 更新用户登录信息
* *
* @param userDto userDto * @param userDto userDto
* @return ResponseBean * @return ResponseBean
* @author tangyi * @author tangyi
* @date 2019/07/05 20:59:06 * @date 2019/07/05 20:59:06
*/ */
@PutMapping("/v1/user") @PutMapping("/v1/user/anonymousUser/updateLoginInfo")
ResponseBean<Boolean> updateUser(UserDto userDto); ResponseBean<Boolean> updateLoginInfo(UserDto userDto);
} }
...@@ -203,14 +203,14 @@ public class UserServiceClientFallbackImpl implements UserServiceClient { ...@@ -203,14 +203,14 @@ public class UserServiceClientFallbackImpl implements UserServiceClient {
} }
/** /**
* 更新用户 * 更新用户登录信息
* *
* @param userDto userDto * @param userDto userDto
* @return ResponseBean * @return ResponseBean
*/ */
@Override @Override
public ResponseBean<Boolean> updateUser(UserDto userDto) { public ResponseBean<Boolean> updateLoginInfo(UserDto userDto) {
log.error("Feign updateUser failed, {}, {}, {}", userDto.getIdentityType(), userDto.getIdentifier(), throwable); log.error("Feign updateLoginInfo failed, {}, {}, {}", userDto.getIdentityType(), userDto.getIdentifier(), throwable);
return null; return null;
} }
......
...@@ -179,7 +179,7 @@ public class MenuController extends BaseController { ...@@ -179,7 +179,7 @@ public class MenuController extends BaseController {
* @author tangyi * @author tangyi
* @date 2018/8/27 15:58 * @date 2018/8/27 15:58
*/ */
@GetMapping("findMenuByRole/{role}") @GetMapping("anonymousUser/findMenuByRole/{role}")
@ApiOperation(value = "根据角色查找菜单", notes = "根据角色id获取角色菜单") @ApiOperation(value = "根据角色查找菜单", notes = "根据角色id获取角色菜单")
@ApiImplicitParam(name = "role", value = "角色名称", required = true, dataType = "String", paramType = "path") @ApiImplicitParam(name = "role", value = "角色名称", required = true, dataType = "String", paramType = "path")
public ResponseBean<List<Menu>> findMenuByRole(@PathVariable String role, @RequestParam @NotBlank String tenantCode) { public ResponseBean<List<Menu>> findMenuByRole(@PathVariable String role, @RequestParam @NotBlank String tenantCode) {
...@@ -194,7 +194,7 @@ public class MenuController extends BaseController { ...@@ -194,7 +194,7 @@ public class MenuController extends BaseController {
* @author tangyi * @author tangyi
* @date 2019/04/26 11:50 * @date 2019/04/26 11:50
*/ */
@GetMapping("findAllMenu") @GetMapping("anonymousUser/findAllMenu")
@ApiOperation(value = "查询所有菜单", notes = "查询所有菜单") @ApiOperation(value = "查询所有菜单", notes = "查询所有菜单")
public ResponseBean<List<Menu>> findAllMenu(@RequestParam @NotBlank String tenantCode) { public ResponseBean<List<Menu>> findAllMenu(@RequestParam @NotBlank String tenantCode) {
Menu menu = new Menu(); Menu menu = new Menu();
......
...@@ -61,7 +61,7 @@ public class TenantController extends BaseController { ...@@ -61,7 +61,7 @@ public class TenantController extends BaseController {
* @author tangyi * @author tangyi
* @date 2019/05/26 10:23 * @date 2019/05/26 10:23
*/ */
@GetMapping("findTenantByTenantCode/{tenantCode}") @GetMapping("anonymousUser/findTenantByTenantCode/{tenantCode}")
public ResponseBean<Tenant> findTenantByTenantCode(@PathVariable String tenantCode) { public ResponseBean<Tenant> findTenantByTenantCode(@PathVariable String tenantCode) {
return new ResponseBean<>(tenantService.getByTenantCode(tenantCode)); return new ResponseBean<>(tenantService.getByTenantCode(tenantCode));
} }
......
...@@ -105,7 +105,7 @@ public class UserController extends BaseController { ...@@ -105,7 +105,7 @@ public class UserController extends BaseController {
* @param tenantCode tenantCode * @param tenantCode tenantCode
* @return ResponseBean * @return ResponseBean
*/ */
@GetMapping("/findUserByIdentifier/{identifier}") @GetMapping("anonymousUser/findUserByIdentifier/{identifier}")
@ApiOperation(value = "获取用户信息", notes = "根据用户name获取用户详细信息") @ApiOperation(value = "获取用户信息", notes = "根据用户name获取用户详细信息")
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(name = "identifier", value = "用户唯一标识", required = true, dataType = "String", paramType = "path"), @ApiImplicitParam(name = "identifier", value = "用户唯一标识", required = true, dataType = "String", paramType = "path"),
...@@ -235,7 +235,7 @@ public class UserController extends BaseController { ...@@ -235,7 +235,7 @@ public class UserController extends BaseController {
* @author tangyi * @author tangyi
* @date 2019/06/21 20:09 * @date 2019/06/21 20:09
*/ */
@PutMapping("updatePassword") @PutMapping("anonymousUser/updatePassword")
@ApiOperation(value = "修改用户密码", notes = "修改用户密码") @ApiOperation(value = "修改用户密码", notes = "修改用户密码")
@ApiImplicitParam(name = "userDto", value = "用户实体user", required = true, dataType = "UserDto") @ApiImplicitParam(name = "userDto", value = "用户实体user", required = true, dataType = "UserDto")
@Log("更新用户密码") @Log("更新用户密码")
...@@ -403,7 +403,7 @@ public class UserController extends BaseController { ...@@ -403,7 +403,7 @@ public class UserController extends BaseController {
@ApiImplicitParam(name = "randomStr", value = "随机数", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "randomStr", value = "随机数", dataType = "String", paramType = "query"),
@ApiImplicitParam(name = "mobile", value = "手机号", dataType = "String", paramType = "query") @ApiImplicitParam(name = "mobile", value = "手机号", dataType = "String", paramType = "query")
}) })
@PostMapping("register") @PostMapping("anonymousUser/register")
@Log("注册用户") @Log("注册用户")
public ResponseBean<Boolean> register(@RequestBody @Valid UserDto userDto) { public ResponseBean<Boolean> register(@RequestBody @Valid UserDto userDto) {
return new ResponseBean<>(userService.register(userDto)); return new ResponseBean<>(userService.register(userDto));
...@@ -425,7 +425,7 @@ public class UserController extends BaseController { ...@@ -425,7 +425,7 @@ public class UserController extends BaseController {
@ApiImplicitParam(name = "identifier", value = "用户唯一标识", required = true, dataType = "String", paramType = "path"), @ApiImplicitParam(name = "identifier", value = "用户唯一标识", required = true, dataType = "String", paramType = "path"),
@ApiImplicitParam(name = "tenantCode", value = "租户标识", required = true, dataType = "String"), @ApiImplicitParam(name = "tenantCode", value = "租户标识", required = true, dataType = "String"),
}) })
@GetMapping("checkExist/{identifier}") @GetMapping("anonymousUser/checkExist/{identifier}")
public ResponseBean<Boolean> checkExist(@PathVariable("identifier") String identifier, @RequestParam Integer identityType, @RequestHeader(SecurityConstant.TENANT_CODE_HEADER) String tenantCode) { public ResponseBean<Boolean> checkExist(@PathVariable("identifier") String identifier, @RequestParam Integer identityType, @RequestHeader(SecurityConstant.TENANT_CODE_HEADER) String tenantCode) {
return new ResponseBean<>(userService.checkIdentifierIsExist(identityType, identifier, tenantCode)); return new ResponseBean<>(userService.checkIdentifierIsExist(identityType, identifier, tenantCode));
} }
...@@ -451,7 +451,7 @@ public class UserController extends BaseController { ...@@ -451,7 +451,7 @@ public class UserController extends BaseController {
* @author tangyi * @author tangyi
* @date 2019/6/7 12:00 * @date 2019/6/7 12:00
*/ */
@PutMapping("/resetPassword") @PutMapping("anonymousUser/resetPassword")
@AdminTenantTeacherAuthorization @AdminTenantTeacherAuthorization
@ApiOperation(value = "重置密码", notes = "根据用户id重置密码") @ApiOperation(value = "重置密码", notes = "根据用户id重置密码")
@ApiImplicitParam(name = "userDto", value = "用户实体user", required = true, dataType = "UserDto") @ApiImplicitParam(name = "userDto", value = "用户实体user", required = true, dataType = "UserDto")
...@@ -459,4 +459,34 @@ public class UserController extends BaseController { ...@@ -459,4 +459,34 @@ public class UserController extends BaseController {
public ResponseBean<Boolean> resetPassword(@RequestBody UserDto userDto) { public ResponseBean<Boolean> resetPassword(@RequestBody UserDto userDto) {
return new ResponseBean<>(userService.resetPassword(userDto)); return new ResponseBean<>(userService.resetPassword(userDto));
} }
/**
* 更新用户的基本信息
*
* @param userDto userDto
* @return ResponseBean
* @author tangyi
* @date 2020/02/29 16:55
*/
@PutMapping("anonymousUser/updateLoginInfo")
@ApiOperation(value = "更新用户登录信息", notes = "根据用户id更新用户的登录信息")
@ApiImplicitParam(name = "userDto", value = "用户实体user", required = true, dataType = "UserDto")
@Log("更新用户登录信息")
public ResponseBean<Boolean> updateLoginInfo(@RequestBody UserDto userDto) {
Boolean success = Boolean.FALSE;
if (StringUtils.isNotBlank(userDto.getIdentifier())) {
UserAuths userAuths = new UserAuths();
userAuths.setIdentifier(userDto.getIdentifier());
userAuths = userAuthsService.getByIdentifier(userAuths);
if (userAuths != null) {
User user = new User();
user.setId(userAuths.getUserId());
user.setLoginTime(userDto.getLoginTime());
user.setModifyDate(userDto.getLoginTime());
user.setModifier(userAuths.getIdentifier());
success = userService.update(user) > 0;
}
}
return new ResponseBean<>(success);
}
} }
...@@ -657,8 +657,10 @@ public class UserService extends CrudService<UserMapper, User> { ...@@ -657,8 +657,10 @@ public class UserService extends CrudService<UserMapper, User> {
userVos = userStream.map(tempUser -> { userVos = userStream.map(tempUser -> {
UserVo tempUserVo = new UserVo(); UserVo tempUserVo = new UserVo();
BeanUtils.copyProperties(tempUser, tempUserVo); BeanUtils.copyProperties(tempUser, tempUserVo);
attachment.setId(tempUser.getAvatarId()); if (tempUser.getAvatarId() != null) {
tempUserVo.setAvatarUrl(attachmentService.getPreviewUrl(attachment)); attachment.setId(tempUser.getAvatarId());
tempUserVo.setAvatarUrl(attachmentService.getPreviewUrl(attachment));
}
return tempUserVo; return tempUserVo;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
} }
......
...@@ -249,7 +249,9 @@ ...@@ -249,7 +249,9 @@
<if test="applicationCode != null"> <if test="applicationCode != null">
application_code = #{applicationCode} , application_code = #{applicationCode} ,
</if> </if>
modifier = #{modifier} , <if test="modifier != null">
modifier = #{modifier} ,
</if>
modify_date = #{modifyDate, jdbcType=TIMESTAMP, javaType=java.util.Date} modify_date = #{modifyDate, jdbcType=TIMESTAMP, javaType=java.util.Date}
where id = #{id} where id = #{id}
</update> </update>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment