mirror of https://github.com/halo-dev/halo-admin
parent
fd56f24b1f
commit
dae208f543
|
@ -1,5 +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";
|
|
||||||
export { default as PluginLayout } from "./PluginLayout.vue";
|
export { default as PluginLayout } from "./PluginLayout.vue";
|
||||||
|
|
|
@ -4,7 +4,7 @@ const textClassification = {
|
||||||
inner:
|
inner:
|
||||||
"inline-flex items-center w-full relative box-border border border-gray-300 formkit-invalid:border-red-500 h-9 rounded-base overflow-hidden focus-within:border-primary mt-2 sm:mt-0",
|
"inline-flex items-center w-full relative box-border border border-gray-300 formkit-invalid:border-red-500 h-9 rounded-base overflow-hidden focus-within:border-primary mt-2 sm:mt-0",
|
||||||
input:
|
input:
|
||||||
"outline-0 bg-white antialiased resize-none w-full text-black block transition-all appearance-none h-9 px-3 text-sm",
|
"outline-0 bg-white antialiased resize-none w-full text-black block transition-all appearance-none h-full px-3 text-sm",
|
||||||
};
|
};
|
||||||
|
|
||||||
const boxClassification = {
|
const boxClassification = {
|
||||||
|
@ -74,8 +74,10 @@ const theme: Record<string, Record<string, string>> = {
|
||||||
"datetime-local": textClassification,
|
"datetime-local": textClassification,
|
||||||
textarea: {
|
textarea: {
|
||||||
...textClassification,
|
...textClassification,
|
||||||
|
inner:
|
||||||
|
"inline-flex items-center w-full relative box-border border border-gray-300 formkit-invalid:border-red-500 h-32 rounded-base overflow-hidden focus-within:border-primary mt-2 sm:mt-0",
|
||||||
input:
|
input:
|
||||||
"outline-0 bg-white antialiased w-full text-black block transition-all appearance-none h-32 px-3 py-2 text-sm",
|
"outline-0 bg-white antialiased w-full text-black block transition-all appearance-none h-full px-3 py-2 text-sm",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import { VButton } from "@halo-dev/components";
|
|
||||||
import { inject, ref } from "vue";
|
|
||||||
import type { Ref } from "vue";
|
|
||||||
import { apiClient } from "@halo-dev/admin-shared";
|
|
||||||
import type { User } from "@halo-dev/api-client";
|
|
||||||
|
|
||||||
interface FormState {
|
|
||||||
state: {
|
|
||||||
password: string;
|
|
||||||
password_confirm?: string;
|
|
||||||
};
|
|
||||||
submitting: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = inject<Ref<User>>("user");
|
|
||||||
const currentUser = inject<User>("currentUser");
|
|
||||||
|
|
||||||
const formState = ref<FormState>({
|
|
||||||
state: {
|
|
||||||
password: "",
|
|
||||||
password_confirm: "",
|
|
||||||
},
|
|
||||||
submitting: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleChangePassword = async () => {
|
|
||||||
try {
|
|
||||||
formState.value.submitting = true;
|
|
||||||
if (user?.value.metadata.name === currentUser?.metadata.name) {
|
|
||||||
await apiClient.user.changePassword("-", formState.value.state);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
} finally {
|
|
||||||
formState.value.submitting = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<FormKit
|
|
||||||
id="password-form"
|
|
||||||
v-model="formState.state"
|
|
||||||
:actions="false"
|
|
||||||
type="form"
|
|
||||||
@submit="handleChangePassword"
|
|
||||||
>
|
|
||||||
<FormKit
|
|
||||||
label="新密码"
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
validation="required"
|
|
||||||
></FormKit>
|
|
||||||
<FormKit
|
|
||||||
label="确认密码"
|
|
||||||
name="password_confirm"
|
|
||||||
type="password"
|
|
||||||
validation="required|confirm"
|
|
||||||
></FormKit>
|
|
||||||
</FormKit>
|
|
||||||
|
|
||||||
<div class="pt-5">
|
|
||||||
<div class="flex justify-start">
|
|
||||||
<VButton
|
|
||||||
:loading="formState.submitting"
|
|
||||||
type="secondary"
|
|
||||||
@click="$formkit.submit('password-form')"
|
|
||||||
>修改密码
|
|
||||||
</VButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,37 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import { VButton } from "@halo-dev/components";
|
|
||||||
import { inject } from "vue";
|
|
||||||
import type { Ref } from "vue";
|
|
||||||
import type { User } from "@halo-dev/api-client";
|
|
||||||
|
|
||||||
const user = inject<Ref<User>>("user");
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<FormKit v-if="user" id="user-form" :actions="false" type="form">
|
|
||||||
<FormKit
|
|
||||||
v-model="user.metadata.name"
|
|
||||||
label="用户名"
|
|
||||||
type="text"
|
|
||||||
validation="required"
|
|
||||||
></FormKit>
|
|
||||||
<FormKit
|
|
||||||
v-model="user.spec.displayName"
|
|
||||||
label="显示名称"
|
|
||||||
type="text"
|
|
||||||
validation="required"
|
|
||||||
></FormKit>
|
|
||||||
<FormKit
|
|
||||||
v-model="user.spec.email"
|
|
||||||
label="电子邮箱"
|
|
||||||
type="email"
|
|
||||||
validation="required"
|
|
||||||
></FormKit>
|
|
||||||
<FormKit v-model="user.spec.bio" label="描述" type="textarea"></FormKit>
|
|
||||||
</FormKit>
|
|
||||||
|
|
||||||
<div class="pt-5">
|
|
||||||
<div class="flex justify-start">
|
|
||||||
<VButton type="secondary">保存</VButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,10 +1,11 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { BasicLayout } from "../layouts";
|
import { apiClient, BasicLayout } from "@halo-dev/admin-shared";
|
||||||
import { IconUpload, VButton, VTabbar } from "@halo-dev/components";
|
import { IconUpload, VButton, VSpace, VTabbar } from "@halo-dev/components";
|
||||||
import { onMounted, provide, ref, watch } from "vue";
|
import { onMounted, provide, ref, watch } from "vue";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { apiClient } from "../utils/api-client";
|
|
||||||
import type { User } from "@halo-dev/api-client";
|
import type { User } from "@halo-dev/api-client";
|
||||||
|
import UserEditingModal from "../components/UserEditingModal.vue";
|
||||||
|
import UserPasswordChangeModal from "../components/UserPasswordChangeModal.vue";
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
|
@ -17,19 +18,11 @@ const tabs = [
|
||||||
label: "个人令牌",
|
label: "个人令牌",
|
||||||
routeName: "PersonalAccessTokens",
|
routeName: "PersonalAccessTokens",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: "profile-modification",
|
|
||||||
label: "资料修改",
|
|
||||||
routeName: "ProfileModification",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "password-change",
|
|
||||||
label: "密码修改",
|
|
||||||
routeName: "PasswordChange",
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const user = ref<User>();
|
const user = ref<User>();
|
||||||
|
const editingModal = ref(false);
|
||||||
|
const passwordChangeModal = ref(false);
|
||||||
|
|
||||||
const { params } = useRoute();
|
const { params } = useRoute();
|
||||||
|
|
||||||
|
@ -75,16 +68,26 @@ const handleTabChange = (id: string) => {
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<BasicLayout>
|
<BasicLayout>
|
||||||
|
<UserEditingModal
|
||||||
|
v-model:visible="editingModal"
|
||||||
|
:user="user"
|
||||||
|
@close="handleFetchUser"
|
||||||
|
/>
|
||||||
|
<UserPasswordChangeModal
|
||||||
|
v-model:visible="passwordChangeModal"
|
||||||
|
:user="user"
|
||||||
|
@close="handleFetchUser"
|
||||||
|
/>
|
||||||
<header class="bg-white">
|
<header class="bg-white">
|
||||||
<div class="h-48 bg-gradient-to-r from-gray-800 to-red-500"></div>
|
<div class="h-48 bg-gradient-to-r from-gray-800 to-red-500"></div>
|
||||||
<div class="px-4 sm:px-6 lg:px-8">
|
<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="-mt-12 flex items-end space-x-5 sm:-mt-16">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="bg-white h-24 w-24 sm:h-32 sm:w-32">
|
<div class="h-24 w-24 sm:h-32 sm:w-32">
|
||||||
<img
|
<img
|
||||||
:src="user?.spec?.avatar"
|
:src="user?.spec?.avatar"
|
||||||
alt="Avatar"
|
alt="Avatar"
|
||||||
class="h-full w-full rounded-full ring-4 ring-white drop-shadow-lg"
|
class="h-full w-full rounded-full bg-white ring-4 ring-white drop-shadow-lg"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -95,11 +98,35 @@ const handleTabChange = (id: string) => {
|
||||||
<h1 class="truncate text-xl font-bold text-gray-900">
|
<h1 class="truncate text-xl font-bold text-gray-900">
|
||||||
<span class="mr-1">{{ user?.spec?.displayName }}</span>
|
<span class="mr-1">{{ user?.spec?.displayName }}</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
<h2 class="text-gray-600">@{{ user?.metadata.name }}</h2>
|
||||||
</div>
|
</div>
|
||||||
<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"
|
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>
|
<FloatingDropdown>
|
||||||
|
<VButton type="default">编辑</VButton>
|
||||||
|
<template #popper>
|
||||||
|
<div class="w-48 p-2">
|
||||||
|
<VSpace class="w-full" direction="column">
|
||||||
|
<VButton
|
||||||
|
v-close-popper
|
||||||
|
block
|
||||||
|
type="secondary"
|
||||||
|
@click="editingModal = true"
|
||||||
|
>
|
||||||
|
修改资料
|
||||||
|
</VButton>
|
||||||
|
<VButton
|
||||||
|
v-close-popper
|
||||||
|
block
|
||||||
|
@click="passwordChangeModal = true"
|
||||||
|
>
|
||||||
|
修改密码
|
||||||
|
</VButton>
|
||||||
|
</VSpace>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</FloatingDropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -1,13 +1,7 @@
|
||||||
import {
|
import { BasicLayout, BlankLayout, definePlugin } from "@halo-dev/admin-shared";
|
||||||
BasicLayout,
|
import UserProfileLayout from "./layouts/UserProfileLayout.vue";
|
||||||
BlankLayout,
|
|
||||||
definePlugin,
|
|
||||||
UserProfileLayout,
|
|
||||||
} from "@halo-dev/admin-shared";
|
|
||||||
import UserList from "./UserList.vue";
|
import UserList from "./UserList.vue";
|
||||||
import UserDetail from "./UserDetail.vue";
|
import UserDetail from "./UserDetail.vue";
|
||||||
import ProfileModification from "./ProfileModification.vue";
|
|
||||||
import PasswordChange from "./PasswordChange.vue";
|
|
||||||
import PersonalAccessTokens from "./PersonalAccessTokens.vue";
|
import PersonalAccessTokens from "./PersonalAccessTokens.vue";
|
||||||
import Login from "./Login.vue";
|
import Login from "./Login.vue";
|
||||||
import { IconUserSettings } from "@halo-dev/components";
|
import { IconUserSettings } from "@halo-dev/components";
|
||||||
|
@ -42,22 +36,13 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
path: ":name",
|
path: ":name",
|
||||||
component: UserProfileLayout,
|
component: UserProfileLayout,
|
||||||
|
name: "User",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "detail",
|
path: "detail",
|
||||||
name: "UserDetail",
|
name: "UserDetail",
|
||||||
component: UserDetail,
|
component: UserDetail,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "profile-modification",
|
|
||||||
name: "ProfileModification",
|
|
||||||
component: ProfileModification,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "password-change",
|
|
||||||
name: "PasswordChange",
|
|
||||||
component: PasswordChange,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "tokens",
|
path: "tokens",
|
||||||
name: "PersonalAccessTokens",
|
name: "PersonalAccessTokens",
|
||||||
|
|
Loading…
Reference in New Issue