mirror of https://github.com/halo-dev/halo-admin
perf: improve user profile page ui
Signed-off-by: Ryan Wang <i@ryanc.cc>pull/581/head
parent
9c9a2ea5c4
commit
3c19615656
|
@ -71,6 +71,8 @@ import IconUserFollow from "~icons/ri/user-follow-line";
|
||||||
import IconExchange from "~icons/ri/exchange-line";
|
import IconExchange from "~icons/ri/exchange-line";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import IconGitHub from "~icons/ri/github-fill";
|
import IconGitHub from "~icons/ri/github-fill";
|
||||||
|
// @ts-ignore
|
||||||
|
import IconUpload from "~icons/ri/upload-cloud-2-line";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
IconDashboard,
|
IconDashboard,
|
||||||
|
@ -109,4 +111,5 @@ export {
|
||||||
IconUserFollow,
|
IconUserFollow,
|
||||||
IconExchange,
|
IconExchange,
|
||||||
IconGitHub,
|
IconGitHub,
|
||||||
|
IconUpload,
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@ const moreMenuRootVisible = ref(false);
|
||||||
const spotlight = ref(false);
|
const spotlight = ref(false);
|
||||||
|
|
||||||
const handleRouteToProfile = () => {
|
const handleRouteToProfile = () => {
|
||||||
router.push({ name: "Profile" });
|
router.push({ path: "/users/profile/detail" });
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { BasicLayout } from "@/layouts";
|
||||||
|
import { VButton } from "@/components/base/button";
|
||||||
|
import { VTabbar } from "@/components/base/tabs";
|
||||||
|
import { IconUpload } from "@/core/icons";
|
||||||
|
import { onMounted, provide, ref } from "vue";
|
||||||
|
import { useRoute, useRouter } from "vue-router";
|
||||||
|
import { users } from "@/views/system/users/users-mock";
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
id: "detail",
|
||||||
|
label: "详情",
|
||||||
|
routeName: "UserDetail",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "profile-modification",
|
||||||
|
label: "资料修改",
|
||||||
|
routeName: "ProfileModification",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "password-change",
|
||||||
|
label: "密码修改",
|
||||||
|
routeName: "PasswordChange",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const user = ref();
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
if (route.params.username) {
|
||||||
|
user.value = users.find((u) => u.username === route.params.username);
|
||||||
|
} else {
|
||||||
|
user.value = users[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
provide("user", user);
|
||||||
|
|
||||||
|
const activeTab = ref();
|
||||||
|
|
||||||
|
const { name: currentRouteName } = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// set default active tab
|
||||||
|
onMounted(() => {
|
||||||
|
const tab = tabs.find((tab) => tab.routeName === currentRouteName);
|
||||||
|
activeTab.value = tab ? tab.id : tabs[0].id;
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleTabChange = (id: string) => {
|
||||||
|
const tab = tabs.find((tab) => tab.id === id);
|
||||||
|
if (tab) {
|
||||||
|
router.push({ name: tab.routeName });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<BasicLayout>
|
||||||
|
<header class="bg-white">
|
||||||
|
<div :class="user.cover" class="h-48 bg-gradient-to-r"></div>
|
||||||
|
<div class="px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="-mt-12 flex items-end space-x-5 sm:-mt-16">
|
||||||
|
<div class="flex">
|
||||||
|
<img
|
||||||
|
:src="user.avatar"
|
||||||
|
alt="Avatar"
|
||||||
|
class="h-24 w-24 rounded-full ring-4 ring-white drop-shadow-lg sm:h-32 sm:w-32"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mt-6 sm:flex sm:min-w-0 sm:flex-1 sm:items-center sm:justify-end sm:space-x-6 sm:pb-1"
|
||||||
|
>
|
||||||
|
<div class="mt-6 block min-w-0 flex-1">
|
||||||
|
<h1 class="truncate text-xl font-bold text-gray-900">
|
||||||
|
<span class="mr-1">{{ user.name }}</span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="justify-stretch mt-6 hidden flex-col space-y-3 sm:flex-row sm:space-y-0 sm:space-x-4 md:flex"
|
||||||
|
>
|
||||||
|
<VButton type="default">退出登录</VButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="absolute top-6 right-6">
|
||||||
|
<div class="">
|
||||||
|
<IconUpload class="text-white" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<section class="bg-white p-4 sm:px-6 lg:px-8">
|
||||||
|
<VTabbar
|
||||||
|
v-model:active-id="activeTab"
|
||||||
|
:items="tabs"
|
||||||
|
class="w-full"
|
||||||
|
type="outline"
|
||||||
|
@change="handleTabChange"
|
||||||
|
></VTabbar>
|
||||||
|
<div class="mt-2">
|
||||||
|
<RouterView></RouterView>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</BasicLayout>
|
||||||
|
</template>
|
|
@ -1,3 +1,4 @@
|
||||||
export { default as BlankLayout } from "./BlankLayout.vue";
|
export { default as BlankLayout } from "./BlankLayout.vue";
|
||||||
export { default as BasicLayout } from "./BasicLayout.vue";
|
export { default as BasicLayout } from "./BasicLayout.vue";
|
||||||
export { default as SystemSettingsLayout } from "./SystemSettingsLayout.vue";
|
export { default as SystemSettingsLayout } from "./SystemSettingsLayout.vue";
|
||||||
|
export { default as UserProfileLayout } from "./UserProfileLayout.vue";
|
||||||
|
|
|
@ -120,7 +120,7 @@ export const minimenus: MenuItemType[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "用户",
|
name: "用户",
|
||||||
path: "/users/profile",
|
path: "/users/profile/detail",
|
||||||
icon: IconUserSettings,
|
icon: IconUserSettings,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
import type { RouteRecordRaw } from "vue-router";
|
import type { RouteRecordRaw } from "vue-router";
|
||||||
import { BasicLayout, BlankLayout, SystemSettingsLayout } from "@/layouts";
|
import {
|
||||||
|
BasicLayout,
|
||||||
|
BlankLayout,
|
||||||
|
SystemSettingsLayout,
|
||||||
|
UserProfileLayout,
|
||||||
|
} from "@/layouts";
|
||||||
|
|
||||||
import Dashboard from "../views/dashboard/Dashboard.vue";
|
import Dashboard from "../views/dashboard/Dashboard.vue";
|
||||||
|
|
||||||
|
@ -19,7 +24,9 @@ import PluginList from "../views/system/plugins/PluginList.vue";
|
||||||
import PluginDetail from "../views/system/plugins/PluginDetail.vue";
|
import PluginDetail from "../views/system/plugins/PluginDetail.vue";
|
||||||
import UserList from "../views/system/users/UserList.vue";
|
import UserList from "../views/system/users/UserList.vue";
|
||||||
import RoleList from "../views/system/roles/RoleList.vue";
|
import RoleList from "../views/system/roles/RoleList.vue";
|
||||||
import Profile from "../views/system/users/Profile.vue";
|
import UserDetail from "../views/system/users/UserDetail.vue";
|
||||||
|
import ProfileModification from "../views/system/users/ProfileModification.vue";
|
||||||
|
import PasswordChange from "../views/system/users/PasswordChange.vue";
|
||||||
import GeneralSettings from "../views/system/settings/GeneralSettings.vue";
|
import GeneralSettings from "../views/system/settings/GeneralSettings.vue";
|
||||||
import NotificationSettings from "../views/system/settings/NotificationSettings.vue";
|
import NotificationSettings from "../views/system/settings/NotificationSettings.vue";
|
||||||
|
|
||||||
|
@ -158,28 +165,51 @@ export const routes: Array<RouteRecordRaw> = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/users",
|
path: "/users",
|
||||||
component: BasicLayout,
|
component: BlankLayout,
|
||||||
redirect: "/users/profile",
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
name: "Users",
|
component: BasicLayout,
|
||||||
component: UserList,
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
name: "Users",
|
||||||
|
component: UserList,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: ":username",
|
path: ":username",
|
||||||
name: "UserDetail",
|
component: UserProfileLayout,
|
||||||
component: Profile,
|
alias: ["profile"],
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "detail",
|
||||||
|
name: "UserDetail",
|
||||||
|
component: UserDetail,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "profile-modification",
|
||||||
|
name: "ProfileModification",
|
||||||
|
component: ProfileModification,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "password-change",
|
||||||
|
name: "PasswordChange",
|
||||||
|
component: PasswordChange,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "profile",
|
path: "",
|
||||||
name: "Profile",
|
component: BasicLayout,
|
||||||
component: Profile,
|
children: [
|
||||||
},
|
{
|
||||||
{
|
path: "roles",
|
||||||
path: "roles",
|
name: "Roles",
|
||||||
name: "Roles",
|
component: RoleList,
|
||||||
component: RoleList,
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { VButton } from "@/components/base/button";
|
||||||
|
import { VInput } from "@/components/base/input";
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<form class="space-y-8 divide-y divide-gray-200">
|
||||||
|
<div class="space-y-8 divide-y divide-gray-200 sm:space-y-5">
|
||||||
|
<div class="mt-6 space-y-6 sm:mt-5 sm:space-y-5">
|
||||||
|
<div
|
||||||
|
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
||||||
|
>
|
||||||
|
原密码
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
||||||
|
<div class="flex max-w-lg shadow-sm">
|
||||||
|
<VInput />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
||||||
|
>
|
||||||
|
新密码
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
||||||
|
<div class="flex max-w-lg shadow-sm">
|
||||||
|
<VInput />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
||||||
|
>
|
||||||
|
确认密码
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
||||||
|
<div class="flex max-w-lg shadow-sm">
|
||||||
|
<VInput />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pt-5">
|
||||||
|
<div class="flex justify-start">
|
||||||
|
<VButton type="secondary">修改密码</VButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</template>
|
|
@ -1,190 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import { VButton } from "@/components/base/button";
|
|
||||||
import { VInput } from "@/components/base/input";
|
|
||||||
import { VTextarea } from "@/components/base/textarea";
|
|
||||||
import { VTag } from "@/components/base/tag";
|
|
||||||
import { VTabItem, VTabs } from "@/components/base/tabs";
|
|
||||||
import { IconUserSettings } from "@/core/icons";
|
|
||||||
import { ref } from "vue";
|
|
||||||
import { useRoute } from "vue-router";
|
|
||||||
import { users } from "./users-mock";
|
|
||||||
|
|
||||||
const activeTab = ref("general");
|
|
||||||
const user = ref();
|
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
|
|
||||||
if (route.params.username) {
|
|
||||||
user.value = users.find((u) => u.username === route.params.username);
|
|
||||||
} else {
|
|
||||||
user.value = users[0];
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<header class="bg-white">
|
|
||||||
<div :class="user.cover" class="h-48 bg-gradient-to-r"></div>
|
|
||||||
<div class="px-4 sm:px-6 lg:px-8">
|
|
||||||
<div class="-mt-12 flex items-end space-x-5 sm:-mt-16">
|
|
||||||
<div class="flex">
|
|
||||||
<img
|
|
||||||
:src="user.avatar"
|
|
||||||
alt="Avatar"
|
|
||||||
class="h-24 w-24 rounded-full ring-4 ring-white drop-shadow-lg sm:h-32 sm:w-32"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mt-6 sm:flex sm:min-w-0 sm:flex-1 sm:items-center sm:justify-end sm:space-x-6 sm:pb-1"
|
|
||||||
>
|
|
||||||
<div class="mt-6 block min-w-0 flex-1">
|
|
||||||
<h1 class="truncate text-xl font-bold text-gray-900">
|
|
||||||
<span class="mr-1">{{ user.name }}</span>
|
|
||||||
<VTag theme="default">
|
|
||||||
<template #leftIcon>
|
|
||||||
<IconUserSettings />
|
|
||||||
</template>
|
|
||||||
{{ user.role }}
|
|
||||||
</VTag>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="justify-stretch mt-6 hidden flex-col space-y-3 sm:flex-row sm:space-y-0 sm:space-x-4 md:flex"
|
|
||||||
>
|
|
||||||
<VButton type="default">退出登录</VButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<section class="bg-white p-4 sm:px-6 lg:px-8">
|
|
||||||
<VTabs v-model:activeId="activeTab">
|
|
||||||
<VTabItem id="general" label="基本资料">
|
|
||||||
<form class="space-y-8 divide-y divide-gray-200">
|
|
||||||
<div class="space-y-8 divide-y divide-gray-200 sm:space-y-5">
|
|
||||||
<div class="mt-6 space-y-6 sm:mt-5 sm:space-y-5">
|
|
||||||
<div
|
|
||||||
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
|
||||||
>
|
|
||||||
用户名
|
|
||||||
</label>
|
|
||||||
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
|
||||||
<div class="flex max-w-lg shadow-sm">
|
|
||||||
<VInput :modelValue="user.username" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
|
||||||
>
|
|
||||||
昵称
|
|
||||||
</label>
|
|
||||||
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
|
||||||
<div class="flex max-w-lg shadow-sm">
|
|
||||||
<VInput :modelValue="user.name" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
|
||||||
>
|
|
||||||
电子邮箱
|
|
||||||
</label>
|
|
||||||
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
|
||||||
<div class="flex max-w-lg shadow-sm">
|
|
||||||
<VInput :modelValue="user.email" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
|
||||||
>
|
|
||||||
个人说明
|
|
||||||
</label>
|
|
||||||
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
|
||||||
<div class="flex max-w-lg shadow-sm">
|
|
||||||
<VTextarea modelValue="Halo" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pt-5">
|
|
||||||
<div class="flex justify-start">
|
|
||||||
<VButton type="secondary"> 保存</VButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</VTabItem>
|
|
||||||
<VTabItem id="password" label="密码">
|
|
||||||
<form class="space-y-8 divide-y divide-gray-200">
|
|
||||||
<div class="space-y-8 divide-y divide-gray-200 sm:space-y-5">
|
|
||||||
<div class="mt-6 space-y-6 sm:mt-5 sm:space-y-5">
|
|
||||||
<div
|
|
||||||
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
|
||||||
>
|
|
||||||
原密码
|
|
||||||
</label>
|
|
||||||
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
|
||||||
<div class="flex max-w-lg shadow-sm">
|
|
||||||
<VInput />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
|
||||||
>
|
|
||||||
新密码
|
|
||||||
</label>
|
|
||||||
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
|
||||||
<div class="flex max-w-lg shadow-sm">
|
|
||||||
<VInput />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
|
||||||
>
|
|
||||||
确认密码
|
|
||||||
</label>
|
|
||||||
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
|
||||||
<div class="flex max-w-lg shadow-sm">
|
|
||||||
<VInput />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pt-5">
|
|
||||||
<div class="flex justify-start">
|
|
||||||
<VButton type="secondary">修改密码</VButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</VTabItem>
|
|
||||||
</VTabs>
|
|
||||||
</section>
|
|
||||||
</template>
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { VInput } from "@/components/base/input";
|
||||||
|
import { VTextarea } from "@/components/base/textarea";
|
||||||
|
import { VButton } from "@/components/base/button";
|
||||||
|
import { inject } from "vue";
|
||||||
|
|
||||||
|
const user = inject("user");
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<form class="space-y-8 divide-y divide-gray-200">
|
||||||
|
<div class="space-y-8 divide-y divide-gray-200 sm:space-y-5">
|
||||||
|
<div class="mt-6 space-y-6 sm:mt-5 sm:space-y-5">
|
||||||
|
<div
|
||||||
|
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
||||||
|
>
|
||||||
|
用户名
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
||||||
|
<div class="flex max-w-lg shadow-sm">
|
||||||
|
<VInput :modelValue="user.username" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
||||||
|
>
|
||||||
|
显示名称
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
||||||
|
<div class="flex max-w-lg shadow-sm">
|
||||||
|
<VInput :modelValue="user.name" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
||||||
|
>
|
||||||
|
电子邮箱
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
||||||
|
<div class="flex max-w-lg shadow-sm">
|
||||||
|
<VInput :modelValue="user.email" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:border-gray-200 sm:pt-5"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2"
|
||||||
|
>
|
||||||
|
个人说明
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:col-span-2 sm:mt-0">
|
||||||
|
<div class="flex max-w-lg shadow-sm">
|
||||||
|
<VTextarea modelValue="Halo" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pt-5">
|
||||||
|
<div class="flex justify-start">
|
||||||
|
<VButton type="secondary"> 保存</VButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</template>
|
|
@ -0,0 +1,80 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { VTag } from "@/components/base/tag";
|
||||||
|
import { IconUserSettings } from "@/core/icons";
|
||||||
|
import { inject } from "vue";
|
||||||
|
|
||||||
|
const user = inject("user");
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="border-t border-gray-200">
|
||||||
|
<dl class="divide-y divide-gray-100">
|
||||||
|
<div
|
||||||
|
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
||||||
|
>
|
||||||
|
<dt class="text-sm font-medium text-gray-900">显示名称</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||||
|
{{ user.name }}
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
||||||
|
>
|
||||||
|
<dt class="text-sm font-medium text-gray-900">用户名</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||||
|
{{ user.username }}
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
||||||
|
>
|
||||||
|
<dt class="text-sm font-medium text-gray-900">电子邮箱</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||||
|
{{ user.email || "未设置" }}
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
||||||
|
>
|
||||||
|
<dt class="text-sm font-medium text-gray-900">角色</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||||
|
<VTag>
|
||||||
|
<template #leftIcon>
|
||||||
|
<IconUserSettings class="h-full w-full" />
|
||||||
|
</template>
|
||||||
|
{{ user.role }}
|
||||||
|
</VTag>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
||||||
|
>
|
||||||
|
<dt class="text-sm font-medium text-gray-900">描述</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||||
|
Hello Halo
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
||||||
|
>
|
||||||
|
<dt class="text-sm font-medium text-gray-900">两步验证</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">已启用</dd>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
||||||
|
>
|
||||||
|
<dt class="text-sm font-medium text-gray-900">注册时间</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||||
|
2022-01-01 00:00:00
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
||||||
|
>
|
||||||
|
<dt class="text-sm font-medium text-gray-900">最近登录时间</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||||
|
2022-05-30 12:00:00
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</template>
|
Loading…
Reference in New Issue