refactor(cma-frontend): route all API calls through shared axios instance (cma-frontend-axios-unify-20260915)
api/index.ts: add permissionApi.getModules/getConfig/saveConfig + alignmentApi.config/tree. views: replace 13 raw fetch calls and 6 local axios.create instances (each hand-building the Authorization header, without the shared 401 redirect / timeout toast) with the shared instance from api/index.ts. KPIAlignment: fixes a live bug - the header value was the string literal 'Bearer ' + token, so /alignment/tree always returned 401 (reproduced against the production bundle). Unwrap semantics preserved: the shared response interceptor returns response.data, so call sites that used res.data were adjusted accordingly. Verified: scan-frontend-tokenless RAW-TOKENLESS=0; vite build ok; headless A/B (new dist vs production bundle, 8 affected pages, real login) -> identical rendered rows and identical pre-existing error profile, /alignment 401->200. Push not executed: main is ahead 4 with other tickets' gated commits (see cma-main-ahead3-push-gate-notice-20260915).
This commit is contained in:
@@ -619,7 +619,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import axios from 'axios'
|
||||
// 统一走 api/index.ts 的 axios 实例(拦截器自动带 Bearer / 统一 401 跳登录 / 超时提示)
|
||||
import api from '../api/index'
|
||||
import { getFixedEntityId } from '../utils/entity'
|
||||
|
||||
// ── 状态 ──
|
||||
@@ -644,13 +645,7 @@ function getEntityId() {
|
||||
return Number(localStorage.getItem('cma_entity_id') || currentEntityId.value || 1)
|
||||
}
|
||||
|
||||
// API 配置
|
||||
const api = axios.create({ baseURL: '/api/cma', timeout: 30000 })
|
||||
api.interceptors.request.use((config: any) => {
|
||||
const token = localStorage.getItem('cma_token')
|
||||
if (token) config.headers.Authorization = `Bearer ${token}`
|
||||
return config
|
||||
})
|
||||
// API 配置:统一使用 api/index.ts 的共享实例(本地 axios 实例 + 手拼 Bearer 已移除)
|
||||
|
||||
// ── 报表1:管理利润表 ──
|
||||
const profitItems = ref<any[]>([])
|
||||
@@ -688,7 +683,7 @@ async function loadNew30() {
|
||||
params.format = 'new'
|
||||
}
|
||||
const r = await api.get('/reports/profit-statement', { params })
|
||||
const d = (r as any).data || {}
|
||||
const d = (r as any) || {}
|
||||
|
||||
if (new30Format.value === 'dual') {
|
||||
dualComparisonData.value = d
|
||||
@@ -749,7 +744,7 @@ async function loadStatutory() {
|
||||
statutoryLoading.value = true
|
||||
try {
|
||||
const r = await api.get('/reports/statutory', { params: { period: reportPeriod.value, entity_id: getEntityId() } })
|
||||
const d = (r as any).data || {}
|
||||
const d = (r as any) || {}
|
||||
statutoryData.value = d
|
||||
statutoryDemoMode.value = !d.cash_flow?.all_items_have_data
|
||||
} catch (e) {
|
||||
@@ -762,11 +757,11 @@ async function loadStatutory() {
|
||||
async function exportStatutory() {
|
||||
exporting.value = true
|
||||
try {
|
||||
const token = localStorage.getItem('cma_token') || ''
|
||||
const url = `/api/cma/reports/statutory/export?period=${reportPeriod.value}&entity_id=${getEntityId()}`
|
||||
const resp = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } })
|
||||
if (!resp.ok) throw new Error('导出失败')
|
||||
const blob = await resp.blob()
|
||||
// 统一走 api 实例(responseType=blob;Bearer 由拦截器注入,非 2xx 直接 reject)
|
||||
const blob: any = await api.get('/reports/statutory/export', {
|
||||
params: { period: reportPeriod.value, entity_id: getEntityId() },
|
||||
responseType: 'blob',
|
||||
})
|
||||
const a = document.createElement('a')
|
||||
a.href = URL.createObjectURL(blob)
|
||||
a.download = `对外法定报表_${reportPeriod.value}.xlsx`
|
||||
@@ -811,7 +806,7 @@ async function loadRestatement() {
|
||||
loadingRestatement.value = true
|
||||
try {
|
||||
const r = await api.get('/reports/restatement', { params: { period: reportPeriod.value, entity_id: getEntityId() } })
|
||||
const d = (r as any).data || {}
|
||||
const d = (r as any) || {}
|
||||
restatementItems.value = d.items || []
|
||||
restatementSummary.value = d.summary || null
|
||||
restatementNetProfit.value = d.net_profit_comparison || null
|
||||
@@ -864,7 +859,7 @@ function onPeriodChange() {
|
||||
async function loadProfit() {
|
||||
try {
|
||||
const r = await api.get('/reports/profit-summary', { params: { period: reportPeriod.value, entity_id: getEntityId() } })
|
||||
profitItems.value = (r as any).data?.items || []
|
||||
profitItems.value = (r as any)?.items || []
|
||||
} catch { profitItems.value = [] }
|
||||
}
|
||||
|
||||
@@ -874,7 +869,7 @@ async function loadBudget() {
|
||||
if (budgetDim.value) params.dimension = budgetDim.value
|
||||
if (budgetLevel.value) params.alert_level = budgetLevel.value
|
||||
const r = await api.get('/reports/budget-execution', { params })
|
||||
const d = (r as any).data || {}
|
||||
const d = (r as any) || {}
|
||||
budgetSummary.value = d.summary || {}
|
||||
budgetItems.value = d.items || []
|
||||
} catch { budgetItems.value = [] }
|
||||
@@ -925,7 +920,7 @@ async function loadProforma() {
|
||||
cash: '/reports/proforma/cash-flow',
|
||||
}
|
||||
const r = await api.get(map[proformaType.value], { params: { period: reportPeriod.value, entity_id: getEntityId() } })
|
||||
proformaData.value = (r as any).data || {}
|
||||
proformaData.value = (r as any) || {}
|
||||
} catch (e) {
|
||||
proformaData.value = null
|
||||
ElMessage.error('加载预编报表失败')
|
||||
@@ -953,7 +948,7 @@ async function loadTrends() {
|
||||
if (trendKpiId.value) params.kpi_id = trendKpiId.value
|
||||
else if (trendDim.value) params.dimension = trendDim.value
|
||||
const r = await api.get('/reports/kpi-trends', { params })
|
||||
trendData.value = (r as any).data?.data || []
|
||||
trendData.value = (r as any)?.data || []
|
||||
nextTick(() => renderTrendCharts())
|
||||
} catch { trendData.value = [] }
|
||||
}
|
||||
@@ -961,14 +956,14 @@ async function loadTrends() {
|
||||
async function loadBsc() {
|
||||
try {
|
||||
const r = await api.get('/reports/bsc-scorecard', { params: { period: reportPeriod.value, entity_id: getEntityId() } })
|
||||
bscData.value = (r as any).data || {}
|
||||
bscData.value = (r as any) || {}
|
||||
} catch { bscData.value = {} }
|
||||
}
|
||||
|
||||
async function loadKpiOptions() {
|
||||
try {
|
||||
const r = await api.get('/kpis', { params: { page_size: 100, entity_id: getEntityId() } })
|
||||
kpiOptions.value = (r as any).data?.data || []
|
||||
kpiOptions.value = (r as any)?.data || []
|
||||
} catch {}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user