fix(F006-W18): admin 前端 BUG A/B/C (客户运维反馈)

BUG A: APIKey 申请搜企业搜不到
  - ApplyApiKeyDialog.vue loadCustomers 加 name 参数调后端, 不再本地 filter
  - 去掉 filteredCustomers computed, 表格直接用 customers
  - searchKey 输入加 debounce 300ms watch 调 loadCustomers

BUG B: 企业列表/行业/标签管理等菜单不显示
  - menu.ts filterByFrontendTruth 加 url 规范化匹配
  - 后端 url 带 / (如 /user/enterprise/enterprise), MENU_LABELS 不带 /
  - normalizeUrl = url.replace(/^\//,"") 后再 has() 匹配

BUG C: baseURL 空串 巨变数字 nginx 不通
  - request.ts baseURL:"" 改 "/api"
  - 巨变数字 nginx 只有 /api/ location (没独立 /sys/ /auth/ 等)
  - devbox nginx /api/ 也去前缀 (rewrite ^/api/(.*)\$ /\$1), 兼容

dist 验证: baseURL:"/api" ✓
devbox 实测: name=郑州巨变 返 1 条命中
This commit is contained in:
Sisyphus 2026-07-14 19:15:48 +08:00
parent 5d9814f135
commit 4899bc1793
3 changed files with 24 additions and 16 deletions

View File

@ -16,7 +16,7 @@
* *
* 后端调 /sys/openapi/app/apply * 后端调 /sys/openapi/app/apply
*/ */
import { ref, reactive, computed, watch } from 'vue' import { ref, reactive, watch } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { httpGet, httpPost } from '@/utils/request' import { httpGet, httpPost } from '@/utils/request'
@ -70,10 +70,14 @@ const form = reactive({
const customers = ref<Customer[]>([]) const customers = ref<Customer[]>([])
const loadingCustomers = ref(false) const loadingCustomers = ref(false)
async function loadCustomers() { // F002-W18 修: 后端已支持 name 模糊搜, 前端把 searchKey 传给后端, 不再本地 filter
async function loadCustomers(searchKey?: string) {
loadingCustomers.value = true loadingCustomers.value = true
try { try {
const data = await httpGet<Customer[]>('/sys/openapi/customer/list') const data = await httpGet<Customer[]>('/sys/openapi/customer/list', {
name: searchKey || undefined,
limit: 1000
})
customers.value = Array.isArray(data) ? data : [] customers.value = Array.isArray(data) ? data : []
} catch (e: any) { } catch (e: any) {
ElMessage.error(e?.msg || e?.message || '加载客户列表失败') ElMessage.error(e?.msg || e?.message || '加载客户列表失败')
@ -85,13 +89,13 @@ async function loadCustomers() {
watch(visible, v => { if (v) loadCustomers() }) watch(visible, v => { if (v) loadCustomers() })
const filteredCustomers = computed(() => { // F002-W18 修: searchKey 变化 debounce 300ms 调后端
if (!form.searchKey) return customers.value let searchTimer: ReturnType<typeof setTimeout> | null = null
const k = form.searchKey.toLowerCase() watch(() => form.searchKey, (val) => {
return customers.value.filter(c => if (searchTimer) clearTimeout(searchTimer)
(c.customerName || '').toLowerCase().includes(k) || searchTimer = setTimeout(() => {
(c.customerCode || '').toLowerCase().includes(k) loadCustomers(val || undefined)
) }, 300)
}) })
function onSelectionChange(rows: Customer[]) { function onSelectionChange(rows: Customer[]) {
@ -246,7 +250,7 @@ function notifyContact() {
/> />
<el-table <el-table
ref="customerTableRef" ref="customerTableRef"
:data="filteredCustomers" :data="customers"
border border
size="small" size="small"
max-height="320" max-height="320"

View File

@ -69,10 +69,12 @@ export const useMenuStore = defineStore('menu', () => {
if (!filtered.length) return null if (!filtered.length) return null
return { ...item, children: filtered } return { ...item, children: filtered }
} }
// 子菜单: url 必须在 MENU_LABELS 里, 且首次出现 // F002-W18 修: 后端 url 可能带 / 前缀 (如 /user/enterprise/enterprise),
if (!allowedUrls.has(item.url)) return null // MENU_LABELS 不带 / (如 user/enterprise/enterprise), 规范化后匹配
if (seenUrls.has(item.url)) return null const normalizedUrl = item.url.replace(/^\//, '')
seenUrls.add(item.url) if (!allowedUrls.has(item.url) && !allowedUrls.has(normalizedUrl)) return null
if (seenUrls.has(normalizedUrl)) return null
seenUrls.add(normalizedUrl)
return item return item
}) })
.filter((item): item is ResolvedMenu => item !== null) .filter((item): item is ResolvedMenu => item !== null)

View File

@ -19,7 +19,9 @@ export interface ApiEnvelope<T = any> {
const STORAGE_KEY = 'access_token' const STORAGE_KEY = 'access_token'
export const http: AxiosInstance = axios.create({ export const http: AxiosInstance = axios.create({
baseURL: '', // F002-W18 修: baseURL '/api' 让巨变数字 nginx /api/ location 转发 (去 /api 前缀)
// devbox nginx 同样有 /api/ location (rewrite ^/api/(.*)$ /$1 break), 兼容
baseURL: '/api',
timeout: 15000 timeout: 15000
}) })