refactor: 临时密码登录功能

This commit is contained in:
TS-QD1 2025-04-23 16:25:57 +08:00
parent 6ff58b943e
commit 5e9857ee99
10 changed files with 739 additions and 12 deletions

View File

@ -10,6 +10,14 @@ ADD COLUMN `wx_open_id` varchar(255) NULL COMMENT '微信-开放平台-openid' A
ADD COLUMN `wx_union_id` varchar(255) NULL COMMENT '微信-开放平台-unionid' AFTER `wx_open_id`;
```
## 开放白名单
### 临时登录接口
```
/router/systemuser/temporary-login
```
# 20250325已上线
## user_expand

View File

@ -3,12 +3,12 @@ package cn.com.tenlion.operator.controller.api.systemuser;
import cn.com.tenlion.operator.pojo.dtos.account.AccountDTO;
import cn.com.tenlion.operator.service.account.IAccountService;
import cn.com.tenlion.operator.service.custompersonal.ICustomPersonalService;
import cn.com.tenlion.operator.service.login.temporary.LoginTemporaryService;
import cn.com.tenlion.projectconfig.util.ProjectConfigUtil;
import ink.wgink.annotation.CheckRequestBodyAnnotation;
import ink.wgink.common.base.DefaultBaseController;
import ink.wgink.exceptions.SearchException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.interfaces.user.IUserBaseService;
import ink.wgink.pojo.result.ErrorResult;
import ink.wgink.pojo.result.SuccessResult;
import ink.wgink.pojo.result.SuccessResultData;
@ -16,7 +16,6 @@ import ink.wgink.service.user.service.IUserService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
/**
* @ClassName: SystemUserlController
@ -28,7 +27,7 @@ import org.springframework.web.servlet.ModelAndView;
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "系统用户接口")
@RestController
@RequestMapping(ISystemConstant.API_PREFIX + "/systemuser")
public class SystemUserApiontroller extends DefaultBaseController {
public class SystemUserController extends DefaultBaseController {
@Autowired
private ICustomPersonalService customPersonalService;
@ -38,6 +37,8 @@ public class SystemUserApiontroller extends DefaultBaseController {
@Autowired
private IUserService iUserService;
@Autowired
private LoginTemporaryService loginTemporaryService;
@ApiOperation(value = "更改开放状态", notes = "更改开放状态")
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@ -77,4 +78,14 @@ public class SystemUserApiontroller extends DefaultBaseController {
throw new SearchException("系统错误");
}
@GetMapping("get-temporary-password")
public SuccessResultData<String> getTemporaryPassword() {
return new SuccessResultData<>(loginTemporaryService.getPassword());
}
@GetMapping("generate-temporary-password")
public SuccessResultData<String> generateTemporaryPassword() {
return new SuccessResultData<>(loginTemporaryService.generatePassword());
}
}

View File

@ -64,7 +64,7 @@ public class SystemUserRouteController extends DefaultBaseController {
List<RoleSimpleDTO> roleSimpleDTOList = userInfoBO.getRoles();
String url = systemProperties.getUrl();
if (userInfoBO.getUserId().equals("1")) {
return new ModelAndView("forward:/default-main");
return new ModelAndView("forward:/route/systemuser/system-select");
}
if (roleSimpleDTOList == null || roleSimpleDTOList.isEmpty()) {
throw new SaveException("角色不存在");
@ -73,7 +73,7 @@ public class SystemUserRouteController extends DefaultBaseController {
StringUtils.contains("项目运营", roleSimpleDTO.getRoleName()) ||
StringUtils.contains("开发人员", roleSimpleDTO.getRoleName()));
if (isAdmin || userInfoBO.getUserId().equals("1")) {
return new ModelAndView("forward:/default-main");
return new ModelAndView("forward:/route/systemuser/system-select");
} else if (roleSimpleDTOList.stream().anyMatch(roleSimpleDTO -> StringUtils.contains("普通用户", roleSimpleDTO.getRoleName()))) {
return new ModelAndView(new RedirectView(ProjectConfigUtil.getText("AiServerUrl")));
}
@ -99,5 +99,24 @@ public class SystemUserRouteController extends DefaultBaseController {
return mv;
}
@GetMapping("home")
public ModelAndView home() {
ModelAndView mv = new ModelAndView();
mv.setViewName("systemuser/home");
return mv;
}
@GetMapping("system-select")
public ModelAndView systemSelect() {
ModelAndView mv = new ModelAndView();
mv.setViewName("systemuser/system-select");
return mv;
}
@GetMapping("temporary-login")
public ModelAndView temporaryLogin() {
ModelAndView mv = new ModelAndView("systemuser/temporary-login");
return mv;
}
}

View File

@ -22,7 +22,7 @@ public class LoginTemporaryAuthFilter extends AbstractAuthenticationProcessingFi
private final LoginTemporaryService loginTemporaryService;
public LoginTemporaryAuthFilter(LoginTemporaryService loginTemporaryService) {
super(new AntPathRequestMatcher("/oauth/temporary", "POST"));
super(new AntPathRequestMatcher("/oauth/temporary/login", "POST"));
this.loginTemporaryService = loginTemporaryService;
}

View File

@ -75,7 +75,7 @@ public class LoginWxOauth2AuthProvider implements AuthenticationProvider {
username = openid;
} else {
UserPO userPO = userService.getPO(userExpandPO.getUserId());
username = userPO.getUserName();
username = userPO.getUserUsername();
if (userPO.getUserState() == 1) {
userService.updateUserState(userPO.getUserId(), UserStateEnum.NORMAL);
}

View File

@ -1,5 +1,6 @@
package cn.com.tenlion.operator.service.login.temporary;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.string.WStringUtil;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@ -11,9 +12,10 @@ public class LoginTemporaryService {
private long lastUpdateTime = 0;
public String generatePassword() {
String code = "" + System.currentTimeMillis();
String code = UUIDUtil.get32UUID();
this.lastUpdateTime = System.currentTimeMillis();
return WStringUtil.randomSubStr(code, 6);
this.password = WStringUtil.randomSubStr(code, 10);
return password;
}
public String getPassword() {

View File

@ -2,10 +2,11 @@ server:
port: 8091
# url: http://127.0.0.1:8091/operator/
url: http://121.36.71.250:58038/operator/
ip: 127.0.0.1
ip: 121.36.71.250
system-title: 运营平台
system-sub-title: 运营平台
default-index-page: route/systemuser/index
default-home-page: route/systemuser/home
servlet:
context-path: /operator
@ -116,7 +117,7 @@ file:
security:
oauth2:
oauth-server: http://127.0.0.1:8091/operator/
oauth-server: http://121.36.71.250:58038/operator/
oauth-logout: ${security.oauth2.oauth-server}/logout?redirect_uri=${server.url}
client:
client-id: 46c4715a2a504dd48398bda88b5c3a88
@ -134,7 +135,7 @@ security:
api-path:
user-center: http://127.0.0.1:8091/operator/
copyright: http://127.0.0.1:7025/copyright/
copyright-external: http://192.168.0.15:7025/copyright/
copyright-external: http://121.36.71.250:58038/copyright/
operator-plugin: http://192.168.0.15:8099/operator-plugin/

View File

@ -0,0 +1,614 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<base th:href="${#request.getContextPath() + '/'}">
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="assets/fonts/font-awesome/css/font-awesome.css"/>
<link rel="stylesheet" href="assets/layuiadmin/layui/css/layui.css" media="all">
<link rel="stylesheet" href="assets/layuiadmin/style/admin.css" media="all">
<style>
.layui-badge {height: auto;}
.layui-card-header {overflow: hidden; white-space: nowrap; text-overflow: ellipsis;}
.count-second-row {padding-bottom: 0px;}
[v-cloak] {display: none;}
</style>
</head>
<body>
<div id="LAY-app" class="layui-fluid">
<div class="layui-row layui-col-space15">
<div class="layui-col-sm12 layui-col-md6">
<div class="layui-row layui-col-space15">
<div class="layui-col-sm4 layui-col-md4">
<div class="layui-card">
<div class="layui-card-header">
系统登录用户量
<span class="layui-badge layui-bg-blue layuiadmin-badge"></span>
</div>
<div class="layui-card-body layuiadmin-card-list">
<p id="loginCount" class="layuiadmin-big-font">0</p>
<p>
增长率
<span class="layuiadmin-span-color">
<span id="loginPercentage">0</span>% <i class="layui-inline fa fa-arrow-up"></i>
</span>
</p>
</div>
</div>
</div>
<div class="layui-col-sm4 layui-col-md4">
<div class="layui-card">
<div class="layui-card-header">
新增用户量
<span class="layui-badge layui-bg-orange layuiadmin-badge"></span>
</div>
<div class="layui-card-body layuiadmin-card-list">
<p id="newUserWeekCount" class="layuiadmin-big-font">0</p>
<p>
占比
<span class="layuiadmin-span-color">
<span id="newUserWeekPercentage">0</span>% <i class="layui-inline fa fa-users"></i></i>
</span>
</p>
</div>
</div>
</div>
<div class="layui-col-sm4 layui-col-md4">
<div class="layui-card">
<div class="layui-card-header">
总用户量
<span class="layui-badge layui-bg-cyan layuiadmin-badge"></span>
</div>
<div class="layui-card-body layuiadmin-card-list">
<p id="userCount" class="layuiadmin-big-font">0</p>
<p>
增长人数
<span class="layuiadmin-span-color">
<span id="userMonthNewCount">0</span> <i class="layui-inline fa fa-arrow-up"></i>
</span>
</p>
</div>
</div>
</div>
</div>
<div class="layui-row layui-col-space15">
<div class="layui-col-sm4 layui-col-md4">
<div class="layui-card">
<div class="layui-card-body">
<div class="layui-card-header">
临时密码
<span class="layui-badge layui-bg-red layuiadmin-badge"><i class="layui-inline fa fa-lock"></i></span>
</div>
<div class="layui-card-body layuiadmin-card-list" v-cloak>
<i class="layui-inline fa fa-key" style="margin-right: 5px;" v-if="temporaryPassword"></i>
<input v-model="temporaryPassword" id="temporaryPassword" readonly style="width: 100px; height: 22px; padding: 2px; border: 1px solid #efefef; text-align: center;" v-if="temporaryPassword" @click="onCopyTemporaryPassword"/>
<button type="button" class="layui-btn layui-btn-primary layui-border layui-btn-xs" @click="onCopyTemporaryPassword" v-if="temporaryPassword">复制</button>
<button type="button" class="layui-btn layui-btn-primary layui-border layui-btn-xs" @click="onGenerateTemporaryPassword" style="margin-left: 2px;">生成</button>
</div>
</div>
</div>
</div>
<div class="layui-col-sm4 layui-col-md4">
<div class="layui-card">
<div class="layui-card-header">
角色数量
<span class="layui-badge layui-bg-red layuiadmin-badge"><i class="layui-inline fa fa-user-o"></i></span>
</div>
<div class="layui-card-body layuiadmin-card-list">
<p id="roleCount" class="layuiadmin-big-font">0</p>
</div>
</div>
</div>
<div class="layui-col-sm4 layui-col-md4">
<div class="layui-card">
<div class="layui-card-header">
职位数量
<span class="layui-badge layui-bg-green layuiadmin-badge"><i class="layui-inline fa fa-briefcase"></i></span>
</div>
<div class="layui-card-body layuiadmin-card-list">
<p id="positionCount" class="layuiadmin-big-font">0</p>
</div>
</div>
</div>
</div>
</div>
<div class="layui-col-sm12 layui-col-md6">
<div class="layui-col-sm12">
<div class="layui-card">
<div class="layui-card-body">
<div id="loginEChart" style="width: 100%; height: 267px;"></div>
</div>
</div>
</div>
</div>
</div>
<div class="layui-row layui-col-space15">
<div class="layui-col-sm6 layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">用户状态占比</div>
<div class="layui-card-body">
<div id="userTypeEChart" style="width: 100%; height: 300px;"></div>
</div>
</div>
</div>
<div class="layui-col-sm6 layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">用户类型占比</div>
<div class="layui-card-body">
<div id="userStateEChart" style="width: 100%; height: 300px;"></div>
</div>
</div>
</div>
</div>
<div class="layui-row layui-col-space15">
<div class="layui-col-sm6 layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">
系统登录日志最新10条
</div>
<div class="layui-card-body layuiadmin-card-list" style="height: 200px; overflow: auto;">
<table class="layui-table" lay-skin="line">
<colgroup>
<col>
<col>
<col width="180">
</colgroup>
<tbody v-cloak>
<tr v-for="loginLogger in loginLoggerList">
<td>
<span class="layui-badge layui-bg-blue"><i class="fa fa-user-circle-o"></i> {{loginLogger.creatorName}}</span> 登录了系统
</td>
<td>{{loginLogger.loginAddress}}</td>
<td><i class="fa fa-clock-o"></i> {{loginLogger.gmtCreate}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="layui-col-sm6 layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">
用户调整日志最新10条
</div>
<div class="layui-card-body layuiadmin-card-list" style="height: 200px; overflow: auto;">
<table class="layui-table" lay-skin="line">
<colgroup>
<col>
<col width="180">
</colgroup>
<tbody v-cloak>
<tr v-for="userAdjustment in userAdjustmentList">
<td v-if="userAdjustment.updateType == 'username'">
<span class="layui-badge layui-bg-blue"><i class="fa fa-user-circle-o"></i> {{userAdjustment.userName}}</span> 变更了用户名为 <span class="layui-badge layui-bg-cyan" :title="'原用户名:'+ userAdjustment.oldValue" style="cursor:pointer;">{{userAdjustment.newValue}}</span>
</td>
<td v-if="userAdjustment.updateType == 'password'">
<span class="layui-badge layui-bg-blue"><i class="fa fa-user-circle-o"></i> {{userAdjustment.userName}}</span> 修改了密码
</td>
<td v-if="userAdjustment.updateType == 'restPassword'">
<span class="layui-badge layui-bg-blue"><i class="fa fa-user-circle-o"></i> {{userAdjustment.userName}}</span> 重置了密码为 <span class="layui-badge layui-bg-cyan">{{userAdjustment.newValue}}</span>
</td>
<td><i class="fa fa-clock-o"></i> {{userAdjustment.gmtCreate}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="assets/js/vue.min.js"></script>
<script type="text/javascript" src="assets/js/vendor/echarts/echarts.min.js"></script>
<script src="assets/layuiadmin/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layuiadmin/' //静态资源所在路径
}).extend({
index: 'lib/index' //主入口模块
}).use(['index', 'animate-numbers'], function() {
var $ = layui.$;
var $win = $(window);
new Vue({
el: '#LAY-app',
data: {
newUserWeekCount: 0,
newUserWeekPercentage: 0,
loginCount: 0,
loginPercentage: 0,
userCount: 0,
userMonthNewCount: 0,
departmentCount: 0,
roleCount: 0,
positionCount: 0,
loginLoggerList: [],
userAdjustmentList: [],
departmentAdjustmentList: [],
userDepartmentAdjustmentList: [],
resizeTimeout: null,
loginEChart: null,
userTypeEChart: null,
temporaryPassword: '',
},
methods: {
countUserWeek: function() {
var self = this;
top.restAjax.get('api/count/count-new-user-by-week', {}, null, function(code, data) {
self.newUserWeekCount = data.data.count;
self.userWeekPercentage = data.data.percentage;
self.$nextTick(function() {
$('#newUserWeekCount').animateNumbers(self.newUserWeekCount);
$('#newUserWeekPercentage').animateNumbers(self.userWeekPercentage);
});
}, function(code, data) {
top.dialog.msg(data.msg);
});
},
countLogin: function() {
var self = this;
top.restAjax.get('api/count/count-login', {}, null, function(code, data) {
self.loginCount = data.data.count;
self.loginPercentage = data.data.percentage
self.$nextTick(function() {
$('#loginCount').animateNumbers(self.loginCount);
$('#loginPercentage').animateNumbers(self.loginPercentage);
});
}, function(code, data) {
top.dialog.msg(data.msg);
});
},
countUser: function() {
var self = this;
top.restAjax.get('api/count/count-user', {}, null, function(code, data) {
self.userCount = data.data.count;
self.userMonthNewCount = data.data.newCount;
self.$nextTick(function() {
$('#userCount').animateNumbers(self.userCount);
$('#userMonthNewCount').animateNumbers(self.userMonthNewCount);
});
}, function(code, data) {
top.dialog.msg(data.msg);
});
},
countDepartment: function() {
var self = this;
top.restAjax.get('api/count/count-department', {}, null, function(code, data) {
self.departmentCount = data.data;
self.$nextTick(function() {
$('#departmentCount').animateNumbers(self.departmentCount);
});
}, function(code, data) {
top.dialog.msg(data.msg);
});
},
countRole: function() {
var self = this;
top.restAjax.get('api/count/count-role', {}, null, function(code, data) {
self.roleCount = data.data;
self.$nextTick(function() {
$('#roleCount').animateNumbers(self.roleCount);
});
}, function(code, data) {
top.dialog.msg(data.msg);
});
},
countPosition: function() {
var self = this;
top.restAjax.get('api/count/count-position', {}, null, function(code, data) {
self.positionCount = data.data;
self.$nextTick(function() {
$('#positionCount').animateNumbers(self.positionCount);
});
}, function(code, data) {
top.dialog.msg(data.msg);
});
},
initLoginEChart: function() {
var self = this;
if(self.loginEChart) {
self.loginEChart.resize();
return;
}
top.restAjax.get('api/count/count-login-for-days/10', {}, null, function(code, data) {
self.loginEChart = echarts.init(document.getElementById('loginEChart'));
self.loginEChart.setOption({
title: {
text: '近期系统登录情况'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
show: true,
},
legend: {
data: ['登录人数']
},
xAxis: {
type: 'category',
data: data.data.dateArray,
splitLine: {
show: true,
lineStyle: {
type: 'dashed'
}
}
},
yAxis: {
type: 'value'
},
series: [{
name: '登录人数',
data: data.data.loginCountArray,
type: 'line',
smooth: true,
stack: '总数',
areaStyle: {},
}]
});
}, function(code, data) {
top.dialog.msg(data.msg);
});
},
initUserTypeEChart: function() {
var self = this;
if(self.userTypeEChart) {
self.userTypeEChart.resize();
return;
}
top.restAjax.get('api/count/count-user-type-proportion', {}, null, function(code, data) {
self.userTypeEChart = echarts.init(document.getElementById('userTypeEChart'));
var legendData = [];
var seriesData = [];
for(var i = 0, item; item = data.data[i++];) {
legendData.push(item.name);
seriesData.push({
name: item.name,
value: item.value,
itemStyle: {
color: item.color
}
})
}
self.userTypeEChart.setOption({
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 10,
data: legendData
},
series: [
{
name: '用户类型占比',
type: 'pie',
radius: '66%',
avoidLabelOverlap: false,
label: {
formatter: '{b|{b}}\n{hr|}\n {c|{c}} {per|{d}%} ',
backgroundColor: '#eee',
borderColor: '#aaa',
borderWidth: 0.5,
borderRadius: 4,
rich: {
b: {
fontSize: 14,
lineHeight: 22,
align: 'center'
},
hr: {
borderColor: '#aaa',
width: '100%',
borderWidth: 0.5,
height: 0
},
per: {
color: '#eee',
backgroundColor: '#334455',
padding: [2, 4],
borderRadius: 2
},
c: {
fontSize: 14,
lineHeight: 22,
align: 'center'
},
}
},
emphasis: {
label: {
show: true,
fontSize: '14',
fontWeight: 'bold'
}
},
data: seriesData
}
]
});
}, function(code, data) {
top.dialog.msg(data.msg);
});
},
initUserStateEChart: function() {
var self = this;
if(self.userStateEChart) {
self.userStateEChart.resize();
return;
}
top.restAjax.get('api/count/count-user-state-proportion', {}, null, function(code, data) {
self.userStateEChart = echarts.init(document.getElementById('userStateEChart'));
var legendData = [];
var seriesData = [];
for(var i = 0, item; item = data.data[i++];) {
legendData.push(item.name);
seriesData.push({
name: item.name,
value: item.value,
itemStyle: {
color: item.color
}
})
}
self.userStateEChart.setOption({
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 10,
data: legendData
},
series: [
{
name: '用户状态占比',
type: 'pie',
radius: '66%',
avoidLabelOverlap: false,
label: {
formatter: '{b|{b}}\n{hr|}\n {c|{c}} {per|{d}%} ',
backgroundColor: '#eee',
borderColor: '#aaa',
borderWidth: 0.5,
borderRadius: 4,
rich: {
b: {
fontSize: 14,
lineHeight: 22,
align: 'center'
},
hr: {
borderColor: '#aaa',
width: '100%',
borderWidth: 0.5,
height: 0
},
per: {
color: '#eee',
backgroundColor: '#334455',
padding: [2, 4],
borderRadius: 2
},
c: {
fontSize: 14,
lineHeight: 22,
align: 'center'
},
}
},
emphasis: {
label: {
show: true,
fontSize: '14',
fontWeight: 'bold'
}
},
data: seriesData
}
]
});
}, function(code, data) {
top.dialog.msg(data.msg);
});
},
initLoginLogger: function() {
var self = this;
top.restAjax.get(top.restAjax.path('api/log/listpage/login-log', []), {
page: 1,
rows: 10
}, null, function(code, data) {
self.loginLoggerList = data.rows;
}, function(code, data) {
top.dialog.msg(data.msg);
});
},
initUserAdjustment: function() {
var self = this;
top.restAjax.get(top.restAjax.path('api/log/listpage/user-adjustment', []), {
page: 1,
rows: 10
}, null, function(code, data) {
self.userAdjustmentList = data.rows;
}, function(code, data) {
top.dialog.msg(data.msg);
});
},
getTemporaryPassword: function() {
var self = this;
top.restAjax.get('api/systemuser/get-temporary-password', {}, null, function(code, data) {
self.temporaryPassword = data.data;
}, function(code, data) {
top.dialog.msg(data.msg)
})
},
onGenerateTemporaryPassword: function() {
var self = this;
top.restAjax.get('api/systemuser/generate-temporary-password', {}, null, function(code, data) {
self.temporaryPassword = data.data;
}, function(code, data) {
top.dialog.msg(data.msg)
})
},
onCopyTemporaryPassword: function() {
const input = document.getElementById('temporaryPassword');
input.select();
try {
const successful = document.execCommand('copy');
if (successful) {
top.dialog.msg('复制成功');
} else {
top.dialog.msg('复制失败');
}
} catch (err) {
top.dialog.msg('复制时出错:', err);
}
}
},
mounted: function() {
var self = this;
self.countUserWeek();
self.countLogin();
self.countUser();
self.countDepartment();
self.countRole();
self.countPosition();
self.initLoginEChart();
self.initUserTypeEChart();
self.initUserStateEChart();
self.initLoginLogger();
self.initUserAdjustment();
self.getTemporaryPassword();
// 事件 - 页面变化
$win.on('resize', function() {
if(self.resizeTimeout) {
return;
}
self.resizeTimeout = setTimeout(function() {
self.initLoginEChart();
self.initUserTypeEChart();
self.initUserStateEChart();
self.resizeTimeout = null;
}, 500);
});
}
})
});
</script>
</body>
</html>

View File

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html lang="en">
<head>
<base th:href="${#request.getContextPath() + '/'}">
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>AI喵著</title>
<style>
html, body {margin: 0;padding: 0;height: 100%;}
.container {width: 100%;height: 100%; display: flex; justify-content: center; align-items: center;}
.container .systems {display: flex; }
.container .systems .system {width: 200px; height: 200px; margin: 10px; cursor: pointer; border-radius: 5px; box-shadow: 0 0 5px silver; padding: 15px; box-sizing: border-box; display: flex; flex-direction: column; justify-content: center; align-items: center;}
.container .systems .system .logo {}
.container .systems .system .title {margin-top: 10px;}
</style>
</head>
<body>
<div class="container">
<div class="systems">
<div class="system" data-href="/operator/default-main">
<div class="logo"></div>
<div class="title">统一用户</div>
</div>
<div class="system" data-href="/operator-plugin">
<div class="logo"></div>
<div class="title">运营平台</div>
</div>
<div class="system" data-href="/copyright">
<div class="logo"></div>
<div class="title">喵著系统</div>
</div>
</div>
</div>
<script src="assets/layuiadmin/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layuiadmin/' //静态资源所在路径
}).extend({
index: 'lib/index' //主入口模块
}).use(['index', 'animate-numbers'], function() {
var $ = layui.$;
$('.system').on('click', function() {
var href = $(this).data('href');
window.location.href = href;
})
});
</script>
</body>
</html>

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<base th:href="${#request.getContextPath() + '/'}">
<meta charset="UTF-8">
<title>临时登录</title>
</head>
<body>
<form action="oauth/temporary/login" method="post" enctype="application/x-www-form-urlencoded">
<div>
<label for="username">用户名:</label>
<input type="text" id="username" name="username" placeholder="输入用户名"/>
</div>
<div>
<label for="password">密码:</label>
<input type="password" id="password" name="password" placeholder="输入密码"/>
</div>
<button type="submit">登录</button>
</form>
</body>
</html>