修复环境变量问题

This commit is contained in:
2026-04-14 11:34:28 +08:00
parent 9a8a1826c9
commit 319baea5e8
8 changed files with 60 additions and 8 deletions

View File

@@ -1,4 +1,4 @@
# 开发环境配置 # 开发环境配置
NEXT_PUBLIC_API_BASE_URL=http://192.168.3.42:8080 API_BASE_URL=http://192.168.3.42:8080
CLIENT_ID=web CLIENT_ID=web
CLIENT_SECRET=web CLIENT_SECRET=web

View File

@@ -122,7 +122,7 @@ type UserProfile = ExtraResp<typeof getProfile>
## 环境变量 ## 环境变量
需要配置: 需要配置:
- `NEXT_PUBLIC_API_BASE_URL` - 后端 API 地址 - `API_BASE_URL` - 后端 API 地址
- `CLIENT_ID`, `CLIENT_SECRET` - OAuth2 设备认证凭据 - `CLIENT_ID`, `CLIENT_SECRET` - OAuth2 设备认证凭据
## 部署 ## 部署

View File

@@ -32,6 +32,7 @@ RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
RUN rm .env
USER nextjs USER nextjs

View File

@@ -12,6 +12,13 @@ export type TokenResp = {
scope?: string scope?: string
} }
export async function getApiUrl() {
return {
success: true,
data: API_BASE_URL,
} satisfies ApiResponse<string>
}
// ====================== // ======================
// public // public
// ====================== // ======================

View File

@@ -8,6 +8,8 @@ import {LayoutStoreProvider} from '@/components/stores/layout'
import {ClientStoreProvider} from '@/components/stores/client' import {ClientStoreProvider} from '@/components/stores/client'
import {getProfile} from '@/actions/auth' import {getProfile} from '@/actions/auth'
import Script from 'next/script' import Script from 'next/script'
import {AppStoreProvider} from '@/components/stores/app'
import {getApiUrl} from '@/actions/base'
export async function generateMetadata(): Promise<Metadata> { export async function generateMetadata(): Promise<Metadata> {
return { return {
@@ -30,12 +32,14 @@ export default async function RootLayout(props: Readonly<{
) )
} }
function StoreProviders(props: {children: ReactNode}) { async function StoreProviders(props: {children: ReactNode}) {
return ( return (
<ProfileStoreProvider profile={getProfile().then(resp => resp.success ? resp.data : null)}> <ProfileStoreProvider profile={getProfile().then(resp => resp.success ? resp.data : null)}>
<LayoutStoreProvider> <LayoutStoreProvider>
<ClientStoreProvider> <ClientStoreProvider>
<AppStoreProvider url={await getApiUrl().then(r => r.data)}>
{props.children} {props.children}
</AppStoreProvider>
</ClientStoreProvider> </ClientStoreProvider>
</LayoutStoreProvider> </LayoutStoreProvider>
</ProfileStoreProvider> </ProfileStoreProvider>

View File

@@ -7,6 +7,7 @@ import {PaymentProps} from './type'
import {payClose} from '@/actions/resource' import {payClose} from '@/actions/resource'
import {useEffect} from 'react' import {useEffect} from 'react'
import {UniversalDesktopPayment} from './universal-desktop-payment' import {UniversalDesktopPayment} from './universal-desktop-payment'
import {useAppStore} from '@/components/stores/app'
export type PaymentModalProps = { export type PaymentModalProps = {
onConfirm: (showFail: boolean) => Promise<void> onConfirm: (showFail: boolean) => Promise<void>
@@ -34,9 +35,10 @@ export function PaymentModal(props: PaymentModalProps) {
} }
// SSE处理方式检查支付状态 // SSE处理方式检查支付状态
const apiUrl = useAppStore('apiUrl')
useEffect(() => { useEffect(() => {
const eventSource = new EventSource( const eventSource = new EventSource(
`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/trade/check?trade_no=${props.inner_no}&method=${props.method}`, `${apiUrl}/api/trade/check?trade_no=${props.inner_no}&method=${props.method}`,
) )
eventSource.onmessage = async (event) => { eventSource.onmessage = async (event) => {
switch (event.data) { switch (event.data) {
@@ -53,7 +55,7 @@ export function PaymentModal(props: PaymentModalProps) {
return () => { return () => {
eventSource.close() eventSource.close()
} }
}, [props]) }, [apiUrl, props])
return ( return (
<Dialog <Dialog

View File

@@ -0,0 +1,38 @@
'use client'
import {createStore, StoreApi} from 'zustand/vanilla'
import {createContext, ReactNode, useContext, useState} from 'react'
import {useStore} from 'zustand/react'
// store
type AppStoreState = {
apiUrl: string
}
export function createAppStore(url: string) {
return createStore<AppStoreState>()(() => ({
apiUrl: url,
}))
}
// provider
const AppStoreContext = createContext<StoreApi<AppStoreState> | null>(null)
export function AppStoreProvider(props: {
url: string
children: ReactNode
}) {
const [store] = useState(() => createAppStore(props.url))
return (
<AppStoreContext.Provider value={store}>
{props.children}
</AppStoreContext.Provider>
)
}
export function useAppStore(name: keyof AppStoreState) {
const context = useContext(AppStoreContext)
if (!context) {
throw new Error('AppStoreContext 没有正确初始化')
}
return useStore(context, c => c[name])
}

View File

@@ -1,6 +1,6 @@
// 定义后端服务URL和OAuth2配置 // 定义后端服务URL和OAuth2配置
const _api_base_url = process.env.NEXT_PUBLIC_API_BASE_URL const _api_base_url = process.env.API_BASE_URL
if (!_api_base_url) throw new Error('NEXT_PUBLIC_API_BASE_URL is not set') if (!_api_base_url) throw new Error('API_BASE_URL is not set')
const API_BASE_URL = _api_base_url const API_BASE_URL = _api_base_url
const _client_id = process.env.CLIENT_ID const _client_id = process.env.CLIENT_ID