修改:改名,后端接口使用相对路径, 不写死域名

This commit is contained in:
马丁 2026-05-02 17:14:45 +08:00
parent 0d523ee5b8
commit 0f2c8d38e7
13 changed files with 37 additions and 26 deletions

2
.env
View File

@ -1,6 +1,6 @@
# API 基础地址,不设置时默认 https://api.xtrader.vip # API 基础地址,不设置时默认 https://api.xtrader.vip
# 连接测试服务器 192.168.3.21:8888 时复制本文件为 .env 或 .env.local 并取消下一行注释: # 连接测试服务器 192.168.3.21:8888 时复制本文件为 .env 或 .env.local 并取消下一行注释:
# VITE_API_BASE_URL=http://192.168.3.14:8888 VITE_API_BASE_URL=/api
# VITE_USE_MOCK_DATA=false # 全部关闭 mock # VITE_USE_MOCK_DATA=false # 全部关闭 mock
# SSH 部署npm run deploy可选覆盖 # SSH 部署npm run deploy可选覆盖

View File

@ -1,2 +1,2 @@
# 生产环境 API 地址npm run build / npm run deploy 时自动使用) # 生产环境 API 地址npm run build / npm run deploy 时自动使用)
VITE_API_BASE_URL=https://api.xtrader.vip VITE_API_BASE_URL=/api

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TestMarket</title> <title>Alpha Market</title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

View File

@ -2,7 +2,7 @@
/** /**
* 将项目打包并部署到远程服务器 * 将项目打包并部署到远程服务器
* 使用方式npm run deploy * 使用方式npm run deploy
* 通过 SSH rsync 部署到 root@38.246.250.238:/opt/1panel/www/sites/pm.xtrader.vip/index * 通过 SSH rsync 部署到 root@38.246.250.238:/opt/1panel/www/sites/pm.aaa.com/index
* *
* 环境变量可选DEPLOY_HOSTDEPLOY_USERDEPLOY_PATH * 环境变量可选DEPLOY_HOSTDEPLOY_USERDEPLOY_PATH
* 依赖rsync系统自带ssh 免密或密钥 * 依赖rsync系统自带ssh 免密或密钥
@ -18,13 +18,13 @@ const distDir = join(projectRoot, 'dist')
const config = { const config = {
host: process.env.DEPLOY_HOST || '38.246.250.238', host: process.env.DEPLOY_HOST || '38.246.250.238',
user: process.env.DEPLOY_USER || 'root', user: process.env.DEPLOY_USER || 'root',
path: process.env.DEPLOY_PATH || '/opt/1panel/www/sites/pm.xtrader.vip/index', path: process.env.DEPLOY_PATH || '/opt/1panel/www/sites/pm.aaa.vip/index',
} }
const target = `${config.user}@${config.host}:${config.path}` const target = `${config.user}@${config.host}:${config.path}`
function build() { function build() {
const apiUrl = process.env.VITE_API_BASE_URL || 'https://api.xtrader.vip' const apiUrl = process.env.VITE_API_BASE_URL || 'https://api.aaa.vip'
console.log(`📦 正在打包项目(.env.production API: ${apiUrl}...`) console.log(`📦 正在打包项目(.env.production API: ${apiUrl}...`)
execSync('npm run build', { execSync('npm run build', {
cwd: projectRoot, cwd: projectRoot,

View File

@ -87,7 +87,7 @@ watch(
> >
<v-icon>mdi-arrow-left</v-icon> <v-icon>mdi-arrow-left</v-icon>
</v-btn> </v-btn>
<v-app-bar-title v-if="currentRoute === '/'">TestMarket</v-app-bar-title> <v-app-bar-title v-if="currentRoute === '/'">Alpha Market</v-app-bar-title>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<template v-if="!userStore.isLoggedIn"> <template v-if="!userStore.isLoggedIn">
<v-menu <v-menu

View File

@ -31,20 +31,31 @@ async function parseJsonBody<T>(res: Response): Promise<T> {
return res.json() as Promise<T> return res.json() as Promise<T>
} }
/** 请求基础 URL默认 https://api.xtrader.vip,可通过环境变量 VITE_API_BASE_URL 覆盖 */ /** 请求基础 URL默认 https://api.aaa.com,可通过环境变量 VITE_API_BASE_URL 覆盖 */
export const BASE_URL = export const BASE_URL =
(import.meta as { env?: { VITE_API_BASE_URL?: string } }).env?.VITE_API_BASE_URL ?? (import.meta as { env?: { VITE_API_BASE_URL?: string } }).env?.VITE_API_BASE_URL ??
'https://api.xtrader.vip' 'https://api.aaa.com'
const FALLBACK_BASE = const FALLBACK_BASE =
typeof window !== 'undefined' ? window.location.origin : 'https://api.xtrader.vip' typeof window !== 'undefined' ? window.location.origin : 'https://api.aaa.com'
/** 生成完整 URL支持相对路径的 BASE_URL */
function buildFullUrl(path: string): URL {
let base = BASE_URL || FALLBACK_BASE
if (!/^https?:\/\//i.test(base)) {
const origin = typeof window !== 'undefined' ? window.location.origin : 'http://localhost'
base = `${origin}${base.startsWith('/') ? '' : '/'}${base}`
}
const cleanBase = base.endsWith('/') ? base.slice(0, -1) : base
const cleanPath = path.startsWith('/') ? path : `/${path}`
return new URL(`${cleanBase}${cleanPath}`)
}
/** 生成 WebSocket URL与 REST API 同源 */ /** 生成 WebSocket URL与 REST API 同源 */
function getWsUrl(path: string): string { function getWsUrl(path: string): string {
const base = BASE_URL || FALLBACK_BASE const url = buildFullUrl(path)
const url = new URL(base)
const protocol = url.protocol === 'https:' ? 'wss:' : 'ws:' const protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'
return `${protocol}//${url.host}${path.startsWith('/') ? path : `/${path}`}` return `${protocol}//${url.host}${url.pathname}${url.search}`
} }
/** CLOB WebSocket URL */ /** CLOB WebSocket URL */
@ -91,7 +102,7 @@ export async function get<T = unknown>(
params?: Record<string, string | number | string[] | number[] | undefined>, params?: Record<string, string | number | string[] | number[] | undefined>,
config?: RequestConfig, config?: RequestConfig,
): Promise<T> { ): Promise<T> {
const url = new URL(path, BASE_URL || window.location.origin) const url = buildFullUrl(path)
if (params) { if (params) {
Object.entries(params).forEach(([key, value]) => { Object.entries(params).forEach(([key, value]) => {
if (value === undefined) return if (value === undefined) return
@ -119,7 +130,7 @@ export async function post<T = unknown>(
body?: unknown, body?: unknown,
config?: RequestConfig, config?: RequestConfig,
): Promise<T> { ): Promise<T> {
const url = new URL(path, BASE_URL || window.location.origin) const url = buildFullUrl(path)
const headers: Record<string, string> = { const headers: Record<string, string> = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept-Language': i18n.global.locale.value as string, 'Accept-Language': i18n.global.locale.value as string,
@ -141,7 +152,7 @@ export async function uploadFile<T = unknown>(
file: File, file: File,
config?: RequestConfig, config?: RequestConfig,
): Promise<T> { ): Promise<T> {
const url = new URL(path, BASE_URL || window.location.origin) const url = buildFullUrl(path)
const form = new FormData() const form = new FormData()
form.append('file', file) form.append('file', file)
const headers: Record<string, string> = { const headers: Record<string, string> = {
@ -165,7 +176,7 @@ export async function put<T = unknown>(
body?: unknown, body?: unknown,
config?: RequestConfig, config?: RequestConfig,
): Promise<T> { ): Promise<T> {
const url = new URL(path, BASE_URL || window.location.origin) const url = buildFullUrl(path)
const headers: Record<string, string> = { const headers: Record<string, string> = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept-Language': i18n.global.locale.value as string, 'Accept-Language': i18n.global.locale.value as string,
@ -187,7 +198,7 @@ export async function httpDelete<T = unknown>(
body?: unknown, body?: unknown,
config?: RequestConfig, config?: RequestConfig,
): Promise<T> { ): Promise<T> {
const url = new URL(path, BASE_URL || window.location.origin) const url = buildFullUrl(path)
const headers: Record<string, string> = { const headers: Record<string, string> = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept-Language': i18n.global.locale.value as string, 'Accept-Language': i18n.global.locale.value as string,

View File

@ -149,7 +149,7 @@
"walletNotInstalled": "Ethereum wallet is not installed. Please install MetaMask, TokenPocket or another Ethereum wallet to continue.", "walletNotInstalled": "Ethereum wallet is not installed. Please install MetaMask, TokenPocket or another Ethereum wallet to continue.",
"invalidAddress": "Invalid wallet address format. Please check your wallet connection.", "invalidAddress": "Invalid wallet address format. Please check your wallet connection.",
"connectFailed": "Failed to connect with wallet. Please check your wallet and try again.", "connectFailed": "Failed to connect with wallet. Please check your wallet and try again.",
"siweStatement": "Sign in to TestMarket" "siweStatement": "Sign in to Alpha Market"
}, },
"apiKey": { "apiKey": {
"title": "API Key Management", "title": "API Key Management",

View File

@ -149,7 +149,7 @@
"walletNotInstalled": "イーサリアムウォレットがインストールされていません。MetaMask、TokenPocket などのウォレットをインストールしてください。", "walletNotInstalled": "イーサリアムウォレットがインストールされていません。MetaMask、TokenPocket などのウォレットをインストールしてください。",
"invalidAddress": "ウォレットアドレスの形式が無効です。接続を確認してください。", "invalidAddress": "ウォレットアドレスの形式が無効です。接続を確認してください。",
"connectFailed": "ウォレットの接続に失敗しました。ウォレットを確認して再試行してください。", "connectFailed": "ウォレットの接続に失敗しました。ウォレットを確認して再試行してください。",
"siweStatement": "TestMarket にサインイン" "siweStatement": "Alpha Market にサインイン"
}, },
"apiKey": { "apiKey": {
"title": "API Key 管理", "title": "API Key 管理",

View File

@ -149,7 +149,7 @@
"walletNotInstalled": "이더리움 지갑이 설치되어 있지 않습니다. MetaMask, TokenPocket 등 지갑을 설치해 주세요.", "walletNotInstalled": "이더리움 지갑이 설치되어 있지 않습니다. MetaMask, TokenPocket 등 지갑을 설치해 주세요.",
"invalidAddress": "지갑 주소 형식이 올바르지 않습니다. 지갑 연결을 확인해 주세요.", "invalidAddress": "지갑 주소 형식이 올바르지 않습니다. 지갑 연결을 확인해 주세요.",
"connectFailed": "지갑 연결에 실패했습니다. 지갑을 확인하고 다시 시도해 주세요.", "connectFailed": "지갑 연결에 실패했습니다. 지갑을 확인하고 다시 시도해 주세요.",
"siweStatement": "TestMarket 로그인" "siweStatement": "Alpha Market 로그인"
}, },
"apiKey": { "apiKey": {
"title": "API Key 관리", "title": "API Key 관리",

View File

@ -149,7 +149,7 @@
"walletNotInstalled": "未检测到以太坊钱包。请安装 MetaMask、TokenPocket 或其他以太坊钱包后重试。", "walletNotInstalled": "未检测到以太坊钱包。请安装 MetaMask、TokenPocket 或其他以太坊钱包后重试。",
"invalidAddress": "钱包地址格式无效,请检查钱包连接。", "invalidAddress": "钱包地址格式无效,请检查钱包连接。",
"connectFailed": "连接钱包失败,请检查钱包后重试。", "connectFailed": "连接钱包失败,请检查钱包后重试。",
"siweStatement": "登录 TestMarket" "siweStatement": "登录 Alpha Market"
}, },
"apiKey": { "apiKey": {
"title": "API Key 管理", "title": "API Key 管理",

View File

@ -149,7 +149,7 @@
"walletNotInstalled": "未偵測到以太坊錢包。請安裝 MetaMask、TokenPocket 或其他以太坊錢包後重試。", "walletNotInstalled": "未偵測到以太坊錢包。請安裝 MetaMask、TokenPocket 或其他以太坊錢包後重試。",
"invalidAddress": "錢包地址格式無效,請檢查錢包連接。", "invalidAddress": "錢包地址格式無效,請檢查錢包連接。",
"connectFailed": "連接錢包失敗,請檢查錢包後重試。", "connectFailed": "連接錢包失敗,請檢查錢包後重試。",
"siweStatement": "登入 TestMarket" "siweStatement": "登入 Alpha Market"
}, },
"apiKey": { "apiKey": {
"title": "API Key 管理", "title": "API Key 管理",

View File

@ -85,7 +85,7 @@ const connectWithWallet = async () => {
scheme, scheme,
domain, domain,
address: signer.address, address: signer.address,
statement: 'Sign in to TestMarket', statement: 'Sign in to Alpha Market',
uri: origin, uri: origin,
version: '1', version: '1',
chainId: chainId, chainId: chainId,

View File

@ -30,13 +30,13 @@
{{ t('profile.edit') }} {{ t('profile.edit') }}
</button> </button>
</div> </div>
<button type="button" class="vip-entry" @click="goMemberCenter"> <!-- <button type="button" class="vip-entry" @click="goMemberCenter">
<span class="vip-entry-title">{{ t('profile.memberCenter') }}</span> <span class="vip-entry-title">{{ t('profile.memberCenter') }}</span>
<span class="vip-entry-right"> <span class="vip-entry-right">
<span class="vip-pill">{{ t('memberCenter.vipLabel', { n: vipLevel }) }}</span> <span class="vip-pill">{{ t('memberCenter.vipLabel', { n: vipLevel }) }}</span>
<span class="vip-chev" aria-hidden="true"></span> <span class="vip-chev" aria-hidden="true"></span>
</span> </span>
</button> </button> -->
</section> </section>
<section class="card wallet-card"> <section class="card wallet-card">