소스 검색

feat: tdesign add profile

xingyu4j 7 달 전
부모
커밋
acf99f2441

+ 9 - 0
apps/web-tdesign/src/layouts/basic.vue

@@ -2,6 +2,7 @@
 import type { NotificationItem } from '@vben/layouts';
 
 import { computed, ref, watch } from 'vue';
+import { useRouter } from 'vue-router';
 
 import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
 import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
@@ -52,6 +53,7 @@ const notifications = ref<NotificationItem[]>([
   },
 ]);
 
+const router = useRouter();
 const userStore = useUserStore();
 const authStore = useAuthStore();
 const accessStore = useAccessStore();
@@ -61,6 +63,13 @@ const showDot = computed(() =>
 );
 
 const menus = computed(() => [
+  {
+    handler: () => {
+      router.push({ name: 'Profile' });
+    },
+    icon: 'lucide:user',
+    text: $t('page.auth.profile'),
+  },
   {
     handler: () => {
       openWindow(VBEN_DOC_URL, {

+ 2 - 1
apps/web-tdesign/src/locales/langs/en-US/page.json

@@ -4,7 +4,8 @@
     "register": "Register",
     "codeLogin": "Code Login",
     "qrcodeLogin": "Qr Code Login",
-    "forgetPassword": "Forget Password"
+    "forgetPassword": "Forget Password",
+    "profile": "Profile"
   },
   "dashboard": {
     "title": "Dashboard",

+ 2 - 1
apps/web-tdesign/src/locales/langs/zh-CN/page.json

@@ -4,7 +4,8 @@
     "register": "注册",
     "codeLogin": "验证码登录",
     "qrcodeLogin": "二维码登录",
-    "forgetPassword": "忘记密码"
+    "forgetPassword": "忘记密码",
+    "profile": "个人中心"
   },
   "dashboard": {
     "title": "概览",

+ 10 - 0
apps/web-tdesign/src/router/routes/modules/vben.ts

@@ -89,6 +89,16 @@ const routes: RouteRecordRaw[] = [
       order: 9999,
     },
   },
+  {
+    name: 'Profile',
+    path: '/profile',
+    component: () => import('#/views/_core/profile/index.vue'),
+    meta: {
+      icon: 'lucide:user',
+      hideInMenu: true,
+      title: $t('page.auth.profile'),
+    },
+  },
 ];
 
 export default routes;

+ 65 - 0
apps/web-tdesign/src/views/_core/profile/base-setting.vue

@@ -0,0 +1,65 @@
+<script setup lang="ts">
+import type { BasicOption } from '@vben/types';
+
+import type { VbenFormSchema } from '#/adapter/form';
+
+import { computed, onMounted, ref } from 'vue';
+
+import { ProfileBaseSetting } from '@vben/common-ui';
+
+import { getUserInfoApi } from '#/api';
+
+const profileBaseSettingRef = ref();
+
+const MOCK_ROLES_OPTIONS: BasicOption[] = [
+  {
+    label: '管理员',
+    value: 'super',
+  },
+  {
+    label: '用户',
+    value: 'user',
+  },
+  {
+    label: '测试',
+    value: 'test',
+  },
+];
+
+const formSchema = computed((): VbenFormSchema[] => {
+  return [
+    {
+      fieldName: 'realName',
+      component: 'Input',
+      label: '姓名',
+    },
+    {
+      fieldName: 'username',
+      component: 'Input',
+      label: '用户名',
+    },
+    {
+      fieldName: 'roles',
+      component: 'Select',
+      componentProps: {
+        mode: 'tags',
+        options: MOCK_ROLES_OPTIONS,
+      },
+      label: '角色',
+    },
+    {
+      fieldName: 'introduction',
+      component: 'Textarea',
+      label: '个人简介',
+    },
+  ];
+});
+
+onMounted(async () => {
+  const data = await getUserInfoApi();
+  profileBaseSettingRef.value.getFormApi().setValues(data);
+});
+</script>
+<template>
+  <ProfileBaseSetting ref="profileBaseSettingRef" :form-schema="formSchema" />
+</template>

+ 49 - 0
apps/web-tdesign/src/views/_core/profile/index.vue

@@ -0,0 +1,49 @@
+<script setup lang="ts">
+import { ref } from 'vue';
+
+import { Profile } from '@vben/common-ui';
+import { useUserStore } from '@vben/stores';
+
+import ProfileBase from './base-setting.vue';
+import ProfileNotificationSetting from './notification-setting.vue';
+import ProfilePasswordSetting from './password-setting.vue';
+import ProfileSecuritySetting from './security-setting.vue';
+
+const userStore = useUserStore();
+
+const tabsValue = ref<string>('basic');
+
+const tabs = ref([
+  {
+    label: '基本设置',
+    value: 'basic',
+  },
+  {
+    label: '安全设置',
+    value: 'security',
+  },
+  {
+    label: '修改密码',
+    value: 'password',
+  },
+  {
+    label: '新消息提醒',
+    value: 'notice',
+  },
+]);
+</script>
+<template>
+  <Profile
+    v-model:model-value="tabsValue"
+    title="个人中心"
+    :user-info="userStore.userInfo"
+    :tabs="tabs"
+  >
+    <template #content>
+      <ProfileBase v-if="tabsValue === 'basic'" />
+      <ProfileSecuritySetting v-if="tabsValue === 'security'" />
+      <ProfilePasswordSetting v-if="tabsValue === 'password'" />
+      <ProfileNotificationSetting v-if="tabsValue === 'notice'" />
+    </template>
+  </Profile>
+</template>

+ 31 - 0
apps/web-tdesign/src/views/_core/profile/notification-setting.vue

@@ -0,0 +1,31 @@
+<script setup lang="ts">
+import { computed } from 'vue';
+
+import { ProfileNotificationSetting } from '@vben/common-ui';
+
+const formSchema = computed(() => {
+  return [
+    {
+      value: true,
+      fieldName: 'accountPassword',
+      label: '账户密码',
+      description: '其他用户的消息将以站内信的形式通知',
+    },
+    {
+      value: true,
+      fieldName: 'systemMessage',
+      label: '系统消息',
+      description: '系统消息将以站内信的形式通知',
+    },
+    {
+      value: true,
+      fieldName: 'todoTask',
+      label: '待办任务',
+      description: '待办任务将以站内信的形式通知',
+    },
+  ];
+});
+</script>
+<template>
+  <ProfileNotificationSetting :form-schema="formSchema" />
+</template>

+ 66 - 0
apps/web-tdesign/src/views/_core/profile/password-setting.vue

@@ -0,0 +1,66 @@
+<script setup lang="ts">
+import type { VbenFormSchema } from '#/adapter/form';
+
+import { computed, ref } from 'vue';
+
+import { ProfilePasswordSetting, z } from '@vben/common-ui';
+
+import { message } from '#/adapter/tdesign';
+
+const profilePasswordSettingRef = ref();
+
+const formSchema = computed((): VbenFormSchema[] => {
+  return [
+    {
+      fieldName: 'oldPassword',
+      label: '旧密码',
+      component: 'VbenInputPassword',
+      componentProps: {
+        placeholder: '请输入旧密码',
+      },
+    },
+    {
+      fieldName: 'newPassword',
+      label: '新密码',
+      component: 'VbenInputPassword',
+      componentProps: {
+        passwordStrength: true,
+        placeholder: '请输入新密码',
+      },
+    },
+    {
+      fieldName: 'confirmPassword',
+      label: '确认密码',
+      component: 'VbenInputPassword',
+      componentProps: {
+        passwordStrength: true,
+        placeholder: '请再次输入新密码',
+      },
+      dependencies: {
+        rules(values) {
+          const { newPassword } = values;
+          return z
+            .string({ required_error: '请再次输入新密码' })
+            .min(1, { message: '请再次输入新密码' })
+            .refine((value) => value === newPassword, {
+              message: '两次输入的密码不一致',
+            });
+        },
+        triggerFields: ['newPassword'],
+      },
+    },
+  ];
+});
+
+function handleSubmit() {
+  message.success('密码修改成功');
+}
+</script>
+<template>
+  <ProfilePasswordSetting
+    ref="profilePasswordSettingRef"
+    class="w-1/3"
+    :form-schema="formSchema"
+    @submit="handleSubmit"
+  />
+</template>

+ 43 - 0
apps/web-tdesign/src/views/_core/profile/security-setting.vue

@@ -0,0 +1,43 @@
+<script setup lang="ts">
+import { computed } from 'vue';
+
+import { ProfileSecuritySetting } from '@vben/common-ui';
+
+const formSchema = computed(() => {
+  return [
+    {
+      value: true,
+      fieldName: 'accountPassword',
+      label: '账户密码',
+      description: '当前密码强度:强',
+    },
+    {
+      value: true,
+      fieldName: 'securityPhone',
+      label: '密保手机',
+      description: '已绑定手机:138****8293',
+    },
+    {
+      value: true,
+      fieldName: 'securityQuestion',
+      label: '密保问题',
+      description: '未设置密保问题,密保问题可有效保护账户安全',
+    },
+    {
+      value: true,
+      fieldName: 'securityEmail',
+      label: '备用邮箱',
+      description: '已绑定邮箱:ant***sign.com',
+    },
+    {
+      value: false,
+      fieldName: 'securityMfa',
+      label: 'MFA 设备',
+      description: '未绑定 MFA 设备,绑定后,可以进行二次确认',
+    },
+  ];
+});
+</script>
+<template>
+  <ProfileSecuritySetting :form-schema="formSchema" />
+</template>