Переглянути джерело

更新API接口路径,添加游客升级功能,优化用户信息管理

wuyi 3 місяців тому
батько
коміт
1d790c8d5d
3 змінених файлів з 167 додано та 9 видалено
  1. 19 2
      src/services/api.ts
  2. 1 0
      src/store/user.ts
  3. 147 7
      src/views/Account.vue

+ 19 - 2
src/services/api.ts

@@ -36,7 +36,7 @@ api.interceptors.response.use(
 );
 );
 
 
 export const login = async (name: string, password: string): Promise<any> => {
 export const login = async (name: string, password: string): Promise<any> => {
-  const response = await api.post("/users/login", {
+  const response = await api.post("/member/login", {
     name,
     name,
     password,
     password,
   });
   });
@@ -44,7 +44,7 @@ export const login = async (name: string, password: string): Promise<any> => {
 };
 };
 
 
 export const profile = async (): Promise<any> => {
 export const profile = async (): Promise<any> => {
-  const response = await api.get("/users/profile");
+  const response = await api.get("/member/profile");
   return response.data;
   return response.data;
 };
 };
 
 
@@ -63,4 +63,21 @@ export const newGuest = async (code?: string): Promise<any> => {
   return response.data;
   return response.data;
 };
 };
 
 
+export const upgradeGuest = async (
+  userId: number,
+  name: string,
+  password: string,
+  email?: string,
+  phone?: string
+): Promise<any> => {
+  const response = await api.post("/member/guestUpgrade", {
+    userId,
+    name,
+    password,
+    email: email || null,
+    phone: phone || null,
+  });
+  return response.data;
+};
+
 export default api;
 export default api;

+ 1 - 0
src/store/user.ts

@@ -47,6 +47,7 @@ export const useUserStore = defineStore("user", () => {
   return {
   return {
     token,
     token,
     userInfo,
     userInfo,
+    setUserInfo,
     login,
     login,
     logout,
     logout,
     sync,
     sync,

+ 147 - 7
src/views/Account.vue

@@ -1,11 +1,24 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { useUserStore } from "@/store/user";
 import { useUserStore } from "@/store/user";
-import { computed } from "vue";
+import { computed, ref } from "vue";
+import { upgradeGuest } from "@/services/api";
 
 
 const userStore = useUserStore();
 const userStore = useUserStore();
 const isLoggedIn = computed(() => !!userStore.token);
 const isLoggedIn = computed(() => !!userStore.token);
+const isGuest = computed(() => {
+  return userStore.userInfo?.vipLevel === "guest";
+});
 const emit = defineEmits(["show-login"]);
 const emit = defineEmits(["show-login"]);
 
 
+const showUpgradeDialog = ref(false);
+const upgradeForm = ref({
+  name: null,
+  password: null,
+  email: undefined,
+  phone: undefined,
+});
+const isLoading = ref(false);
+
 const handleLogout = () => {
 const handleLogout = () => {
   userStore.logout();
   userStore.logout();
 };
 };
@@ -13,6 +26,43 @@ const handleLogout = () => {
 const showLoginDialog = () => {
 const showLoginDialog = () => {
   emit("show-login");
   emit("show-login");
 };
 };
+
+const handleUpgrade = async () => {
+  if (!upgradeForm.value.name || !upgradeForm.value.password) {
+    alert("请填写用户名和密码");
+    return;
+  }
+
+  isLoading.value = true;
+  try {
+    const response = await upgradeGuest(
+      userStore.userInfo.id,
+      upgradeForm.value.name,
+      upgradeForm.value.password,
+      upgradeForm.value.email || undefined,
+      upgradeForm.value.phone || undefined
+    );
+
+    // 更新用户信息
+    userStore.setUserInfo(response.user);
+    showUpgradeDialog.value = false;
+
+    // 重置表单
+    upgradeForm.value = {
+      name: null,
+      password: null,
+      email: undefined,
+      phone: undefined,
+    };
+
+    alert("升级成功!");
+  } catch (error) {
+    console.error("升级失败", error);
+    alert("升级失败,请重试");
+  } finally {
+    isLoading.value = false;
+  }
+};
 </script>
 </script>
 
 
 <template>
 <template>
@@ -50,12 +100,22 @@ const showLoginDialog = () => {
           {{ isLoggedIn ? userStore.userInfo?.name || "用户" : "点击登录账号" }}
           {{ isLoggedIn ? userStore.userInfo?.name || "用户" : "点击登录账号" }}
         </h2>
         </h2>
       </div>
       </div>
-      <button
-        v-if="isLoggedIn"
-        class="px-3 py-1.5 rounded-lg bg-brand text-slate-900 text-sm font-medium"
-      >
-        开通会员
-      </button>
+      <div v-if="isLoggedIn" class="flex gap-2">
+        <button
+          v-if="isGuest"
+          @click="showUpgradeDialog = true"
+          class="px-3 py-1.5 rounded-lg bg-blue-500 text-white text-sm font-medium hover:bg-blue-600 transition"
+        >
+          成为正式用户
+        </button>
+        <button
+          class="px-3 py-1.5 rounded-lg bg-brand text-slate-900 text-sm font-medium"
+          :disabled="isGuest"
+          :class="{ 'opacity-50 cursor-not-allowed': isGuest }"
+        >
+          开通会员
+        </button>
+      </div>
       <button
       <button
         v-else
         v-else
         @click="showLoginDialog"
         @click="showLoginDialog"
@@ -100,6 +160,86 @@ const showLoginDialog = () => {
         </svg>
         </svg>
       </button>
       </button>
     </div>
     </div>
+
+    <!-- 升级弹窗 -->
+    <div
+      v-if="showUpgradeDialog"
+      class="fixed inset-0 bg-black/50 flex items-center justify-center z-50"
+      @click.self="showUpgradeDialog = false"
+    >
+      <div class="bg-white rounded-2xl p-6 w-full max-w-md mx-4">
+        <h3 class="text-xl font-semibold text-gray-900 mb-4">成为正式用户</h3>
+
+        <form @submit.prevent="handleUpgrade" class="space-y-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 mb-1">
+              用户名 <span class="text-red-500">*</span>
+            </label>
+            <input
+              v-model="upgradeForm.name"
+              type="text"
+              required
+              class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
+              placeholder="请输入用户名"
+            />
+          </div>
+
+          <div>
+            <label class="block text-sm font-medium text-gray-700 mb-1">
+              密码 <span class="text-red-500">*</span>
+            </label>
+            <input
+              v-model="upgradeForm.password"
+              type="password"
+              required
+              class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
+              placeholder="请输入密码"
+            />
+          </div>
+
+          <div>
+            <label class="block text-sm font-medium text-gray-700 mb-1">
+              邮箱
+            </label>
+            <input
+              v-model="upgradeForm.email"
+              type="email"
+              class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
+              placeholder="请输入邮箱(可选)"
+            />
+          </div>
+
+          <div>
+            <label class="block text-sm font-medium text-gray-700 mb-1">
+              手机号
+            </label>
+            <input
+              v-model="upgradeForm.phone"
+              type="tel"
+              class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
+              placeholder="请输入手机号(可选)"
+            />
+          </div>
+
+          <div class="flex gap-3 pt-4">
+            <button
+              type="button"
+              @click="showUpgradeDialog = false"
+              class="flex-1 px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition"
+            >
+              取消
+            </button>
+            <button
+              type="submit"
+              :disabled="isLoading"
+              class="flex-1 px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition disabled:opacity-50"
+            >
+              {{ isLoading ? "处理中..." : "确认升级" }}
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
   </section>
   </section>
 </template>
 </template>
 <style scoped>
 <style scoped>