fix: 移除所有硬编码的localhost:8080,使用相对路径

- 创建utils/config.ts集中管理API_BASE和文件URL
- 删除.env文件(VITE_SERVER_API_URL=http://localhost:8080)
- env.ts默认API前缀改为/api/v1匹配后端路由
- 替换16处硬编码的localhost:8080引用
This commit is contained in:
2026-05-03 19:48:07 +08:00
parent 6d5d1922f5
commit fbc2e5ac91
17 changed files with 32 additions and 37 deletions
@@ -3,6 +3,8 @@ import { ref } from 'vue'
import type { Team } from './types'
import { getFileUrl } from '@/utils/config'
const { teams } = defineProps<{
teams: Team[]
}>()
@@ -10,11 +12,7 @@ const { teams } = defineProps<{
const activeTeam = ref<Team>(teams[0])
function getAssetUrl(path: string) {
if (!path)
return ''
if (path.startsWith('http'))
return path
return `${import.meta.env.VITE_API_BASE || 'http://localhost:8080'}${path}`
return getFileUrl(path)
}
</script>
@@ -7,6 +7,7 @@ import { useRoute, useRouter } from 'vue-router'
import ThemePopover from '@/components/custom-theme/theme-popover.vue'
import LanguageChange from '@/components/language-change.vue'
import { getFileUrl } from '@/utils/config'
const { t } = useI18n()
const mode = useColorMode()
@@ -31,20 +32,11 @@ const siteSettings = ref({
const siteName = computed(() => siteSettings.value.siteName)
const userAvatar = computed(() => {
const avatar = currentUser.value?.avatar
if (!avatar)
return ''
if (avatar.startsWith('http'))
return avatar
return `${import.meta.env.VITE_API_BASE || 'http://localhost:8080'}${avatar}`
return getFileUrl(currentUser.value?.avatar)
})
function getAssetUrl(path: string) {
if (!path)
return ''
if (path.startsWith('http'))
return path
return `${import.meta.env.VITE_API_BASE || 'http://localhost:8080'}${path}`
return getFileUrl(path)
}
const logoSrc = computed(() => {
+2 -5
View File
@@ -7,6 +7,7 @@ import LanguageChange from '@/components/language-change.vue'
import ThemePopover from '@/components/custom-theme/theme-popover.vue'
import ToggleTheme from '@/components/toggle-theme.vue'
import api from '@/services/api'
import { getFileUrl } from '@/utils/config'
const router = useRouter()
@@ -72,11 +73,7 @@ const breadcrumbs = computed(() => {
})
function getAssetUrl(path: string) {
if (!path)
return ''
if (path.startsWith('http'))
return path
return `${import.meta.env.VITE_API_BASE || 'http://localhost:8080'}${path}`
return getFileUrl(path)
}
function updateFavicon(favicon: string) {
@@ -5,6 +5,7 @@ import { useRoute, useRouter } from 'vue-router'
import { toast } from 'vue-sonner'
import { BasicPage } from '@/components/global-layout'
import { API_BASE } from '@/utils/config'
interface CardType {
id: number
@@ -23,7 +24,6 @@ interface CardTypePermission {
const route = useRoute()
const router = useRouter()
const API_BASE = 'http://localhost:8080/api/v1'
const loading = ref(true)
const saving = ref(false)
@@ -7,10 +7,10 @@ import { toast } from 'vue-sonner'
import type { AgentApp } from '@/pages/admin/agent-apps/data/schema'
import { BasicPage } from '@/components/global-layout'
import { API_BASE } from '@/utils/config'
const route = useRoute()
const router = useRouter()
const API_BASE = 'http://localhost:8080/api/v1'
const loading = ref(true)
const saving = ref(false)
@@ -5,10 +5,10 @@ import { useRoute, useRouter } from 'vue-router'
import { toast } from 'vue-sonner'
import { BasicPage } from '@/components/global-layout'
import { API_BASE } from '@/utils/config'
const route = useRoute()
const router = useRouter()
const API_BASE = 'http://localhost:8080/api/v1'
const loading = ref(true)
const saving = ref(false)
@@ -5,9 +5,9 @@ import { useRouter } from 'vue-router'
import { toast } from 'vue-sonner'
import { BasicPage } from '@/components/global-layout'
import { API_BASE } from '@/utils/config'
const router = useRouter()
const API_BASE = 'http://localhost:8080/api/v1'
const saving = ref(false)
const applications = ref<Array<{ id: number, name: string }>>([])
@@ -5,9 +5,9 @@ import { useRouter } from 'vue-router'
import { toast } from 'vue-sonner'
import { BasicPage } from '@/components/global-layout'
import { API_BASE } from '@/utils/config'
const router = useRouter()
const API_BASE = 'http://localhost:8080/api/v1'
const saving = ref(false)
const applications = ref<Array<{ id: number, name: string }>>([])
@@ -5,11 +5,10 @@ import { useRoute } from 'vue-router'
import { toast } from 'vue-sonner'
import { BasicPage } from '@/components/global-layout'
import { API_BASE } from '@/utils/config'
const route = useRoute()
const API_BASE = 'http://localhost:8080/api/v1'
const loading = ref(false)
const saving = ref(false)
@@ -5,11 +5,10 @@ import { useRoute } from 'vue-router'
import { toast } from 'vue-sonner'
import { BasicPage } from '@/components/global-layout'
import { API_BASE } from '@/utils/config'
const route = useRoute()
const API_BASE = 'http://localhost:8080/api/v1'
const loading = ref(false)
const saving = ref(false)
@@ -4,6 +4,8 @@ import { useRouter } from 'vue-router'
import type { App } from '../data/schema'
import { getFileUrl } from '@/utils/config'
const props = defineProps<{
app: App
}>()
@@ -25,7 +27,7 @@ function formatDate(date: string | Date) {
<div class="flex items-start justify-between">
<div class="flex items-center gap-3">
<div class="size-10 rounded-lg bg-primary/10 flex items-center justify-center">
<img v-if="props.app.icon_url" :src="props.app.icon_url.startsWith('http') ? props.app.icon_url : `http://localhost:8080${props.app.icon_url}`" class="size-6 object-cover rounded" alt="" />
<img v-if="props.app.icon_url" :src="getFileUrl(props.app.icon_url)" class="size-6 object-cover rounded" alt="" />
<Box v-else class="size-6 text-primary" />
</div>
<div>
@@ -22,6 +22,7 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { getFileUrl } from '@/utils/config'
export function getColumns(actions: {
onGoToSettings: (app: App) => void
@@ -55,7 +56,7 @@ export function getColumns(actions: {
h('div', { class: 'h-8 w-8 rounded bg-primary/10 flex items-center justify-center flex-shrink-0 overflow-hidden' }, [
row.original.icon_url
? h('img', {
src: `http://localhost:8080${row.original.icon_url}`,
src: getFileUrl(row.original.icon_url),
alt: row.getValue('name') as string,
class: 'w-full h-full object-cover',
})
@@ -5,10 +5,9 @@ import { useRouter } from 'vue-router'
import { toast } from 'vue-sonner'
import { BasicPage } from '@/components/global-layout'
import { API_BASE } from '@/utils/config'
const router = useRouter()
const API_BASE = 'http://localhost:8080/api/v1'
const loading = ref(false)
const showSuccessDialog = ref(false)
const createdAppId = ref<number | null>(null)
@@ -11,11 +11,11 @@ import ConfirmDialog from '@/components/confirm-dialog.vue'
import SingleFilter from '@/components/data-table/single-filter.vue'
import { BasicPage } from '@/components/global-layout'
import DataTable from '@/pages/admin/card-types/components/data-table.vue'
import { API_BASE } from '@/utils/config'
const { t } = useI18n()
const router = useRouter()
const API_BASE = 'http://localhost:8080/api/v1'
interface Application {
id: string
+1 -1
View File
@@ -2,7 +2,7 @@
import { Code, Eye, Loader2 } from 'lucide-vue-next'
import { onMounted, ref } from 'vue'
const API_BASE = 'http://localhost:8080/api/v1'
import { API_BASE } from '@/utils/config'
interface DynamicCode {
id: string
+8
View File
@@ -0,0 +1,8 @@
export const API_BASE = import.meta.env.VITE_API_BASE_URL || '/api/v1'
export function getFileUrl(path: string): string {
if (!path) return ''
if (path.startsWith('http')) return path
const base = import.meta.env.VITE_API_BASE || ''
return `${base}${path}`
}
+1 -1
View File
@@ -10,7 +10,7 @@ import { z } from 'zod'
const EnvSchema = z.object({
VITE_SERVER_API_URL: z.string().default(''),
VITE_SERVER_API_PREFIX: z.string().default('/api'),
VITE_SERVER_API_PREFIX: z.string().default('/api/v1'),
VITE_SERVER_API_TIMEOUT: z.coerce.number().default(5000),
})