1
0

feat(web): 使用模块化js 增加账号改密、注销

This commit is contained in:
2024-11-18 18:51:55 +08:00
parent 05f4ad5b57
commit c466e5e49f
14 changed files with 393 additions and 150 deletions

View File

@@ -1,6 +1,7 @@
package com.eshore.gringotts.web; package com.eshore.gringotts.web;
import com.blinkfox.fenix.EnableFenix; import com.blinkfox.fenix.EnableFenix;
import com.eshore.gringotts.web.domain.user.service.UserService;
import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner; import org.springframework.boot.ApplicationRunner;
@@ -25,12 +26,19 @@ import org.springframework.scheduling.annotation.EnableAsync;
@EnableConfigurationProperties @EnableConfigurationProperties
@EnableEncryptableProperties @EnableEncryptableProperties
public class WebApplication implements ApplicationRunner { public class WebApplication implements ApplicationRunner {
private final UserService userService;
public WebApplication(UserService userService) {
this.userService = userService;
}
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args); SpringApplication.run(WebApplication.class, args);
} }
@Override @Override
public void run(ApplicationArguments args) throws Exception { public void run(ApplicationArguments args) throws Exception {
// Test Something // 初始化系统管理员
userService.initial();
} }
} }

View File

@@ -2,6 +2,9 @@ package com.eshore.gringotts.web.configuration;
import cn.dev33.satoken.interceptor.SaInterceptor; import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@@ -11,11 +14,18 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
* @author lanyuanxiaoyao * @author lanyuanxiaoyao
* @date 2024-11-14 * @date 2024-11-14
*/ */
// @Configuration @Configuration
public class SaTokenConfiguration implements WebMvcConfigurer { public class SaTokenConfiguration implements WebMvcConfigurer {
private static final Logger logger = LoggerFactory.getLogger(SaTokenConfiguration.class);
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SaInterceptor(handler -> StpUtil.checkLogin())) registry.addInterceptor(
new SaInterceptor(handler -> {
logger.info("Handler {}", handler);
StpUtil.checkLogin();
})
)
.addPathPatterns("/**") .addPathPatterns("/**")
.excludePathPatterns("/*.html") .excludePathPatterns("/*.html")
.excludePathPatterns("/assets/**") .excludePathPatterns("/assets/**")

View File

@@ -41,19 +41,18 @@ public class UserController {
@PostMapping("/register") @PostMapping("/register")
public void register(@RequestBody RegisterRequest request) { public void register(@RequestBody RegisterRequest request) {
logger.info("Register request: {}", request); logger.info("Register request: {}", request);
userService.register(request); userService.register(request.username, request.password, request.role);
} }
@PostMapping("/login") @PostMapping("/login")
public AmisResponse<UserService.UserInformation> login(@RequestBody LoginRequest request) { public AmisResponse<UserService.UserInformation> login(@RequestBody LoginRequest request) {
logger.info("Login request: {}", request); logger.info("Login request: {}", request);
return AmisResponse.responseSuccess(userService.login(request)); return AmisResponse.responseSuccess(userService.login(request.username, request.password));
} }
@GetMapping("/logout/{username}") @GetMapping("/logout")
public void logout(@PathVariable("username") String username) { public void logout() {
logger.info("Logout request: {}", username); userService.logout();
userService.logout(username);
} }
@GetMapping("/exists_username/{username}") @GetMapping("/exists_username/{username}")
@@ -64,14 +63,14 @@ public class UserController {
} }
@Data @Data
public static class LoginRequest { public static final class LoginRequest {
private String username; private String username;
private String password; private String password;
private String checkCode; private String checkCode;
} }
@Data @Data
public static class RegisterRequest { public static final class RegisterRequest {
private String username; private String username;
private String password; private String password;
private User.Role role; private User.Role role;

View File

@@ -3,10 +3,13 @@ package com.eshore.gringotts.web.domain.user.controller;
import com.eshore.gringotts.web.configuration.amis.AmisListResponse; import com.eshore.gringotts.web.configuration.amis.AmisListResponse;
import com.eshore.gringotts.web.configuration.amis.AmisResponse; import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.user.service.UserService; import com.eshore.gringotts.web.domain.user.service.UserService;
import lombok.Data;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; 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.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@@ -32,6 +35,17 @@ public class UserManagementController {
return AmisListResponse.responseListData(userService.list()); return AmisListResponse.responseListData(userService.list());
} }
@GetMapping("/detail/{username}")
public AmisResponse<UserService.UserDetail> detail(@PathVariable String username) {
return AmisResponse.responseSuccess(userService.detail(username));
}
@PostMapping("/change_password")
public AmisResponse<Object> changePassword(@RequestBody ChangePasswordRequest request) {
userService.changePassword(request.oldPassword, request.newPassword);
return AmisResponse.responseSuccess();
}
@GetMapping("/disable/{username}") @GetMapping("/disable/{username}")
public AmisResponse<Object> disable(@PathVariable String username) { public AmisResponse<Object> disable(@PathVariable String username) {
userService.disable(username); userService.disable(username);
@@ -43,4 +57,10 @@ public class UserManagementController {
userService.enable(username); userService.enable(username);
return AmisResponse.responseSuccess(); return AmisResponse.responseSuccess();
} }
@Data
public static final class ChangePasswordRequest {
private String oldPassword;
private String newPassword;
}
} }

View File

@@ -5,7 +5,6 @@ import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import com.eshore.gringotts.web.domain.user.controller.UserController;
import com.eshore.gringotts.web.domain.user.entity.User; import com.eshore.gringotts.web.domain.user.entity.User;
import com.eshore.gringotts.web.domain.user.repository.UserRepository; import com.eshore.gringotts.web.domain.user.repository.UserRepository;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -33,11 +32,33 @@ public class UserService {
this.userRepository = userRepository; this.userRepository = userRepository;
} }
private static String encryptPassword(String password) {
String salt = "tY2gNdkt7x%%HcCAFc";
return SecureUtil.sha256(StrUtil.format("{}{}", salt, password));
}
/**
* 当数据库里没有用户的时候,增加一个默认的系统管理员
*/
public void initial() {
if (userRepository.count() == 0) {
User user = new User();
user.setUsername("administrator@eshore.com");
user.setPassword(encryptPassword("administrator"));
user.setRole(User.Role.ADMINISTRATOR);
user.setState(User.State.NORMAL);
userRepository.save(user);
}
}
/**
* 获取当前登陆账号状态
*/
public UserInformation state() { public UserInformation state() {
try { try {
// long id = StpUtil.getLoginIdAsLong(); long id = StpUtil.getLoginIdAsLong();
// User user = userRepository.findById(id).orElseThrow(LoginNotFoundException::new); User user = userRepository.findById(id).orElseThrow(LoginNotFoundException::new);
User user = userRepository.findByUsername("lanyuanxiaoyao@qq.com").orElseThrow(LoginNotFoundException::new); // User user = userRepository.findByUsername("administrator@eshore.com").orElseThrow(LoginNotFoundException::new);
StpUtil.login(user.getId()); StpUtil.login(user.getId());
return new UserInformation(user, StpUtil.getTokenInfo()); return new UserInformation(user, StpUtil.getTokenInfo());
} catch (NotLoginException e) { } catch (NotLoginException e) {
@@ -45,13 +66,16 @@ public class UserService {
} }
} }
public UserInformation login(UserController.LoginRequest request) { /**
User user = userRepository.findByUsername(request.getUsername()).orElseThrow(LoginFailureException::new); * 登陆操作
*/
public UserInformation login(String username, String password) {
User user = userRepository.findByUsername(username).orElseThrow(LoginFailureException::new);
if (user.getState() == User.State.CHECKING) { if (user.getState() == User.State.CHECKING) {
throw new LoginFailureByCheckingException(); throw new LoginFailureByCheckingException();
} else if (user.getState() == User.State.DISABLED) { } else if (user.getState() == User.State.DISABLED) {
throw new LoginFailureByDisabledException(); throw new LoginFailureByDisabledException();
} else if (!StrUtil.equals(encryptPassword(request.getPassword()), user.getPassword())) { } else if (!StrUtil.equals(encryptPassword(password), user.getPassword())) {
throw new LoginFailureException(); throw new LoginFailureException();
} else { } else {
StpUtil.login(user.getId()); StpUtil.login(user.getId());
@@ -59,23 +83,41 @@ public class UserService {
} }
} }
public void logout(String username) { /**
User user = userRepository.findByUsername(username).orElseThrow(LogoutFailureException::new); * 登出操作
StpUtil.login(user.getId()); */
public void logout() {
StpUtil.logout();
} }
public void register(UserController.RegisterRequest request) { /**
userRepository.save(toUser(request)); * 注册操作
*/
public void register(String username, String password, User.Role role) {
User user = new User();
user.setUsername(username);
user.setPassword(encryptPassword(password));
user.setRole(role);
userRepository.save(user);
} }
/**
* 是否存在用户名
*/
public boolean exitsUsername(String username) { public boolean exitsUsername(String username) {
return userRepository.existsByUsername(username); return userRepository.existsByUsername(username);
} }
/**
* 禁用账号
*/
public void disable(String username) { public void disable(String username) {
userRepository.updateStateByUsername(username, User.State.DISABLED); userRepository.updateStateByUsername(username, User.State.DISABLED);
} }
/**
* 启用账号
*/
public void enable(String username) { public void enable(String username) {
userRepository.updateStateByUsername(username, User.State.NORMAL); userRepository.updateStateByUsername(username, User.State.NORMAL);
} }
@@ -86,17 +128,26 @@ public class UserService {
.collect(UserListItem::new); .collect(UserListItem::new);
} }
private String encryptPassword(String password) { public void changePassword(String oldPassword, String newPassword) {
String salt = "tY2gNdkt7x%%HcCAFc"; long id = StpUtil.getLoginIdAsLong();
return SecureUtil.sha256(StrUtil.format("{}{}", salt, password)); User user = userRepository.findById(id).orElseThrow(LoginNotFoundException::new);
if (StrUtil.equals(encryptPassword(oldPassword), user.getPassword())) {
user.setPassword(encryptPassword(newPassword));
userRepository.save(user);
} else {
throw new ChangePasswordFailureException();
}
} }
private User toUser(UserController.RegisterRequest request) { public UserDetail detail(String username) {
User user = new User(); User user = userRepository.findByUsername(username).orElseThrow(UserNotFoundException::new);
user.setUsername(request.getUsername()); return new UserDetail(user);
user.setPassword(encryptPassword(request.getPassword())); }
user.setRole(request.getRole());
return user; public static class UserNotFoundException extends RuntimeException {
public UserNotFoundException() {
super("账号不存在");
}
} }
public static class LoginFailureException extends RuntimeException { public static class LoginFailureException extends RuntimeException {
@@ -133,6 +184,12 @@ public class UserService {
} }
} }
public static class ChangePasswordFailureException extends RuntimeException {
public ChangePasswordFailureException() {
super("原密码不正确");
}
}
@Data @Data
public static class UserInformation { public static class UserInformation {
private String username; private String username;
@@ -164,4 +221,23 @@ public class UserService {
this.updateTime = user.getUpdateTime(); this.updateTime = user.getUpdateTime();
} }
} }
@Data
public static class UserDetail {
private Long id;
private String username;
private User.Role role;
private User.State state;
private LocalDateTime createTime;
private LocalDateTime updateTime;
public UserDetail(User user) {
this.id = user.getId();
this.username = user.getUsername();
this.role = user.getRole();
this.state = user.getState();
this.createTime = user.getCreateTime();
this.updateTime = user.getUpdateTime();
}
}
} }

View File

@@ -1,4 +1,4 @@
function crudCommonOptions() { export function crudCommonOptions() {
return { return {
affixHeader: false, affixHeader: false,
stopAutoRefreshWhenModalIsOpen: true, stopAutoRefreshWhenModalIsOpen: true,
@@ -8,7 +8,7 @@ function crudCommonOptions() {
} }
} }
function readOnlyDialogOptions() { export function readOnlyDialogOptions() {
return { return {
actions: [], actions: [],
showCloseButton: false, showCloseButton: false,
@@ -18,7 +18,17 @@ function readOnlyDialogOptions() {
} }
} }
function paginationCommonOptions(perPage = true, maxButtons = 5) { export function horizontalFormOptions() {
return {
mode: 'horizontal',
canAccessSuperData: false,
horizontal: {
left: 2,
},
}
}
export function paginationCommonOptions(perPage = true, maxButtons = 5) {
let option = { let option = {
type: 'pagination', type: 'pagination',
layout: [ layout: [
@@ -34,7 +44,7 @@ function paginationCommonOptions(perPage = true, maxButtons = 5) {
return option return option
} }
function paginationTemplate(perPage = 20, maxButtons = 5) { export function paginationTemplate(perPage = 20, maxButtons = 5) {
return { return {
perPage: perPage, perPage: perPage,
headerToolbar: [ headerToolbar: [
@@ -48,7 +58,7 @@ function paginationTemplate(perPage = 20, maxButtons = 5) {
} }
} }
function mappingField(field, mapping) { export function mappingField(field, mapping) {
let mapData = { let mapData = {
'*': `<span class='label bg-gray-300'>\${${field}}</span>`, '*': `<span class='label bg-gray-300'>\${${field}}</span>`,
} }
@@ -70,97 +80,33 @@ function mappingItem(label, value, color = 'bg-info') {
} }
} }
const userRoleMapping = [ export const userRoleMapping = [
mappingItem('数据提供方', 'PROVIDER', 'bg-blue-500'), mappingItem('数据提供方', 'PROVIDER', 'bg-blue-500'),
mappingItem('数据使用方', 'CUSTOMER', 'bg-purple-500'), mappingItem('数据使用方', 'CUSTOMER', 'bg-purple-500'),
mappingItem('审核监管方', 'CHECKER', 'bg-cyan-500'), mappingItem('审核监管方', 'CHECKER', 'bg-cyan-500'),
mappingItem('系统管理员', 'ADMINISTRATOR', 'bg-green-500'), mappingItem('系统管理员', 'ADMINISTRATOR', 'bg-green-500'),
] ]
const userStateMapping = [ export const userStateMapping = [
mappingItem('审查中', 'CHECKING', 'bg-warning'), mappingItem('审查中', 'CHECKING', 'bg-warning'),
mappingItem('正常', 'NORMAL', 'bg-success'), mappingItem('正常', 'NORMAL', 'bg-success'),
mappingItem('禁用', 'DISABLED', 'bg-danger'), mappingItem('禁用', 'DISABLED', 'bg-danger'),
] ]
function userAddDialog() { function api(method, url) {
return { return {
actionType: 'dialog', method: method,
dialog: { url: url,
title: '新用户注册', headers: {
actions: [ token: '${token|default:undefined}',
{
type: 'reset',
label: '清空',
},
{
type: 'submit',
label: '注册',
level: 'primary',
}
],
body: {
type: 'form',
api: '${base}/user/register',
mode: 'horizontal',
canAccessSuperData: false,
horizontal: {
left: 2,
},
body: [
{
type: 'input-email',
name: 'username',
label: '邮箱',
placeholder: '请输入邮箱',
required: true,
clearable: true,
clearValueOnEmpty: true,
validateApi: '${base}/user/exists_username/${username}'
},
{
type: 'input-password',
name: 'password',
label: '密码',
placeholder: '请输入密码',
required: true,
clearable: true,
clearValueOnEmpty: true,
validations: {
matchRegexp: /^(?=.*\d)(?!.*(\d)\1{2})(?!.*(012|123|234|345|456|567|678|789|987|876|765|654|543|432|321|210))(?=.*[a-zA-Z])(?=.*[^\da-zA-Z\s]).{8,16}$/
},
validationErrors: {
matchRegexp: '密码至少包含字母、数字、特殊字符8-16位并且不能连续出现3个大小连续或相同的数字',
}
},
{
type: 'input-password',
name: 'confirm-password',
label: '确认密码',
placeholder: '请再次输入密码',
required: true,
clearable: true,
validations: {
equalsField: 'password'
},
validationErrors: {
equalsField: '两次输入密码不一致',
}
},
{
type: 'radios',
name: 'role',
label: '角色',
required: true,
selectFirst: true,
options: [
{label: '数据提供方', value: 'PROVIDER'},
{label: '数据使用方', value: 'CUSTOMER'},
{label: '审查监管方', value: 'CHECKER'},
]
},
]
}
} }
} }
} }
export function apiGet(url) {
return api('get', url)
}
export function apiPost(url) {
return api('post', url)
}

View File

@@ -1,5 +1,6 @@
const information = { export const information = {
debug: false, debug: true,
baseUrl: 'http://127.0.0.1:20080', baseUrl: '',
// baseUrl: 'http://127.0.0.1:20080',
title: '可信供给中心', title: '可信供给中心',
} }

View File

@@ -1,4 +1,4 @@
function overviewTab() { export function tabOverview() {
return { return {
title: '概览', title: '概览',
icon: 'fa fa-house', icon: 'fa fa-house',

View File

@@ -1,14 +1,14 @@
function userTab() { import {userRegisterDialog} from './user/dialog-user-register.js'
import {apiGet, crudCommonOptions, mappingField, userRoleMapping, userStateMapping} from '../common.js'
export function tabUser() {
return { return {
title: '用户管理', title: '用户管理',
icon: 'fa fa-user', icon: 'fa fa-user',
body: [ body: [
{ {
type: 'crud', type: 'crud',
api: { api: apiGet('${base}/user_management/list'),
method: 'get',
url: '${base}/user_management/list'
},
...crudCommonOptions(), ...crudCommonOptions(),
headerToolbar: [ headerToolbar: [
'reload', 'reload',
@@ -16,8 +16,8 @@ function userTab() {
type: 'action', type: 'action',
icon: 'fa fa-plus', icon: 'fa fa-plus',
tooltip: '新增账号', tooltip: '新增账号',
...userAddDialog(), ...userRegisterDialog(),
} },
], ],
columns: [ columns: [
{ {
@@ -61,7 +61,7 @@ function userTab() {
size: 'xs', size: 'xs',
}, },
{ {
visibleOn: "${state === 'NORMAL'}", visibleOn: "${state === 'NORMAL' && role !== 'ADMINISTRATOR'}",
label: '禁用', label: '禁用',
icon: 'fa fa-ban', icon: 'fa fa-ban',
level: 'danger', level: 'danger',
@@ -73,7 +73,7 @@ function userTab() {
}, },
{ {
visibleOn: "${state === 'DISABLED'}", visibleOn: "${state === 'DISABLED' && role !== 'ADMINISTRATOR'}",
label: '启用', label: '启用',
icon: 'fa fa-check', icon: 'fa fa-check',
level: 'success', level: 'success',

View File

@@ -0,0 +1,64 @@
import {horizontalFormOptions, apiPost} from '../../common.js'
export function userChangePasswordDialog() {
return {
actionType: 'dialog',
dialog: {
title: '修改密码',
actions: [
{
type: 'reset',
label: '清空',
},
{
type: 'submit',
label: '修改',
level: 'primary',
}
],
body: {
type: 'form',
api: apiPost('${base}/user_management/change_password'),
...horizontalFormOptions(),
body: [
{
type: 'input-password',
name: 'oldPassword',
label: '旧密码',
placeholder: '请输入旧密码',
required: true,
},
{
type: 'input-password',
name: 'newPassword',
label: '新密码',
placeholder: '请输入新密码',
required: true,
clearable: true,
clearValueOnEmpty: true,
validations: {
matchRegexp: /^(?=.*\d)(?!.*(\d)\1{2})(?!.*(012|123|234|345|456|567|678|789|987|876|765|654|543|432|321|210))(?=.*[a-zA-Z])(?=.*[^\da-zA-Z\s]).{8,16}$/
},
validationErrors: {
matchRegexp: '密码至少包含字母、数字、特殊字符8-16位并且不能连续出现3个大小连续或相同的数字',
}
},
{
type: 'input-password',
name: 'confirmNewPassword',
label: '确认新密码',
placeholder: '请再次输入新密码',
required: true,
clearable: true,
validations: {
equalsField: 'newPassword'
},
validationErrors: {
equalsField: '两次输入密码不一致',
}
},
]
}
}
}
}

View File

@@ -0,0 +1,34 @@
import {horizontalFormOptions} from "../../common.js";
export function userDetailDialog() {
return {
actionType: 'dialog',
dialog: {
title: '用户注册',
actions: [],
body: {
type: 'form',
api: '${base}/user_management/detail/${username}',
...horizontalFormOptions(),
static: true,
body: [
{
type: 'input-email',
name: 'username',
label: '邮箱',
},
{
type: 'input-password',
name: 'password',
label: '密码',
},
{
type: 'radios',
name: 'role',
label: '角色',
},
]
}
}
}
}

View File

@@ -0,0 +1,79 @@
import {horizontalFormOptions} from "../../common.js";
export function userRegisterDialog() {
return {
actionType: 'dialog',
dialog: {
title: '用户注册',
actions: [
{
type: 'reset',
label: '清空',
},
{
type: 'submit',
label: '注册',
level: 'primary',
}
],
body: {
type: 'form',
api: '${base}/user/register',
...horizontalFormOptions(),
body: [
{
type: 'input-email',
name: 'username',
label: '邮箱',
placeholder: '请输入邮箱',
required: true,
clearable: true,
clearValueOnEmpty: true,
validateApi: '${base}/user/exists_username/${username}'
},
{
type: 'input-password',
name: 'password',
label: '密码',
placeholder: '请输入密码',
required: true,
clearable: true,
clearValueOnEmpty: true,
validations: {
matchRegexp: /^(?=.*\d)(?!.*(\d)\1{2})(?!.*(012|123|234|345|456|567|678|789|987|876|765|654|543|432|321|210))(?=.*[a-zA-Z])(?=.*[^\da-zA-Z\s]).{8,16}$/
},
validationErrors: {
matchRegexp: '密码至少包含字母、数字、特殊字符8-16位并且不能连续出现3个大小连续或相同的数字',
}
},
{
type: 'input-password',
name: 'confirm-password',
label: '确认密码',
placeholder: '请再次输入密码',
required: true,
clearable: true,
validations: {
equalsField: 'password'
},
validationErrors: {
equalsField: '两次输入密码不一致',
}
},
{
type: 'radios',
name: 'role',
label: '角色',
required: true,
selectFirst: true,
options: [
{label: '数据提供方', value: 'PROVIDER'},
{label: '数据使用方', value: 'CUSTOMER'},
{label: '审查监管方', value: 'CHECKER'},
]
},
]
}
}
}
}

View File

@@ -23,23 +23,20 @@
<div id="root"></div> <div id="root"></div>
</body> </body>
<script src="assets/sdk/sdk.js"></script> <script src="assets/sdk/sdk.js"></script>
<script src="assets/component/constants.js"></script> <script type="module">
<script src="assets/component/common.js"></script> import {information} from './assets/component/constants.js'
<script src="assets/component/pages/overview-tab.js"></script> import {userChangePasswordDialog} from './assets/component/pages/user/dialog-user-change-password'
<script src="assets/component/pages/user-tab.js"></script> import {tabUser} from './assets/component/pages/tab-user.js'
<script> import {tabOverview} from './assets/component/pages/tab-overview.js'
import {apiGet} from "./assets/component/common.js";
(function () { (function () {
let amis = amisRequire('amis/embed') let amis = amisRequire('amis/embed')
let amisJSON = { let amisJSON = {
id: 'header-service',
className: 'h-full', className: 'h-full',
type: 'service', type: 'service',
api: { api: apiGet('${base}/user/state'),
method: 'get',
url: '${base}/user/state',
headers: {
token: '${token}'
},
},
onEvent: { onEvent: {
fetchInited: { fetchInited: {
actions: [ actions: [
@@ -48,6 +45,7 @@
actionType: 'url', actionType: 'url',
args: { args: {
url: '/login.html', url: '/login.html',
blank: false,
} }
} }
] ]
@@ -66,10 +64,14 @@
trigger: 'hover', trigger: 'hover',
buttons: [ buttons: [
{ {
label: '个人资料', label: '修改密码',
...userChangePasswordDialog(),
}, },
{ {
label: '退出登陆', label: '退出登陆',
actionType: 'ajax',
api: apiGet('${base}/user/logout'),
reload: 'header-service',
} }
] ]
} }
@@ -80,14 +82,13 @@
type: 'tabs', type: 'tabs',
tabsMode: 'vertical', tabsMode: 'vertical',
tabs: [ tabs: [
userTab(), tabOverview(),
overviewTab(), tabUser(),
] ]
}, },
} }
] ]
} }
let debug = false
amis.embed( amis.embed(
'#root', '#root',
amisJSON, amisJSON,
@@ -98,10 +99,10 @@
}, },
{ {
theme: 'antd', theme: 'antd',
enableAMISDebug: debug, enableAMISDebug: information.debug,
}, },
); );
if (debug) { if (information.debug) {
console.log('Source', amisJSON) console.log('Source', amisJSON)
} }
})() })()

View File

@@ -23,9 +23,11 @@
<div id="root"></div> <div id="root"></div>
</body> </body>
<script src="assets/sdk/sdk.js"></script> <script src="assets/sdk/sdk.js"></script>
<script src="assets/component/constants.js"></script>
<script src="assets/component/common.js"></script> <script src="assets/component/common.js"></script>
<script> <script type="module">
import {information} from './assets/component/constants.js'
import {userRegisterDialog} from './assets/component/pages/user/dialog-user-register'
(function () { (function () {
let amis = amisRequire('amis/embed') let amis = amisRequire('amis/embed')
let amisJSON = { let amisJSON = {
@@ -53,11 +55,14 @@
api: '${base}/user/login', api: '${base}/user/login',
redirect: '/index.html?token=${token}', redirect: '/index.html?token=${token}',
mode: 'horizontal', mode: 'horizontal',
horizontal: {
left: 2,
},
actions: [ actions: [
{ {
type: 'action', type: 'action',
label: '注册', label: '注册',
...userAddDialog(), ...userRegisterDialog(),
}, },
{ {
type: 'action', type: 'action',