fix: 修复 Docker 部署 API 地址与数据库连接问题

This commit is contained in:
2026-05-09 09:29:34 +08:00
parent 86568660a4
commit c2315f68dc
15 changed files with 665 additions and 119 deletions

View File

@@ -315,44 +315,123 @@ th {
.list-foot {
display: grid;
grid-template-columns: auto auto 1fr auto;
grid-template-columns: 1fr auto 1fr;
align-items: center;
gap: 10px;
color: #64748b;
font-size: 13px;
}
.list-foot button {
min-height: 32px;
border: 1px solid #d7e0ea;
border-radius: 8px;
background: #fff;
color: #334155;
font-weight: 750;
gap: 16px;
margin-top: 8px;
}
.pager {
display: inline-flex;
justify-content: center;
gap: 6px;
padding: 4px;
border: 1px solid #e2e8f0;
border-radius: 12px;
background: #f8fafc;
}
.pager button {
width: 32px;
height: 32px;
padding: 0;
border: 0;
border-radius: 9px;
background: transparent;
color: #334155;
font-size: 14px;
font-weight: 800;
transition: background 160ms ease, color 160ms ease, box-shadow 160ms ease;
}
.pager button:hover:not(.active) {
background: #fff;
color: #059669;
box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
}
.pager button.active {
border-color: #059669;
background: #059669;
color: #fff;
box-shadow: 0 8px 16px rgba(5, 150, 105, .20);
}
.list-foot input {
width: 42px;
height: 30px;
.list-foot .page-summary {
color: #64748b;
font-size: 14px;
font-weight: 650;
}
.page-nav {
color: #64748b;
}
.page-size-wrap {
position: relative;
justify-self: end;
}
.page-size {
justify-self: end;
min-width: 112px;
min-height: 38px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 9px;
padding: 0 14px;
border: 1px solid #d7e0ea;
border-radius: 7px;
text-align: center;
border-radius: 10px;
background: #fff;
box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
color: #334155;
font-size: 14px;
font-weight: 750;
white-space: nowrap;
transition: border-color 160ms ease, color 160ms ease;
}
.page-size:hover {
border-color: rgba(16, 185, 129, .32);
color: #0f9f78;
}
.page-size-dropdown {
position: absolute;
bottom: calc(100% + 6px);
right: 0;
z-index: 40;
display: grid;
border: 1px solid #d7e0ea;
border-radius: 10px;
background: #fff;
box-shadow: 0 12px 32px rgba(15, 23, 42, .14);
overflow: hidden;
}
.page-size-dropdown button {
height: 36px;
display: grid;
place-items: center;
border: 0;
border-radius: 0;
background: transparent;
color: #334155;
font-size: 13px;
font-weight: 750;
white-space: nowrap;
padding: 0 20px;
transition: background 120ms ease, color 120ms ease;
}
.page-size-dropdown button:hover {
background: #f0fdf4;
color: #059669;
}
.page-size-dropdown button.active {
background: #059669;
color: #fff;
}
.preview-column {
@@ -640,4 +719,15 @@ th {
.list-foot {
grid-template-columns: 1fr;
}
.list-foot {
gap: 12px;
justify-items: stretch;
}
.pager,
.page-size-wrap,
.page-size {
justify-self: stretch;
}
}

View File

@@ -27,26 +27,8 @@ const authIdleTimeoutMs =
? authIdleTimeoutMinutes * 60 * 1000
: 30 * 60 * 1000
function resolveBrowserApiBaseUrl(state) {
const server = state?.server || {}
const configuredHost = String(server.host || '127.0.0.1').trim()
const port = Number(server.port || 8000)
const apiPrefix = String(import.meta.env.VITE_API_BASE_PREFIX || '/api/v1').replace(/\/$/, '') || '/api/v1'
if (typeof window === 'undefined') {
return `http://${configuredHost}:${port}${apiPrefix}`
}
const browserHost = window.location.hostname
const normalizedHost = configuredHost.toLowerCase()
const host =
normalizedHost === '0.0.0.0' ||
normalizedHost === '::' ||
(normalizedHost === '127.0.0.1' && browserHost && browserHost !== '127.0.0.1' && browserHost !== 'localhost')
? browserHost
: configuredHost
return `http://${host}:${port}${apiPrefix}`
function resolveBrowserApiBaseUrl() {
return '/api/v1'
}
let sessionRouter = null

View File

@@ -39,9 +39,11 @@ function readStoredApiBaseUrl() {
return resolveBrowserReachableApiBaseUrl(window.localStorage.getItem(API_BASE_STORAGE_KEY) || '')
}
let runtimeApiBaseUrl = resolveBrowserReachableApiBaseUrl(
readStoredApiBaseUrl() || import.meta.env.VITE_API_BASE_URL || '/api/v1'
)
let runtimeApiBaseUrl = normalizeApiBaseUrl('/api/v1')
if (typeof window !== 'undefined') {
window.localStorage.removeItem(API_BASE_STORAGE_KEY)
}
export function setRuntimeApiBaseUrl(value) {
runtimeApiBaseUrl = resolveBrowserReachableApiBaseUrl(value)

View File

@@ -63,7 +63,7 @@
</thead>
<tbody>
<tr
v-for="doc in filteredDocuments"
v-for="doc in visibleDocuments"
:key="doc.name"
class="doc-row"
:class="{ selected: selectedDocument?.name === doc.name }"
@@ -93,6 +93,7 @@
</div>
<footer class="list-foot">
<template v-if="false">
<span> {{ filteredDocuments.length }} </span>
<button type="button">10/ <i class="mdi mdi-chevron-down"></i></button>
<div class="pager" aria-label="分页">
@@ -102,6 +103,45 @@
<button type="button" aria-label="下一页"><i class="mdi mdi-chevron-right"></i></button>
</div>
<label>前往 <input value="1" aria-label="页码" /> </label>
</template>
<span class="page-summary"> {{ totalCount }} 目前第 {{ currentPage }} </span>
<div class="pager" aria-label="分页">
<button class="page-nav" type="button" :disabled="currentPage === 1" aria-label="上一页" @click="currentPage--">
<i class="mdi mdi-chevron-left"></i>
</button>
<button
v-for="page in totalPages"
:key="page"
class="page-number"
:class="{ active: currentPage === page }"
type="button"
:aria-current="currentPage === page ? 'page' : undefined"
@click="currentPage = page"
>
{{ page }}
</button>
<button class="page-nav" type="button" :disabled="currentPage === totalPages" aria-label="下一页" @click="currentPage++">
<i class="mdi mdi-chevron-right"></i>
</button>
</div>
<div class="page-size-wrap">
<button class="page-size" type="button" @click="pageSizeOpen = !pageSizeOpen">
{{ pageSize }} /<i class="mdi mdi-chevron-down"></i>
</button>
<div v-if="pageSizeOpen" class="page-size-dropdown" role="listbox">
<button
v-for="size in pageSizes"
:key="size"
type="button"
role="option"
:aria-selected="pageSize === size"
:class="{ active: pageSize === size }"
@click="changePageSize(size)"
>
{{ size }} /
</button>
</div>
</div>
</footer>
</section>
</div>

View File

@@ -1,5 +1,7 @@
import { computed, ref } from 'vue'
import { watch } from 'vue'
export default {
name: 'PoliciesView' ,
setup(props, { emit }) {
@@ -230,6 +232,30 @@ export default {
})
)
const currentPage = ref(1)
const pageSize = ref(10)
const pageSizes = [10, 20, 50]
const pageSizeOpen = ref(false)
const totalCount = computed(() => filteredDocuments.value.length)
const totalPages = computed(() => Math.max(1, Math.ceil(totalCount.value / pageSize.value)))
const visibleDocuments = computed(() => {
const start = (currentPage.value - 1) * pageSize.value
return filteredDocuments.value.slice(start, start + pageSize.value)
})
function changePageSize(size) {
pageSize.value = size
pageSizeOpen.value = false
currentPage.value = 1
}
watch(filteredDocuments, () => {
currentPage.value = 1
pageSizeOpen.value = false
})
return {
folderSearch,
activeFolder,
@@ -237,7 +263,15 @@ export default {
folders,
documents,
filteredFolders,
filteredDocuments
filteredDocuments,
currentPage,
pageSize,
pageSizes,
pageSizeOpen,
totalCount,
totalPages,
visibleDocuments,
changePageSize
}
}
}