更新
This commit is contained in:
parent
7e7c6c2340
commit
5e6251880b
@ -38,7 +38,7 @@ github地址:https://gitee.com/ktianc/kinit👩👦👦
|
|||||||
|
|
||||||
- [x] 👨🎓用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
- [x] 👨🎓用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
||||||
|
|
||||||
- [ ] 🏡个人主页:配置用户个人信息,密码修改等。
|
- [x] 🏡个人主页:配置用户个人信息,密码修改等。
|
||||||
|
|
||||||
- [x] 📚字典管理:对系统中经常使用的一些较为固定的数据进行维护。
|
- [x] 📚字典管理:对系统中经常使用的一些较为固定的数据进行维护。
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ github地址:https://gitee.com/ktianc/kinit👩👦👦
|
|||||||
|
|
||||||
- [ ] 🗓️操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
- [ ] 🗓️操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
||||||
|
|
||||||
- [ ] 🔒登录认证:目前支持用户使用手机号+密码方式登录。
|
- [x] 🔒登录认证:目前支持用户使用手机号+密码方式登录。
|
||||||
|
|
||||||
说明:新建用户密码默认为手机号后六位;
|
说明:新建用户密码默认为手机号后六位;
|
||||||
|
|
||||||
|
@ -35,42 +35,42 @@ export default [
|
|||||||
name: 'Github',
|
name: 'Github',
|
||||||
icon: 'akar-icons:github-fill',
|
icon: 'akar-icons:github-fill',
|
||||||
message: 'workplace.introduction',
|
message: 'workplace.introduction',
|
||||||
personal: 'Archer',
|
personal: 'kinit',
|
||||||
time: new Date()
|
time: new Date()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Vue',
|
name: 'Vue',
|
||||||
icon: 'logos:vue',
|
icon: 'logos:vue',
|
||||||
message: 'workplace.introduction',
|
message: 'workplace.introduction',
|
||||||
personal: 'Archer',
|
personal: 'kinit',
|
||||||
time: new Date()
|
time: new Date()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Angular',
|
name: 'Angular',
|
||||||
icon: 'logos:angular-icon',
|
icon: 'logos:angular-icon',
|
||||||
message: 'workplace.introduction',
|
message: 'workplace.introduction',
|
||||||
personal: 'Archer',
|
personal: 'kinit',
|
||||||
time: new Date()
|
time: new Date()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'React',
|
name: 'React',
|
||||||
icon: 'logos:react',
|
icon: 'logos:react',
|
||||||
message: 'workplace.introduction',
|
message: 'workplace.introduction',
|
||||||
personal: 'Archer',
|
personal: 'kinit',
|
||||||
time: new Date()
|
time: new Date()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Webpack',
|
name: 'Webpack',
|
||||||
icon: 'logos:webpack',
|
icon: 'logos:webpack',
|
||||||
message: 'workplace.introduction',
|
message: 'workplace.introduction',
|
||||||
personal: 'Archer',
|
personal: 'kinit',
|
||||||
time: new Date()
|
time: new Date()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Vite',
|
name: 'Vite',
|
||||||
icon: 'vscode-icons:file-type-vite',
|
icon: 'vscode-icons:file-type-vite',
|
||||||
message: 'workplace.introduction',
|
message: 'workplace.introduction',
|
||||||
personal: 'Archer',
|
personal: 'kinit',
|
||||||
time: new Date()
|
time: new Date()
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -23,3 +23,11 @@ export const getUserApi = (dataId: number): Promise<IResponse> => {
|
|||||||
export const postCurrentUserResetPassword = (data: any): Promise<IResponse> => {
|
export const postCurrentUserResetPassword = (data: any): Promise<IResponse> => {
|
||||||
return request.post({ url: `/vadmin/auth/user/current/reset/password/`, data })
|
return request.post({ url: `/vadmin/auth/user/current/reset/password/`, data })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const postCurrentUserUpdateInfo = (data: any): Promise<IResponse> => {
|
||||||
|
return request.post({ url: `/vadmin/auth/user/current/update/info/`, data })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getCurrentUserInfo = (): Promise<IResponse> => {
|
||||||
|
return request.get({ url: `/vadmin/auth/user/current/info/` })
|
||||||
|
}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ElDropdown, ElDropdownMenu, ElDropdownItem, ElMessageBox } from 'element-plus'
|
import { ElDropdown, ElDropdownMenu, ElDropdownItem, ElMessageBox } from 'element-plus'
|
||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
import { useCache } from '@/hooks/web/useCache'
|
|
||||||
import { resetRouter } from '@/router'
|
import { resetRouter } from '@/router'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
import { useTagsViewStore } from '@/store/modules/tagsView'
|
import { useTagsViewStore } from '@/store/modules/tagsView'
|
||||||
import { useAppStoreWithOut } from '@/store/modules/app'
|
import { useAuthStoreWithOut } from '@/store/modules/auth'
|
||||||
|
|
||||||
const tagsViewStore = useTagsViewStore()
|
const tagsViewStore = useTagsViewStore()
|
||||||
|
|
||||||
@ -16,9 +15,9 @@ const prefixCls = getPrefixCls('user-info')
|
|||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
const { wsCache } = useCache()
|
const authStore = useAuthStoreWithOut()
|
||||||
|
|
||||||
const { replace } = useRouter()
|
const { replace, push } = useRouter()
|
||||||
|
|
||||||
const loginOut = () => {
|
const loginOut = () => {
|
||||||
ElMessageBox.confirm(t('common.loginOutMessage'), t('common.reminder'), {
|
ElMessageBox.confirm(t('common.loginOutMessage'), t('common.reminder'), {
|
||||||
@ -27,7 +26,7 @@ const loginOut = () => {
|
|||||||
type: 'warning'
|
type: 'warning'
|
||||||
})
|
})
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
wsCache.clear()
|
authStore.logout()
|
||||||
tagsViewStore.delAllViews()
|
tagsViewStore.delAllViews()
|
||||||
resetRouter() // 重置静态路由表
|
resetRouter() // 重置静态路由表
|
||||||
replace('/login')
|
replace('/login')
|
||||||
@ -39,9 +38,11 @@ const toDocument = () => {
|
|||||||
window.open('https://element-plus-admin-doc.cn/')
|
window.open('https://element-plus-admin-doc.cn/')
|
||||||
}
|
}
|
||||||
|
|
||||||
const appStore = useAppStoreWithOut()
|
const toHome = () => {
|
||||||
|
push('/system/home')
|
||||||
|
}
|
||||||
|
|
||||||
const user = wsCache.get(appStore.getUserInfo)
|
const user = authStore.getUser
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -59,7 +60,7 @@ const user = wsCache.get(appStore.getUserInfo)
|
|||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<ElDropdownMenu>
|
<ElDropdownMenu>
|
||||||
<ElDropdownItem>
|
<ElDropdownItem>
|
||||||
<div @click="toDocument">个人主页</div>
|
<div @click="toHome">个人主页</div>
|
||||||
</ElDropdownItem>
|
</ElDropdownItem>
|
||||||
<ElDropdownItem>
|
<ElDropdownItem>
|
||||||
<div @click="toDocument">前端项目文档</div>
|
<div @click="toDocument">前端项目文档</div>
|
||||||
|
@ -201,7 +201,7 @@ export default {
|
|||||||
yield: '产量',
|
yield: '产量',
|
||||||
dynamic: '动态',
|
dynamic: '动态',
|
||||||
push: '推送',
|
push: '推送',
|
||||||
pushCode: 'Archer 推送 代码到 Github',
|
pushCode: 'kinit 推送 代码到 Github',
|
||||||
follow: '关注'
|
follow: '关注'
|
||||||
},
|
},
|
||||||
formDemo: {
|
formDemo: {
|
||||||
|
@ -7,10 +7,12 @@ import { useNProgress } from '@/hooks/web/useNProgress'
|
|||||||
import { usePermissionStoreWithOut } from '@/store/modules/permission'
|
import { usePermissionStoreWithOut } from '@/store/modules/permission'
|
||||||
import { usePageLoading } from '@/hooks/web/usePageLoading'
|
import { usePageLoading } from '@/hooks/web/usePageLoading'
|
||||||
import { getRoleMenusApi } from '@/api/login'
|
import { getRoleMenusApi } from '@/api/login'
|
||||||
|
import { useAuthStoreWithOut } from '@/store/modules/auth'
|
||||||
|
|
||||||
const permissionStore = usePermissionStoreWithOut()
|
const permissionStore = usePermissionStoreWithOut()
|
||||||
|
|
||||||
const appStore = useAppStoreWithOut()
|
const appStore = useAppStoreWithOut()
|
||||||
|
const authStore = useAuthStoreWithOut()
|
||||||
|
|
||||||
const { wsCache } = useCache()
|
const { wsCache } = useCache()
|
||||||
|
|
||||||
@ -27,6 +29,9 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
if (to.path === '/login') {
|
if (to.path === '/login') {
|
||||||
next({ path: '/' })
|
next({ path: '/' })
|
||||||
} else {
|
} else {
|
||||||
|
if (!authStore.getIsUser) {
|
||||||
|
await authStore.getUserInfo()
|
||||||
|
}
|
||||||
if (permissionStore.getIsAddRouters) {
|
if (permissionStore.getIsAddRouters) {
|
||||||
next()
|
next()
|
||||||
return
|
return
|
||||||
|
@ -4,26 +4,47 @@ import { UserLoginType } from '@/api/login/types'
|
|||||||
import { loginApi } from '@/api/login'
|
import { loginApi } from '@/api/login'
|
||||||
import { useAppStore } from '@/store/modules/app'
|
import { useAppStore } from '@/store/modules/app'
|
||||||
import { useCache } from '@/hooks/web/useCache'
|
import { useCache } from '@/hooks/web/useCache'
|
||||||
|
import { getCurrentUserInfo } from '@/api/vadmin/auth/user'
|
||||||
|
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
const { wsCache } = useCache()
|
const { wsCache } = useCache()
|
||||||
|
|
||||||
|
export interface UserState {
|
||||||
|
id?: number
|
||||||
|
telephone?: string
|
||||||
|
name?: string
|
||||||
|
nickname?: string
|
||||||
|
avatar?: string
|
||||||
|
gender?: string
|
||||||
|
roles?: Recordable[]
|
||||||
|
create_datetime?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AuthState {
|
||||||
|
user: UserState
|
||||||
|
isUser: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export const useAuthStore = defineStore({
|
export const useAuthStore = defineStore({
|
||||||
id: 'auth',
|
id: 'auth',
|
||||||
state: () => {
|
state: (): AuthState => {
|
||||||
return {}
|
return {
|
||||||
|
user: {},
|
||||||
|
isUser: false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
persist: {
|
persist: {
|
||||||
// 开启持久化存储
|
// 开启持久化存储
|
||||||
enabled: true,
|
enabled: true
|
||||||
strategies: [
|
},
|
||||||
{
|
getters: {
|
||||||
key: 'authStore',
|
getUser(): UserState {
|
||||||
storage: localStorage
|
return this.user
|
||||||
}
|
},
|
||||||
]
|
getIsUser(): boolean {
|
||||||
|
return this.isUser
|
||||||
|
}
|
||||||
},
|
},
|
||||||
getters: {},
|
|
||||||
actions: {
|
actions: {
|
||||||
async login(formData: UserLoginType) {
|
async login(formData: UserLoginType) {
|
||||||
const res = await loginApi(formData)
|
const res = await loginApi(formData)
|
||||||
@ -31,8 +52,24 @@ export const useAuthStore = defineStore({
|
|||||||
wsCache.set(appStore.getToken, `${res.data.token_type} ${res.data.access_token}`)
|
wsCache.set(appStore.getToken, `${res.data.token_type} ${res.data.access_token}`)
|
||||||
// 存储用户信息
|
// 存储用户信息
|
||||||
wsCache.set(appStore.getUserInfo, res.data.user)
|
wsCache.set(appStore.getUserInfo, res.data.user)
|
||||||
|
this.user = res.data.user
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
|
},
|
||||||
|
logout() {
|
||||||
|
wsCache.clear()
|
||||||
|
this.user = {}
|
||||||
|
},
|
||||||
|
updateUser(data: UserState) {
|
||||||
|
this.user.gender = data.gender
|
||||||
|
this.user.name = data.name
|
||||||
|
this.user.nickname = data.nickname
|
||||||
|
wsCache.set(appStore.getUserInfo, this.user)
|
||||||
|
},
|
||||||
|
async getUserInfo() {
|
||||||
|
const res = await getCurrentUserInfo()
|
||||||
|
wsCache.set(appStore.getUserInfo, res.data)
|
||||||
|
this.user = res.data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { asyncRouterMap, constantRouterMap } from '@/router'
|
import { constantRouterMap } from '@/router'
|
||||||
import { generateRoutesFn1, generateRoutesFn2, flatMultiLevelRoutes } from '@/utils/routerHelper'
|
import { generateRoutesFn2, flatMultiLevelRoutes } from '@/utils/routerHelper'
|
||||||
import { store } from '../index'
|
import { store } from '../index'
|
||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
|
||||||
|
73
kinit-admin/src/views/Home/Home.vue
Normal file
73
kinit-admin/src/views/Home/Home.vue
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ElCard, ElRow, ElCol, ElTabs, ElTabPane, ElAvatar } from 'element-plus'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import InfoWrite from './components/InfoWrite.vue'
|
||||||
|
import PasswordWrite from './components/PasswordWrite.vue'
|
||||||
|
import { useAuthStoreWithOut } from '@/store/modules/auth'
|
||||||
|
import avatar from '@/assets/imgs/avatar.jpg'
|
||||||
|
import { selectDictLabel, DictDetail } from '@/utils/dict'
|
||||||
|
import { useDictStore } from '@/store/modules/dict'
|
||||||
|
|
||||||
|
const activeName = ref('info')
|
||||||
|
|
||||||
|
const authStore = useAuthStoreWithOut()
|
||||||
|
|
||||||
|
let genderOptions = ref<DictDetail[]>([])
|
||||||
|
|
||||||
|
const getOptions = async () => {
|
||||||
|
const dictStore = useDictStore()
|
||||||
|
const dictOptions = await dictStore.getDictObj(['sys_vadmin_gender'])
|
||||||
|
genderOptions.value = dictOptions.sys_vadmin_gender
|
||||||
|
}
|
||||||
|
|
||||||
|
getOptions()
|
||||||
|
|
||||||
|
const user = authStore.getUser
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ElRow :gutter="20">
|
||||||
|
<ElCol :xs="24" :sm="12" :md="8">
|
||||||
|
<ElCard shadow="hover" class="pb-30px">
|
||||||
|
<div class="text-center">
|
||||||
|
<ElAvatar :size="80" :src="user.avatar ? user.avatar : avatar" />
|
||||||
|
<p style="font-size: 24px">{{ user.name }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="pl-20px pt-30px">
|
||||||
|
<div class="leading-relaxed">
|
||||||
|
<span class="pl-10px w-80px inline-block">姓名:</span>
|
||||||
|
<span class="pl-10px">{{ user.name }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="leading-relaxed">
|
||||||
|
<span class="pl-10px w-80px inline-block">昵称:</span>
|
||||||
|
<span class="pl-10px">{{ user.nickname }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="leading-relaxed">
|
||||||
|
<span class="pl-10px w-80px inline-block">手机号:</span>
|
||||||
|
<span class="pl-10px">{{ user.telephone }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="leading-relaxed">
|
||||||
|
<span class="pl-10px w-80px inline-block">性别:</span>
|
||||||
|
<span class="pl-10px">{{ selectDictLabel(genderOptions, user.gender as string) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="leading-relaxed">
|
||||||
|
<span class="pl-10px w-80px inline-block">创建时间:</span>
|
||||||
|
<span class="pl-10px">{{ user.create_datetime }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ElCard>
|
||||||
|
</ElCol>
|
||||||
|
<ElCol :xs="24" :sm="12" :md="16">
|
||||||
|
<ElCard shadow="hover">
|
||||||
|
<ElTabs v-model="activeName">
|
||||||
|
<ElTabPane label="基本信息" name="info">
|
||||||
|
<InfoWrite />
|
||||||
|
</ElTabPane>
|
||||||
|
<ElTabPane label="修改密码" name="password">
|
||||||
|
<PasswordWrite />
|
||||||
|
</ElTabPane>
|
||||||
|
</ElTabs>
|
||||||
|
</ElCard>
|
||||||
|
</ElCol>
|
||||||
|
</ElRow>
|
||||||
|
</template>
|
120
kinit-admin/src/views/Home/components/InfoWrite.vue
Normal file
120
kinit-admin/src/views/Home/components/InfoWrite.vue
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, unref, ref } from 'vue'
|
||||||
|
import { Form } from '@/components/Form'
|
||||||
|
import { ElButton } from 'element-plus'
|
||||||
|
import { useForm } from '@/hooks/web/useForm'
|
||||||
|
import { postCurrentUserUpdateInfo } from '@/api/vadmin/auth/user'
|
||||||
|
import { useValidator } from '@/hooks/web/useValidator'
|
||||||
|
import { useAuthStoreWithOut } from '@/store/modules/auth'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
const { required } = useValidator()
|
||||||
|
|
||||||
|
const authStore = useAuthStoreWithOut()
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
name: [required()],
|
||||||
|
gender: [required()]
|
||||||
|
}
|
||||||
|
|
||||||
|
const schema = reactive<FormSchema[]>([
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
label: '用户名称',
|
||||||
|
component: 'Input',
|
||||||
|
colProps: {
|
||||||
|
span: 24
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
style: {
|
||||||
|
width: '50%'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'nickname',
|
||||||
|
label: '用户昵称',
|
||||||
|
component: 'Input',
|
||||||
|
colProps: {
|
||||||
|
span: 24
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
style: {
|
||||||
|
width: '50%'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'gender',
|
||||||
|
label: '性别',
|
||||||
|
colProps: {
|
||||||
|
span: 24
|
||||||
|
},
|
||||||
|
component: 'Radio',
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: '男',
|
||||||
|
value: '0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '女',
|
||||||
|
value: '1'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'save',
|
||||||
|
colProps: {
|
||||||
|
span: 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
const { register, elFormRef, methods } = useForm()
|
||||||
|
|
||||||
|
const { setValues } = methods
|
||||||
|
setValues(authStore.getUser)
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const save = async () => {
|
||||||
|
const formRef = unref(elFormRef)
|
||||||
|
await formRef?.validate(async (isValid) => {
|
||||||
|
if (isValid) {
|
||||||
|
loading.value = true
|
||||||
|
const { getFormData } = methods
|
||||||
|
const formData = await getFormData()
|
||||||
|
try {
|
||||||
|
const res = await postCurrentUserUpdateInfo(formData)
|
||||||
|
if (res) {
|
||||||
|
authStore.updateUser(res.data)
|
||||||
|
ElMessage.success('保存成功')
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Form
|
||||||
|
:schema="schema"
|
||||||
|
:rules="rules"
|
||||||
|
hide-required-asterisk
|
||||||
|
class="dark:(border-1 border-[var(--el-border-color)] border-solid)"
|
||||||
|
@register="register"
|
||||||
|
>
|
||||||
|
<template #save>
|
||||||
|
<div class="w-[50%]">
|
||||||
|
<ElButton :loading="loading" type="primary" class="w-[100%]" @click="save"> 保存 </ElButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
114
kinit-admin/src/views/Home/components/PasswordWrite.vue
Normal file
114
kinit-admin/src/views/Home/components/PasswordWrite.vue
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, unref, ref } from 'vue'
|
||||||
|
import { Form } from '@/components/Form'
|
||||||
|
import { ElButton } from 'element-plus'
|
||||||
|
import { useForm } from '@/hooks/web/useForm'
|
||||||
|
import { postCurrentUserResetPassword } from '@/api/vadmin/auth/user'
|
||||||
|
import { useValidator } from '@/hooks/web/useValidator'
|
||||||
|
import { useAuthStoreWithOut } from '@/store/modules/auth'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
const { required } = useValidator()
|
||||||
|
|
||||||
|
const authStore = useAuthStoreWithOut()
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
password: [
|
||||||
|
required(),
|
||||||
|
{ min: 8, max: 16, message: '长度需为8-16个字符,请重新输入。', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
password_two: [
|
||||||
|
required(),
|
||||||
|
{ min: 8, max: 16, message: '长度需为8-16个字符,请重新输入。', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const schema = reactive<FormSchema[]>([
|
||||||
|
{
|
||||||
|
field: 'title',
|
||||||
|
colProps: {
|
||||||
|
span: 24
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'password',
|
||||||
|
label: '新密码',
|
||||||
|
component: 'InputPassword',
|
||||||
|
colProps: {
|
||||||
|
span: 24
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
style: {
|
||||||
|
width: '50%'
|
||||||
|
},
|
||||||
|
placeholder: '请输入新密码'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'password_two',
|
||||||
|
label: '再次输入新密码',
|
||||||
|
component: 'InputPassword',
|
||||||
|
colProps: {
|
||||||
|
span: 24
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
style: {
|
||||||
|
width: '50%'
|
||||||
|
},
|
||||||
|
placeholder: '请再次输入新密码'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'save',
|
||||||
|
colProps: {
|
||||||
|
span: 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
const { register, elFormRef, methods } = useForm()
|
||||||
|
|
||||||
|
const { setValues } = methods
|
||||||
|
setValues(authStore.getUser)
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const save = async () => {
|
||||||
|
const formRef = unref(elFormRef)
|
||||||
|
await formRef?.validate(async (isValid) => {
|
||||||
|
if (isValid) {
|
||||||
|
loading.value = true
|
||||||
|
const { getFormData } = methods
|
||||||
|
const formData = await getFormData()
|
||||||
|
try {
|
||||||
|
const res = await postCurrentUserResetPassword(formData)
|
||||||
|
if (res) {
|
||||||
|
formRef.resetFields()
|
||||||
|
ElMessage.success('保存成功')
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Form
|
||||||
|
:schema="schema"
|
||||||
|
:rules="rules"
|
||||||
|
hide-required-asterisk
|
||||||
|
class="dark:(border-1 border-[var(--el-border-color)] border-solid)"
|
||||||
|
@register="register"
|
||||||
|
>
|
||||||
|
<template #save>
|
||||||
|
<div class="w-[50%]">
|
||||||
|
<ElButton :loading="loading" type="primary" class="w-[100%]" @click="save"> 保存 </ElButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, unref, ref, watch } from 'vue'
|
import { reactive, unref, ref, watch } from 'vue'
|
||||||
import { Form } from '@/components/Form'
|
import { Form } from '@/components/Form'
|
||||||
import { ElButton, ElCheckbox, ElLink } from 'element-plus'
|
import { ElButton } from 'element-plus'
|
||||||
import { useForm } from '@/hooks/web/useForm'
|
import { useForm } from '@/hooks/web/useForm'
|
||||||
import { postCurrentUserResetPassword } from '@/api/vadmin/auth/user'
|
import { postCurrentUserResetPassword } from '@/api/vadmin/auth/user'
|
||||||
import { usePermissionStore } from '@/store/modules/permission'
|
import { usePermissionStore } from '@/store/modules/permission'
|
||||||
|
@ -24,14 +24,12 @@ let menuTypeOptions = ref<DictDetail[]>([])
|
|||||||
|
|
||||||
const getOptions = async () => {
|
const getOptions = async () => {
|
||||||
const dictStore = useDictStore()
|
const dictStore = useDictStore()
|
||||||
const result = await dictStore.getDictObj(['sys_vadmin_menu_type'])
|
const dictOptions = await dictStore.getDictObj(['sys_vadmin_menu_type'])
|
||||||
menuTypeOptions.value = result.sys_vadmin_menu_type
|
menuTypeOptions.value = dictOptions.sys_vadmin_menu_type
|
||||||
}
|
}
|
||||||
|
|
||||||
getOptions()
|
getOptions()
|
||||||
|
|
||||||
console.log(menuTypeOptions)
|
|
||||||
|
|
||||||
const { register, tableObject, methods } = useTable<TableData>({
|
const { register, tableObject, methods } = useTable<TableData>({
|
||||||
getListApi: getMenuListApi,
|
getListApi: getMenuListApi,
|
||||||
delListApi: delMenuListApi,
|
delListApi: delMenuListApi,
|
||||||
@ -115,6 +113,7 @@ getList()
|
|||||||
:loading="tableObject.loading"
|
:loading="tableObject.loading"
|
||||||
:selection="false"
|
:selection="false"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
|
default-expand-all
|
||||||
@register="register"
|
@register="register"
|
||||||
>
|
>
|
||||||
<template #title="{ row }">
|
<template #title="{ row }">
|
||||||
|
@ -15,9 +15,21 @@ import Write from './components/Write.vue'
|
|||||||
import { Dialog } from '@/components/Dialog'
|
import { Dialog } from '@/components/Dialog'
|
||||||
import { ElButton, ElMessage, ElSwitch } from 'element-plus'
|
import { ElButton, ElMessage, ElSwitch } from 'element-plus'
|
||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
|
import { selectDictLabel, DictDetail } from '@/utils/dict'
|
||||||
|
import { useDictStore } from '@/store/modules/dict'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
let genderOptions = ref<DictDetail[]>([])
|
||||||
|
|
||||||
|
const getOptions = async () => {
|
||||||
|
const dictStore = useDictStore()
|
||||||
|
const dictOptions = await dictStore.getDictObj(['sys_vadmin_gender'])
|
||||||
|
genderOptions.value = dictOptions.sys_vadmin_gender
|
||||||
|
}
|
||||||
|
|
||||||
|
getOptions()
|
||||||
|
|
||||||
const { register, tableObject, methods } = useTable({
|
const { register, tableObject, methods } = useTable({
|
||||||
getListApi: getUserListApi,
|
getListApi: getUserListApi,
|
||||||
delListApi: delUserListApi,
|
delListApi: delUserListApi,
|
||||||
@ -124,6 +136,10 @@ getList()
|
|||||||
<template #is_active="{ row }">
|
<template #is_active="{ row }">
|
||||||
<ElSwitch :value="row.is_active" disabled />
|
<ElSwitch :value="row.is_active" disabled />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #gender="{ row }">
|
||||||
|
{{ selectDictLabel(genderOptions, row.gender) }}
|
||||||
|
</template>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
<Dialog v-model="dialogVisible" :title="dialogTitle" width="700px">
|
<Dialog v-model="dialogVisible" :title="dialogTitle" width="700px">
|
||||||
|
@ -65,8 +65,7 @@ ALLOW_HEADERS = ["*"]
|
|||||||
"""
|
"""
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
# 测试库
|
# 测试库
|
||||||
SQLALCHEMY_DATABASE_URL = "mysql+asyncmy://root:Ktianc123@rm-bp181adf0phw2o0r05o.mysql.rds.aliyuncs.com:3306/kinit"
|
SQLALCHEMY_DATABASE_URL = "mysql+asyncmy://root:123456@127.0.0.1:3306/kinit"
|
||||||
# SQLALCHEMY_DATABASE_URL = "mysql+asyncmy://root:123456@127.0.0.1:3306/kinit"
|
|
||||||
SQLALCHEMY_DATABASE_TYPE = "mysql"
|
SQLALCHEMY_DATABASE_TYPE = "mysql"
|
||||||
else:
|
else:
|
||||||
# 正式库
|
# 正式库
|
||||||
|
@ -57,6 +57,18 @@ class UserDal(DalBase):
|
|||||||
await self.db.flush()
|
await self.db.flush()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
async def update_current_info(self, user: models.VadminUser, data: schemas.UserUpdate):
|
||||||
|
"""
|
||||||
|
更新当前用户信息
|
||||||
|
"""
|
||||||
|
user.name = data.name
|
||||||
|
user.nickname = data.nickname
|
||||||
|
user.gender = data.gender
|
||||||
|
self.db.add(user)
|
||||||
|
await self.db.flush()
|
||||||
|
await self.db.refresh(user)
|
||||||
|
return self.out_dict(user)
|
||||||
|
|
||||||
|
|
||||||
class RoleDal(DalBase):
|
class RoleDal(DalBase):
|
||||||
|
|
||||||
|
@ -52,10 +52,7 @@ class UserOut(UserSimpleOut):
|
|||||||
class UserUpdate(BaseModel):
|
class UserUpdate(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
nickname: Optional[str] = None
|
nickname: Optional[str] = None
|
||||||
is_active: Optional[bool] = True
|
|
||||||
is_cancel: Optional[bool] = False
|
|
||||||
gender: Optional[str] = "0"
|
gender: Optional[str] = "0"
|
||||||
role_ids: Optional[List[int]] = []
|
|
||||||
|
|
||||||
|
|
||||||
class ResetPwd(BaseModel):
|
class ResetPwd(BaseModel):
|
||||||
|
@ -53,6 +53,7 @@ async def login_for_access_token(request: Request, data: dict = Depends(authenti
|
|||||||
"name": user.name,
|
"name": user.name,
|
||||||
"nickname": user.nickname,
|
"nickname": user.nickname,
|
||||||
"avatar": user.avatar,
|
"avatar": user.avatar,
|
||||||
|
"gender": user.gender,
|
||||||
"roles": [{"name": i.name, "value": i.role_key} for i in user.roles]
|
"roles": [{"name": i.name, "value": i.role_key} for i in user.roles]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ async def delete_users(ids: list = Depends(id_list), auth: Auth = Depends(login_
|
|||||||
return SuccessResponse("删除成功")
|
return SuccessResponse("删除成功")
|
||||||
|
|
||||||
|
|
||||||
@app.put("/users/{data_id}/", summary="更新用户基本信息")
|
@app.put("/users/{data_id}/", summary="更新用户信息")
|
||||||
async def put_user(data_id: int, data: schemas.User, auth: Auth = Depends(login_auth)):
|
async def put_user(data_id: int, data: schemas.User, auth: Auth = Depends(login_auth)):
|
||||||
return SuccessResponse(await crud.UserDal(auth.db).put_data(data_id, data))
|
return SuccessResponse(await crud.UserDal(auth.db).put_data(data_id, data))
|
||||||
|
|
||||||
@ -55,6 +55,16 @@ async def user_current_reset_password(data: schemas.ResetPwd, auth: Auth = Depen
|
|||||||
return SuccessResponse(await crud.UserDal(auth.db).reset_current_password(auth.user, data))
|
return SuccessResponse(await crud.UserDal(auth.db).reset_current_password(auth.user, data))
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/user/current/update/info/", summary="更新当前用户基本信息")
|
||||||
|
async def post_user_current_update_info( data: schemas.UserUpdate, auth: Auth = Depends(login_auth)):
|
||||||
|
return SuccessResponse(await crud.UserDal(auth.db).update_current_info(auth.user, data))
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/user/current/info/", summary="获取当前用户基本信息")
|
||||||
|
async def get_user_current_info(auth: Auth = Depends(login_auth)):
|
||||||
|
return SuccessResponse(schemas.UserSimpleOut.from_orm(auth.user).dict())
|
||||||
|
|
||||||
|
|
||||||
###########################################################
|
###########################################################
|
||||||
# 角色管理
|
# 角色管理
|
||||||
###########################################################
|
###########################################################
|
||||||
|
Loading…
x
Reference in New Issue
Block a user