mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-08 01:17:23 +08:00
chore: update
This commit is contained in:
parent
309e31fcd9
commit
02b2568427
@ -1,4 +1,5 @@
|
|||||||
buttons:
|
buttons:
|
||||||
|
pureAccountSettings: Account Settings
|
||||||
pureLoginOut: LoginOut
|
pureLoginOut: LoginOut
|
||||||
pureLogin: Login
|
pureLogin: Login
|
||||||
pureSystemSet: Open ProjectConfig
|
pureSystemSet: Open ProjectConfig
|
||||||
@ -10,7 +11,6 @@ buttons:
|
|||||||
pureCloseAllTabs: Close AllTabs
|
pureCloseAllTabs: Close AllTabs
|
||||||
pureContentFullScreen: Content FullScreen
|
pureContentFullScreen: Content FullScreen
|
||||||
pureContentExitFullScreen: Content ExitFullScreen
|
pureContentExitFullScreen: Content ExitFullScreen
|
||||||
pureUserSettings: User Settings
|
|
||||||
menus:
|
menus:
|
||||||
pureHome: Home
|
pureHome: Home
|
||||||
pureLogin: Login
|
pureLogin: Login
|
||||||
@ -176,4 +176,4 @@ login:
|
|||||||
purePassWordRuleReg: The password format should be any combination of 8-18 digits
|
purePassWordRuleReg: The password format should be any combination of 8-18 digits
|
||||||
purePassWordSureReg: Please enter confirm password
|
purePassWordSureReg: Please enter confirm password
|
||||||
purePassWordDifferentReg: The two passwords do not match!
|
purePassWordDifferentReg: The two passwords do not match!
|
||||||
purePassWordUpdateReg: Password has been updated
|
purePassWordUpdateReg: Password has been updated
|
@ -1,4 +1,5 @@
|
|||||||
buttons:
|
buttons:
|
||||||
|
pureAccountSettings: 账户设置
|
||||||
pureLoginOut: 退出系统
|
pureLoginOut: 退出系统
|
||||||
pureLogin: 登录
|
pureLogin: 登录
|
||||||
pureSystemSet: 打开项目配置
|
pureSystemSet: 打开项目配置
|
||||||
@ -10,7 +11,6 @@ buttons:
|
|||||||
pureCloseAllTabs: 关闭全部标签页
|
pureCloseAllTabs: 关闭全部标签页
|
||||||
pureContentFullScreen: 内容区全屏
|
pureContentFullScreen: 内容区全屏
|
||||||
pureContentExitFullScreen: 内容区退出全屏
|
pureContentExitFullScreen: 内容区退出全屏
|
||||||
pureUserSettings: 个人设置
|
|
||||||
menus:
|
menus:
|
||||||
pureHome: 首页
|
pureHome: 首页
|
||||||
pureLogin: 登录
|
pureLogin: 登录
|
||||||
|
21
mock/mine.ts
Normal file
21
mock/mine.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { defineFakeRoute } from "vite-plugin-fake-server/client";
|
||||||
|
|
||||||
|
export default defineFakeRoute([
|
||||||
|
{
|
||||||
|
url: "/mine",
|
||||||
|
method: "get",
|
||||||
|
response: () => {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
avatar: "https://avatars.githubusercontent.com/u/44761321",
|
||||||
|
username: "admin",
|
||||||
|
nickname: "Coder",
|
||||||
|
email: "pureadmin@163.com",
|
||||||
|
phone: "15888886789",
|
||||||
|
description: "一个热爱开源的前端工程师"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
@ -1,52 +0,0 @@
|
|||||||
import { defineFakeRoute } from "vite-plugin-fake-server/client";
|
|
||||||
|
|
||||||
export default defineFakeRoute([
|
|
||||||
{
|
|
||||||
url: "/get-regions",
|
|
||||||
method: "get",
|
|
||||||
response: () => {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
code: "001",
|
|
||||||
name: "中国",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
code: "001001",
|
|
||||||
name: "北京市",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
code: "001001001",
|
|
||||||
name: "东城区"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: "001001002",
|
|
||||||
name: "西城区"
|
|
||||||
}
|
|
||||||
// 其他区
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: "001002",
|
|
||||||
name: "上海市",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
code: "001002001",
|
|
||||||
name: "黄浦区"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: "001002002",
|
|
||||||
name: "徐汇区"
|
|
||||||
}
|
|
||||||
// 其他区
|
|
||||||
]
|
|
||||||
}
|
|
||||||
// 其他城市
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]);
|
|
@ -1,21 +0,0 @@
|
|||||||
import { defineFakeRoute } from "vite-plugin-fake-server/client";
|
|
||||||
|
|
||||||
export default defineFakeRoute([
|
|
||||||
{
|
|
||||||
url: "/get-user-info",
|
|
||||||
method: "get",
|
|
||||||
response: () => {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data: {
|
|
||||||
avatarUrl: "https://avatars.githubusercontent.com/u/44761321",
|
|
||||||
nickName: "企丸丸",
|
|
||||||
introduce: "我是幻兽帕鲁里的明星",
|
|
||||||
regionCode: "001002001",
|
|
||||||
address: "冰鸟密域祭坛地下城",
|
|
||||||
userName: "admin"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]);
|
|
@ -23,8 +23,3 @@ export const formUpload = data => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**所在区域数据*/
|
|
||||||
export const getRegions = (params?: object) => {
|
|
||||||
return http.request<Result>("get", "/get-regions", { params });
|
|
||||||
};
|
|
||||||
|
@ -29,12 +29,18 @@ export type RefreshTokenResult = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type UserInfo = {
|
export type UserInfo = {
|
||||||
avatarUrl: string;
|
/** 头像 */
|
||||||
nickName: string;
|
avatar: string;
|
||||||
introduce: string;
|
/** 用户名 */
|
||||||
regionCode: string;
|
username: string;
|
||||||
address: string;
|
/** 昵称 */
|
||||||
userName: string;
|
nickname: string;
|
||||||
|
/** 邮箱 */
|
||||||
|
email: string;
|
||||||
|
/** 联系电话 */
|
||||||
|
phone: string;
|
||||||
|
/** 简介 */
|
||||||
|
description: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserInfoResult = {
|
export type UserInfoResult = {
|
||||||
@ -47,12 +53,12 @@ export const getLogin = (data?: object) => {
|
|||||||
return http.request<UserResult>("post", "/login", { data });
|
return http.request<UserResult>("post", "/login", { data });
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 刷新token */
|
/** 刷新`token` */
|
||||||
export const refreshTokenApi = (data?: object) => {
|
export const refreshTokenApi = (data?: object) => {
|
||||||
return http.request<RefreshTokenResult>("post", "/refresh-token", { data });
|
return http.request<RefreshTokenResult>("post", "/refresh-token", { data });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**获取个人信息 */
|
/** 账户设置-个人信息 */
|
||||||
export const getUserInfo = (data?: object) => {
|
export const getMine = (data?: object) => {
|
||||||
return http.request<UserInfoResult>("get", "/get-user-info", { data });
|
return http.request<UserInfoResult>("get", "/mine", { data });
|
||||||
};
|
};
|
||||||
|
@ -8,22 +8,22 @@ import Breadcrumb from "./sidebar/breadCrumb.vue";
|
|||||||
import topCollapse from "./sidebar/topCollapse.vue";
|
import topCollapse from "./sidebar/topCollapse.vue";
|
||||||
import { useTranslationLang } from "../hooks/useTranslationLang";
|
import { useTranslationLang } from "../hooks/useTranslationLang";
|
||||||
import globalization from "@/assets/svg/globalization.svg?component";
|
import globalization from "@/assets/svg/globalization.svg?component";
|
||||||
|
import AccountSettingsIcon from "@iconify-icons/ri/user-settings-line";
|
||||||
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
||||||
import Setting from "@iconify-icons/ri/settings-3-line";
|
import Setting from "@iconify-icons/ri/settings-3-line";
|
||||||
import Check from "@iconify-icons/ep/check";
|
import Check from "@iconify-icons/ep/check";
|
||||||
import UserSettingsLine from "@iconify-icons/ri/user-settings-line";
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
layout,
|
layout,
|
||||||
device,
|
device,
|
||||||
logout,
|
logout,
|
||||||
handleOpenUserSettings,
|
|
||||||
onPanel,
|
onPanel,
|
||||||
pureApp,
|
pureApp,
|
||||||
username,
|
username,
|
||||||
userAvatar,
|
userAvatar,
|
||||||
avatarsStyle,
|
avatarsStyle,
|
||||||
toggleSideBar,
|
toggleSideBar,
|
||||||
|
toAccountSettings,
|
||||||
getDropdownItemStyle,
|
getDropdownItemStyle,
|
||||||
getDropdownItemClass
|
getDropdownItemClass
|
||||||
} = useNav();
|
} = useNav();
|
||||||
@ -94,12 +94,12 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
|||||||
</span>
|
</span>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu class="logout">
|
<el-dropdown-menu class="logout">
|
||||||
<el-dropdown-item @click="handleOpenUserSettings">
|
<el-dropdown-item @click="toAccountSettings">
|
||||||
<IconifyIconOffline
|
<IconifyIconOffline
|
||||||
:icon="UserSettingsLine"
|
:icon="AccountSettingsIcon"
|
||||||
style="margin: 5px"
|
style="margin: 5px"
|
||||||
/>
|
/>
|
||||||
{{ t("buttons.pureUserSettings") }}
|
{{ t("buttons.pureAccountSettings") }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item @click="logout">
|
<el-dropdown-item @click="logout">
|
||||||
<IconifyIconOffline
|
<IconifyIconOffline
|
||||||
@ -187,7 +187,7 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
|||||||
}
|
}
|
||||||
|
|
||||||
.logout {
|
.logout {
|
||||||
max-width: 160px;
|
max-width: 120px;
|
||||||
|
|
||||||
::v-deep(.el-dropdown-menu__item) {
|
::v-deep(.el-dropdown-menu__item) {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
@ -9,10 +9,10 @@ import { useNav } from "@/layout/hooks/useNav";
|
|||||||
import { useTranslationLang } from "../../hooks/useTranslationLang";
|
import { useTranslationLang } from "../../hooks/useTranslationLang";
|
||||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
import globalization from "@/assets/svg/globalization.svg?component";
|
import globalization from "@/assets/svg/globalization.svg?component";
|
||||||
|
import AccountSettingsIcon from "@iconify-icons/ri/user-settings-line";
|
||||||
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
||||||
import Setting from "@iconify-icons/ri/settings-3-line";
|
import Setting from "@iconify-icons/ri/settings-3-line";
|
||||||
import Check from "@iconify-icons/ep/check";
|
import Check from "@iconify-icons/ep/check";
|
||||||
import UserSettingsLine from "@iconify-icons/ri/user-settings-line";
|
|
||||||
|
|
||||||
const menuRef = ref();
|
const menuRef = ref();
|
||||||
|
|
||||||
@ -27,9 +27,9 @@ const {
|
|||||||
username,
|
username,
|
||||||
userAvatar,
|
userAvatar,
|
||||||
avatarsStyle,
|
avatarsStyle,
|
||||||
|
toAccountSettings,
|
||||||
getDropdownItemStyle,
|
getDropdownItemStyle,
|
||||||
getDropdownItemClass,
|
getDropdownItemClass
|
||||||
handleOpenUserSettings
|
|
||||||
} = useNav();
|
} = useNav();
|
||||||
|
|
||||||
const defaultActive = computed(() =>
|
const defaultActive = computed(() =>
|
||||||
@ -109,9 +109,12 @@ nextTick(() => {
|
|||||||
<p v-if="username" class="dark:text-white">{{ username }}</p>
|
<p v-if="username" class="dark:text-white">{{ username }}</p>
|
||||||
</span>
|
</span>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-item @click="handleOpenUserSettings">
|
<el-dropdown-item @click="toAccountSettings">
|
||||||
<IconifyIconOffline :icon="UserSettingsLine" style="margin: 5px" />
|
<IconifyIconOffline
|
||||||
{{ t("buttons.pureUserSettings") }}
|
:icon="AccountSettingsIcon"
|
||||||
|
style="margin: 5px"
|
||||||
|
/>
|
||||||
|
{{ t("buttons.pureAccountSettings") }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-menu class="logout">
|
<el-dropdown-menu class="logout">
|
||||||
<el-dropdown-item @click="logout">
|
<el-dropdown-item @click="logout">
|
||||||
|
@ -12,10 +12,10 @@ import { getParentPaths, findRouteByPath } from "@/router/utils";
|
|||||||
import { useTranslationLang } from "../../hooks/useTranslationLang";
|
import { useTranslationLang } from "../../hooks/useTranslationLang";
|
||||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
import globalization from "@/assets/svg/globalization.svg?component";
|
import globalization from "@/assets/svg/globalization.svg?component";
|
||||||
|
import AccountSettingsIcon from "@iconify-icons/ri/user-settings-line";
|
||||||
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
||||||
import Setting from "@iconify-icons/ri/settings-3-line";
|
import Setting from "@iconify-icons/ri/settings-3-line";
|
||||||
import Check from "@iconify-icons/ep/check";
|
import Check from "@iconify-icons/ep/check";
|
||||||
import UserSettingsLine from "@iconify-icons/ri/user-settings-line";
|
|
||||||
|
|
||||||
const menuRef = ref();
|
const menuRef = ref();
|
||||||
const defaultActive = ref(null);
|
const defaultActive = ref(null);
|
||||||
@ -31,9 +31,9 @@ const {
|
|||||||
userAvatar,
|
userAvatar,
|
||||||
getDivStyle,
|
getDivStyle,
|
||||||
avatarsStyle,
|
avatarsStyle,
|
||||||
|
toAccountSettings,
|
||||||
getDropdownItemStyle,
|
getDropdownItemStyle,
|
||||||
getDropdownItemClass,
|
getDropdownItemClass
|
||||||
handleOpenUserSettings
|
|
||||||
} = useNav();
|
} = useNav();
|
||||||
|
|
||||||
function getDefaultActive(routePath) {
|
function getDefaultActive(routePath) {
|
||||||
@ -142,9 +142,12 @@ watch(
|
|||||||
<p v-if="username" class="dark:text-white">{{ username }}</p>
|
<p v-if="username" class="dark:text-white">{{ username }}</p>
|
||||||
</span>
|
</span>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-item @click="handleOpenUserSettings">
|
<el-dropdown-item @click="toAccountSettings">
|
||||||
<IconifyIconOffline :icon="UserSettingsLine" style="margin: 5px" />
|
<IconifyIconOffline
|
||||||
{{ t("buttons.pureUserSettings") }}
|
:icon="AccountSettingsIcon"
|
||||||
|
style="margin: 5px"
|
||||||
|
/>
|
||||||
|
{{ t("buttons.pureAccountSettings") }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-menu class="logout">
|
<el-dropdown-menu class="logout">
|
||||||
<el-dropdown-item @click="logout">
|
<el-dropdown-item @click="logout">
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { ref } from "vue";
|
|
||||||
import { useNav } from "@/layout/hooks/useNav";
|
|
||||||
import leftLine from "@iconify-icons/ri/arrow-left-s-line";
|
|
||||||
import userLine from "@iconify-icons/ri/user-3-line";
|
|
||||||
import profileLine from "@iconify-icons/ri/profile-line";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import { getUserInfo } from "@/api/user";
|
|
||||||
|
|
||||||
import UserInfoManage from "@/layout/components/userSettings/userInfoManage.vue";
|
|
||||||
import SafeManage from "@/layout/components/userSettings/safeManage.vue";
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
const { getLogo, isCollapse } = useNav();
|
|
||||||
const userInfo = ref({
|
|
||||||
nickName: "",
|
|
||||||
avatarUrl: "",
|
|
||||||
userName: ""
|
|
||||||
});
|
|
||||||
getUserInfo().then(res => {
|
|
||||||
userInfo.value = res.data;
|
|
||||||
});
|
|
||||||
const handleBack = () => {
|
|
||||||
router.go(-1);
|
|
||||||
};
|
|
||||||
|
|
||||||
const witchPane = ref("userInfoManage");
|
|
||||||
const panes = [
|
|
||||||
{
|
|
||||||
key: "userInfoManage",
|
|
||||||
label: "基本设置",
|
|
||||||
icon: userLine,
|
|
||||||
component: UserInfoManage
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "safeManage",
|
|
||||||
label: "安全设置",
|
|
||||||
icon: profileLine,
|
|
||||||
component: SafeManage
|
|
||||||
}
|
|
||||||
];
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<el-container class="h-full">
|
|
||||||
<el-aside class="settings-sidebar px-2" width="210px">
|
|
||||||
<el-menu :default-active="witchPane" class="settings-menu">
|
|
||||||
<el-menu-item @click="handleBack">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<IconifyIconOffline :icon="leftLine" />
|
|
||||||
<img :src="getLogo()" class="w-6 h-6" alt="logo" />
|
|
||||||
<span class="ml-2">返回</span>
|
|
||||||
</div>
|
|
||||||
</el-menu-item>
|
|
||||||
<li class="flex items-center ml-8 mt-4">
|
|
||||||
<div>
|
|
||||||
<el-avatar :size="80" :src="userInfo.avatarUrl" />
|
|
||||||
</div>
|
|
||||||
<div class="pl-4 flex-col">
|
|
||||||
<p>{{ userInfo.nickName }}</p>
|
|
||||||
<p>
|
|
||||||
<el-text class="mt-2" type="info">{{
|
|
||||||
userInfo.userName
|
|
||||||
}}</el-text>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<el-menu-item
|
|
||||||
v-for="item in panes"
|
|
||||||
:key="item.key"
|
|
||||||
:index="item.key"
|
|
||||||
@click="witchPane = item.key"
|
|
||||||
>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<el-icon><IconifyIconOffline :icon="item.icon" /></el-icon>
|
|
||||||
<span>{{ item.label }}</span>
|
|
||||||
</div>
|
|
||||||
</el-menu-item>
|
|
||||||
</el-menu>
|
|
||||||
</el-aside>
|
|
||||||
<el-main>
|
|
||||||
<component :is="panes.find(item => item.key === witchPane).component" />
|
|
||||||
</el-main>
|
|
||||||
</el-container>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.settings-sidebar {
|
|
||||||
background: $menuBg;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-menu {
|
|
||||||
color: $subMenuActiveText;
|
|
||||||
background-color: transparent !important;
|
|
||||||
border: none !important;
|
|
||||||
|
|
||||||
::v-deep(.el-menu-item) {
|
|
||||||
position: relative;
|
|
||||||
background-color: transparent !important;
|
|
||||||
|
|
||||||
div {
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-active {
|
|
||||||
span {
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
position: absolute;
|
|
||||||
inset: 0 8px;
|
|
||||||
margin: 4px 0;
|
|
||||||
clear: both;
|
|
||||||
content: "";
|
|
||||||
background: var(--el-color-primary) !important;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,56 +0,0 @@
|
|||||||
<script setup lang="ts"></script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<el-card shadow="never">
|
|
||||||
<template #header>安全设置</template>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<div class="flex-1">
|
|
||||||
<p>账户密码</p>
|
|
||||||
<p class="wp-4">
|
|
||||||
<el-text class="mx-1" type="info">当前密码强度:强</el-text>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="w-64">
|
|
||||||
<el-link type="primary" :underline="false">修改</el-link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-divider />
|
|
||||||
<div class="flex items-center">
|
|
||||||
<div class="flex-1">
|
|
||||||
<p>密保手机</p>
|
|
||||||
<p class="wp-4">
|
|
||||||
<el-text class="mx-1" type="info">已经绑定手机:138****1234</el-text>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="w-64">
|
|
||||||
<el-link type="primary" :underline="false">修改</el-link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-divider />
|
|
||||||
<div class="flex items-center">
|
|
||||||
<div class="flex-1">
|
|
||||||
<p>密保问题</p>
|
|
||||||
<p class="wp-4">
|
|
||||||
<el-text class="mx-1" type="info">
|
|
||||||
未设置密保问题,密保问题可有效保护账户安全
|
|
||||||
</el-text>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="w-64">
|
|
||||||
<el-link type="primary" :underline="false">设置</el-link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-divider />
|
|
||||||
<div class="flex items-center">
|
|
||||||
<div class="flex-1">
|
|
||||||
<p>备用邮箱</p>
|
|
||||||
<p class="wp-4">
|
|
||||||
<el-text class="mx-1" type="info">已绑定邮箱:ant***sign.com</el-text>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="w-64">
|
|
||||||
<el-link type="primary" :underline="false">修改</el-link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
</template>
|
|
@ -99,8 +99,8 @@ export function useNav() {
|
|||||||
emitter.emit("openPanel");
|
emitter.emit("openPanel");
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleOpenUserSettings() {
|
function toAccountSettings() {
|
||||||
router.push({ name: "UserSettings" });
|
router.push({ name: "AccountSettings" });
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleSideBar() {
|
function toggleSideBar() {
|
||||||
@ -163,8 +163,8 @@ export function useNav() {
|
|||||||
userAvatar,
|
userAvatar,
|
||||||
avatarsStyle,
|
avatarsStyle,
|
||||||
tooltipEffect,
|
tooltipEffect,
|
||||||
|
toAccountSettings,
|
||||||
getDropdownItemStyle,
|
getDropdownItemStyle,
|
||||||
getDropdownItemClass,
|
getDropdownItemClass
|
||||||
handleOpenUserSettings
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -40,13 +40,13 @@ export default [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/user-settings",
|
path: "/account-settings",
|
||||||
name: "UserSettings",
|
name: "AccountSettings",
|
||||||
component: () => import("@/layout/components/userSettings/index.vue"),
|
component: () => import("@/views/account-settings/index.vue"),
|
||||||
meta: {
|
meta: {
|
||||||
title: $t("buttons.pureUserSettings"),
|
title: $t("buttons.pureAccountSettings"),
|
||||||
showLink: false,
|
showLink: false,
|
||||||
rank: 103
|
rank: 104
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
] satisfies Array<RouteConfigsTable>;
|
] satisfies Array<RouteConfigsTable>;
|
||||||
|
48
src/views/account-settings/components/accountManagement.vue
Normal file
48
src/views/account-settings/components/accountManagement.vue
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
// 仅提供示例,请根据具体业务自行实现
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="ml-[120px] min-w-[180px] max-w-[70%]">
|
||||||
|
<h3 class="my-8">账户管理</h3>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="flex-1">
|
||||||
|
<p>账户密码</p>
|
||||||
|
<el-text class="mx-1" type="info">当前密码强度:强</el-text>
|
||||||
|
</div>
|
||||||
|
<el-button type="primary" text>修改</el-button>
|
||||||
|
</div>
|
||||||
|
<el-divider />
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="flex-1">
|
||||||
|
<p>密保手机</p>
|
||||||
|
<el-text class="mx-1" type="info">已经绑定手机:158****6789</el-text>
|
||||||
|
</div>
|
||||||
|
<el-button type="primary" text>修改</el-button>
|
||||||
|
</div>
|
||||||
|
<el-divider />
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="flex-1">
|
||||||
|
<p>密保问题</p>
|
||||||
|
<el-text class="mx-1" type="info">
|
||||||
|
未设置密保问题,密保问题可有效保护账户安全
|
||||||
|
</el-text>
|
||||||
|
</div>
|
||||||
|
<el-button type="primary" text>修改</el-button>
|
||||||
|
</div>
|
||||||
|
<el-divider />
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="flex-1">
|
||||||
|
<p>备用邮箱</p>
|
||||||
|
<el-text class="mx-1" type="info">已绑定邮箱:pure***@163.com</el-text>
|
||||||
|
</div>
|
||||||
|
<el-button type="primary" text>修改</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-divider--horizontal {
|
||||||
|
border-top: 0.1px var(--el-border-color) var(--el-border-style);
|
||||||
|
}
|
||||||
|
</style>
|
58
src/views/account-settings/components/preferences.vue
Normal file
58
src/views/account-settings/components/preferences.vue
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { message } from "@/utils/message";
|
||||||
|
|
||||||
|
const list = ref([
|
||||||
|
{
|
||||||
|
title: "账户密码",
|
||||||
|
illustrate: "其他用户的消息将以站内信的形式通知",
|
||||||
|
checked: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "系统消息",
|
||||||
|
illustrate: "系统消息将以站内信的形式通知",
|
||||||
|
checked: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "待办任务",
|
||||||
|
illustrate: "待办任务将以站内信的形式通知",
|
||||||
|
checked: false
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
function onChange(val, item) {
|
||||||
|
message(`${item.title}设置成功`, { type: "success" });
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="ml-[120px] min-w-[180px] max-w-[70%]">
|
||||||
|
<h3 class="my-8">偏好设置</h3>
|
||||||
|
<div v-for="(item, index) in list" :key="index">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="flex-1">
|
||||||
|
<p>{{ item.title }}</p>
|
||||||
|
<p class="wp-4">
|
||||||
|
<el-text class="mx-1" type="info">
|
||||||
|
{{ item.illustrate }}
|
||||||
|
</el-text>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<el-switch
|
||||||
|
v-model="item.checked"
|
||||||
|
inline-prompt
|
||||||
|
active-text="是"
|
||||||
|
inactive-text="否"
|
||||||
|
@change="val => onChange(val, item)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<el-divider />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-divider--horizontal {
|
||||||
|
border-top: 0.1px var(--el-border-color) var(--el-border-style);
|
||||||
|
}
|
||||||
|
</style>
|
@ -8,8 +8,7 @@ import type { FormInstance, FormRules } from "element-plus";
|
|||||||
import { formUpload } from "@/api/mock";
|
import { formUpload } from "@/api/mock";
|
||||||
import { message } from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import { createFormData } from "@pureadmin/utils";
|
import { createFormData } from "@pureadmin/utils";
|
||||||
import { getRegions } from "@/api/mock";
|
import { getMine, UserInfo } from "@/api/user";
|
||||||
import { getUserInfo, UserInfo } from "@/api/user";
|
|
||||||
const { userAvatar, getLogo, username } = useNav();
|
const { userAvatar, getLogo, username } = useNav();
|
||||||
const cropRef = ref();
|
const cropRef = ref();
|
||||||
const upload = ref();
|
const upload = ref();
|
||||||
@ -18,19 +17,19 @@ const userInfoFormRef = ref<FormInstance>();
|
|||||||
// 从服务器拉取用户信息,然后填充表单
|
// 从服务器拉取用户信息,然后填充表单
|
||||||
|
|
||||||
const userInfoFormData = reactive({
|
const userInfoFormData = reactive({
|
||||||
avatarUrl: "",
|
avatar: "",
|
||||||
nickName: "",
|
nickname: "",
|
||||||
introduce: "",
|
email: "",
|
||||||
regionCode: "",
|
phone: "",
|
||||||
address: ""
|
description: ""
|
||||||
});
|
});
|
||||||
|
|
||||||
getUserInfo().then(res => {
|
getMine().then(res => {
|
||||||
Object.assign(userInfoFormData, res.data);
|
Object.assign(userInfoFormData, res.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
const rules = reactive<FormRules<UserInfo>>({
|
const rules = reactive<FormRules<UserInfo>>({
|
||||||
nickName: [
|
nickname: [
|
||||||
{ required: true, message: "昵称必填", trigger: "blur" },
|
{ required: true, message: "昵称必填", trigger: "blur" },
|
||||||
{ min: 3, max: 5, message: "长度最小3最大16", trigger: "blur" }
|
{ min: 3, max: 5, message: "长度最小3最大16", trigger: "blur" }
|
||||||
]
|
]
|
||||||
@ -81,13 +80,6 @@ const handleSubmitImage = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const options = ref(); // 级联选择器的选项数据
|
|
||||||
|
|
||||||
// 设置区域数据
|
|
||||||
getRegions().then(res => {
|
|
||||||
options.value = res.data;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 监听级联选择器的值变化
|
// 监听级联选择器的值变化
|
||||||
const handleCascaderChange = value => {
|
const handleCascaderChange = value => {
|
||||||
console.log(value);
|
console.log(value);
|
||||||
@ -104,11 +96,34 @@ const onSubmit = async (formEl: FormInstance) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function createFilter(queryString) {
|
||||||
|
return item => {
|
||||||
|
return item.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function querySearchEmail(queryString, callback) {
|
||||||
|
const emailList = [
|
||||||
|
{ value: "@qq.com" },
|
||||||
|
{ value: "@126.com" },
|
||||||
|
{ value: "@163.com" }
|
||||||
|
];
|
||||||
|
let results = [];
|
||||||
|
let queryList = [];
|
||||||
|
emailList.map(item =>
|
||||||
|
queryList.push({ value: queryString.split("@")[0] + item.value })
|
||||||
|
);
|
||||||
|
results = queryString
|
||||||
|
? queryList.filter(createFilter(queryString))
|
||||||
|
: queryList;
|
||||||
|
callback(results);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-card shadow="never">
|
<div class="ml-[120px] min-w-[180px] max-w-[70%]">
|
||||||
<template #header>基本信息</template>
|
<h3 class="my-8">个人信息</h3>
|
||||||
<el-form
|
<el-form
|
||||||
ref="userInfoFormRef"
|
ref="userInfoFormRef"
|
||||||
label-position="top"
|
label-position="top"
|
||||||
@ -132,37 +147,42 @@ const onSubmit = async (formEl: FormInstance) => {
|
|||||||
</el-button>
|
</el-button>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="昵称" prop="nickName">
|
<el-form-item label="昵称" prop="nickname">
|
||||||
<el-input v-model="userInfoFormData.nickName" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="简介">
|
|
||||||
<el-input
|
<el-input
|
||||||
v-model="userInfoFormData.introduce"
|
v-model="userInfoFormData.nickname"
|
||||||
type="textarea"
|
placeholder="请输入昵称"
|
||||||
:autosize="{ minRows: 4, maxRows: 6 }"
|
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="所在地区">
|
<el-form-item label="邮箱" prop="email">
|
||||||
<el-cascader
|
<el-autocomplete
|
||||||
v-model="userInfoFormData.regionCode"
|
v-model="userInfoFormData.email"
|
||||||
:options="options"
|
:fetch-suggestions="querySearchEmail"
|
||||||
:props="{ value: 'code', label: 'name', emitPath: false }"
|
:trigger-on-focus="false"
|
||||||
placeholder="请选择"
|
placeholder="请输入邮箱"
|
||||||
@change="handleCascaderChange"
|
clearable
|
||||||
|
class="w-full"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="街道地址">
|
<el-form-item label="联系电话">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="userInfoFormData.address"
|
v-model="userInfoFormData.phone"
|
||||||
placeholder="请输入"
|
placeholder="请输入联系电话"
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item label="简介">
|
||||||
<el-button type="primary" @click="onSubmit(userInfoFormRef)"
|
<el-input
|
||||||
>更新基本信息</el-button
|
v-model="userInfoFormData.description"
|
||||||
>
|
placeholder="请输入简介"
|
||||||
|
type="textarea"
|
||||||
|
:autosize="{ minRows: 6, maxRows: 8 }"
|
||||||
|
maxlength="56"
|
||||||
|
show-word-limit
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-button type="primary" @click="onSubmit(userInfoFormRef)">
|
||||||
|
更新信息
|
||||||
|
</el-button>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="isShow"
|
v-model="isShow"
|
||||||
@ -180,5 +200,5 @@ const onSubmit = async (formEl: FormInstance) => {
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</el-card>
|
</div>
|
||||||
</template>
|
</template>
|
7
src/views/account-settings/components/securityLog.vue
Normal file
7
src/views/account-settings/components/securityLog.vue
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="ml-[120px] min-w-[180px] max-w-[70%]">
|
||||||
|
<h3 class="my-8">安全日志</h3>
|
||||||
|
</div>
|
||||||
|
</template>
|
145
src/views/account-settings/index.vue
Normal file
145
src/views/account-settings/index.vue
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { getMine } from "@/api/user";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { ReText } from "@/components/ReText";
|
||||||
|
import Profile from "./components/profile.vue";
|
||||||
|
import Preferences from "./components/preferences.vue";
|
||||||
|
import SecurityLog from "./components/securityLog.vue";
|
||||||
|
import AccountManagement from "./components/accountManagement.vue";
|
||||||
|
|
||||||
|
import leftLine from "@iconify-icons/ri/arrow-left-s-line";
|
||||||
|
import ProfileIcon from "@iconify-icons/ri/user-3-line";
|
||||||
|
import PreferencesIcon from "@iconify-icons/ri/settings-3-line";
|
||||||
|
import SecurityLogIcon from "@iconify-icons/ri/window-line";
|
||||||
|
import AccountManagementIcon from "@iconify-icons/ri/profile-line";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "AccountSettings"
|
||||||
|
});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const userInfo = ref({
|
||||||
|
avatar: "",
|
||||||
|
username: "",
|
||||||
|
nickname: ""
|
||||||
|
});
|
||||||
|
const panes = [
|
||||||
|
{
|
||||||
|
key: "profile",
|
||||||
|
label: "个人信息",
|
||||||
|
icon: ProfileIcon,
|
||||||
|
component: Profile
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "preferences",
|
||||||
|
label: "偏好设置",
|
||||||
|
icon: PreferencesIcon,
|
||||||
|
component: Preferences
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "securityLog",
|
||||||
|
label: "安全日志",
|
||||||
|
icon: SecurityLogIcon,
|
||||||
|
component: SecurityLog
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "accountManagement",
|
||||||
|
label: "账户管理",
|
||||||
|
icon: AccountManagementIcon,
|
||||||
|
component: AccountManagement
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const witchPane = ref("profile");
|
||||||
|
|
||||||
|
getMine().then(res => {
|
||||||
|
userInfo.value = res.data;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-container class="h-full">
|
||||||
|
<el-aside class="settings-sidebar px-2" width="240px">
|
||||||
|
<el-menu :default-active="witchPane" class="settings-menu">
|
||||||
|
<el-menu-item
|
||||||
|
class="hover:transition-all hover:duration-200 hover:text-base"
|
||||||
|
@click="router.go(-1)"
|
||||||
|
>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<IconifyIconOffline :icon="leftLine" />
|
||||||
|
<span class="ml-2">返回</span>
|
||||||
|
</div>
|
||||||
|
</el-menu-item>
|
||||||
|
<div class="flex items-center ml-8 mt-4 mb-4">
|
||||||
|
<el-avatar :size="48" :src="userInfo.avatar" />
|
||||||
|
<div class="ml-4 flex flex-col max-w-[130px]">
|
||||||
|
<ReText class="font-bold !self-baseline">
|
||||||
|
{{ userInfo.nickname }}
|
||||||
|
</ReText>
|
||||||
|
<ReText class="!self-baseline" type="info">
|
||||||
|
{{ userInfo.username }}
|
||||||
|
</ReText>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-menu-item
|
||||||
|
v-for="item in panes"
|
||||||
|
:key="item.key"
|
||||||
|
:index="item.key"
|
||||||
|
@click="witchPane = item.key"
|
||||||
|
>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<el-icon><IconifyIconOffline :icon="item.icon" /></el-icon>
|
||||||
|
<span>{{ item.label }}</span>
|
||||||
|
</div>
|
||||||
|
</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
</el-aside>
|
||||||
|
<el-main>
|
||||||
|
<component :is="panes.find(item => item.key === witchPane).component" />
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.settings-sidebar {
|
||||||
|
overflow: hidden;
|
||||||
|
background: $menuBg;
|
||||||
|
border-right: 1px solid var(--pure-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-menu {
|
||||||
|
color: $subMenuActiveText;
|
||||||
|
background-color: transparent !important;
|
||||||
|
border: none !important;
|
||||||
|
|
||||||
|
::v-deep(.el-menu-item) {
|
||||||
|
position: relative;
|
||||||
|
background-color: transparent !important;
|
||||||
|
|
||||||
|
div {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
span {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0 8px;
|
||||||
|
margin: 4px 0;
|
||||||
|
clear: both;
|
||||||
|
content: "";
|
||||||
|
background: var(--el-color-primary) !important;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
x
Reference in New Issue
Block a user