Ver Fonte

订阅功能调试

victor.zhou há 3 meses atrás
pai
commit
74c06826d1

+ 17 - 22
README.md

@@ -1,30 +1,25 @@
-api 文档: https://www.yuque.com/kolo7/ly4p08/koe2e766ehtb7gai?singleDoc# 《PAYMENT_API》
-https://www.yuque.com/kolo7/ly4p08/yps2h45o8l3cktgb?singleDoc# 《AUTH_API》
-https://www.yuque.com/kolo7/ly4p08/rz9ylvxih1ibv476?singleDoc# 《APPLE_AUTH_API》
-设计文档:https://www.yuque.com/kolo7/ly4p08/lgz7bru6f2gvrciq?singleDoc# 《统一登录充值平台》
-https://www.yuque.com/kolo7/ly4p08/uuwa89hedxi4qtds?singleDoc# 《google Pay》
+api 文档: https://www.yuque.com/kolo7/ly4p08/koe2e766ehtb7gai?singleDoc# 《PAYMENT_API》
+https://www.yuque.com/kolo7/ly4p08/yps2h45o8l3cktgb?singleDoc# 《AUTH_API》
+https://www.yuque.com/kolo7/ly4p08/rz9ylvxih1ibv476?singleDoc# 《APPLE_AUTH_API》
+设计文档:https://www.yuque.com/kolo7/ly4p08/lgz7bru6f2gvrciq?singleDoc# 《统一登录充值平台》
+https://www.yuque.com/kolo7/ly4p08/uuwa89hedxi4qtds?singleDoc# 《google Pay》
 
-包名:com.ipeaking.recipemuse
-
-
-[iOS内购(IAP)自动续订订阅类型总结](https://juejin.cn/post/6844903924193853453)
+订阅产品api:https://www.yuque.com/kolo7/ly4p08/gz4urnur0hmpqfd5?singleDoc# 《SUBSCRIPTION_API》录充值平台》
 
 
-```bash
-# 克隆项目
-git clone https://github.com/liu-ziting/what-to-eat.git
-cd what-to-eat
+包名:com.ipeaking.recipemuse
 
-# 安装依赖
-npm install
 
-# 配置环境变量
-cp .env.example .env
-# 编辑 .env 文件,添加你的 AI API 密钥
+[iOS内购(IAP)自动续订订阅类型总结](https://juejin.cn/post/6844903924193853453)
 
-# 启动开发服务器
-npm run dev
 
-# 🎯 首次启动后,点击导航栏的 ⚙️ 图标可以动态配置AI模型参数
-```
 
+### 订阅
+获取价格配置
+创建订阅订单
+创建订阅
+查询订阅状态
+查询用户所有订阅
+取消订阅
+恢复订阅
+更新支付方式

+ 9 - 0
src/api/index.ts

@@ -39,3 +39,12 @@ export function logout() {
     method: 'post',
   })
 }
+
+
+// 获取价格配置
+export function getPriceConfig() {
+  return request({
+    url: '/api/v1/subscriptions/prices',
+    method: 'get',
+  })
+}

+ 226 - 271
src/components/GlobalNavigation.vue

@@ -1,240 +1,192 @@
 <template>
-    <nav class="bg-white border-2 border-[#0A0910] max-w-7xl mx-auto rounded-lg mb-4 shadow-lg">
-        <div class="px-4 py-6 md:px-6">
-            <!-- 桌面端导航 -->
-            <div class="hidden md:flex items-center justify-between">
-                <!-- Logo区域 -->
-                <router-link to="/" class="flex items-center gap-3 transition-transform duration-200" @click="rotateLogo">
-                    <div
-                        class="w-12 h-12 bg-gradient-to-br from-yellow-400 to-orange-500 rounded-lg flex items-center justify-center border-2 border-[#0A0910]"
-                        :class="{ 'rotate-logo': isLogoRotating }"
-                    >
-                        <span class="text-white text-xl font-bold">饭</span>
-                    </div>
-                    <div>
-                        <div class="text-2xl font-black text-dark-800 tracking-wider">
-                            {{ pageTitle }}
-                        </div>
-                        <div class="text-xs text-gray-600 font-medium">{{ pageSubtitle }}</div>
-                    </div>
-                </router-link>
+  <nav class="bg-white border-2 border-[#0A0910] max-w-7xl mx-auto rounded-lg mb-4 shadow-lg">
+    <div class="px-4 py-6 md:px-6">
+      <!-- 桌面端导航 -->
+      <div class="hidden md:flex items-center justify-between">
+        <!-- Logo区域 -->
+        <router-link to="/" class="flex items-center gap-3 transition-transform duration-200" @click="rotateLogo">
+          <div
+            class="w-12 h-12 bg-gradient-to-br from-yellow-400 to-orange-500 rounded-lg flex items-center justify-center border-2 border-[#0A0910]"
+            :class="{ 'rotate-logo': isLogoRotating }">
+            <span class="text-white text-xl font-bold">饭</span>
+          </div>
+          <div>
+            <div class="text-2xl font-black text-dark-800 tracking-wider">
+              {{ pageTitle }}
+            </div>
+            <div class="text-xs text-gray-600 font-medium">{{ pageSubtitle }}</div>
+          </div>
+        </router-link>
+
+        <!-- 导航菜单 -->
+        <div class="flex items-center gap-2">
+          <LoginButton />
+          <!-- 设置按钮 -->
+          <!-- <SettingsButton /> -->
+          <!-- 主要功能 -->
 
-                <!-- 导航菜单 -->
-                <div class="flex items-center gap-2">
-                    <LoginButton />
-                    <!-- 设置按钮 -->
-                    <!-- <SettingsButton /> -->
-                    <!-- 主要功能 -->
-                    <router-link
-                        to="/"
-                        class="flex items-center gap-1 px-3 py-2 rounded-lg font-bold border-2 border-[#0A0910] transition-all duration-200 transform hover:scale-105 text-sm"
-                        :class="$route.path === '/' ? 'bg-yellow-400 text-gray-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'"
-                    >
-                        <span>🏠</span>
-                        <span>{{ t('navigation.home') }}</span>
-                    </router-link>
-                    <router-link
-                        to="/today-eat"
-                        class="flex items-center gap-1 px-3 py-2 rounded-lg font-bold border-2 border-[#0A0910] transition-all duration-200 transform hover:scale-105 text-sm"
-                        :class="$route.path === '/today-eat' ? 'bg-yellow-400 text-gray-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'"
-                    >
-                        <span>🎲</span>
-                        <span>{{ t('navigation.todayEat') }}</span>
-                    </router-link>
-                    <router-link
-                        to="/table-design"
-                        class="flex items-center gap-1 px-3 py-2 rounded-lg font-bold border-2 border-[#0A0910] transition-all duration-200 transform hover:scale-105 text-sm"
-                        :class="$route.path === '/table-design' ? 'bg-yellow-400 text-gray-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'"
-                    >
-                        <span>🍽️</span>
-                        <span>{{ t('navigation.tableDesign') }}</span>
-                    </router-link>
-                    <router-link
-                        to="/fortune-cooking"
-                        class="flex items-center gap-1 px-3 py-2 rounded-lg font-bold border-2 border-[#0A0910] transition-all duration-200 transform hover:scale-105 text-sm"
-                        :class="$route.path === '/fortune-cooking' ? 'bg-yellow-400 text-gray-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'"
-                    >
-                        <span>🔮</span>
-                        <span>{{ t('navigation.fortuneCooking') }}</span>
-                    </router-link>
-                    <router-link
-                        to="/sauce-design"
-                        class="flex items-center gap-1 px-3 py-2 rounded-lg font-bold border-2 border-[#0A0910] transition-all duration-200 transform hover:scale-105 text-sm"
-                        :class="$route.path === '/sauce-design' ? 'bg-yellow-400 text-gray-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'"
-                    >
-                        <span>🥄</span>
-                        <span>{{ t('navigation.sauceDesign') }}</span>
-                    </router-link>
+          <template v-if="false">
+            <router-link to="/"
+              class="flex items-center gap-1 px-3 py-2 rounded-lg font-bold border-2 border-[#0A0910] transition-all duration-200 transform hover:scale-105 text-sm"
+              :class="$route.path === '/' ? 'bg-yellow-400 text-gray-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'">
+              <span>🏠</span>
+              <span>{{ t('navigation.home') }}</span>
+            </router-link>
+            <router-link to="/today-eat"
+              class="flex items-center gap-1 px-3 py-2 rounded-lg font-bold border-2 border-[#0A0910] transition-all duration-200 transform hover:scale-105 text-sm"
+              :class="$route.path === '/today-eat' ? 'bg-yellow-400 text-gray-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'">
+              <span>🎲</span>
+              <span>{{ t('navigation.todayEat') }}</span>
+            </router-link>
+            <router-link to="/table-design"
+              class="flex items-center gap-1 px-3 py-2 rounded-lg font-bold border-2 border-[#0A0910] transition-all duration-200 transform hover:scale-105 text-sm"
+              :class="$route.path === '/table-design' ? 'bg-yellow-400 text-gray-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'">
+              <span>🍽️</span>
+              <span>{{ t('navigation.tableDesign') }}</span>
+            </router-link>
+            <router-link to="/fortune-cooking"
+              class="flex items-center gap-1 px-3 py-2 rounded-lg font-bold border-2 border-[#0A0910] transition-all duration-200 transform hover:scale-105 text-sm"
+              :class="$route.path === '/fortune-cooking' ? 'bg-yellow-400 text-gray-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'">
+              <span>🔮</span>
+              <span>{{ t('navigation.fortuneCooking') }}</span>
+            </router-link>
+            <router-link to="/sauce-design"
+              class="flex items-center gap-1 px-3 py-2 rounded-lg font-bold border-2 border-[#0A0910] transition-all duration-200 transform hover:scale-105 text-sm"
+              :class="$route.path === '/sauce-design' ? 'bg-yellow-400 text-gray-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'">
+              <span>🥄</span>
+              <span>{{ t('navigation.sauceDesign') }}</span>
+            </router-link>
 
-                    <!-- 更多菜单下拉 -->
-                    <div class="relative" @mouseleave="handleMouseLeave">
-                        <button
-                            @mouseenter="handleMouseEnter"
-                            @click="showMoreMenu = !showMoreMenu"
-                            :class="[
-                                'flex items-center gap-1 px-3 py-2 rounded-lg font-bold border-2 border-[#0A0910] transition-all duration-200 transform hover:scale-105 text-sm',
-                                isMoreMenuActive ? 'bg-yellow-400 text-gray-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
-                            ]"
-                        >
-                            <span>⋯</span>
-                            <span>{{ t('navigation.more') }}</span>
-                        </button>
+            <!-- 更多菜单下拉 -->
+            <div class="relative" @mouseleave="handleMouseLeave">
+              <button @mouseenter="handleMouseEnter" @click="showMoreMenu = !showMoreMenu" :class="[
+                'flex items-center gap-1 px-3 py-2 rounded-lg font-bold border-2 border-[#0A0910] transition-all duration-200 transform hover:scale-105 text-sm',
+                isMoreMenuActive ? 'bg-yellow-400 text-gray-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
+              ]">
+                <span>⋯</span>
+                <span>{{ t('navigation.more') }}</span>
+              </button>
 
-                        <!-- 下拉菜单 -->
-                        <div
-                            v-if="showMoreMenu"
-                            @mouseenter="handleMouseEnter"
-                            class="absolute right-0 top-full mt-0.5 w-40 bg-white border-2 border-[#0A0910] rounded-lg shadow-lg z-50 overflow-hidden"
-                        >
-                            <router-link
-                                to="/favorites"
-                                @click="showMoreMenu = false"
-                                class="flex items-center gap-2 px-4 py-3 text-sm font-bold transition-colors duration-200 hover:bg-gray-100"
-                                :class="$route.path === '/favorites' ? 'bg-yellow-100 text-gray-800' : 'text-gray-700'"
-                            >
-                                <span>❤️</span>
-                                <span>{{ t('navigation.favorites') }}</span>
-                            </router-link>
-                            <router-link
-                                to="/gallery"
-                                @click="showMoreMenu = false"
-                                class="flex items-center gap-2 px-4 py-3 text-sm font-bold transition-colors duration-200 hover:bg-gray-100"
-                                :class="$route.path === '/gallery' ? 'bg-yellow-100 text-gray-800' : 'text-gray-700'"
-                            >
-                                <span>🖼️</span>
-                                <span>{{ t('navigation.gallery') }}</span>
-                            </router-link>
-                            <router-link
-                                to="/about"
-                                @click="showMoreMenu = false"
-                                class="flex items-center gap-2 px-4 py-3 text-sm font-bold transition-colors duration-200 hover:bg-gray-100"
-                                :class="$route.path === '/about' ? 'bg-yellow-100 text-gray-800' : 'text-gray-700'"
-                            >
-                                <span>📖</span>
-                                <span>{{ t('navigation.about') }}</span>
-                            </router-link>
-                        </div>
-                    </div>
-                </div>
+              <!-- 下拉菜单 -->
+              <div v-if="showMoreMenu" @mouseenter="handleMouseEnter"
+                class="absolute right-0 top-full mt-0.5 w-40 bg-white border-2 border-[#0A0910] rounded-lg shadow-lg z-50 overflow-hidden">
+                <router-link to="/favorites" @click="showMoreMenu = false"
+                  class="flex items-center gap-2 px-4 py-3 text-sm font-bold transition-colors duration-200 hover:bg-gray-100"
+                  :class="$route.path === '/favorites' ? 'bg-yellow-100 text-gray-800' : 'text-gray-700'">
+                  <span>❤️</span>
+                  <span>{{ t('navigation.favorites') }}</span>
+                </router-link>
+                <router-link to="/gallery" @click="showMoreMenu = false"
+                  class="flex items-center gap-2 px-4 py-3 text-sm font-bold transition-colors duration-200 hover:bg-gray-100"
+                  :class="$route.path === '/gallery' ? 'bg-yellow-100 text-gray-800' : 'text-gray-700'">
+                  <span>🖼️</span>
+                  <span>{{ t('navigation.gallery') }}</span>
+                </router-link>
+                <router-link to="/about" @click="showMoreMenu = false"
+                  class="flex items-center gap-2 px-4 py-3 text-sm font-bold transition-colors duration-200 hover:bg-gray-100"
+                  :class="$route.path === '/about' ? 'bg-yellow-100 text-gray-800' : 'text-gray-700'">
+                  <span>📖</span>
+                  <span>{{ t('navigation.about') }}</span>
+                </router-link>
+              </div>
             </div>
+          </template>
+
+        </div>
+      </div>
 
-            <!-- 移动端导航 -->
-            <div class="md:hidden">
-                <!-- 顶部Logo和菜单按钮 -->
-                <div class="flex items-center justify-between">
-                    <router-link to="/" class="flex items-center gap-2" @click="rotateLogo">
-                        <div
-                            class="w-10 h-10 bg-gradient-to-br from-yellow-400 to-orange-500 rounded-lg flex items-center justify-center border-2 border-[#0A0910]"
-                            :class="{ 'rotate-logo': isLogoRotating }"
-                        >
-                            <span class="text-white text-lg font-bold">饭</span>
-                        </div>
-                        <div>
-                            <div class="text-lg font-black text-dark-800 tracking-wider">
-                                {{ pageTitle }}
-                            </div>
-                            <div class="text-xs text-gray-600 font-medium">{{ pageSubtitle }}</div>
-                        </div>
-                    </router-link>
-                    <div class="flex items-center gap-2">
-                    
-                        <LoginButton />
-                        <!-- 移动端设置按钮 -->
-                        <!-- <SettingsButton /> -->
-                        <!-- <button @click="showMobileMenu = !showMobileMenu" class="p-2 bg-gray-100 hover:bg-gray-200 rounded-lg border-2 border-[#0A0910] transition-colors">
+      <!-- 移动端导航 -->
+      <div class="md:hidden">
+        <!-- 顶部Logo和菜单按钮 -->
+        <div class="flex items-center justify-between">
+          <router-link to="/" class="flex items-center gap-2" @click="rotateLogo">
+            <div
+              class="w-10 h-10 bg-gradient-to-br from-yellow-400 to-orange-500 rounded-lg flex items-center justify-center border-2 border-[#0A0910]"
+              :class="{ 'rotate-logo': isLogoRotating }">
+              <span class="text-white text-lg font-bold">饭</span>
+            </div>
+            <div>
+              <div class="text-lg font-black text-dark-800 tracking-wider">
+                {{ pageTitle }}
+              </div>
+              <div class="text-xs text-gray-600 font-medium">{{ pageSubtitle }}</div>
+            </div>
+          </router-link>
+          <div class="flex items-center gap-2">
+
+            <LoginButton />
+            <!-- 移动端设置按钮 -->
+            <!-- <SettingsButton /> -->
+            <!-- <button @click="showMobileMenu = !showMobileMenu" class="p-2 bg-gray-100 hover:bg-gray-200 rounded-lg border-2 border-[#0A0910] transition-colors">
                             <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
                             </svg>
                         </button> -->
-                    </div>
-                </div>
-
-                <!-- 移动端菜单 - 横向滚动标签栏 -->
-                <div v-if="showMobileMenu" class="border-t-2 border-gray-200 pt-3 mt-3">
-                    <!-- 横向滚动导航 -->
-                    <div class="overflow-x-auto scrollbar-hide">
-                        <div class="flex gap-2 pb-2 min-w-max">
-                            <router-link
-                                to="/"
-                                @click="showMobileMenu = false"
-                                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
-                                :class="$route.path === '/' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'"
-                            >
-                                <span>🏠</span>
-                                <span>{{ t('navigation.home') }}</span>
-                            </router-link>
-                            <router-link
-                                to="/today-eat"
-                                @click="showMobileMenu = false"
-                                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
-                                :class="$route.path === '/today-eat' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'"
-                            >
-                                <span>🎲</span>
-                                <span>{{ t('navigation.todayEat') }}</span>
-                            </router-link>
-                            <router-link
-                                to="/table-design"
-                                @click="showMobileMenu = false"
-                                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
-                                :class="$route.path === '/table-design' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'"
-                            >
-                                <span>🍽️</span>
-                                <span>{{ t('navigation.tableDesign') }}</span>
-                            </router-link>
-                            <router-link
-                                to="/sauce-design"
-                                @click="showMobileMenu = false"
-                                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
-                                :class="$route.path === '/sauce-design' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'"
-                            >
-                                <span>🥄</span>
-                                <span>{{ t('navigation.sauceDesign') }}</span>
-                            </router-link>
-                            <router-link
-                                to="/fortune-cooking"
-                                @click="showMobileMenu = false"
-                                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
-                                :class="$route.path === '/fortune-cooking' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'"
-                            >
-                                <span>🔮</span>
-                                <span>{{ t('navigation.fortuneCooking') }}</span>
-                            </router-link>
-                            <router-link
-                                to="/favorites"
-                                @click="showMobileMenu = false"
-                                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
-                                :class="$route.path === '/favorites' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'"
-                            >
-                                <span>❤️</span>
-                                <span>{{ t('navigation.favorites') }}</span>
-                            </router-link>
-                            <router-link
-                                to="/gallery"
-                                @click="showMobileMenu = false"
-                                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
-                                :class="$route.path === '/gallery' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'"
-                            >
-                                <span>🖼️</span>
-                                <span>{{ t('navigation.gallery') }}</span>
-                            </router-link>
-                            <router-link
-                                to="/about"
-                                @click="showMobileMenu = false"
-                                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
-                                :class="$route.path === '/about' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'"
-                            >
-                                <span>📖</span>
-                                <span>{{ t('navigation.about') }}</span>
-                            </router-link>
-                        </div>
-                    </div>
+          </div>
+        </div>
 
-                    <!-- 滚动提示 -->
-                    <div class="text-center text-xs text-gray-500 mt-1">{{ t('navigation.scrollHint') }}</div>
-                </div>
+        <!-- 移动端菜单 - 横向滚动标签栏 -->
+        <div v-if="showMobileMenu" class="border-t-2 border-gray-200 pt-3 mt-3">
+          <!-- 横向滚动导航 -->
+          <div class="overflow-x-auto scrollbar-hide">
+            <div class="flex gap-2 pb-2 min-w-max">
+              <router-link to="/" @click="showMobileMenu = false"
+                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
+                :class="$route.path === '/' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'">
+                <span>🏠</span>
+                <span>{{ t('navigation.home') }}</span>
+              </router-link>
+              <router-link to="/today-eat" @click="showMobileMenu = false"
+                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
+                :class="$route.path === '/today-eat' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'">
+                <span>🎲</span>
+                <span>{{ t('navigation.todayEat') }}</span>
+              </router-link>
+              <router-link to="/table-design" @click="showMobileMenu = false"
+                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
+                :class="$route.path === '/table-design' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'">
+                <span>🍽️</span>
+                <span>{{ t('navigation.tableDesign') }}</span>
+              </router-link>
+              <router-link to="/sauce-design" @click="showMobileMenu = false"
+                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
+                :class="$route.path === '/sauce-design' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'">
+                <span>🥄</span>
+                <span>{{ t('navigation.sauceDesign') }}</span>
+              </router-link>
+              <router-link to="/fortune-cooking" @click="showMobileMenu = false"
+                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
+                :class="$route.path === '/fortune-cooking' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'">
+                <span>🔮</span>
+                <span>{{ t('navigation.fortuneCooking') }}</span>
+              </router-link>
+              <router-link to="/favorites" @click="showMobileMenu = false"
+                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
+                :class="$route.path === '/favorites' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'">
+                <span>❤️</span>
+                <span>{{ t('navigation.favorites') }}</span>
+              </router-link>
+              <router-link to="/gallery" @click="showMobileMenu = false"
+                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
+                :class="$route.path === '/gallery' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'">
+                <span>🖼️</span>
+                <span>{{ t('navigation.gallery') }}</span>
+              </router-link>
+              <router-link to="/about" @click="showMobileMenu = false"
+                class="flex items-center gap-1.5 px-3 py-2 rounded-full font-bold border-2 border-[#0A0910] transition-all duration-200 whitespace-nowrap text-sm"
+                :class="$route.path === '/about' ? 'bg-yellow-400 text-gray-800 shadow-md' : 'bg-white text-gray-700 hover:bg-gray-50 active:scale-95'">
+                <span>📖</span>
+                <span>{{ t('navigation.about') }}</span>
+              </router-link>
             </div>
+          </div>
+
+          <!-- 滚动提示 -->
+          <div class="text-center text-xs text-gray-500 mt-1">{{ t('navigation.scrollHint') }}</div>
         </div>
-    </nav>
+      </div>
+    </div>
+  </nav>
 </template>
 
 <script setup lang="ts">
@@ -252,102 +204,105 @@ const isLogoRotating = ref(false)
 let hideMenuTimer: NodeJS.Timeout | null = null
 
 const rotateLogo = () => {
-    isLogoRotating.value = true
-    setTimeout(() => {
-        isLogoRotating.value = false
-    }, 500)
+  isLogoRotating.value = true
+  setTimeout(() => {
+    isLogoRotating.value = false
+  }, 500)
 }
 const route = useRoute()
 
 // 根据当前路由显示不同的页面标题
 const pageTitle = computed(() => {
-    const pathKey = route.path.replace('/', '') || 'home'
-    const key = pathKey.replace(/-([a-z])/g, (g) => g[1].toUpperCase())
-    return t(`navigation.pageTitle.${key}`, t('navigation.pageTitle.home'))
+  const pathKey = route.path.replace('/', '') || 'home'
+  const key = pathKey.replace(/-([a-z])/g, (g) => g[1].toUpperCase())
+  return t(`navigation.pageTitle.${key}`, t('navigation.pageTitle.home'))
 })
 
 const pageSubtitle = computed(() => {
-    const pathKey = route.path.replace('/', '') || 'home'
-    const key = pathKey.replace(/-([a-z])/g, (g) => g[1].toUpperCase())
-    return t(`navigation.pageSubtitle.${key}`, t('navigation.pageSubtitle.default'))
+  const pathKey = route.path.replace('/', '') || 'home'
+  const key = pathKey.replace(/-([a-z])/g, (g) => g[1].toUpperCase())
+  return t(`navigation.pageSubtitle.${key}`, t('navigation.pageSubtitle.default'))
 })
 
 // 检查更多菜单中的页面是否处于活跃状态
 const isMoreMenuActive = computed(() => {
-    return ['/favorites', '/gallery', '/about'].includes(route.path)
+  return ['/favorites', '/gallery', '/about'].includes(route.path)
 })
 
 // 处理鼠标进入事件
 const handleMouseEnter = () => {
-    if (hideMenuTimer) {
-        clearTimeout(hideMenuTimer)
-        hideMenuTimer = null
-    }
-    showMoreMenu.value = true
+  if (hideMenuTimer) {
+    clearTimeout(hideMenuTimer)
+    hideMenuTimer = null
+  }
+  showMoreMenu.value = true
 }
 
 // 处理鼠标离开事件
 const handleMouseLeave = () => {
-    hideMenuTimer = setTimeout(() => {
-        showMoreMenu.value = false
-    }, 150) // 150ms延迟,给用户足够时间移动鼠标
+  hideMenuTimer = setTimeout(() => {
+    showMoreMenu.value = false
+  }, 150) // 150ms延迟,给用户足够时间移动鼠标
 }
 </script>
 
 <style scoped>
 /* Logo旋转动画 */
 @keyframes rotate {
-    0% {
-        transform: rotate(0deg);
-    }
-    100% {
-        transform: rotate(360deg);
-    }
+  0% {
+    transform: rotate(0deg);
+  }
+
+  100% {
+    transform: rotate(360deg);
+  }
 }
 
 .rotate-logo {
-    animation: rotate 0.5s ease-out;
+  animation: rotate 0.5s ease-out;
 }
 
 /* 移动端菜单展开动画 */
 @keyframes slideDown {
-    from {
-        opacity: 0;
-        transform: translateY(-10px);
-    }
-    to {
-        opacity: 1;
-        transform: translateY(0);
-    }
+  from {
+    opacity: 0;
+    transform: translateY(-10px);
+  }
+
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
 }
 
 .flex {
-    animation: slideDown 0.3s ease-out;
+  animation: slideDown 0.3s ease-out;
 }
 
 /* 下拉菜单动画 */
 @keyframes dropDown {
-    from {
-        opacity: 0;
-        transform: translateY(-10px);
-    }
-    to {
-        opacity: 1;
-        transform: translateY(0);
-    }
+  from {
+    opacity: 0;
+    transform: translateY(-10px);
+  }
+
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
 }
 
 .absolute {
-    animation: dropDown 0.2s ease-out;
+  animation: dropDown 0.2s ease-out;
 }
 
 /* 隐藏滚动条 */
 .scrollbar-hide {
-    -ms-overflow-style: none;
-    scrollbar-width: none;
+  -ms-overflow-style: none;
+  scrollbar-width: none;
 }
 
 .scrollbar-hide::-webkit-scrollbar {
-    display: none;
+  display: none;
 }
 </style>

+ 4 - 2
src/main.ts

@@ -12,7 +12,7 @@ import SauceDesign from './views/SauceDesign.vue'
 import FortuneCooking from './views/FortuneCooking.vue'
 import SettingsDemo from './views/SettingsDemo.vue'
 import Profile from './views/Profile.vue'
-import ManageSubscription from './views/ManageSubscription.vue'
+import SubscriptionList from './views/SubscriptionList.vue'
 import { autoRefreshEnvSettings } from './utils/envWatcher'
 import './style.css'
 
@@ -20,6 +20,7 @@ import { Toast, setToastDefaultOptions } from 'vant';
 import 'vant/lib/index.css';
 
 import i18n from './i18n'
+import Pay from './views/Pay.vue'
 
 const routes = [
     { path: '/', component: Home },
@@ -33,7 +34,8 @@ const routes = [
     { path: '/fortune-cooking', component: FortuneCooking },
     { path: '/settings-demo', component: SettingsDemo },
     { path: '/profile', component: Profile },
-    { path: '/manage-subscription', component: ManageSubscription }
+    { path: '/sub-list', component: SubscriptionList },
+    { path: '/pay', component: Pay },
 ]
 
 const router = createRouter({

+ 1 - 1
src/utils/request.ts

@@ -79,7 +79,7 @@ service.interceptors.response.use(
       showFailToast(msg)
       return Promise.reject('error')
     } else {
-      return res.data
+      return res.data.data
     }
   },
   (error) => {

+ 1 - 15
src/views/Home.vue

@@ -774,21 +774,7 @@ onMounted(() => {
     checkToken()
     addEventListener()
     // setTimeout(() => {
-    //     getTokenHandler({
-    //         "code": 0,
-    //         "success": true,
-    //         "message": "认证成功",
-    //         "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6IjI3NjIwMzg3NkBxcS5jb20iLCJleHAiOjE3NjM1MTY4MTMsImdvb2dsZV9pZCI6IiIsImlhdCI6MTc2MzQzMDQxMywiaXNzIjoiYmVla2VlcGluZy1zeXN0ZW0iLCJuYW1lIjoiMjc2MjAzODc2IiwidXNlcl9pZCI6InVzZXJfYXBwbGVfMDAxNzQ2LmJfMTc2MzQzMDQxMyJ9.dcrMSGkDoKgFf9b9w1CHvnun92GxEZPOCjB-OOhrWLY",
-    //         "user": {
-    //             "id": "user_apple_001746.b_1763430413",
-    //             "email": "276203876@qq.com",
-    //             "name": "276203876",
-    //             "picture": "",
-    //             "apple_id": "001746.b066d194b82f46eaac8f3f26b9a915fc.0901",
-    //             "created_at": "2025-11-18T09:46:53.991614433+08:00",
-    //             "updated_at": "2025-11-18T09:46:53.991614433+08:00"
-    //         }
-    //     })
+    //     getTokenHandler({"code":0,"success":true,"message":"认证成功","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6IjI3NjIwMzg3NkBxcS5jb20iLCJleHAiOjE3NjQzOTY1MzEsImdvb2dsZV9pZCI6IiIsImlhdCI6MTc2NDMxMDEzMSwiaXNzIjoiYmVla2VlcGluZy1zeXN0ZW0iLCJuYW1lIjoiMjc2MjAzODc2IiwidXNlcl9pZCI6IjI3NjIwMzg3NkBxcS5jb20ifQ.o2a8p04SmbqO04i5jKZMo9hH0jP-KU0l3szPWphg6I4","user":{"id":"276203876@qq.com","email":"276203876@qq.com","name":"276203876","picture":"","apple_id":"001746.b066d194b82f46eaac8f3f26b9a915fc.0901","created_at":"2025-11-28T14:08:51.477165511+08:00","updated_at":"2025-11-28T14:08:51.477165511+08:00"}})
     // }, 1000)
 })
 

+ 0 - 145
src/views/ManageSubscription.vue

@@ -1,145 +0,0 @@
-<template>
-    <div class="min-h-screen bg-yellow-400 px-2 md:px-4 py-6">
-        <!-- 全局导航 -->
-        <GlobalNavigation />
-
-        <div class="max-w-2xl mx-auto">
-            <!-- 页面标题区域 -->
-            <div class="mb-6">
-                <div class="flex items-center justify-between mb-4">
-                    <h1 class="text-3xl md:text-4xl font-bold text-dark-800">Complete Your Subscription</h1>
-                    <div class="w-[168px] bg-blue-600 text-white px-4 py-2 rounded-full border-2 border-[#0A0910]">
-                        <p class="font-bold text-sm md:text-base">Premium Plan</p>
-                        <p class="text-xs md:text-sm">• $9.99/month</p>
-                    </div>
-                </div>
-            </div>
-
-            <!-- 订阅摘要卡片 -->
-            <div class="mb-6">
-                <div class="bg-white border-2 border-[#0A0910] rounded-lg p-6 md:p-8">
-                    <h2 class="text-2xl font-bold text-blue-700 mb-6">Subscription Summary</h2>
-                    
-                    <div class="space-y-4">
-                        <!-- Plan -->
-                        <div class="flex justify-between items-center">
-                            <span class="text-gray-600">Plan:</span>
-                            <span class="text-lg font-bold text-dark-800">Premium Plan</span>
-                        </div>
-                        
-                        <!-- Price -->
-                        <div class="flex justify-between items-center">
-                            <span class="text-gray-600">Price:</span>
-                            <span class="text-lg font-bold text-dark-800">$9.99/month</span>
-                        </div>
-                        
-                        <!-- Billing Cycle -->
-                        <div class="flex justify-between items-center">
-                            <span class="text-gray-600">Billing Cycle:</span>
-                            <span class="text-lg font-bold text-dark-800">Monthly</span>
-                        </div>
-                    </div>
-                </div>
-            </div>
-
-            <!-- 选择支付方式 -->
-            <div class="mb-6">
-                <h2 class="text-2xl font-bold text-dark-800 mb-4">Choose Payment Method</h2>
-                
-                <div class="flex gap-4 mb-6">
-                    <!-- Google Pay -->
-                    <button
-                        @click="selectPaymentMethod('google')"
-                        :class="[
-                            'bg-white border-2 rounded-lg p-6 transition-all duration-200',
-                            selectedPayment === 'google' 
-                                ? 'border-blue-600 shadow-lg' 
-                                : 'border-[#0A0910] hover:border-blue-400'
-                        ]"
-                    >
-                        <div class="flex items-center justify-center h-16">
-                            <div class="flex items-center gap-3">
-                                <svg class="w-12 h-12" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
-                                    <path d="M24 9.5C20.65 9.5 17.45 10.65 14.9 12.7L18.3 16.1C19.95 14.85 21.95 14.15 24 14.15C28.55 14.15 32.35 17.4 33.25 21.75H38.95C37.95 14.45 31.65 9.5 24 9.5Z" fill="#EA4335"/>
-                                    <path d="M9.05 24C9.05 26.05 9.55 28 10.45 29.7L5.8 33.1C4.1 30.35 3 27.25 3 24C3 20.75 4.1 17.65 5.8 14.9L10.45 18.3C9.55 20 9.05 21.95 9.05 24Z" fill="#FBBC05"/>
-                                    <path d="M24 38.5C20.65 38.5 17.45 37.35 14.9 35.3L10.45 38.7C13.2 41.4 16.95 43 21 43.5V43.5C28.3 42.5 34.3 37.5 36.75 30.75H33.25C32.35 35.1 28.55 38.5 24 38.5Z" fill="#34A853"/>
-                                    <path d="M45 24C45 22.85 44.9 21.7 44.7 20.6H24V27.65H35.4C34.7 30.55 32.85 32.95 30.35 34.45L33.85 37.2C37.95 33.45 40.2 28.15 40.2 24C40.2 22.85 40.1 21.7 39.9 20.6H45V24Z" fill="#4285F4"/>
-                                </svg>
-                                <span class="text-xl font-bold text-dark-800">Google Pay</span>
-                            </div>
-                        </div>
-                    </button>
-
-                    <!-- Apple Pay -->
-                    <button
-                        @click="selectPaymentMethod('apple')"
-                        :class="[
-                            'border-2 rounded-lg p-6 transition-all duration-200',
-                            selectedPayment === 'apple' 
-                                ? 'bg-black border-blue-600 shadow-lg' 
-                                : 'bg-black border-[#0A0910] hover:border-blue-400'
-                        ]"
-                    >
-                        <div class="flex items-center justify-center h-16">
-                            <div class="flex items-center gap-3">
-                                <svg class="w-10 h-10" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
-                                    <path d="M17.05 20.28C16.03 21.23 14.96 21.08 13.93 20.63C12.84 20.17 11.85 20.15 10.7 20.63C9.28 21.25 8.52 21.07 7.62 20.28C2.02 14.58 2.83 5.97 9.26 5.67C10.76 5.75 11.79 6.52 12.65 6.58C13.95 6.31 15.21 5.52 16.61 5.63C18.31 5.78 19.6 6.45 20.45 7.65C16.77 9.87 17.63 14.72 20.95 16.11C20.27 17.89 19.4 19.65 17.04 20.29L17.05 20.28ZM12.53 5.62C12.38 3.06 14.42 0.93 16.87 0.75C17.2 3.66 14.18 5.89 12.53 5.62Z" fill="white"/>
-                                </svg>
-                                <span class="text-xl font-bold text-white">Apple Pay</span>
-                            </div>
-                        </div>
-                    </button>
-                </div>
-            </div>
-
-            <!-- 完成订阅按钮和条款 -->
-            <div class="mb-6">
-                <button
-                    @click="handleCompleteSubscription"
-                    :disabled="!selectedPayment"
-                    class="w-full bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 text-white px-6 py-4 rounded-lg font-bold text-lg border-2 border-[#0A0910] transition-all duration-300 transform hover:scale-105 disabled:scale-100 disabled:cursor-not-allowed mb-4"
-                >
-                    Complete Subscription
-                </button>
-                
-                <p class="text-center text-sm text-gray-600">
-                    By subscribing, you agree to our 
-                    <a href="#" class="text-blue-600 hover:text-blue-700 underline">Terms of Service</a>
-                    and 
-                    <a href="#" class="text-blue-600 hover:text-blue-700 underline">Privacy Policy</a>.
-                </p>
-            </div>
-        </div>
-
-        <!-- 底部 -->
-        <GlobalFooter />
-    </div>
-</template>
-
-<script setup lang="ts">
-import { ref } from 'vue'
-import GlobalNavigation from '@/components/GlobalNavigation.vue'
-import GlobalFooter from '@/components/GlobalFooter.vue'
-import { showToast } from 'vant'
-import 'vant/es/toast/style'
-
-const selectedPayment = ref<'google' | 'apple' | ''>('')
-
-const selectPaymentMethod = (method: 'google' | 'apple') => {
-    selectedPayment.value = method
-}
-
-const handleCompleteSubscription = () => {
-    if (!selectedPayment.value) {
-        showToast('请选择支付方式')
-        return
-    }
-    
-    const paymentName = selectedPayment.value === 'google' ? 'Google Pay' : 'Apple Pay'
-    showToast(`正在使用 ${paymentName} 完成订阅...`)
-}
-</script>
-
-<style scoped>
-/* 保持与项目整体风格一致 */
-</style>

+ 156 - 0
src/views/Pay.vue

@@ -0,0 +1,156 @@
+<template>
+  <div class="min-h-screen bg-yellow-400 px-2 md:px-4 py-6">
+    <!-- 全局导航 -->
+    <GlobalNavigation />
+
+    <div class="max-w-2xl mx-auto">
+      <!-- 页面标题区域 -->
+      <div class="mb-6">
+        <div class="flex items-center justify-between mb-4">
+          <h1 class="text-3xl md:text-4xl font-bold text-dark-800">Complete Your Subscription</h1>
+          <div class="w-[168px] bg-blue-600 text-white px-4 py-2 rounded-full border-2 border-[#0A0910]">
+            <p class="font-bold text-sm md:text-base">Premium Plan</p>
+            <p class="text-xs md:text-sm">• $9.99/month</p>
+          </div>
+        </div>
+      </div>
+
+      <!-- 订阅摘要卡片 -->
+      <div class="mb-6">
+        <div class="bg-white border-2 border-[#0A0910] rounded-lg p-6 md:p-8">
+          <h2 class="text-2xl font-bold text-blue-700 mb-6">Subscription Summary</h2>
+
+          <div class="space-y-4">
+            <!-- Plan -->
+            <div class="flex justify-between items-center">
+              <span class="text-gray-600">Plan:</span>
+              <span class="text-lg font-bold text-dark-800">Premium Plan</span>
+            </div>
+
+            <!-- Price -->
+            <div class="flex justify-between items-center">
+              <span class="text-gray-600">Price:</span>
+              <span class="text-lg font-bold text-dark-800">$9.99/month</span>
+            </div>
+
+            <!-- Billing Cycle -->
+            <div class="flex justify-between items-center">
+              <span class="text-gray-600">Billing Cycle:</span>
+              <span class="text-lg font-bold text-dark-800">Monthly</span>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 选择支付方式 -->
+      <div class="mb-6">
+        <h2 class="text-2xl font-bold text-dark-800 mb-4">Choose Payment Method</h2>
+
+        <div class="flex gap-4 mb-6">
+          <!-- Google Pay -->
+          <button @click="selectPaymentMethod('google')" :class="[
+            'bg-white border-2 rounded-lg p-6 transition-all duration-200',
+            selectedPayment === 'google'
+              ? 'border-blue-600 shadow-lg'
+              : 'border-[#0A0910] hover:border-blue-400'
+          ]">
+            <div class="flex items-center justify-center h-16">
+              <div class="flex items-center gap-3">
+                <svg class="w-12 h-12" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
+                  <path
+                    d="M24 9.5C20.65 9.5 17.45 10.65 14.9 12.7L18.3 16.1C19.95 14.85 21.95 14.15 24 14.15C28.55 14.15 32.35 17.4 33.25 21.75H38.95C37.95 14.45 31.65 9.5 24 9.5Z"
+                    fill="#EA4335" />
+                  <path
+                    d="M9.05 24C9.05 26.05 9.55 28 10.45 29.7L5.8 33.1C4.1 30.35 3 27.25 3 24C3 20.75 4.1 17.65 5.8 14.9L10.45 18.3C9.55 20 9.05 21.95 9.05 24Z"
+                    fill="#FBBC05" />
+                  <path
+                    d="M24 38.5C20.65 38.5 17.45 37.35 14.9 35.3L10.45 38.7C13.2 41.4 16.95 43 21 43.5V43.5C28.3 42.5 34.3 37.5 36.75 30.75H33.25C32.35 35.1 28.55 38.5 24 38.5Z"
+                    fill="#34A853" />
+                  <path
+                    d="M45 24C45 22.85 44.9 21.7 44.7 20.6H24V27.65H35.4C34.7 30.55 32.85 32.95 30.35 34.45L33.85 37.2C37.95 33.45 40.2 28.15 40.2 24C40.2 22.85 40.1 21.7 39.9 20.6H45V24Z"
+                    fill="#4285F4" />
+                </svg>
+                <span class="text-xl font-bold text-dark-800">Google Pay</span>
+              </div>
+            </div>
+          </button>
+
+          <!-- Apple Pay -->
+          <button @click="selectPaymentMethod('apple')" :class="[
+            'border-2 rounded-lg p-6 transition-all duration-200',
+            selectedPayment === 'apple'
+              ? 'bg-black border-blue-600 shadow-lg'
+              : 'bg-black border-[#0A0910] hover:border-blue-400'
+          ]">
+            <div class="flex items-center justify-center h-16">
+              <div class="flex items-center gap-3">
+                <svg class="w-10 h-10" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+                  <path
+                    d="M17.05 20.28C16.03 21.23 14.96 21.08 13.93 20.63C12.84 20.17 11.85 20.15 10.7 20.63C9.28 21.25 8.52 21.07 7.62 20.28C2.02 14.58 2.83 5.97 9.26 5.67C10.76 5.75 11.79 6.52 12.65 6.58C13.95 6.31 15.21 5.52 16.61 5.63C18.31 5.78 19.6 6.45 20.45 7.65C16.77 9.87 17.63 14.72 20.95 16.11C20.27 17.89 19.4 19.65 17.04 20.29L17.05 20.28ZM12.53 5.62C12.38 3.06 14.42 0.93 16.87 0.75C17.2 3.66 14.18 5.89 12.53 5.62Z"
+                    fill="white" />
+                </svg>
+                <span class="text-xl font-bold text-white">Apple Pay</span>
+              </div>
+            </div>
+          </button>
+        </div>
+      </div>
+
+      <!-- 完成订阅按钮和条款 -->
+      <div class="mb-6">
+        <button @click="handleCompleteSubscription" :disabled="!selectedPayment"
+          class="w-full bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 text-white px-6 py-4 rounded-lg font-bold text-lg border-2 border-[#0A0910] transition-all duration-300 transform hover:scale-105 disabled:scale-100 disabled:cursor-not-allowed mb-4">
+          Complete Subscription
+        </button>
+
+        <p class="text-center text-sm text-gray-600">
+          By subscribing, you agree to our
+          <a href="#" class="text-blue-600 hover:text-blue-700 underline">Terms of Service</a>
+          and
+          <a href="#" class="text-blue-600 hover:text-blue-700 underline">Privacy Policy</a>.
+        </p>
+      </div>
+    </div>
+
+    <!-- 底部 -->
+    <GlobalFooter />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import GlobalNavigation from '@/components/GlobalNavigation.vue'
+import GlobalFooter from '@/components/GlobalFooter.vue'
+import { showToast } from 'vant'
+import 'vant/es/toast/style'
+import { getPriceConfig } from '@/api'
+
+const selectedPayment = ref<'google' | 'apple' | ''>('')
+
+
+const selectPaymentMethod = (method: 'google' | 'apple') => {
+  selectedPayment.value = method
+}
+
+const handleCompleteSubscription = () => {
+  if (!selectedPayment.value) {
+    showToast('请选择支付方式')
+    return
+  }
+
+  const paymentName = selectedPayment.value === 'google' ? 'Google Pay' : 'Apple Pay'
+  showToast(`正在使用 ${paymentName} 完成订阅...`)
+}
+
+const productList = ref([])
+getPriceConfig().then((res) => {
+  productList.value = res?.prices || []
+  console.log('getPriceConfig', productList.value)
+}).catch((err) => {
+    console.error(err)
+  })
+</script>
+
+<style scoped>
+/* 保持与项目整体风格一致 */
+</style>

+ 164 - 0
src/views/SubscriptionList.vue

@@ -0,0 +1,164 @@
+<template>
+  <div class="min-h-screen bg-yellow-400 px-2 md:px-4 py-6">
+    <!-- 全局导航 -->
+    <GlobalNavigation />
+
+    <div class="max-w-2xl mx-auto space-y-6">
+      <!-- 页面标题区域 -->
+      <div class="text-center mb-8">
+        <h1 class="text-3xl font-bold text-gray-800 mb-2">Choose Your Plan</h1>
+        <p class="text-gray-600">
+          Unlock premium features with our flexible 
+          <br/>
+          subscription options
+        </p>
+      </div>
+
+      <!-- 7天免费试用卡片 -->
+      <div class="bg-white rounded-3xl shadow-lg overflow-hidden">
+        <!-- 卡片头部 -->
+        <div class="bg-indigo-100 px-6 py-4">
+          <h2 class="text-2xl font-bold text-indigo-700">7-Day Free Trial</h2>
+        </div>
+        
+        <!-- 卡片内容 -->
+        <div class="px-6 py-8">
+          <!-- 价格 -->
+          <div class="mb-6">
+            <span class="text-5xl font-bold text-gray-800">$0</span>
+            <span class="text-xl text-gray-500 ml-2">for 7 days</span>
+          </div>
+          
+          <!-- 特性列表 -->
+          <div class="space-y-4 mb-8">
+            <div class="flex items-center">
+              <svg class="w-6 h-6 text-green-500 mr-3 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
+              </svg>
+              <span class="text-gray-700 text-lg">Full access to all features</span>
+            </div>
+            <div class="flex items-center">
+              <svg class="w-6 h-6 text-green-500 mr-3 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
+              </svg>
+              <span class="text-gray-700 text-lg">No credit card required</span>
+            </div>
+            <div class="flex items-center">
+              <svg class="w-6 h-6 text-green-500 mr-3 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
+              </svg>
+              <span class="text-gray-700 text-lg">Cancel anytime</span>
+            </div>
+          </div>
+          
+          <!-- 按钮 -->
+          <button 
+            @click="handleFreeTrial"
+            class="w-full bg-indigo-100 hover:bg-indigo-200 text-indigo-700 font-semibold py-4 px-6 rounded-2xl transition-colors duration-200"
+          >
+            Start Free Trial
+          </button>
+        </div>
+      </div>
+
+      <!-- Premium 高级套餐卡片 -->
+      <div class="bg-white rounded-3xl shadow-lg overflow-hidden border-2 border-indigo-600">
+        <!-- 卡片头部 -->
+        <div class="bg-indigo-600 px-6 py-4">
+          <h2 class="text-2xl font-bold text-white">Premium Plan</h2>
+        </div>
+        
+        <!-- 卡片内容 -->
+        <div class="px-6 py-8">
+          <!-- 价格 -->
+          <div class="mb-6">
+            <span class="text-5xl font-bold text-gray-800">$9.99</span>
+            <span class="text-xl text-gray-500 ml-2">per month</span>
+          </div>
+          
+          <!-- 特性列表 -->
+          <div class="space-y-4 mb-8">
+            <div class="flex items-center">
+              <svg class="w-6 h-6 text-green-500 mr-3 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
+              </svg>
+              <span class="text-gray-700 text-lg">All features included</span>
+            </div>
+            <div class="flex items-center">
+              <svg class="w-6 h-6 text-green-500 mr-3 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
+              </svg>
+              <span class="text-gray-700 text-lg">Priority support</span>
+            </div>
+            <div class="flex items-center">
+              <svg class="w-6 h-6 text-green-500 mr-3 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
+              </svg>
+              <span class="text-gray-700 text-lg">Cancel anytime</span>
+            </div>
+          </div>
+          
+          <!-- 按钮 -->
+          <button 
+            @click="handlePremium"
+            class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-semibold py-4 px-6 rounded-2xl transition-colors duration-200"
+          >
+            Get Premium
+          </button>
+        </div>
+      </div>
+    </div>
+
+    <!-- 底部 -->
+    <GlobalFooter />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import GlobalNavigation from '@/components/GlobalNavigation.vue'
+import GlobalFooter from '@/components/GlobalFooter.vue'
+
+// 处理免费试用按钮点击
+const handleFreeTrial = () => {
+  showToast('开始7天免费试用', 'success')
+}
+
+// 处理高级套餐按钮点击
+const handlePremium = () => {
+  showToast('正在跳转到支付页面...', 'info')
+}
+
+// 自定义 Toast 提示函数
+const showToast = (message: string, type: 'success' | 'error' | 'warning' | 'info') => {
+  const toast = document.createElement('div')
+  toast.className = `fixed top-4 right-4 px-4 py-2 rounded-lg text-white text-sm font-medium z-50 transition-all duration-300 transform translate-x-full`
+
+  const styles = {
+    success: 'bg-green-500',
+    error: 'bg-red-500',
+    warning: 'bg-yellow-500',
+    info: 'bg-blue-500'
+  }
+
+  toast.className += ` ${styles[type]}`
+  toast.textContent = message
+
+  document.body.appendChild(toast)
+
+  setTimeout(() => {
+    toast.style.transform = 'translateX(0)'
+  }, 10)
+
+  setTimeout(() => {
+    toast.style.transform = 'translateX(full)'
+    setTimeout(() => {
+      document.body.removeChild(toast)
+    }, 300)
+  }, 2000)
+}
+</script>
+
+<style scoped>
+/* 保持与项目整体风格一致 */
+</style>

+ 3 - 1
原型页面/方案设计.md

@@ -27,4 +27,6 @@ setOptions({ idleTime })
 失效时间点:
 将失效时间提前10分钟
 const expireTime = parseInt(res.data.expTime - 10 * 1000 * 6)
-通过对比超时时间来判断是否需要刷新token, 还是重新登录
+通过对比超时时间来判断是否需要刷新token, 还是重新登录
+
+