feat: 新增消息和我的页面并重构首页布局
新增消息页 (message) 和我的页 (mine),包含基础布局和授权状态展示。 新增 AppTabbar 组件实现底部导航栏,支持首页、消息、我的三栏切换。 重构首页布局,将原有测试功能移入测试中心并更新页面标题。 更新 app.config.js 和组件类型声明以支持新页面和组件。
Showing
11 changed files
with
481 additions
and
98 deletions
| ... | @@ -7,7 +7,10 @@ export {} | ... | @@ -7,7 +7,10 @@ export {} |
| 7 | 7 | ||
| 8 | declare module 'vue' { | 8 | declare module 'vue' { |
| 9 | export interface GlobalComponents { | 9 | export interface GlobalComponents { |
| 10 | + AppTabbar: typeof import('./src/components/AppTabbar.vue')['default'] | ||
| 10 | IndexNav: typeof import('./src/components/indexNav.vue')['default'] | 11 | IndexNav: typeof import('./src/components/indexNav.vue')['default'] |
| 12 | + NutTabbar: typeof import('@nutui/nutui-taro')['Tabbar'] | ||
| 13 | + NutTabbarItem: typeof import('@nutui/nutui-taro')['TabbarItem'] | ||
| 11 | Picker: typeof import('./src/components/time-picker-data/picker.vue')['default'] | 14 | Picker: typeof import('./src/components/time-picker-data/picker.vue')['default'] |
| 12 | PosterBuilder: typeof import('./src/components/PosterBuilder/index.vue')['default'] | 15 | PosterBuilder: typeof import('./src/components/PosterBuilder/index.vue')['default'] |
| 13 | QrCode: typeof import('./src/components/qrCode.vue')['default'] | 16 | QrCode: typeof import('./src/components/qrCode.vue')['default'] | ... | ... |
| 1 | export default { | 1 | export default { |
| 2 | pages: [ | 2 | pages: [ |
| 3 | 'pages/index/index', | 3 | 'pages/index/index', |
| 4 | + 'pages/message/index', | ||
| 5 | + 'pages/mine/index', | ||
| 4 | 'pages/pay-test/index', | 6 | 'pages/pay-test/index', |
| 5 | 'pages/pay-bridge/index', | 7 | 'pages/pay-bridge/index', |
| 6 | 'pages/webview-preview/index', | 8 | 'pages/webview-preview/index', | ... | ... |
src/components/AppTabbar.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <view class="app-tabbar"> | ||
| 3 | + <nut-tabbar | ||
| 4 | + :model-value="activeTab" | ||
| 5 | + bottom | ||
| 6 | + placeholder | ||
| 7 | + safe-area-inset-bottom | ||
| 8 | + :active-color="activeColor" | ||
| 9 | + :unactive-color="inactiveColor" | ||
| 10 | + @tab-switch="handleTabSwitch" | ||
| 11 | + > | ||
| 12 | + <nut-tabbar-item | ||
| 13 | + v-for="item in tabItems" | ||
| 14 | + :key="item.name" | ||
| 15 | + :name="item.name" | ||
| 16 | + :tab-title="item.title" | ||
| 17 | + > | ||
| 18 | + <template #icon="{ active }"> | ||
| 19 | + <component | ||
| 20 | + :is="item.icon" | ||
| 21 | + size="18" | ||
| 22 | + :color="active ? activeColor : inactiveColor" | ||
| 23 | + /> | ||
| 24 | + </template> | ||
| 25 | + </nut-tabbar-item> | ||
| 26 | + </nut-tabbar> | ||
| 27 | + </view> | ||
| 28 | +</template> | ||
| 29 | + | ||
| 30 | +<script setup> | ||
| 31 | +import { computed } from 'vue' | ||
| 32 | +import Taro from '@tarojs/taro' | ||
| 33 | +import { Home, Message, My } from '@nutui/icons-vue-taro' | ||
| 34 | + | ||
| 35 | +const props = defineProps({ | ||
| 36 | + current: { | ||
| 37 | + type: String, | ||
| 38 | + required: true, | ||
| 39 | + }, | ||
| 40 | +}) | ||
| 41 | + | ||
| 42 | +const activeColor = '#a67939' | ||
| 43 | +const inactiveColor = '#8b95a7' | ||
| 44 | + | ||
| 45 | +const tabItems = [ | ||
| 46 | + { | ||
| 47 | + name: 'home', | ||
| 48 | + title: '首页', | ||
| 49 | + icon: Home, | ||
| 50 | + url: '/pages/index/index', | ||
| 51 | + }, | ||
| 52 | + { | ||
| 53 | + name: 'message', | ||
| 54 | + title: '消息', | ||
| 55 | + icon: Message, | ||
| 56 | + url: '/pages/message/index', | ||
| 57 | + }, | ||
| 58 | + { | ||
| 59 | + name: 'mine', | ||
| 60 | + title: '我的', | ||
| 61 | + icon: My, | ||
| 62 | + url: '/pages/mine/index', | ||
| 63 | + }, | ||
| 64 | +] | ||
| 65 | + | ||
| 66 | +const activeTab = computed(() => props.current) | ||
| 67 | + | ||
| 68 | +const handleTabSwitch = (...args) => { | ||
| 69 | + const nextTab = args[1] | ||
| 70 | + const target = tabItems.find((item) => item.name === nextTab) | ||
| 71 | + | ||
| 72 | + if (!target || target.name === props.current) { | ||
| 73 | + return | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + Taro.redirectTo({ | ||
| 77 | + url: target.url, | ||
| 78 | + }) | ||
| 79 | +} | ||
| 80 | +</script> | ||
| 81 | + | ||
| 82 | +<style lang="less"> | ||
| 83 | +.app-tabbar { | ||
| 84 | + :deep(.nut-tabbar) { | ||
| 85 | + left: 24rpx; | ||
| 86 | + right: 24rpx; | ||
| 87 | + bottom: 24rpx; | ||
| 88 | + width: auto; | ||
| 89 | + border: 2rpx solid rgba(166, 121, 57, 0.12); | ||
| 90 | + border-radius: 999rpx; | ||
| 91 | + background: rgba(255, 255, 255, 0.96); | ||
| 92 | + box-shadow: 0 24rpx 60rpx rgba(15, 23, 42, 0.12); | ||
| 93 | + overflow: hidden; | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + :deep(.nut-tabbar-item_icon-box) { | ||
| 97 | + padding-top: 8rpx; | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + :deep(.nut-tabbar-item_icon-box_nav-word) { | ||
| 101 | + margin-top: 8rpx; | ||
| 102 | + font-size: 22rpx; | ||
| 103 | + font-weight: 600; | ||
| 104 | + } | ||
| 105 | +} | ||
| 106 | +</style> |
| 1 | <template> | 1 | <template> |
| 2 | <view class="index-page"> | 2 | <view class="index-page"> |
| 3 | - <view class="index-header"> | 3 | + <view class="page-content"> |
| 4 | - <text class="title">觉林寺</text> | 4 | + <view class="hero-card"> |
| 5 | - </view> | 5 | + <text class="hero-eyebrow">觉林寺小程序</text> |
| 6 | - <view class="index-body"> | 6 | + <text class="hero-title">首页</text> |
| 7 | - <text class="tip">授权和支付最小测试入口</text> | 7 | + <text class="hero-desc"> |
| 8 | + 当前先完成首页、消息、我的三栏结构,测试能力统一收口到测试中心,避免首页继续堆放调试按钮。 | ||
| 9 | + </text> | ||
| 10 | + </view> | ||
| 11 | + | ||
| 8 | <view class="status-card"> | 12 | <view class="status-card"> |
| 9 | - <text class="status-label">当前授权状态</text> | 13 | + <view> |
| 10 | - <text class="status-value" :class="{ authed: is_authed }"> | 14 | + <text class="section-label">当前授权状态</text> |
| 11 | - {{ is_authed ? '已授权' : '未授权' }} | 15 | + <text class="status-text">应用启动时会优先尝试静默授权</text> |
| 16 | + </view> | ||
| 17 | + <text class="status-tag" :class="{ authed: isAuthed }"> | ||
| 18 | + {{ isAuthed ? '已授权' : '未授权' }} | ||
| 12 | </text> | 19 | </text> |
| 13 | </view> | 20 | </view> |
| 14 | - <button class="primary-btn" @tap="goToPayTest">进入支付测试页</button> | 21 | + |
| 15 | - <button class="secondary-btn" @tap="goToWebviewPreview">打开 WebView 预览页</button> | 22 | + <view class="overview-grid"> |
| 16 | - <button class="secondary-btn" @tap="refreshAuthStatus">刷新授权状态</button> | 23 | + <view class="overview-card"> |
| 24 | + <text class="card-title">首页</text> | ||
| 25 | + <text class="card-desc">展示当前项目概览与测试入口。</text> | ||
| 26 | + </view> | ||
| 27 | + <view class="overview-card"> | ||
| 28 | + <text class="card-title">消息</text> | ||
| 29 | + <text class="card-desc">后续承接通知、订单提醒与系统消息。</text> | ||
| 30 | + </view> | ||
| 31 | + <view class="overview-card"> | ||
| 32 | + <text class="card-title">我的</text> | ||
| 33 | + <text class="card-desc">后续承接个人信息、授权状态与常用功能。</text> | ||
| 34 | + </view> | ||
| 35 | + </view> | ||
| 36 | + | ||
| 37 | + <view class="test-entry-card"> | ||
| 38 | + <text class="section-label">测试入口</text> | ||
| 39 | + <text class="test-entry-desc"> | ||
| 40 | + 支付测试与 WebView 预览已移入测试中心,首页只保留统一入口。 | ||
| 41 | + </text> | ||
| 42 | + <button class="primary-btn" @tap="goToTestCenter">进入测试中心</button> | ||
| 43 | + </view> | ||
| 17 | </view> | 44 | </view> |
| 45 | + | ||
| 46 | + <AppTabbar current="home" /> | ||
| 18 | </view> | 47 | </view> |
| 19 | </template> | 48 | </template> |
| 20 | 49 | ||
| 21 | <script setup> | 50 | <script setup> |
| 22 | import { ref } from 'vue' | 51 | import { ref } from 'vue' |
| 23 | import Taro, { useDidShow } from '@tarojs/taro' | 52 | import Taro, { useDidShow } from '@tarojs/taro' |
| 53 | +import AppTabbar from '@/components/AppTabbar.vue' | ||
| 24 | import { hasAuth } from '@/utils/authRedirect' | 54 | import { hasAuth } from '@/utils/authRedirect' |
| 25 | 55 | ||
| 26 | -Taro.setNavigationBarTitle({ title: '首页' }) | 56 | +const isAuthed = ref(false) |
| 27 | - | ||
| 28 | -const is_authed = ref(false) | ||
| 29 | 57 | ||
| 30 | const refreshAuthStatus = () => { | 58 | const refreshAuthStatus = () => { |
| 31 | - is_authed.value = hasAuth() | 59 | + isAuthed.value = hasAuth() |
| 32 | } | 60 | } |
| 33 | 61 | ||
| 34 | -const goToPayTest = () => { | 62 | +const goToTestCenter = () => { |
| 35 | Taro.navigateTo({ | 63 | Taro.navigateTo({ |
| 36 | url: '/pages/pay-test/index', | 64 | url: '/pages/pay-test/index', |
| 37 | }) | 65 | }) |
| 38 | } | 66 | } |
| 39 | 67 | ||
| 40 | -const goToWebviewPreview = () => { | ||
| 41 | - Taro.navigateTo({ | ||
| 42 | - url: '/pages/webview-preview/index', | ||
| 43 | - }) | ||
| 44 | -} | ||
| 45 | - | ||
| 46 | useDidShow(() => { | 68 | useDidShow(() => { |
| 47 | refreshAuthStatus() | 69 | refreshAuthStatus() |
| 48 | }) | 70 | }) |
| ... | @@ -51,85 +73,128 @@ useDidShow(() => { | ... | @@ -51,85 +73,128 @@ useDidShow(() => { |
| 51 | <style lang="less"> | 73 | <style lang="less"> |
| 52 | .index-page { | 74 | .index-page { |
| 53 | min-height: 100vh; | 75 | min-height: 100vh; |
| 54 | - display: flex; | 76 | + background: |
| 55 | - flex-direction: column; | 77 | + radial-gradient(circle at top right, rgba(166, 121, 57, 0.18), transparent 32%), |
| 56 | - align-items: center; | 78 | + linear-gradient(180deg, #fffaf3 0%, #f6f7fb 100%); |
| 57 | - background-color: #f5f5f5; | ||
| 58 | - | ||
| 59 | - .index-header { | ||
| 60 | - width: 100%; | ||
| 61 | - padding: 80rpx 0 40rpx; | ||
| 62 | - display: flex; | ||
| 63 | - justify-content: center; | ||
| 64 | 79 | ||
| 65 | - .title { | 80 | + .page-content { |
| 66 | - font-size: 48rpx; | 81 | + padding: 32rpx 24rpx 0; |
| 67 | - font-weight: bold; | 82 | + box-sizing: border-box; |
| 68 | - color: #333; | ||
| 69 | - } | ||
| 70 | } | 83 | } |
| 71 | 84 | ||
| 72 | - .index-body { | 85 | + .hero-card, |
| 73 | - flex: 1; | 86 | + .status-card, |
| 74 | - display: flex; | 87 | + .overview-card, |
| 75 | - width: 100%; | 88 | + .test-entry-card { |
| 76 | - padding: 0 48rpx 80rpx; | 89 | + background: rgba(255, 255, 255, 0.94); |
| 90 | + border: 2rpx solid rgba(166, 121, 57, 0.08); | ||
| 91 | + border-radius: 28rpx; | ||
| 92 | + box-shadow: 0 20rpx 60rpx rgba(15, 23, 42, 0.06); | ||
| 77 | box-sizing: border-box; | 93 | box-sizing: border-box; |
| 94 | + } | ||
| 95 | + | ||
| 96 | + .hero-card { | ||
| 97 | + display: flex; | ||
| 78 | flex-direction: column; | 98 | flex-direction: column; |
| 99 | + padding: 36rpx 32rpx; | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + .hero-eyebrow { | ||
| 103 | + font-size: 24rpx; | ||
| 104 | + font-weight: 600; | ||
| 105 | + letter-spacing: 4rpx; | ||
| 106 | + color: #a67939; | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + .hero-title { | ||
| 110 | + margin-top: 12rpx; | ||
| 111 | + font-size: 52rpx; | ||
| 112 | + font-weight: 700; | ||
| 113 | + color: #1f2937; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + .hero-desc { | ||
| 117 | + margin-top: 18rpx; | ||
| 118 | + font-size: 26rpx; | ||
| 119 | + line-height: 1.8; | ||
| 120 | + color: #6b7280; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + .status-card { | ||
| 124 | + margin-top: 24rpx; | ||
| 125 | + padding: 28rpx 32rpx; | ||
| 126 | + display: flex; | ||
| 79 | align-items: center; | 127 | align-items: center; |
| 80 | - justify-content: center; | 128 | + justify-content: space-between; |
| 81 | gap: 24rpx; | 129 | gap: 24rpx; |
| 130 | + } | ||
| 131 | + | ||
| 132 | + .section-label { | ||
| 133 | + display: block; | ||
| 134 | + font-size: 30rpx; | ||
| 135 | + font-weight: 600; | ||
| 136 | + color: #111827; | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + .status-text, | ||
| 140 | + .card-desc, | ||
| 141 | + .test-entry-desc { | ||
| 142 | + display: block; | ||
| 143 | + margin-top: 12rpx; | ||
| 144 | + font-size: 24rpx; | ||
| 145 | + line-height: 1.7; | ||
| 146 | + color: #6b7280; | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + .status-tag { | ||
| 150 | + flex-shrink: 0; | ||
| 151 | + padding: 12rpx 22rpx; | ||
| 152 | + border-radius: 999rpx; | ||
| 153 | + font-size: 24rpx; | ||
| 154 | + font-weight: 600; | ||
| 155 | + color: #b45309; | ||
| 156 | + background: #fef3c7; | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + .status-tag.authed { | ||
| 160 | + color: #166534; | ||
| 161 | + background: #dcfce7; | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + .overview-grid { | ||
| 165 | + margin-top: 24rpx; | ||
| 166 | + display: grid; | ||
| 167 | + grid-template-columns: repeat(2, minmax(0, 1fr)); | ||
| 168 | + gap: 20rpx; | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + .overview-card { | ||
| 172 | + padding: 28rpx; | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + .overview-card:last-child { | ||
| 176 | + grid-column: 1 / span 2; | ||
| 177 | + } | ||
| 178 | + | ||
| 179 | + .card-title { | ||
| 180 | + display: block; | ||
| 181 | + font-size: 30rpx; | ||
| 182 | + font-weight: 600; | ||
| 183 | + color: #111827; | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + .test-entry-card { | ||
| 187 | + margin-top: 24rpx; | ||
| 188 | + padding: 32rpx; | ||
| 189 | + } | ||
| 82 | 190 | ||
| 83 | - .tip { | 191 | + .primary-btn { |
| 84 | - font-size: 28rpx; | 192 | + margin-top: 24rpx; |
| 85 | - color: #999; | 193 | + border-radius: 999rpx; |
| 86 | - } | 194 | + font-size: 30rpx; |
| 87 | - | 195 | + line-height: 88rpx; |
| 88 | - .status-card { | 196 | + color: #fff; |
| 89 | - width: 100%; | 197 | + background: linear-gradient(135deg, #a67939, #8f5e20); |
| 90 | - padding: 32rpx; | ||
| 91 | - border-radius: 24rpx; | ||
| 92 | - background: #fff; | ||
| 93 | - display: flex; | ||
| 94 | - align-items: center; | ||
| 95 | - justify-content: space-between; | ||
| 96 | - box-sizing: border-box; | ||
| 97 | - box-shadow: 0 16rpx 40rpx rgba(0, 0, 0, 0.04); | ||
| 98 | - | ||
| 99 | - .status-label { | ||
| 100 | - font-size: 28rpx; | ||
| 101 | - color: #666; | ||
| 102 | - } | ||
| 103 | - | ||
| 104 | - .status-value { | ||
| 105 | - font-size: 30rpx; | ||
| 106 | - font-weight: 600; | ||
| 107 | - color: #d9485f; | ||
| 108 | - } | ||
| 109 | - | ||
| 110 | - .authed { | ||
| 111 | - color: #2d8c4d; | ||
| 112 | - } | ||
| 113 | - } | ||
| 114 | - | ||
| 115 | - .primary-btn, | ||
| 116 | - .secondary-btn { | ||
| 117 | - width: 100%; | ||
| 118 | - border-radius: 999rpx; | ||
| 119 | - font-size: 30rpx; | ||
| 120 | - line-height: 88rpx; | ||
| 121 | - } | ||
| 122 | - | ||
| 123 | - .primary-btn { | ||
| 124 | - color: #fff; | ||
| 125 | - background: linear-gradient(135deg, #111827, #374151); | ||
| 126 | - } | ||
| 127 | - | ||
| 128 | - .secondary-btn { | ||
| 129 | - color: #374151; | ||
| 130 | - background: #fff; | ||
| 131 | - border: 2rpx solid #d1d5db; | ||
| 132 | - } | ||
| 133 | } | 198 | } |
| 134 | } | 199 | } |
| 135 | </style> | 200 | </style> | ... | ... |
src/pages/message/index.config.js
0 → 100644
src/pages/message/index.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <view class="message-page"> | ||
| 3 | + <view class="page-content"> | ||
| 4 | + <view class="hero-card"> | ||
| 5 | + <text class="hero-title">消息</text> | ||
| 6 | + <text class="hero-desc"> | ||
| 7 | + 这里预留给系统通知、预约提醒和支付结果消息。当前先完成 Tab 栏结构,后续再接真实消息数据。 | ||
| 8 | + </text> | ||
| 9 | + </view> | ||
| 10 | + | ||
| 11 | + <view class="placeholder-card"> | ||
| 12 | + <text class="section-title">当前状态</text> | ||
| 13 | + <text class="section-desc"> | ||
| 14 | + 暂无消息内容,后续可在这里接接口列表、未读计数和消息详情跳转。 | ||
| 15 | + </text> | ||
| 16 | + </view> | ||
| 17 | + </view> | ||
| 18 | + | ||
| 19 | + <AppTabbar current="message" /> | ||
| 20 | + </view> | ||
| 21 | +</template> | ||
| 22 | + | ||
| 23 | +<script setup> | ||
| 24 | +import AppTabbar from '@/components/AppTabbar.vue' | ||
| 25 | +</script> | ||
| 26 | + | ||
| 27 | +<style lang="less"> | ||
| 28 | +.message-page { | ||
| 29 | + min-height: 100vh; | ||
| 30 | + background: | ||
| 31 | + radial-gradient(circle at top left, rgba(166, 121, 57, 0.12), transparent 28%), | ||
| 32 | + linear-gradient(180deg, #fffaf4 0%, #f4f6fb 100%); | ||
| 33 | + | ||
| 34 | + .page-content { | ||
| 35 | + padding: 32rpx 24rpx 0; | ||
| 36 | + box-sizing: border-box; | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + .hero-card, | ||
| 40 | + .placeholder-card { | ||
| 41 | + padding: 32rpx; | ||
| 42 | + border-radius: 28rpx; | ||
| 43 | + background: rgba(255, 255, 255, 0.94); | ||
| 44 | + border: 2rpx solid rgba(166, 121, 57, 0.08); | ||
| 45 | + box-shadow: 0 20rpx 60rpx rgba(15, 23, 42, 0.06); | ||
| 46 | + box-sizing: border-box; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + .hero-title, | ||
| 50 | + .section-title { | ||
| 51 | + display: block; | ||
| 52 | + font-size: 40rpx; | ||
| 53 | + font-weight: 700; | ||
| 54 | + color: #111827; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + .hero-desc, | ||
| 58 | + .section-desc { | ||
| 59 | + display: block; | ||
| 60 | + margin-top: 16rpx; | ||
| 61 | + font-size: 26rpx; | ||
| 62 | + line-height: 1.8; | ||
| 63 | + color: #6b7280; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + .placeholder-card { | ||
| 67 | + margin-top: 24rpx; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + .section-title { | ||
| 71 | + font-size: 30rpx; | ||
| 72 | + } | ||
| 73 | +} | ||
| 74 | +</style> |
src/pages/mine/index.config.js
0 → 100644
src/pages/mine/index.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <view class="mine-page"> | ||
| 3 | + <view class="page-content"> | ||
| 4 | + <view class="hero-card"> | ||
| 5 | + <text class="hero-title">我的</text> | ||
| 6 | + <text class="hero-desc"> | ||
| 7 | + 这里预留给个人资料、授权信息和常用入口。当前阶段先提供基础占位和授权状态展示。 | ||
| 8 | + </text> | ||
| 9 | + </view> | ||
| 10 | + | ||
| 11 | + <view class="status-card"> | ||
| 12 | + <text class="section-title">授权状态</text> | ||
| 13 | + <view class="status-row"> | ||
| 14 | + <text class="section-desc">当前小程序登录态</text> | ||
| 15 | + <text class="status-tag" :class="{ authed: isAuthed }"> | ||
| 16 | + {{ isAuthed ? '已授权' : '未授权' }} | ||
| 17 | + </text> | ||
| 18 | + </view> | ||
| 19 | + </view> | ||
| 20 | + </view> | ||
| 21 | + | ||
| 22 | + <AppTabbar current="mine" /> | ||
| 23 | + </view> | ||
| 24 | +</template> | ||
| 25 | + | ||
| 26 | +<script setup> | ||
| 27 | +import { ref } from 'vue' | ||
| 28 | +import { useDidShow } from '@tarojs/taro' | ||
| 29 | +import AppTabbar from '@/components/AppTabbar.vue' | ||
| 30 | +import { hasAuth } from '@/utils/authRedirect' | ||
| 31 | + | ||
| 32 | +const isAuthed = ref(false) | ||
| 33 | + | ||
| 34 | +useDidShow(() => { | ||
| 35 | + isAuthed.value = hasAuth() | ||
| 36 | +}) | ||
| 37 | +</script> | ||
| 38 | + | ||
| 39 | +<style lang="less"> | ||
| 40 | +.mine-page { | ||
| 41 | + min-height: 100vh; | ||
| 42 | + background: | ||
| 43 | + radial-gradient(circle at top right, rgba(166, 121, 57, 0.14), transparent 30%), | ||
| 44 | + linear-gradient(180deg, #fffaf4 0%, #f3f5f9 100%); | ||
| 45 | + | ||
| 46 | + .page-content { | ||
| 47 | + padding: 32rpx 24rpx 0; | ||
| 48 | + box-sizing: border-box; | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + .hero-card, | ||
| 52 | + .status-card { | ||
| 53 | + padding: 32rpx; | ||
| 54 | + border-radius: 28rpx; | ||
| 55 | + background: rgba(255, 255, 255, 0.94); | ||
| 56 | + border: 2rpx solid rgba(166, 121, 57, 0.08); | ||
| 57 | + box-shadow: 0 20rpx 60rpx rgba(15, 23, 42, 0.06); | ||
| 58 | + box-sizing: border-box; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + .hero-title, | ||
| 62 | + .section-title { | ||
| 63 | + display: block; | ||
| 64 | + font-size: 40rpx; | ||
| 65 | + font-weight: 700; | ||
| 66 | + color: #111827; | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + .hero-desc, | ||
| 70 | + .section-desc { | ||
| 71 | + display: block; | ||
| 72 | + margin-top: 16rpx; | ||
| 73 | + font-size: 26rpx; | ||
| 74 | + line-height: 1.8; | ||
| 75 | + color: #6b7280; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + .status-card { | ||
| 79 | + margin-top: 24rpx; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + .section-title { | ||
| 83 | + font-size: 30rpx; | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + .status-row { | ||
| 87 | + margin-top: 20rpx; | ||
| 88 | + display: flex; | ||
| 89 | + align-items: center; | ||
| 90 | + justify-content: space-between; | ||
| 91 | + gap: 24rpx; | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + .status-tag { | ||
| 95 | + flex-shrink: 0; | ||
| 96 | + padding: 12rpx 22rpx; | ||
| 97 | + border-radius: 999rpx; | ||
| 98 | + font-size: 24rpx; | ||
| 99 | + font-weight: 600; | ||
| 100 | + color: #b45309; | ||
| 101 | + background: #fef3c7; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + .status-tag.authed { | ||
| 105 | + color: #166534; | ||
| 106 | + background: #dcfce7; | ||
| 107 | + } | ||
| 108 | +} | ||
| 109 | +</style> |
| 1 | <template> | 1 | <template> |
| 2 | <view class="pay-test-page"> | 2 | <view class="pay-test-page"> |
| 3 | <view class="hero-card"> | 3 | <view class="hero-card"> |
| 4 | - <text class="hero-title">微信支付最小测试页</text> | 4 | + <text class="hero-title">测试中心</text> |
| 5 | <text class="hero-desc"> | 5 | <text class="hero-desc"> |
| 6 | - 这里仅验证授权是否可用,以及点击按钮后能否成功拉起微信支付弹框。 | 6 | + 这里统一承接当前首页里的测试能力,包括 WebView 预览和微信支付拉起测试。 |
| 7 | </text> | 7 | </text> |
| 8 | </view> | 8 | </view> |
| 9 | 9 | ||
| 10 | <view class="panel"> | 10 | <view class="panel"> |
| 11 | <view class="panel-head"> | 11 | <view class="panel-head"> |
| 12 | + <text class="panel-title">调试入口</text> | ||
| 13 | + </view> | ||
| 14 | + <text class="panel-tip"> | ||
| 15 | + 如需验证 H5 通过小程序桥页发起支付,可先从这里进入 WebView 预览页。 | ||
| 16 | + </text> | ||
| 17 | + <button class="outline-btn" @tap="goToWebviewPreview"> | ||
| 18 | + 打开 WebView 预览页 | ||
| 19 | + </button> | ||
| 20 | + </view> | ||
| 21 | + | ||
| 22 | + <view class="panel"> | ||
| 23 | + <view class="panel-head"> | ||
| 12 | <text class="panel-title">授权状态</text> | 24 | <text class="panel-title">授权状态</text> |
| 13 | <text class="auth-tag" :class="{ authed: is_authed }"> | 25 | <text class="auth-tag" :class="{ authed: is_authed }"> |
| 14 | {{ is_authed ? '已授权' : '未授权' }} | 26 | {{ is_authed ? '已授权' : '未授权' }} |
| ... | @@ -53,7 +65,7 @@ | ... | @@ -53,7 +65,7 @@ |
| 53 | 65 | ||
| 54 | <script setup> | 66 | <script setup> |
| 55 | import { ref, watch } from 'vue' | 67 | import { ref, watch } from 'vue' |
| 56 | -import { useDidShow, useLoad } from '@tarojs/taro' | 68 | +import Taro, { useDidShow, useLoad } from '@tarojs/taro' |
| 57 | import { useWechatMiniPay } from '@/composables/useWechatMiniPay' | 69 | import { useWechatMiniPay } from '@/composables/useWechatMiniPay' |
| 58 | 70 | ||
| 59 | const order_id = ref('') | 71 | const order_id = ref('') |
| ... | @@ -91,6 +103,12 @@ const handleRefreshAuth = async () => { | ... | @@ -91,6 +103,12 @@ const handleRefreshAuth = async () => { |
| 91 | }) | 103 | }) |
| 92 | } | 104 | } |
| 93 | 105 | ||
| 106 | +const goToWebviewPreview = () => { | ||
| 107 | + Taro.navigateTo({ | ||
| 108 | + url: '/pages/webview-preview/index', | ||
| 109 | + }) | ||
| 110 | +} | ||
| 111 | + | ||
| 94 | const handlePay = async () => { | 112 | const handlePay = async () => { |
| 95 | await pay_by_order_id(order_id.value, { | 113 | await pay_by_order_id(order_id.value, { |
| 96 | auto_auth: false, | 114 | auto_auth: false, | ... | ... |
-
Please register or login to post a comment