更新
This commit is contained in:
parent
7700c383d6
commit
44b0ca4601
@ -1,6 +1,6 @@
|
||||
import request from '@/utils/request'
|
||||
import global from '@/utils/global'
|
||||
|
||||
const userKey:string = 'tansci_boot_user'
|
||||
const tokenKey:string = 'tansci_boot_token'
|
||||
const menuKey:string = 'tansci_boot_menu'
|
||||
|
||||
@ -15,18 +15,6 @@ export function removeToken() {
|
||||
sessionStorage.removeItem(tokenKey);
|
||||
}
|
||||
|
||||
// 用户信息
|
||||
export function getUser() {
|
||||
let user = sessionStorage.getItem(userKey);
|
||||
return user ? JSON.parse(user) : null;
|
||||
}
|
||||
export function setUser(data:any) {
|
||||
return sessionStorage.setItem(userKey, JSON.stringify(data));
|
||||
}
|
||||
export function removeUser() {
|
||||
return sessionStorage.removeItem(userKey);
|
||||
}
|
||||
|
||||
// 菜单信息
|
||||
export function getMenus() {
|
||||
let menu = sessionStorage.getItem(menuKey);
|
||||
@ -50,11 +38,10 @@ export function login(data:any){
|
||||
code: data.code
|
||||
}
|
||||
}).then((res:any) => {
|
||||
setToken(res.data.result.token)
|
||||
setUser(res.data.result)
|
||||
resolve(res.data.result.token)
|
||||
setToken(res.data.result.token)
|
||||
resolve(res.data.result.token)
|
||||
}).catch((e:any) => {
|
||||
reject(e)
|
||||
reject(e)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -66,7 +53,6 @@ export function logout(){
|
||||
method: 'get'
|
||||
}).then(() => {
|
||||
removeToken()
|
||||
removeUser()
|
||||
location.reload()
|
||||
})
|
||||
}
|
||||
@ -83,4 +69,15 @@ export function getCode(){
|
||||
reject(e)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export async function getUserInfo() {
|
||||
await request({
|
||||
url: '/tansci/sysuser/info',
|
||||
method: 'get'
|
||||
}).then((res:any) => {
|
||||
if(res.data.result){
|
||||
global.user.info = res.data.result
|
||||
}
|
||||
})
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 92 KiB |
BIN
tansci-boot-ui/src/assets/image/login-left.png
Normal file
BIN
tansci-boot-ui/src/assets/image/login-left.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 97 KiB |
@ -1,17 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, onBeforeMount, onDeactivated } from "vue"
|
||||
import { reactive, onMounted, onBeforeMount, onDeactivated, getCurrentInstance, ref } from "vue"
|
||||
import type { FormInstance, Action } from 'element-plus'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { isDark, toggleDark } from '@/composables'
|
||||
import { getUser, getMenus, logout } from "@/api/auth"
|
||||
import { getMenus, logout } from "@/api/auth"
|
||||
import { modifyPass } from "@/api/system/user"
|
||||
import Submenu from "@/components/Submenu.vue"
|
||||
import TabsMenu from "@/components/TabsMenu.vue"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const logo = new URL('../../assets/image/logo.png', import.meta.url).href
|
||||
const state = reactive({
|
||||
headerHeight: '52px',
|
||||
asideWidth: '180px',
|
||||
routers: [],
|
||||
defaultHeight: null,
|
||||
username: '未登录'
|
||||
userVisible: false,
|
||||
user: {
|
||||
avatar: '',
|
||||
username: '',
|
||||
nickname: '未登录',
|
||||
password: '',
|
||||
rePassword: '',
|
||||
oldPassword: ''
|
||||
}
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
@ -30,10 +42,7 @@
|
||||
})
|
||||
state.routers = routers
|
||||
|
||||
let user:any = getUser()
|
||||
if(user){
|
||||
state.username = user.nickname
|
||||
}
|
||||
state.user = proxy.$global.user.info
|
||||
|
||||
window.addEventListener('resize', onDefaultHeight);
|
||||
})
|
||||
@ -48,11 +57,45 @@
|
||||
function onHeaderCommand(command:any){
|
||||
if('logout' === command){
|
||||
logout()
|
||||
} else if('password' === command){
|
||||
|
||||
} else if('personal' === command){
|
||||
state.userVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
const userRef = ref<FormInstance>();
|
||||
const validatePass = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请输入确认密码'));
|
||||
} else if (value !== state.user.password) {
|
||||
callback(new Error('两次输入密码不一致!'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
const onUserSubmit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate((valid)=>{
|
||||
if(valid){
|
||||
modifyPass({
|
||||
username: state.user.username,
|
||||
password: state.user.password,
|
||||
oldPassword: state.user.oldPassword
|
||||
}).then(res=>{
|
||||
if(res){
|
||||
state.userVisible = false
|
||||
ElMessageBox.alert('修改密码成功,请重新登录!', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
type: 'warning',
|
||||
callback: (action: Action) =>{
|
||||
logout()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="layout-container">
|
||||
@ -60,6 +103,7 @@
|
||||
<el-header :height="state.headerHeight">
|
||||
<div class="header-logo">
|
||||
<el-image :src="logo"></el-image>
|
||||
<span class="title">{{proxy.$global.title}}</span>
|
||||
</div>
|
||||
<div class="header-content">
|
||||
<div class="header-dark">
|
||||
@ -73,12 +117,12 @@
|
||||
<div class="header-login">
|
||||
<el-dropdown @command="onHeaderCommand">
|
||||
<span class="el-dropdown-link">
|
||||
<span>{{state.username}}</span>
|
||||
<span>{{state.user.nickname}}</span>
|
||||
<el-icon class="el-icon--right"><arrow-down /></el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="password">修改密码</el-dropdown-item>
|
||||
<el-dropdown-item command="personal">个人中心</el-dropdown-item>
|
||||
<el-dropdown-item command="logout">退出</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
@ -102,11 +146,75 @@
|
||||
</el-aside>
|
||||
<el-main>
|
||||
<TabsMenu></TabsMenu>
|
||||
<router-view style="margin: 0 0.3rem 0 0.1rem"/>
|
||||
<el-card :shadow="proxy.$global.cardShadow" style="margin: 0.3rem;">
|
||||
<el-scrollbar :height="state.defaultHeight-150">
|
||||
<router-view />
|
||||
</el-scrollbar>
|
||||
</el-card>
|
||||
</el-main>
|
||||
</el-container>
|
||||
<el-backtop target=".el-main"></el-backtop>
|
||||
</el-container>
|
||||
<el-dialog v-model="state.userVisible" title="个人中心" width="40%" :show-close="false">
|
||||
<el-form :model="state.user" ref="userRef" :rules="rules" label-width="80px" status-icon>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="用户头像" prop="avatar">
|
||||
<el-avatar :size="50" :src="state.user.avatar" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户名称" prop="username">
|
||||
<el-input v-model="state.user.username" disabled style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户昵称" prop="nickname">
|
||||
<el-input v-model="state.user.nickname" disabled placeholder="请输入昵称" style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户电话" prop="phone">
|
||||
<el-input v-model="state.user.phone" disabled style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户邮箱" prop="email">
|
||||
<el-input v-model="state.user.email" disabled style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="原始密码" prop="oldPassword" :rules="[{required: true, message: '请输入原始密码', trigger: 'blur'}]">
|
||||
<el-input v-model="state.user.oldPassword" type="password" placeholder="请输入原始密码" style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="用户密码" prop="password" :rules="[{required: true, message: '请输入密码', trigger: 'blur'},
|
||||
{pattern: /^[a-zA-Z]\w{5,17}$/, message: '以字母开头,长度在6~18之间,只能包含字母、数字和下划线', trigger: 'blur'}]">
|
||||
<el-input v-model="state.user.password" type="password" placeholder="请输入密码" style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item prop="rePassword" label="确认密码" :rules="[{required: true, message: '请输入确认密码', trigger: 'blur'},{validator: validatePass, trigger: 'blur'}]">
|
||||
<el-input v-model="state.user.rePassword" type="password" placeholder="请输入确认密码"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="onUserSubmit(userRef)" type="primary">修改密码</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
@ -122,6 +230,12 @@
|
||||
line-height: 52px;
|
||||
padding-left: 0.2rem;
|
||||
cursor: pointer;
|
||||
.title{
|
||||
padding-left: 0.6rem;
|
||||
color: var(-t);
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
.header-content{
|
||||
display: flex;
|
||||
@ -171,7 +285,7 @@
|
||||
.el-main{
|
||||
padding: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.el-main::-webkit-scrollbar{
|
||||
width: 0px;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { createRouter, createWebHistory } from "vue-router"
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getToken, removeToken, removeUser, setMenus } from "@/api/auth"
|
||||
import { getToken, removeToken, setMenus, getUserInfo } from "@/api/auth"
|
||||
import common from '@/utils/common'
|
||||
import { generateRoutes } from "./permission"
|
||||
|
||||
@ -42,11 +42,11 @@ router.beforeEach(async (to:any, from:any, next) => {
|
||||
setMenus([...routers])
|
||||
})
|
||||
await common.getDictData()
|
||||
|
||||
await getUserInfo()
|
||||
|
||||
next({ ...to, replace: true })
|
||||
} catch (error:any) {
|
||||
removeToken()
|
||||
removeUser()
|
||||
ElMessage.error(error.data || 'Has Error')
|
||||
next(`/login`)
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import request from '@/utils/request'
|
||||
import common from '@/utils/common'
|
||||
import Layout from '@/components/layout/Index.vue'
|
||||
|
||||
const modules = import.meta.glob('../views/**/**.vue')
|
||||
@ -13,7 +12,7 @@ export const filterRouter = (routers:any, level:any) => {
|
||||
var setIframe = () => {
|
||||
router.component = loadView(`/common/Iframe`)
|
||||
router.props = { url: router.path }
|
||||
router.path = "/" + common.uuid()
|
||||
router.path = "/" + router.name
|
||||
}
|
||||
|
||||
if(router.path && router.path.startsWith('http') && router.meta.openMode === 1){
|
||||
|
||||
@ -5,6 +5,9 @@
|
||||
// 主题
|
||||
--theme: #2F9688;
|
||||
|
||||
// 文字
|
||||
--t: #1d1d1f;
|
||||
|
||||
// 局部背景
|
||||
// --el-bg-color: radial-gradient( white 0%, #FAFDFE 10%, #ddf8e7 50%, #FAFDFE 90%, white 100%);
|
||||
// --el-bg-color: radial-gradient(#d9f8e5 0%, #FAFDFE 80%, #e7fcef 100%);
|
||||
@ -36,7 +39,7 @@ body {
|
||||
* Dialog 对话框
|
||||
*/
|
||||
.el-dialog__header{
|
||||
background-color: var(--el-color-primary);
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
margin-right: 0;
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
// 全局变量配置
|
||||
export default {
|
||||
title: 'Tansci Boot',
|
||||
baseApi: import.meta.env.VITE_BASE_API,
|
||||
cardShadow: 'always',
|
||||
cardShadow: 'never',
|
||||
user: {
|
||||
info: {}
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, getCurrentInstance } from "vue"
|
||||
import { reactive, onMounted } from "vue"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const state = reactive({
|
||||
|
||||
})
|
||||
@ -12,9 +11,9 @@
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="home-container" :shadow="proxy.$global.cardShadow">
|
||||
<div class="home-container">
|
||||
首页
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.home-container{
|
||||
|
||||
@ -14,8 +14,8 @@
|
||||
<style scoped>
|
||||
iframe{
|
||||
position: absolute;
|
||||
left: 180px;
|
||||
top: 100px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
const loginFormRef = ref<FormInstance>()
|
||||
|
||||
const logo = new URL('../../assets/image/logo.png', import.meta.url).href
|
||||
const loginLogo = new URL('../../assets/image/login-icon.png', import.meta.url).href
|
||||
const loginLogo = new URL('../../assets/image/login-left.png', import.meta.url).href
|
||||
const codeImg = ref()
|
||||
|
||||
const state = reactive({
|
||||
@ -81,7 +81,7 @@
|
||||
<div class="main-title">帐号登录</div>
|
||||
<div class="main-container">
|
||||
<div class="logo">
|
||||
<el-image :src="loginLogo" style="width: 100%; height: 100%;"></el-image>
|
||||
<el-image :src="loginLogo" style="width: 100%; height: 80%;"></el-image>
|
||||
</div>
|
||||
<div class="form">
|
||||
<el-form :model="state.loginForm" :rules="rules" size="large" ref="loginFormRef">
|
||||
@ -95,8 +95,8 @@
|
||||
<el-input type="password" v-model="state.loginForm.password" prefix-icon="Lock" show-password placeholder="请输入密码" style="width:100%"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="code" :rules="[{required: true,message: '请输入验证码',trigger: 'blur'}]">
|
||||
<el-input v-model="state.loginForm.code" prefix-icon="HelpFilled" placeholder="请输入验证码" style="width:70%; margin-right: 1%"></el-input>
|
||||
<img :src="codeImg" @click="onCode" style="width: 29%; height: 38px;">
|
||||
<el-input v-model="state.loginForm.code" prefix-icon="HelpFilled" placeholder="请输入验证码" style="width: calc(100% - 110px); margin-right: 6px;"></el-input>
|
||||
<el-image @click="onCode" :src="codeImg" fit="fill" style="width: 102px; height: 38px; border: 1px solid #dcdfe6; border-radius: 4px;"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="state.loginForm.remember">记住密码</el-checkbox>
|
||||
@ -134,7 +134,7 @@
|
||||
padding: 0 20%;
|
||||
.title{
|
||||
padding: 0 1rem;
|
||||
color: var(--t9);
|
||||
color: var(--t);
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
}
|
||||
@ -145,6 +145,7 @@
|
||||
font-size: 32px;
|
||||
text-align: center;
|
||||
padding: 5rem 0;
|
||||
color: var(--t);
|
||||
}
|
||||
.main-container{
|
||||
display: flex;
|
||||
@ -169,7 +170,7 @@
|
||||
.login-footer{
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
color: #606266;
|
||||
color: #1d1d1f;
|
||||
padding-top: 1.2rem;
|
||||
.copy{
|
||||
padding-top: 1rem;
|
||||
|
||||
@ -1,21 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, getCurrentInstance } from "vue"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
import { reactive, onMounted } from "vue"
|
||||
|
||||
const state = reactive({
|
||||
shadow: 'always',
|
||||
})
|
||||
const state = reactive({
|
||||
shadow: 'always',
|
||||
})
|
||||
|
||||
onMounted(()=>{
|
||||
|
||||
})
|
||||
onMounted(()=>{
|
||||
|
||||
})
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="codegen-container" :shadow="proxy.$global.cardShadow">
|
||||
<div class="codegen-container">
|
||||
开发中
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.codegen-container{
|
||||
|
||||
@ -9,10 +9,16 @@
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<e-card :shadow="proxy.$global.cardShadow">
|
||||
<iframe :src="state.url" width="100%" height="90%" frameborder="0"></iframe>
|
||||
</e-card>
|
||||
<div>
|
||||
<iframe :src="state.url" width="100%" height="100%" frameborder="0"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
|
||||
iframe{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
||||
@ -1,9 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, getCurrentInstance } from "vue"
|
||||
import { reactive, onMounted } from "vue"
|
||||
import Table from '@/components/Table.vue'
|
||||
import { page } from "@/api/monitor/loginLog"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
page: {
|
||||
@ -74,11 +73,11 @@
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="loginlog-container" :shadow="proxy.$global.cardShadow">
|
||||
<div class="loginlog-container">
|
||||
<Table :data="state.tableData" :column="state.tableTitle" :operation="state.operation" :page="state.page" :loading="state.loading"
|
||||
@onSizeChange="onSizeChange" @onCurrentChange="onCurrentChange" @setCellColor="setCellColor">
|
||||
</Table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.loginlog-container{
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import {onMounted, reactive, ref, unref, getCurrentInstance} from 'vue'
|
||||
import {onMounted, reactive, ref, unref} from 'vue'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import type {FormInstance} from 'element-plus'
|
||||
import Table from '@/components/Table.vue'
|
||||
import {page,kick} from '@/api/monitor/onlineUser'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const searchForm = reactive({
|
||||
username: null
|
||||
})
|
||||
@ -85,7 +84,7 @@
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="onlineuser-container" :shadow="proxy.$global.cardShadow">
|
||||
<div class="onlineuser-container">
|
||||
<Table :data="table.tableData" :column="table.tableTitle" :operation="table.operation" :page="table.page" :loading="table.loading"
|
||||
@onSizeChange="onSizeChange" @onCurrentChange="onCurrentChange">
|
||||
<template #search>
|
||||
@ -97,7 +96,7 @@
|
||||
<el-button @click="onKick(scope)" type='primary' text='primary' style="color:var(--edit); padding:0;">踢人</el-button>
|
||||
</template>
|
||||
</Table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
.onlineuser-container{
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, getCurrentInstance } from "vue"
|
||||
import { reactive, onMounted } from "vue"
|
||||
import Table from '@/components/Table.vue'
|
||||
import { page } from "@/api/monitor/operLog"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
page: {
|
||||
@ -85,7 +84,7 @@
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="operlog-container" :shadow="proxy.$global.cardShadow">
|
||||
<div class="operlog-container">
|
||||
<Table :data="state.tableData" :column="state.tableTitle" :operation="state.operation" :page="state.page" :loading="state.loading"
|
||||
@onSizeChange="onSizeChange" @onCurrentChange="onCurrentChange" @setCellColor="setCellColor">
|
||||
<template #column="scope">
|
||||
@ -126,7 +125,7 @@
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.operlog-container{
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import {onMounted, reactive, ref, getCurrentInstance} from 'vue'
|
||||
import {onMounted, reactive, ref} from 'vue'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import type {FormInstance} from 'element-plus'
|
||||
import common from '@/utils/common'
|
||||
import Table from '@/components/Table.vue'
|
||||
import {tree,save,update,del} from '@/api/system/dict'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const table = reactive({
|
||||
loading: false,
|
||||
operation:{
|
||||
@ -144,7 +143,7 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-card class="dict-container" :shadow="proxy.$global.cardShadow">
|
||||
<div class="dict-container">
|
||||
<Table :data="table.tableData" :column="table.tableTitle" :operation="table.operation" :page="false" :loading="table.loading">
|
||||
<template #search>
|
||||
<div><el-button @click="onAdd(null)" type="primary">添加</el-button></div>
|
||||
@ -206,7 +205,7 @@
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.dict-container{
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import {onMounted, reactive, ref, getCurrentInstance} from 'vue'
|
||||
import {onMounted, reactive, ref} from 'vue'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import type {FormInstance} from 'element-plus'
|
||||
import {list,save,update,del} from '@/api/system/menu'
|
||||
import ElIcon from '@/components/ElIcon.vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const menuFormRef = ref<FormInstance>();
|
||||
const state = reactive({
|
||||
treeData: [],
|
||||
@ -188,20 +187,22 @@
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="menu-container" :shadow="proxy.$global.cardShadow">
|
||||
<el-card class="menu-tree" shadow="never">
|
||||
<el-tree :data="state.treeData" :props="{children: 'children', label: 'chineseName'}" highlight-current @node-click="onNodeClick" empty-text="暂无菜单">
|
||||
<template #default="{ node, data }">
|
||||
<span class="custom-tree-node">
|
||||
<el-icon v-if="data.icon" style="vertical-align: middle;padding-right:10px;">
|
||||
<component :is="data.icon"></component>
|
||||
</el-icon>
|
||||
<span>{{ node.label }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-card>
|
||||
<el-card class="menu-form" shadow="never">
|
||||
<div class="menu-container">
|
||||
<div class="menu-tree">
|
||||
<el-scrollbar height="45rem">
|
||||
<el-tree :data="state.treeData" :props="{children: 'children', label: 'chineseName'}" highlight-current @node-click="onNodeClick" empty-text="暂无菜单">
|
||||
<template #default="{ node, data }">
|
||||
<span class="custom-tree-node">
|
||||
<el-icon v-if="data.icon" style="vertical-align: middle;padding-right:10px;">
|
||||
<component :is="data.icon"></component>
|
||||
</el-icon>
|
||||
<span>{{ node.label }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div class="menu-form">
|
||||
<el-radio-group @change="onTypeChange" v-model="state.type">
|
||||
<el-radio-button :label="1">菜单</el-radio-button>
|
||||
<el-radio-button :label="2">按钮</el-radio-button>
|
||||
@ -268,17 +269,17 @@
|
||||
<el-button type="primary" @click="onSubmit(menuFormRef)">提交</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss">
|
||||
.menu-container{
|
||||
padding-bottom: 1.5rem;
|
||||
display: flex;
|
||||
.menu-tree{
|
||||
float: left;
|
||||
margin-right: 1rem;
|
||||
min-width: 300px;
|
||||
min-height: 700px;
|
||||
border-right: 1px solid #e4e7ed;
|
||||
margin: 0 4rem 0 1rem;
|
||||
min-width: 12rem;
|
||||
.el-tree-node:hover>.el-tree-node__content{
|
||||
background-color: #fff !important;
|
||||
color: var(--theme) !important;
|
||||
@ -290,6 +291,7 @@
|
||||
}
|
||||
}
|
||||
.menu-form{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,11 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import {onMounted, reactive, ref, getCurrentInstance} from 'vue'
|
||||
import {onMounted, reactive, ref} from 'vue'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import type {FormInstance} from 'element-plus'
|
||||
import Table from '@/components/Table.vue'
|
||||
import {list,save,update,del} from '@/api/system/org'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const table = reactive({
|
||||
loading: false,
|
||||
operation:{
|
||||
@ -127,7 +126,7 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-card class="org-container" :shadow="proxy.$global.cardShadow">
|
||||
<div class="org-container">
|
||||
<Table :data="table.tableData" :column="table.tableTitle" :operation="table.operation" :page="false" :loading="table.loading">
|
||||
<template #search>
|
||||
<div><el-button @click="onAdd(null)" type="primary">添加</el-button></div>
|
||||
@ -157,7 +156,7 @@
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.org-container{
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import {onMounted, reactive, ref, unref, getCurrentInstance} from 'vue'
|
||||
import {onMounted, reactive, ref, unref} from 'vue'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import type {FormInstance} from 'element-plus'
|
||||
import {page,save,update,del,dataPermissions,orgList,menuPermissions,menuList} from '@/api/system/role'
|
||||
import Table from '@/components/Table.vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const searchForm = reactive({
|
||||
name: null,
|
||||
})
|
||||
@ -209,7 +208,7 @@
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="role-container" :shadow="proxy.$global.cardShadow">
|
||||
<div class="role-container">
|
||||
<Table :data="table.tableData" :column="table.tableTitle" :operation="table.operation" :page="table.page" :loading="table.loading"
|
||||
@onSizeChange="onSizeChange" @onCurrentChange="onCurrentChange">
|
||||
<template #search>
|
||||
@ -263,7 +262,7 @@
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
.role-container{
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import {onMounted, reactive, ref, unref, getCurrentInstance} from 'vue'
|
||||
import {onMounted, reactive, ref, unref} from 'vue'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import type {FormInstance} from 'element-plus'
|
||||
import Table from '@/components/Table.vue'
|
||||
import {page,save,update,del,roleList} from '@/api/system/user'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const searchForm = reactive({
|
||||
username: null
|
||||
})
|
||||
@ -218,7 +217,7 @@
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="user-container" :shadow="proxy.$global.cardShadow">
|
||||
<div class="user-container">
|
||||
<Table :data="table.tableData" :column="table.tableTitle" :operation="table.operation" :page="table.page" :loading="table.loading"
|
||||
@onSizeChange="onSizeChange" @onCurrentChange="onCurrentChange" @onSwitchChange="onSwitchChange">
|
||||
<template #search>
|
||||
@ -252,7 +251,7 @@
|
||||
<el-col :span="12">
|
||||
<el-form-item v-if="form.operate == 0" label="密码" prop="password" :rules="[{required: true, message: '请输入密码', trigger: 'blur'},
|
||||
{pattern: /^[a-zA-Z]\w{5,17}$/, message: '以字母开头,长度在6~18之间,只能包含字母、数字和下划线', trigger: 'blur'}]">
|
||||
<el-input v-model="form.userForm.password" placeholder="请输入密码" style="width: 100%"/>
|
||||
<el-input v-model="form.userForm.password" type="password" placeholder="请输入密码" style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
@ -327,7 +326,7 @@
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
.user-container{
|
||||
|
||||
@ -8,6 +8,7 @@ import com.tansci.common.Wrapper;
|
||||
import com.tansci.common.annotation.Log;
|
||||
import com.tansci.common.constant.Constants;
|
||||
import com.tansci.domain.SysUser;
|
||||
import com.tansci.domain.vo.UserAuthVo;
|
||||
import com.tansci.service.SysUserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@ -48,6 +49,13 @@ public class SysUserController {
|
||||
return WrapMapper.wrap(Wrapper.SUCCESS_CODE, Wrapper.SUCCESS_MESSAGE, sysUserService.list(user));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "用户信息", notes = "用户信息")
|
||||
@Log(modul = "用户管理", type = Constants.SELECT, desc = "用户信息")
|
||||
@GetMapping("/info")
|
||||
public Wrapper<UserAuthVo> info() {
|
||||
return WrapMapper.wrap(Wrapper.SUCCESS_CODE, Wrapper.SUCCESS_MESSAGE, sysUserService.info());
|
||||
}
|
||||
|
||||
@ApiOperation(value = "添加", notes = "添加")
|
||||
@Log(modul = "用户管理", type = Constants.INSERT, desc = "添加")
|
||||
@PostMapping("/save")
|
||||
|
||||
@ -93,6 +93,10 @@ public class SysUser {
|
||||
@ApiModelProperty(value = "备注")
|
||||
private String remarks;
|
||||
|
||||
@TableField(exist = false)
|
||||
@ApiModelProperty(value = "原密码")
|
||||
private String oldPassword;
|
||||
|
||||
@TableField(exist = false)
|
||||
@ApiModelProperty(value = "角色ID")
|
||||
private String roleId;
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package com.tansci.domain.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @ClassName: UserAuthVo.java
|
||||
* @ClassPath: com.tansci.domain.vo.UserAuthVo.java
|
||||
* @Description: 用户权限信息
|
||||
* @Author: tanyp
|
||||
* @Date: 2023/3/29 9:13
|
||||
**/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ApiModel(value = "用户权限信息")
|
||||
public class UserAuthVo {
|
||||
|
||||
@ApiModelProperty(value = "用户名称")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty(value = "用户昵称")
|
||||
private String nickname;
|
||||
|
||||
@ApiModelProperty(value = "用户类型:1、管理员,2、普通用户")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty(value = "头像")
|
||||
private String avatar;
|
||||
|
||||
@ApiModelProperty(value = "手机号")
|
||||
private String phone;
|
||||
|
||||
@ApiModelProperty(value = "邮箱")
|
||||
private String email;
|
||||
|
||||
}
|
||||
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.tansci.domain.SysUser;
|
||||
import com.tansci.domain.vo.SysUserVo;
|
||||
import com.tansci.domain.vo.UserAuthVo;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
@ -22,6 +23,8 @@ public interface SysUserService extends IService<SysUser> {
|
||||
|
||||
List<SysUser> list(SysUser user);
|
||||
|
||||
UserAuthVo info();
|
||||
|
||||
Object insert(SysUser user);
|
||||
|
||||
Object update(SysUser user);
|
||||
|
||||
@ -12,6 +12,7 @@ import com.tansci.domain.SysUser;
|
||||
import com.tansci.domain.SysUserRole;
|
||||
import com.tansci.domain.vo.SysUserSessionVo;
|
||||
import com.tansci.domain.vo.SysUserVo;
|
||||
import com.tansci.domain.vo.UserAuthVo;
|
||||
import com.tansci.mapper.SysUserMapper;
|
||||
import com.tansci.service.SysLoginLogService;
|
||||
import com.tansci.service.SysUserRoleService;
|
||||
@ -27,7 +28,6 @@ import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @ClassName: SysUserServiceImpl.java
|
||||
@ -77,6 +77,18 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserAuthVo info() {
|
||||
SysUser user = this.baseMapper.selectById(String.valueOf(StpUtil.getLoginId()));
|
||||
return UserAuthVo.builder()
|
||||
.username(user.getUsername())
|
||||
.nickname(user.getNickname())
|
||||
.type(user.getType())
|
||||
.phone(user.getPhone())
|
||||
.email(user.getEmail())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object insert(SysUser user) {
|
||||
Integer count = this.baseMapper.selectCount(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, user.getUsername()));
|
||||
@ -137,7 +149,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
throw new BusinessException("登录失败,用户名或密码有误!");
|
||||
}
|
||||
|
||||
if(Objects.equals(Constants.USER_IS_LOGIN_ON, sysUser.getIsLogin())){
|
||||
if (Objects.equals(Constants.USER_IS_LOGIN_ON, sysUser.getIsLogin())) {
|
||||
loginLog.setType("失败");
|
||||
loginLog.setMessage("该账号已被禁用");
|
||||
throw new BusinessException("登录失败,该账号已被禁用!");
|
||||
@ -174,7 +186,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
public Object modifyPass(SysUser user) {
|
||||
SysUser sysUser = this.baseMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, user.getUsername()));
|
||||
|
||||
if (Objects.isNull(sysUser) || !Objects.equals(Sha256Util.getSHA256(sysUser.getPassword()), Sha256Util.getSHA256(user.getPassword()))) {
|
||||
if (Objects.isNull(sysUser) || !Objects.equals(sysUser.getPassword(), Sha256Util.getSHA256(user.getOldPassword()))) {
|
||||
throw new BusinessException("原始密码错误,请重新输入!");
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user