Files
medical-mall/pages/mall/delivery/test.uvue
2026-01-28 19:13:13 +08:00

418 lines
9.4 KiB
Plaintext

<template>
<view class="container">
<view class="header">
<text class="title">Supabase 连接测试</text>
</view>
<view class="config-info">
<text class="label">当前配置:</text>
<text class="value">URL: {{ config.url }}</text>
<text class="value">Key: {{ config.keyMasked }}</text>
</view>
<view class="test-section">
<button class="btn-primary" @click="runAllTests" :disabled="isLoading">
{{ isLoading ? '测试中...' : '运行全部测试' }}
</button>
</view>
<view class="results" v-if="testResults.length > 0">
<text class="section-title">测试结果</text>
<view
class="result-item"
v-for="(result, index) in testResults"
:key="index"
:class="{ success: result.success, error: !result.success }"
>
<text class="result-icon">{{ result.success ? '✅' : '❌' }}</text>
<text class="result-text">{{ result.name }}</text>
<text class="result-message">{{ result.message }}</text>
<text v-if="result.errorDetails" class="error-details">{{ result.errorDetails }}</text>
</view>
</view>
<view class="quick-tests">
<text class="section-title">单项测试</text>
<button class="btn-secondary" @click="testConnection">测试连接</button>
<button class="btn-secondary" @click="testQuery">测试查询</button>
<button class="btn-secondary" @click="testAuth">测试认证</button>
</view>
</view>
</template>
<script lang="uts">
// 导入你的封装库和配置
import supa from '@/components/supadb/aksupainstance.uts'
import { SUPA_URL, SUPA_KEY } from '@/ak/config.uts'
// 定义测试结果类型
type TestResult = {
name: string
success: boolean
message: string
errorDetails?: string
}
// 定义用户类型(用于类型安全查询)
type User = {
id?: number
email?: string
nickname?: string
phone?: string
created_at?: string
}
export default {
data() {
return {
config: {
url: SUPA_URL,
key: SUPA_KEY,
keyMasked: SUPA_KEY.substring(0, 20) + '...' // 隐藏部分密钥
},
isLoading: false,
testResults: [] as TestResult[]
}
},
onLoad() {
console.log('🎯 Supabase 测试页面加载完成')
console.log('📋 配置信息:', {
url: SUPA_URL,
hasKey: !!SUPA_KEY
})
},
methods: {
// 获取错误消息的安全函数
getErrorMessage(err: any): string {
if (err == null) return '未知错误'
if (typeof err === 'string') return err
if (typeof err === 'object') {
if (err.message) return err.message
if (err.error) return err.error
if (err.msg) return err.msg
return JSON.stringify(err)
}
return String(err)
},
// 安全执行测试
async safeExecute<T>(promise: Promise<T>, operationName: string): Promise<{ success: boolean; data?: T; error?: string }> {
try {
const result = await promise
return { success: true, data: result }
} catch (err) {
const errorMessage = this.getErrorMessage(err)
console.error(`❌ ${operationName} 失败:`, err)
return { success: false, error: errorMessage }
}
},
// 测试连接
async testConnection(): Promise<TestResult> {
console.log('🔍 开始测试连接...')
const result = await this.safeExecute(
uni.request({
url: `${SUPA_URL}/rest/v1/`,
method: 'GET',
header: {
'apikey': SUPA_KEY,
'Authorization': `Bearer ${SUPA_KEY}`,
'Content-Type': 'application/json'
},
timeout: 10000
}),
'基础连接测试'
)
if (result.success) {
const response = result.data as any
if (response.statusCode === 200 || response.statusCode === 404) {
return {
name: '基础连接',
success: true,
message: `API 可达 (HTTP ${response.statusCode})`,
errorDetails: response.statusCode === 404 ? 'API 响应正常,但请求的资源不存在' : undefined
}
} else {
return {
name: '基础连接',
success: false,
message: `HTTP 错误`,
errorDetails: `状态码: ${response.statusCode}, 数据: ${JSON.stringify(response.data)}`
}
}
} else {
return {
name: '基础连接',
success: false,
message: '连接失败',
errorDetails: result.error
}
}
},
// 测试查询
async testQuery(): Promise<TestResult> {
console.log('🔍 开始测试查询...')
// 尝试查询 users 表
const queryResult = await this.safeExecute(
supa.from('users').select('id, email, nickname').limit(1).execute(),
'查询测试'
)
if (queryResult.success) {
const { data, error } = queryResult.data as any
if (error) {
const errorMsg = this.getErrorMessage(error)
// 检查是否是表不存在的错误
if (errorMsg.includes('relation') && errorMsg.includes('does not exist')) {
return {
name: '查询测试',
success: false,
message: '表不存在',
errorDetails: 'users 表不存在,建议先在 Studio 中创建表'
}
}
return {
name: '查询测试',
success: false,
message: '查询出错',
errorDetails: errorMsg
}
}
return {
name: '查询测试',
success: true,
message: `查询成功,返回 ${data?.length || 0} 条记录`,
errorDetails: data && data.length > 0 ? `第一条: ${JSON.stringify(data[0])}` : '表为空'
}
} else {
return {
name: '查询测试',
success: false,
message: '查询失败',
errorDetails: queryResult.error
}
}
},
// 测试认证
async testAuth(): Promise<TestResult> {
console.log('🔍 开始测试认证...')
const authResult = await this.safeExecute(
supa.auth.getSession(),
'认证测试'
)
if (authResult.success) {
const { data, error } = authResult.data as any
if (error) {
return {
name: '认证测试',
success: false,
message: '获取会话失败',
errorDetails: this.getErrorMessage(error)
}
}
if (data?.session) {
return {
name: '认证测试',
success: true,
message: '用户已登录',
errorDetails: `用户: ${data.session.user.email || data.session.user.phone || 'ID: ' + data.session.user.id}`
}
} else {
return {
name: '认证测试',
success: true,
message: '未登录(正常状态)',
errorDetails: '当前没有活动会话,需要先登录'
}
}
} else {
return {
name: '认证测试',
success: false,
message: '认证失败',
errorDetails: authResult.error
}
}
},
// 运行所有测试
async runAllTests() {
this.isLoading = true
this.testResults = []
try {
// 依次运行测试
const tests = [
{ name: 'connection', func: this.testConnection },
{ name: 'query', func: this.testQuery },
{ name: 'auth', func: this.testAuth }
]
for (const test of tests) {
console.log(`🧪 运行测试: ${test.name}`)
const result = await test.func.call(this)
this.testResults.push(result)
// 短暂延迟,让用户看到测试进度
await new Promise(resolve => setTimeout(resolve, 500))
}
// 总结结果
const passed = this.testResults.filter(r => r.success).length
const total = this.testResults.length
console.log(`📈 测试总结: ${passed}/${total} 通过`)
} catch (error) {
console.error('❌ 运行测试时发生错误:', error)
this.testResults.push({
name: '整体测试',
success: false,
message: '测试框架错误',
errorDetails: this.getErrorMessage(error)
})
} finally {
this.isLoading = false
}
}
}
}
</script>
<style>
.container {
padding: 30rpx;
background-color: #f8f9fa;
min-height: 100vh;
}
.header {
text-align: center;
margin-bottom: 40rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
.config-info {
background-color: #fff;
padding: 20rpx;
border-radius: 12rpx;
margin-bottom: 30rpx;
}
.label {
font-size: 28rpx;
color: #666;
display: block;
margin-bottom: 10rpx;
}
.value {
font-size: 24rpx;
color: #333;
display: block;
margin-bottom: 8rpx;
word-break: break-all;
}
.test-section {
margin-bottom: 40rpx;
}
.btn-primary {
width: 100%;
height: 80rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
border-radius: 12rpx;
font-size: 28rpx;
border: none;
margin-bottom: 20rpx;
}
.btn-secondary {
width: 100%;
height: 70rpx;
background-color: #6c757d;
color: #fff;
border-radius: 8rpx;
font-size: 26rpx;
border: none;
margin-bottom: 15rpx;
}
.btn-primary:disabled, .btn-secondary:disabled {
background-color: #ccc;
}
.results {
margin-bottom: 40rpx;
}
.section-title {
font-size: 30rpx;
font-weight: bold;
color: #333;
display: block;
margin-bottom: 20rpx;
}
.result-item {
background-color: #fff;
padding: 20rpx;
border-radius: 12rpx;
margin-bottom: 15rpx;
}
.result-item.success {
border-left: 4px solid #28a745;
background-color: #d4edda;
}
.result-item.error {
border-left: 4px solid #dc3545;
background-color: #f8d7da;
}
.result-icon {
font-size: 32rpx;
margin-right: 10rpx;
vertical-align: middle;
}
.result-text {
font-size: 26rpx;
color: #333;
font-weight: bold;
vertical-align: middle;
}
.result-message {
display: block;
font-size: 24rpx;
color: #666;
margin-top: 8rpx;
}
.error-details {
display: block;
font-size: 20rpx;
color: #856404;
background-color: #fff3cd;
padding: 8rpx;
border-radius: 4rpx;
margin-top: 8rpx;
word-break: break-all;
white-space: pre-wrap;
}
</style>