Procházet zdrojové kódy

📦 增加修改个人信息页面

快乐的梦鱼 před 2 týdny
rodič
revize
163f4ad15a

+ 24 - 1
src/api/auth/UserApi.ts

@@ -90,7 +90,30 @@ export class UserApi extends AppServerRequestModule<DataModel> {
   }) {
   }) {
     return (await this.post('/content/main_body_user/changepwd', data, '更新密码'))
     return (await this.post('/content/main_body_user/changepwd', data, '更新密码'))
   }
   }
-
+  async getUserInfo() {
+    return (await this.post('/content/main_body_user/getMainBodyUser', {}, '获取用户信息', undefined, UserInfo)).data as UserInfo;
+  }  
+  async updateUserInfo(data: {
+    nickname?: string,
+    avatar?: string,
+    intro?: string,
+    password?: string,
+  }) {
+    return (await this.post('/content/main_body_user/editMainBodyUser', data, '更新用户信息'))
+  }
+  async updateSystemUserInfo(data: {
+    username?: string,
+    nickname?: string,
+    avatar?: string,
+    intro?: string,
+  }) {
+    return (await this.post('/user/profile', {
+      username: data.username,
+      nickname: data?.nickname,
+      avatar: data?.avatar,
+      bio: data?.intro,
+    }, '更新用户信息'))
+  }
   async refresh() {
   async refresh() {
     return (await this.post('/ich/inheritor/refresh', {}, '刷新token', undefined, LoginResult)).data as LoginResult;
     return (await this.post('/ich/inheritor/refresh', {}, '刷新token', undefined, LoginResult)).data as LoginResult;
   }
   }

+ 1 - 1
src/common/upload/ImageUploadCo.ts

@@ -1,5 +1,5 @@
 import CommonContent from "@/api/CommonContent";
 import CommonContent from "@/api/CommonContent";
-import type { AntUploadRequestOption, UploadCoInterface } from "@/components/dynamicf/UploadImageFormItem";
+import type { AntUploadRequestOption, UploadCoInterface } from "@imengyu/imengyu-web-shared";
 
 
 export function useImageSimpleUploadCo(additionData?: Record<string, any>) : UploadCoInterface {
 export function useImageSimpleUploadCo(additionData?: Record<string, any>) : UploadCoInterface {
 
 

+ 1 - 0
src/components/NavBar.vue

@@ -49,6 +49,7 @@
       <template #overlay>
       <template #overlay>
         <a-menu>
         <a-menu>
           <a-menu-item key="2" @click="router.push('/change-password')">修改密码</a-menu-item>
           <a-menu-item key="2" @click="router.push('/change-password')">修改密码</a-menu-item>
+          <a-menu-item key="4" @click="router.push('/update-profile')">修改个人信息</a-menu-item>
           <a-menu-item key="3" @click="logout">退出登录</a-menu-item>
           <a-menu-item key="3" @click="logout">退出登录</a-menu-item>
         </a-menu>
         </a-menu>
       </template>
       </template>

src/pages/change-password.vue → src/pages/user/change-password.vue


+ 145 - 0
src/pages/user/update-profile.vue

@@ -0,0 +1,145 @@
+<template>
+  <div class="login main-background main-background-type0">
+    <div class="nav-placeholder"></div>
+    <!-- 表单 -->
+    <section class="main-section ">
+      <div class="content small-h">
+        <div class="title">
+          <h2>修改个人信息</h2>
+        </div>
+        <div class="form-container">
+          <template v-if="isSuccess">
+            <a-result
+              status="success"
+              title="修改成功"
+            >
+              <template #extra>
+                <a-button class="mt-3" block @click="router.back()">返回</a-button>
+              </template>
+            </a-result>
+          </template>
+          <template v-else>
+            <DynamicForm 
+              ref="form"
+              :model="formModel" 
+              :options="formOptions"
+            />
+            <a-button type="primary" block :loading="isSubmiting" @click="handleSubmit">确认修改</a-button>
+            <a-button class="mt-3" block @click="router.back()">返回</a-button>
+          </template>
+        </div>
+      </div>
+    </section>
+  </div>
+</template>
+
+<script setup lang="ts">
+import UserApi from '@/api/auth/UserApi';
+import { DynamicForm, type IDynamicFormOptions, type IDynamicFormRef } from '@imengyu/vue-dynamic-form';
+import { message, Modal, type FormInstance } from 'ant-design-vue';
+import { onMounted, ref } from 'vue';
+import { useRouter } from 'vue-router';
+import { useAuthStore } from '@/stores/auth';
+import { useBeforeUploadImageChecker } from '@imengyu/imengyu-web-shared';
+import { useImageSimpleUploadCo } from '@/common/upload/ImageUploadCo';
+
+const form = ref<IDynamicFormRef>();
+const formModel = ref({
+  avatar: '',
+  nickname: '',
+  intro: '',
+});
+const formOptions = ref<IDynamicFormOptions>({
+  formLabelCol: { span: 6 },
+  formWrapperCol: { span: 24 },
+  formAdditionaProps: {
+    layout: 'vertical'
+  },
+  formItems: [
+    {
+      label: '',
+      name: 'avatar',
+      type: 'single-image',
+      additionalProps: {
+        class: 'text-center',
+        placeholder: '请上传图片',
+        name: 'file',
+        accept: 'image/*',
+        beforeUpload: useBeforeUploadImageChecker(),
+        uploadCo: useImageSimpleUploadCo()
+      },
+    },
+    {
+      label: '昵称',
+      name: 'nickname',
+      type: 'text',
+      additionalProps: {
+        placeholder: '请输入昵称' 
+      }
+    },
+    {
+      label: '个人介绍',
+      name: 'intro',
+      type: 'text-area',
+      additionalProps: {
+        placeholder: '请输入个人介绍' 
+      }
+    },
+  ],
+  formRules: {
+  },
+});
+
+const isSubmiting = ref(false);
+const isSuccess = ref(false);
+
+const router = useRouter();
+const authStore = useAuthStore();
+
+onMounted(async () => {
+  if (authStore.userInfo) {
+    formModel.value.avatar = authStore.userInfo.avatar;
+    formModel.value.nickname = authStore.userInfo.nickname;
+    formModel.value.intro = (authStore.userInfo.intro || authStore.userInfo.bio || '') as string;
+  }
+});
+
+async function handleSubmit() {
+  isSubmiting.value = true;
+  try {
+    await (form.value?.getFormRef() as FormInstance).validate();
+  } catch {
+    isSubmiting.value = false;
+    return;
+  }
+
+  try {
+    await UserApi.updateSystemUserInfo({
+      username: authStore.userInfo?.username,
+      nickname: formModel.value.nickname,
+      avatar: formModel.value.avatar,
+      intro: formModel.value.intro,
+    });
+    if (authStore.userInfo) {
+      authStore.userInfo.avatar = formModel.value.avatar;
+      authStore.userInfo.nickname = formModel.value.nickname;
+      authStore.userInfo.intro = formModel.value.intro;
+    }
+    message.success('修改个人信息成功');
+    isSuccess.value = true;
+  } catch (error) {
+    Modal.error({
+      title: '修改个人信息失败',
+      content: '' + error,
+    });
+  } finally {
+    isSubmiting.value = false;
+  }
+}
+</script>
+
+<style lang="scss">
+.login {
+  min-height: calc(100vh - 50px);
+}
+</style>

+ 6 - 1
src/router/index.ts

@@ -13,7 +13,12 @@ const router = createRouter({
     {
     {
       path: '/change-password',
       path: '/change-password',
       name: 'ChangePassword',
       name: 'ChangePassword',
-      component: () => import('@/pages/change-password.vue'),
+      component: () => import('@/pages/user/change-password.vue'),
+    },
+    {
+      path: '/update-profile',
+      name: 'UpdateProfile',
+      component: () => import('@/pages/user/update-profile.vue'),
     },
     },
     {
     {
       path: '/login',
       path: '/login',

+ 7 - 1
src/stores/auth.ts

@@ -20,10 +20,11 @@ export const useAuthStore = defineStore('auth', {
       try {
       try {
         const query = route.query.internalAuth as string|undefined;
         const query = route.query.internalAuth as string|undefined;
         let res = localStorage.getItem(STORAGE_KEY);
         let res = localStorage.getItem(STORAGE_KEY);
+        let saveLoginData = false;
         if (!res && query) {
         if (!res && query) {
           res = decodeURIComponent(query);
           res = decodeURIComponent(query);
           this.loginFromEmbed = true;
           this.loginFromEmbed = true;
-          this.saveLoginData();
+          saveLoginData = true;
         }
         }
         if (!res)
         if (!res)
           throw 'no storage';
           throw 'no storage';
@@ -35,6 +36,9 @@ export const useAuthStore = defineStore('auth', {
         this.loginType = authInfo.loginType;
         this.loginType = authInfo.loginType;
         this.loginFromEmbed = authInfo.loginFromEmbed;
         this.loginFromEmbed = authInfo.loginFromEmbed;
 
 
+        if (saveLoginData)
+          this.saveLoginData();
+
         // 检查token是否过期,如果快要过期,则刷新token
         // 检查token是否过期,如果快要过期,则刷新token
         /*if (canRefresh && Date.now() > this.expireAt + 1000 * 3600 * 5) {
         /*if (canRefresh && Date.now() > this.expireAt + 1000 * 3600 * 5) {
           const refreshResult = await UserApi.refresh();
           const refreshResult = await UserApi.refresh();
@@ -70,6 +74,8 @@ export const useAuthStore = defineStore('auth', {
       this.userInfo = loginResult.userInfo;
       this.userInfo = loginResult.userInfo;
       this.loginType = loginType;
       this.loginType = loginType;
       this.expireAt = (loginResult.expiresIn || 0) + Date.now();
       this.expireAt = (loginResult.expiresIn || 0) + Date.now();
+      this.loginFromEmbed = false;
+      this.saveLoginData();
     },
     },
     saveLoginData() {
     saveLoginData() {
       localStorage.setItem(STORAGE_KEY, 
       localStorage.setItem(STORAGE_KEY,