forked from wangziqi/gongxue-base
test: add taro h5 interaction smoke
This commit is contained in:
@@ -43,7 +43,7 @@ export default {
|
||||
options: {},
|
||||
},
|
||||
h5: {
|
||||
publicPath: './',
|
||||
publicPath: '/',
|
||||
staticDirectory: 'static',
|
||||
output: {
|
||||
filename: 'js/[name].[contenthash:8].js',
|
||||
|
||||
@@ -25,6 +25,15 @@ declare const process: {
|
||||
env: Record<string, string | undefined>;
|
||||
};
|
||||
|
||||
type ProcessLike = {
|
||||
env?: Record<string, string | undefined>;
|
||||
};
|
||||
|
||||
function envValue(key: string) {
|
||||
const runtimeProcess = typeof process === 'undefined' ? undefined : (process as ProcessLike);
|
||||
return runtimeProcess?.env?.[key];
|
||||
}
|
||||
|
||||
const forbiddenFrontendKeys = [
|
||||
'SUPABASE_SERVICE_ROLE_KEY',
|
||||
'SUPABASE_SECRET_KEY',
|
||||
@@ -72,11 +81,11 @@ function assertNoForbiddenKeys(input: Record<string, unknown>, source: string) {
|
||||
}
|
||||
|
||||
export const appEnv: AppEnv = {
|
||||
portal: (process.env.TARO_APP_PORTAL || 'student') as Portal,
|
||||
apiBaseUrl: process.env.TARO_APP_API_BASE_URL || 'http://127.0.0.1:8787',
|
||||
supabaseUrl: process.env.TARO_APP_SUPABASE_URL || '',
|
||||
supabasePublishableKey: process.env.TARO_APP_SUPABASE_PUBLISHABLE_KEY || '',
|
||||
tenantCode: process.env.TARO_APP_TENANT_CODE || '',
|
||||
portal: (envValue('TARO_APP_PORTAL') || 'student') as Portal,
|
||||
apiBaseUrl: envValue('TARO_APP_API_BASE_URL') || 'http://127.0.0.1:8787',
|
||||
supabaseUrl: envValue('TARO_APP_SUPABASE_URL') || '',
|
||||
supabasePublishableKey: envValue('TARO_APP_SUPABASE_PUBLISHABLE_KEY') || '',
|
||||
tenantCode: envValue('TARO_APP_TENANT_CODE') || '',
|
||||
};
|
||||
|
||||
let runtimeConfigPromise: Promise<AppEnv> | null = null;
|
||||
@@ -103,7 +112,7 @@ export function applyRuntimeConfig(input: RuntimeConfigInput, source = 'runtime
|
||||
}
|
||||
|
||||
export async function loadRuntimeConfig() {
|
||||
if (process.env.TARO_ENV !== 'h5' || typeof window === 'undefined' || typeof window.fetch !== 'function') {
|
||||
if (!isH5Runtime() || typeof window === 'undefined' || typeof window.fetch !== 'function') {
|
||||
return appEnv;
|
||||
}
|
||||
|
||||
@@ -138,8 +147,20 @@ export function ensureRuntimeConfigLoaded() {
|
||||
}
|
||||
|
||||
export function assertFrontendSecretsAreAbsent() {
|
||||
const leaked = forbiddenFrontendKeys.filter(key => process.env[key]);
|
||||
const leaked = forbiddenFrontendKeys.filter(key => envValue(key));
|
||||
if (leaked.length) {
|
||||
throw new Error(`Forbidden secret env in Taro build: ${leaked.join(', ')}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function taroRuntimeEnv() {
|
||||
return envValue('TARO_ENV') || '';
|
||||
}
|
||||
|
||||
export function isH5Runtime() {
|
||||
return taroRuntimeEnv() === 'h5' || (typeof window !== 'undefined' && typeof document !== 'undefined');
|
||||
}
|
||||
|
||||
export function isWeappRuntime() {
|
||||
return taroRuntimeEnv() === 'weapp';
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { Button, Text, View } from '@tarojs/components';
|
||||
import { appEnv, assertFrontendSecretsAreAbsent, ensureRuntimeConfigLoaded } from '@/env';
|
||||
import { appEnv, assertFrontendSecretsAreAbsent, ensureRuntimeConfigLoaded, isH5Runtime } from '@/env';
|
||||
import { resolveTenant } from '@/services/api';
|
||||
import './index.css';
|
||||
|
||||
function hostFromRuntime() {
|
||||
if (process.env.TARO_ENV === 'h5' && typeof window !== 'undefined') return window.location.host;
|
||||
if (isH5Runtime() && typeof window !== 'undefined') return window.location.host;
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
loadSchoolRecommendationReports,
|
||||
type SchoolRecommendationReport,
|
||||
} from '@/services/ai';
|
||||
import { isH5Runtime } from '@/env';
|
||||
import { loadProfile, type StudentProfile } from '@/services/profile';
|
||||
import '../student.css';
|
||||
|
||||
@@ -25,7 +26,7 @@ function recommendationRows(report: SchoolRecommendationReport | null) {
|
||||
}
|
||||
|
||||
function saveExportFile(fileName: string, content: string, mimeType: string) {
|
||||
if (process.env.TARO_ENV === 'h5' && typeof window !== 'undefined' && typeof document !== 'undefined') {
|
||||
if (isH5Runtime() && typeof window !== 'undefined' && typeof document !== 'undefined') {
|
||||
const blob = new Blob([content], { type: mimeType });
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
@@ -94,7 +95,7 @@ export default function StudentAiSchoolPage() {
|
||||
const payload = await exportSchoolRecommendationReport(current.id, format);
|
||||
if (!payload.item?.contentText) throw new Error('后端未返回报告内容');
|
||||
saveExportFile(payload.item.fileName, payload.item.contentText, payload.item.mimeType);
|
||||
if (process.env.TARO_ENV === 'h5') Taro.showToast({ title: '报告已导出', icon: 'success' });
|
||||
if (isH5Runtime()) Taro.showToast({ title: '报告已导出', icon: 'success' });
|
||||
} catch (nextError) {
|
||||
setError(nextError instanceof Error ? nextError.message : '导出失败');
|
||||
} finally {
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
type ContentAsset,
|
||||
type SignedAssetLink,
|
||||
} from '@/services/catalog';
|
||||
import { isH5Runtime } from '@/env';
|
||||
import '../student.css';
|
||||
|
||||
type PreviewState = {
|
||||
@@ -20,7 +21,7 @@ type PreviewState = {
|
||||
|
||||
function openUrl(url?: string, copiedText = '签名链接已复制,请在浏览器中打开') {
|
||||
if (!url) return;
|
||||
if (process.env.TARO_ENV === 'h5' && typeof window !== 'undefined') {
|
||||
if (isH5Runtime() && typeof window !== 'undefined') {
|
||||
window.open(url, '_blank', 'noopener,noreferrer');
|
||||
return;
|
||||
}
|
||||
@@ -129,10 +130,10 @@ export default function StudentAssetsPage() {
|
||||
<Text className='row-meta'>下载前请确认页面水印和追踪码。签名 URL 不会长期保存,过期后需要重新申请。</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{previewState.kind === 'preview' && process.env.TARO_ENV === 'h5' ? (
|
||||
{previewState.kind === 'preview' && isH5Runtime() ? (
|
||||
<WebView className='asset-preview-iframe' src={previewState.link.url || ''} />
|
||||
) : null}
|
||||
{previewState.kind === 'preview' && process.env.TARO_ENV !== 'h5' ? (
|
||||
{previewState.kind === 'preview' && !isH5Runtime() ? (
|
||||
<View className='asset-download-confirm'>
|
||||
<Text className='row-main'>已获取预览授权</Text>
|
||||
<Text className='row-meta'>当前小程序容器不直接嵌入私有文件。请先确认水印追踪码,再使用外部打开或复制签名链接。</Text>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
type PaymentCreateResult,
|
||||
type SvipPlan,
|
||||
} from '@/services/commerce';
|
||||
import { isH5Runtime, isWeappRuntime } from '@/env';
|
||||
import { loadProfile, type StudentProfile } from '@/services/profile';
|
||||
import '../student.css';
|
||||
|
||||
@@ -56,7 +57,7 @@ function buildPaymentUrl(result?: PaymentCreateResult) {
|
||||
|
||||
function tryOpenPaymentUrl(url: string) {
|
||||
if (!url) return false;
|
||||
if (process.env.TARO_ENV === 'h5' && typeof window !== 'undefined') {
|
||||
if (isH5Runtime() && typeof window !== 'undefined') {
|
||||
window.location.href = url;
|
||||
return true;
|
||||
}
|
||||
@@ -167,8 +168,8 @@ export default function StudentCheckoutPage() {
|
||||
const paymentPayload = await createPayment({
|
||||
orderNo: nextOrder.orderNo,
|
||||
provider,
|
||||
returnUrl: process.env.TARO_ENV === 'h5' && typeof window !== 'undefined' ? window.location.href : undefined,
|
||||
quitUrl: process.env.TARO_ENV === 'h5' && typeof window !== 'undefined' ? window.location.href : undefined,
|
||||
returnUrl: isH5Runtime() && typeof window !== 'undefined' ? window.location.href : undefined,
|
||||
quitUrl: isH5Runtime() && typeof window !== 'undefined' ? window.location.href : undefined,
|
||||
});
|
||||
setPayment(paymentPayload.item || null);
|
||||
setMessage(provider === 'manual' ? '已生成线下支付记录,请联系教务或客服确认。' : '支付参数已生成,请继续完成支付。');
|
||||
@@ -181,7 +182,7 @@ export default function StudentCheckoutPage() {
|
||||
|
||||
async function handleOpenPayment() {
|
||||
if (!payment) return;
|
||||
if (payment.provider === 'wechat_pay' && process.env.TARO_ENV === 'weapp') {
|
||||
if (payment.provider === 'wechat_pay' && isWeappRuntime()) {
|
||||
const paramsForWeapp = payment.paymentParams || {};
|
||||
Taro.requestPayment(paramsForWeapp as unknown as Taro.requestPayment.Option)
|
||||
.then(() => order?.orderNo ? pollStatus(order.orderNo) : undefined)
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
type PaymentCreateResult,
|
||||
} from '@/services/commerce';
|
||||
import { getTenantContext } from '@/services/api';
|
||||
import { isH5Runtime } from '@/env';
|
||||
import '../student.css';
|
||||
|
||||
function centsToYuan(value?: number | null) {
|
||||
@@ -94,13 +95,13 @@ export default function StudentOrderDetailPage() {
|
||||
const payload = await createPayment({
|
||||
orderNo,
|
||||
provider: provider || detail?.payProvider || status?.payProvider || 'alipay',
|
||||
returnUrl: process.env.TARO_ENV === 'h5' && typeof window !== 'undefined' ? window.location.href : undefined,
|
||||
quitUrl: process.env.TARO_ENV === 'h5' && typeof window !== 'undefined' ? window.location.href : undefined,
|
||||
returnUrl: isH5Runtime() && typeof window !== 'undefined' ? window.location.href : undefined,
|
||||
quitUrl: isH5Runtime() && typeof window !== 'undefined' ? window.location.href : undefined,
|
||||
});
|
||||
const nextPayment = payload.item || null;
|
||||
setPayment(nextPayment);
|
||||
const url = paymentUrl(nextPayment);
|
||||
if (url && process.env.TARO_ENV === 'h5' && typeof window !== 'undefined') {
|
||||
if (url && isH5Runtime() && typeof window !== 'undefined') {
|
||||
window.location.href = url;
|
||||
} else if (url) {
|
||||
await Taro.setClipboardData({ data: url });
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
type PublicQuestionBankItem,
|
||||
type TenantContentNotificationItem,
|
||||
} from '@/services/tenantAdmin';
|
||||
import { isH5Runtime } from '@/env';
|
||||
import '../admin.css';
|
||||
|
||||
function displayBankName(item: PublicQuestionBankItem) {
|
||||
@@ -74,7 +75,7 @@ function readLocalFileAsText(file: File) {
|
||||
|
||||
function openH5FilePicker(format: ImportSourceFormat) {
|
||||
return new Promise<{ fileName: string; text?: string; fileBase64?: string }>((resolve, reject) => {
|
||||
if (process.env.TARO_ENV !== 'h5' || typeof document === 'undefined') {
|
||||
if (!isH5Runtime() || typeof document === 'undefined') {
|
||||
reject(new Error('当前端暂未接入文件选择,请粘贴 JSON/CSV 内容后预览导入。'));
|
||||
return;
|
||||
}
|
||||
@@ -111,7 +112,7 @@ function base64ToUint8Array(base64: string) {
|
||||
}
|
||||
|
||||
function downloadTemplateFile(template: ImportTemplateItem) {
|
||||
if (process.env.TARO_ENV !== 'h5' || typeof document === 'undefined') {
|
||||
if (!isH5Runtime() || typeof document === 'undefined') {
|
||||
throw new Error('当前端暂不支持直接下载模板,请先使用模板预览。');
|
||||
}
|
||||
if (!template.contentBase64) throw new Error('模板内容为空,请重新加载模板。');
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { isH5Runtime } from '../env';
|
||||
|
||||
export type ApiAuthMode = 'auto' | 'none' | 'supabase' | 'legacy';
|
||||
|
||||
export type SupabaseAccessTokenProvider = () => Promise<string | null>;
|
||||
|
||||
async function defaultH5SupabaseAccessTokenProvider() {
|
||||
if (process.env.TARO_ENV !== 'h5') return null;
|
||||
if (!isH5Runtime()) return null;
|
||||
const { getSupabaseAccessToken } = await import('./supabase');
|
||||
return getSupabaseAccessToken();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
import { isH5Runtime } from '@/env';
|
||||
|
||||
export type AccentType = 'us' | 'uk';
|
||||
|
||||
@@ -62,7 +63,7 @@ export async function playWordPronunciation(word: string, accent: AccentType = '
|
||||
|
||||
const url = pronunciationUrl(text, accent);
|
||||
|
||||
if (process.env.TARO_ENV === 'h5' && typeof Audio !== 'undefined') {
|
||||
if (isH5Runtime() && typeof Audio !== 'undefined') {
|
||||
try {
|
||||
const audio = new Audio(url);
|
||||
audio.preload = 'auto';
|
||||
|
||||
Reference in New Issue
Block a user