fix: 企业切换数据同步(8/10页面+shared组件)
This commit is contained in:
@@ -375,7 +375,8 @@ function openCreate() {
|
|||||||
function loadData() {
|
function loadData() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
kpis.value = []
|
kpis.value = []
|
||||||
api.get('/kpis', { params: { dimension: props.dimension, page_size: 100 } })
|
const eid = Number(localStorage.getItem('cma_entity_id') || 1)
|
||||||
|
api.get('/kpis', { params: { dimension: props.dimension, page_size: 100, entity_id: eid } })
|
||||||
.then((r: any) => {
|
.then((r: any) => {
|
||||||
kpis.value = (r.data || []).map((k: any) => ({
|
kpis.value = (r.data || []).map((k: any) => ({
|
||||||
...k,
|
...k,
|
||||||
|
|||||||
@@ -437,6 +437,10 @@ import DriverFactorBudget from '../components/DriverFactorBudget.vue'
|
|||||||
const activeTab = ref('input')
|
const activeTab = ref('input')
|
||||||
const currentYear = new Date().getFullYear()
|
const currentYear = new Date().getFullYear()
|
||||||
const currentMonth = new Date().getMonth() + 1
|
const currentMonth = new Date().getMonth() + 1
|
||||||
|
|
||||||
|
function getEntityId() {
|
||||||
|
return Number(localStorage.getItem('cma_entity_id') || 1)
|
||||||
|
}
|
||||||
const yearOptions = computed(() => { const y: number[] = []; for (let i = currentYear - 2; i <= currentYear + 2; i++) y.push(i); return y })
|
const yearOptions = computed(() => { const y: number[] = []; for (let i = currentYear - 2; i <= currentYear + 2; i++) y.push(i); return y })
|
||||||
const filterYear = ref(currentYear); const filterMonth = ref(0); const searchKpi = ref('')
|
const filterYear = ref(currentYear); const filterMonth = ref(0); const searchKpi = ref('')
|
||||||
const loading = ref(false); const budgetList = ref<any[]>([]); const page = ref(1); const pageSize = ref(20); const total = ref(0); const noMap = ref(false)
|
const loading = ref(false); const budgetList = ref<any[]>([]); const page = ref(1); const pageSize = ref(20); const total = ref(0); const noMap = ref(false)
|
||||||
@@ -494,7 +498,7 @@ const addForm = ref({ kpi_id: null as any, year: currentYear, month: new Date().
|
|||||||
const addKpiOptions = ref<any[]>([]); const addKpiLoading = ref(false); const addSaving = ref(false)
|
const addKpiOptions = ref<any[]>([]); const addKpiLoading = ref(false); const addSaving = ref(false)
|
||||||
async function searchKpiForAdd(query: string) {
|
async function searchKpiForAdd(query: string) {
|
||||||
addKpiLoading.value = true
|
addKpiLoading.value = true
|
||||||
try { const r: any = await kpiApi.list({ keyword: query, page_size: 20 }); const d = r.data || r || []; addKpiOptions.value = Array.isArray(d) ? d : (d.items || []) } catch { }
|
try { const r: any = await kpiApi.list({ keyword: query, page_size: 20, entity_id: getEntityId() }); const d = r.data || r || []; addKpiOptions.value = Array.isArray(d) ? d : (d.items || []) } catch { }
|
||||||
addKpiLoading.value = false
|
addKpiLoading.value = false
|
||||||
}
|
}
|
||||||
async function doAddBudget() {
|
async function doAddBudget() {
|
||||||
@@ -516,11 +520,11 @@ async function loadBudget() {
|
|||||||
if (mapCodes.size === 0) { budgetList.value = []; total.value = 0; return }
|
if (mapCodes.size === 0) { budgetList.value = []; total.value = 0; return }
|
||||||
noMap.value = false; loading.value = true
|
noMap.value = false; loading.value = true
|
||||||
try {
|
try {
|
||||||
const params: any = { page: page.value, page_size: pageSize.value }; if (filterYear.value) params.year = filterYear.value; if (filterMonth.value > 0) params.budget_month = filterMonth.value; if (searchKpi.value) params.keyword = searchKpi.value
|
const params: any = { page: page.value, page_size: pageSize.value, entity_id: getEntityId() }; if (filterYear.value) params.year = filterYear.value; if (filterMonth.value > 0) params.budget_month = filterMonth.value; if (searchKpi.value) params.keyword = searchKpi.value
|
||||||
const r: any = await budgetApi.list(params); const d = r.data || r || []; const allPlans = (Array.isArray(d) ? d : (d.items || [])) as any[]
|
const r: any = await budgetApi.list(params); const d = r.data || r || []; const allPlans = (Array.isArray(d) ? d : (d.items || [])) as any[]
|
||||||
// 只保留选中地图关联KPI的预算记录
|
// 只保留选中地图关联KPI的预算记录
|
||||||
const plans = allPlans.filter((p: any) => mapCodes.has(p.kpi_code))
|
const plans = allPlans.filter((p: any) => mapCodes.has(p.kpi_code))
|
||||||
const kr: any = await kpiApi.list({ page_size: 100, keyword: searchKpi.value || undefined }); const kd = kr.data || kr || []; const ak = Array.isArray(kd) ? kd : (kd.items || [])
|
const kr: any = await kpiApi.list({ page_size: 100, keyword: searchKpi.value || undefined, entity_id: getEntityId() }); const kd = kr.data || kr || []; const ak = Array.isArray(kd) ? kd : (kd.items || [])
|
||||||
const mk = ak.filter((k: any) => mapCodes.has(k.kpi_code)); const pk = new Set(plans.map((p: any) => p.kpi_code))
|
const mk = ak.filter((k: any) => mapCodes.has(k.kpi_code)); const pk = new Set(plans.map((p: any) => p.kpi_code))
|
||||||
const ek = mk.filter((k: any) => !pk.has(k.kpi_code)).map((k: any) => ({ kpi_id: k.id, kpi_code: k.kpi_code, kpi_name: k.kpi_name, dimension: k.dimension, unit: k.unit || '', period: `${filterYear.value || currentYear}-${String(filterMonth.value || 1).padStart(2, '0')}`, budget_value: null, version: 'v1.0', status: '', precision: 0, step: 1 }))
|
const ek = mk.filter((k: any) => !pk.has(k.kpi_code)).map((k: any) => ({ kpi_id: k.id, kpi_code: k.kpi_code, kpi_name: k.kpi_name, dimension: k.dimension, unit: k.unit || '', period: `${filterYear.value || currentYear}-${String(filterMonth.value || 1).padStart(2, '0')}`, budget_value: null, version: 'v1.0', status: '', precision: 0, step: 1 }))
|
||||||
budgetList.value = [...plans.map((item: any) => initRow({ ...item, _empty: false })), ...ek.map(item => initRow({ ...item, _empty: true }))]
|
budgetList.value = [...plans.map((item: any) => initRow({ ...item, _empty: false })), ...ek.map(item => initRow({ ...item, _empty: true }))]
|
||||||
@@ -596,9 +600,9 @@ const strategyTree = ref<any[]>([]); const strategyFilterYear = ref(currentYear)
|
|||||||
|
|
||||||
async function loadStrategyBudget() {
|
async function loadStrategyBudget() {
|
||||||
if (!selectedMap.value) return
|
if (!selectedMap.value) return
|
||||||
try { const p: any = { budget_year: strategyFilterYear.value }; if (strategyFilterMonth.value > 0) p.budget_month = strategyFilterMonth.value; const r: any = await budgetApi.list(p); const d = r.data || r || []; const plans = (Array.isArray(d) ? d : (d.items || [])) as any[]; strategyAllBudgetPlans.value = plans
|
try { const p: any = { budget_year: strategyFilterYear.value, entity_id: getEntityId() }; if (strategyFilterMonth.value > 0) p.budget_month = strategyFilterMonth.value; const r: any = await budgetApi.list(p); const d = r.data || r || []; const plans = (Array.isArray(d) ? d : (d.items || [])) as any[]; strategyAllBudgetPlans.value = plans
|
||||||
let dims = selectedMap.value.dimensions; if (typeof dims === 'string') { try { dims = JSON.parse(dims) } catch { dims = [] } }; if (!Array.isArray(dims) || dims.length === 0) { strategyTree.value = []; return }
|
let dims = selectedMap.value.dimensions; if (typeof dims === 'string') { try { dims = JSON.parse(dims) } catch { dims = [] } }; if (!Array.isArray(dims) || dims.length === 0) { strategyTree.value = []; return }
|
||||||
const kr: any = await kpiApi.list({ page_size: 100 }); const kd = kr.data || kr || []; const km = new Map<string, any>(); (Array.isArray(kd) ? kd : (kd.items || [])).forEach((k: any) => km.set(k.kpi_code, k))
|
const kr: any = await kpiApi.list({ page_size: 100, entity_id: getEntityId() }); const kd = kr.data || kr || []; const km = new Map<string, any>(); (Array.isArray(kd) ? kd : (kd.items || [])).forEach((k: any) => km.set(k.kpi_code, k))
|
||||||
const tree: any[] = []
|
const tree: any[] = []
|
||||||
for (const dim of dims) { const dt = { budget: 0, kpiCount: 0 }; const objs = (dim.objectives || []).map((obj: any) => { const kpis = (obj.kpis || []).map((code: string) => { const kpi = km.get(code); const plan = plans.find((p: any) => p.kpi_code === code); const bv = plan ? plan.budget_value : null; dt.kpiCount++; if (bv) dt.budget += bv; return { kpi_code: code, kpi_id: kpi?.id || null, kpi_name: kpi?.kpi_name || code, unit: kpi?.unit || '', precision: kpi?.precision || 0, step: kpi?.step || 1, dimension: dim.key, period: plan?.period || `${strategyFilterYear.value}-${String(strategyFilterMonth.value || 1).padStart(2, '0')}`, version: plan?.version || 'v1.0', budget_value: bv, plan_id: plan?.id || null, _editValue: bv ?? 0, _changed: false, _saving: false, _dimKey: dim.key } }).filter(Boolean); return { name: obj.name, kpis } }); tree.push({ key: dim.key, name: dim.name, icon: dim.icon, color: dim.color, kpiCount: dt.kpiCount, totalBudget: dt.budget, objectives: objs }) }
|
for (const dim of dims) { const dt = { budget: 0, kpiCount: 0 }; const objs = (dim.objectives || []).map((obj: any) => { const kpis = (obj.kpis || []).map((code: string) => { const kpi = km.get(code); const plan = plans.find((p: any) => p.kpi_code === code); const bv = plan ? plan.budget_value : null; dt.kpiCount++; if (bv) dt.budget += bv; return { kpi_code: code, kpi_id: kpi?.id || null, kpi_name: kpi?.kpi_name || code, unit: kpi?.unit || '', precision: kpi?.precision || 0, step: kpi?.step || 1, dimension: dim.key, period: plan?.period || `${strategyFilterYear.value}-${String(strategyFilterMonth.value || 1).padStart(2, '0')}`, version: plan?.version || 'v1.0', budget_value: bv, plan_id: plan?.id || null, _editValue: bv ?? 0, _changed: false, _saving: false, _dimKey: dim.key } }).filter(Boolean); return { name: obj.name, kpis } }); tree.push({ key: dim.key, name: dim.name, icon: dim.icon, color: dim.color, kpiCount: dt.kpiCount, totalBudget: dt.budget, objectives: objs }) }
|
||||||
strategyTree.value = tree
|
strategyTree.value = tree
|
||||||
@@ -625,20 +629,20 @@ async function approveVersion(row: any, action: string) { const l = action === '
|
|||||||
async function resubmitVersion(row: any) { try { await ElMessageBox.confirm(`确认重新提交版本「${row.version}」?`, '确认'); await budgetApi.versionSubmit({ version: row.version }); ElMessage.success('已重新提交'); loadVersions() } catch { } }
|
async function resubmitVersion(row: any) { try { await ElMessageBox.confirm(`确认重新提交版本「${row.version}」?`, '确认'); await budgetApi.versionSubmit({ version: row.version }); ElMessage.success('已重新提交'); loadVersions() } catch { } }
|
||||||
|
|
||||||
const versionYear = ref(currentYear); const versionsList = ref<any[]>([]); const versionsLoading = ref(false); const selectedVersions = ref<any[]>([]); const showVersionDiff = ref(false); const diffLoading = ref(false); const diffData = ref<any>(null); const currentVersion = ref('')
|
const versionYear = ref(currentYear); const versionsList = ref<any[]>([]); const versionsLoading = ref(false); const selectedVersions = ref<any[]>([]); const showVersionDiff = ref(false); const diffLoading = ref(false); const diffData = ref<any>(null); const currentVersion = ref('')
|
||||||
async function loadVersions() { versionsLoading.value = true; try { const r: any = await budgetApi.versions({ year: versionYear.value }); const d = r.data || []; versionsList.value = d.map((v: any) => ({ ...v, _selected: false })); currentVersion.value = d[0]?.version || '' } catch (e) { ElMessage.error('加载版本列表失败') }; versionsLoading.value = false }
|
async function loadVersions() { versionsLoading.value = true; try { const r: any = await budgetApi.versions({ year: versionYear.value, entity_id: getEntityId() }); const d = r.data || []; versionsList.value = d.map((v: any) => ({ ...v, _selected: false })); currentVersion.value = d[0]?.version || '' } catch (e) { ElMessage.error('加载版本列表失败') }; versionsLoading.value = false }
|
||||||
function onVersionSelect(row: any) { selectedVersions.value = versionsList.value.filter((v: any) => v._selected); if (selectedVersions.value.length > 2) { row._selected = false; selectedVersions.value = versionsList.value.filter((v: any) => v._selected) } }
|
function onVersionSelect(row: any) { selectedVersions.value = versionsList.value.filter((v: any) => v._selected); if (selectedVersions.value.length > 2) { row._selected = false; selectedVersions.value = versionsList.value.filter((v: any) => v._selected) } }
|
||||||
async function loadVersionDiff() { if (selectedVersions.value.length !== 2) return; diffLoading.value = true; try { const [a, b] = selectedVersions.value; const r: any = await budgetApi.versionDiff({ version_a: a.version, version_b: b.version, year: versionYear.value }); diffData.value = r; showVersionDiff.value = true } catch (e) { ElMessage.error('加载版本对比失败') }; diffLoading.value = false }
|
async function loadVersionDiff() { if (selectedVersions.value.length !== 2) return; diffLoading.value = true; try { const [a, b] = selectedVersions.value; const r: any = await budgetApi.versionDiff({ version_a: a.version, version_b: b.version, year: versionYear.value }); diffData.value = r; showVersionDiff.value = true } catch (e) { ElMessage.error('加载版本对比失败') }; diffLoading.value = false }
|
||||||
|
|
||||||
const execFilterYear = ref(currentYear); const execFilterMonth = ref(new Date().getMonth()); const execFilterDim = ref(''); const execLoading = ref(false); const execReport = ref<any[]>([]); const execSummaryCards = ref<any[]>([])
|
const execFilterYear = ref(currentYear); const execFilterMonth = ref(new Date().getMonth()); const execFilterDim = ref(''); const execLoading = ref(false); const execReport = ref<any[]>([]); const execSummaryCards = ref<any[]>([])
|
||||||
async function loadExecutionReport() {
|
async function loadExecutionReport() {
|
||||||
execLoading.value = true
|
execLoading.value = true
|
||||||
try { const r: any = await budgetApi.deviationReport({ year: execFilterYear.value, month: execFilterMonth.value, dimension: execFilterDim.value || undefined, hierarchical: true }); const items: any[] = r.items || []; const en = items.map((i: any) => ({ ...i, execution_rate: i.budget_value && i.budget_value > 0 ? Math.round((i.actual_value || 0) / i.budget_value * 100) : 0, deviation_value: (i.actual_value || 0) - (i.budget_value || 0) })); execReport.value = en; const hb = en.filter((i: any) => i.budget_value != null); const ob = en.filter((i: any) => i.is_over_budget); const ar = hb.length > 0 ? Math.round(hb.reduce((s, i) => s + (i.execution_rate || 0), 0) / hb.length) : 0; const tb = hb.reduce((s, i) => s + (i.budget_value || 0), 0); const ta = hb.reduce((s, i) => s + (i.actual_value || 0), 0); execSummaryCards.value = [{ label: '有预算KPI', value: `${hb.length}/${en.length}`, color: '#409eff' }, { label: '超预算KPI', value: ob.length.toString(), color: '#f56c6c' }, { label: '平均执行率', value: `${ar}%`, color: ar > 100 ? '#f56c6c' : '#67c23a' }, { label: '预算执行进度', value: tb > 0 ? `${Math.round(ta / tb * 100)}%` : '-', color: '#e6a23c' }] } catch (e) { ElMessage.error('加载执行报告失败') }
|
try { const r: any = await budgetApi.deviationReport({ year: execFilterYear.value, month: execFilterMonth.value, dimension: execFilterDim.value || undefined, hierarchical: true, entity_id: getEntityId() }); const items: any[] = r.items || []; const en = items.map((i: any) => ({ ...i, execution_rate: i.budget_value && i.budget_value > 0 ? Math.round((i.actual_value || 0) / i.budget_value * 100) : 0, deviation_value: (i.actual_value || 0) - (i.budget_value || 0) })); execReport.value = en; const hb = en.filter((i: any) => i.budget_value != null); const ob = en.filter((i: any) => i.is_over_budget); const ar = hb.length > 0 ? Math.round(hb.reduce((s, i) => s + (i.execution_rate || 0), 0) / hb.length) : 0; const tb = hb.reduce((s, i) => s + (i.budget_value || 0), 0); const ta = hb.reduce((s, i) => s + (i.actual_value || 0), 0); execSummaryCards.value = [{ label: '有预算KPI', value: `${hb.length}/${en.length}`, color: '#409eff' }, { label: '超预算KPI', value: ob.length.toString(), color: '#f56c6c' }, { label: '平均执行率', value: `${ar}%`, color: ar > 100 ? '#f56c6c' : '#67c23a' }, { label: '预算执行进度', value: tb > 0 ? `${Math.round(ta / tb * 100)}%` : '-', color: '#e6a23c' }] } catch (e) { ElMessage.error('加载执行报告失败') }
|
||||||
execLoading.value = false
|
execLoading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
async function doDecompose() {
|
async function doDecompose() {
|
||||||
decomposing.value = true; decomposeResult.value = ''; decomposeDetails.value = []
|
decomposing.value = true; decomposeResult.value = ''; decomposeDetails.value = []
|
||||||
try { const r: any = await budgetApi.autoDecompose({ year: decomposeForm.value.year, method: decomposeForm.value.method }); decomposeResult.value = r.message || '分解成功'; if (r.results) decomposeDetails.value = r.results.map((res: any) => ({ kpi_code: res.kpi_code, kpi_name: res.kpi_name, annual_budget: res.annual_budget, method: res.method === 'equal' ? '均分' : '加权', monthly_count: res.monthly.length })); ElMessage.success('年度预算分解完成'); loadBudget() } catch (e: any) { ElMessage.error(e.detail || e.message || '分解失败') }
|
try { const r: any = await budgetApi.autoDecompose({ year: decomposeForm.value.year, method: decomposeForm.value.method, entity_id: getEntityId() }); decomposeResult.value = r.message || '分解成功'; if (r.results) decomposeDetails.value = r.results.map((res: any) => ({ kpi_code: res.kpi_code, kpi_name: res.kpi_name, annual_budget: res.annual_budget, method: res.method === 'equal' ? '均分' : '加权', monthly_count: res.monthly.length })); ElMessage.success('年度预算分解完成'); loadBudget() } catch (e: any) { ElMessage.error(e.detail || e.message || '分解失败') }
|
||||||
decomposing.value = false
|
decomposing.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,7 +661,7 @@ function loadMethodDetail(id: string) {
|
|||||||
|
|
||||||
async function refreshMethodComparison() {
|
async function refreshMethodComparison() {
|
||||||
try {
|
try {
|
||||||
const r: any = await budgetApi.methodComparison({ entity: 'hanke' })
|
const r: any = await budgetApi.methodComparison({ entity: 'hanke', entity_id: getEntityId() })
|
||||||
budgetMethods.value = r.methods || []
|
budgetMethods.value = r.methods || []
|
||||||
selectedMethod.value = r.recommended || 'zero_based'
|
selectedMethod.value = r.recommended || 'zero_based'
|
||||||
loadMethodDetail(selectedMethod.value)
|
loadMethodDetail(selectedMethod.value)
|
||||||
@@ -721,7 +725,7 @@ let comparisonChart: any = null
|
|||||||
|
|
||||||
async function loadComparisonKpiOptions() {
|
async function loadComparisonKpiOptions() {
|
||||||
try {
|
try {
|
||||||
const r: any = await kpiApi.list({ page_size: 200 })
|
const r: any = await kpiApi.list({ page_size: 200, entity_id: getEntityId() })
|
||||||
const d = r.data || r || []
|
const d = r.data || r || []
|
||||||
comparisonKpiOptions.value = Array.isArray(d) ? d : (d.items || [])
|
comparisonKpiOptions.value = Array.isArray(d) ? d : (d.items || [])
|
||||||
} catch { comparisonKpiOptions.value = [] }
|
} catch { comparisonKpiOptions.value = [] }
|
||||||
@@ -730,7 +734,7 @@ async function loadComparisonKpiOptions() {
|
|||||||
async function loadComparison() {
|
async function loadComparison() {
|
||||||
comparisonLoading.value = true
|
comparisonLoading.value = true
|
||||||
try {
|
try {
|
||||||
const params: any = { year: comparisonYear.value }
|
const params: any = { year: comparisonYear.value, entity_id: getEntityId() }
|
||||||
if (comparisonKpiId.value) params.kpi_id = comparisonKpiId.value
|
if (comparisonKpiId.value) params.kpi_id = comparisonKpiId.value
|
||||||
const r: any = await budgetApi.getComparison(params)
|
const r: any = await budgetApi.getComparison(params)
|
||||||
comparisonData.value = r.months_data || []
|
comparisonData.value = r.months_data || []
|
||||||
@@ -846,7 +850,7 @@ const alertPeriodOptions = computed(() => {
|
|||||||
async function loadDeviationAlerts() {
|
async function loadDeviationAlerts() {
|
||||||
alertLoading.value = true
|
alertLoading.value = true
|
||||||
try {
|
try {
|
||||||
const params: any = {}
|
const params: any = { entity_id: getEntityId() }
|
||||||
if (alertFilterPeriod.value) params.period = alertFilterPeriod.value
|
if (alertFilterPeriod.value) params.period = alertFilterPeriod.value
|
||||||
if (alertFilterLevel.value) params.alert_level = alertFilterLevel.value
|
if (alertFilterLevel.value) params.alert_level = alertFilterLevel.value
|
||||||
if (alertFilterStatus.value) params.status = alertFilterStatus.value
|
if (alertFilterStatus.value) params.status = alertFilterStatus.value
|
||||||
@@ -863,6 +867,7 @@ async function doDeviationCheck() {
|
|||||||
const r: any = await budgetApi.deviationCheck({
|
const r: any = await budgetApi.deviationCheck({
|
||||||
period: alertFilterPeriod.value,
|
period: alertFilterPeriod.value,
|
||||||
threshold: 20,
|
threshold: 20,
|
||||||
|
entity_id: getEntityId(),
|
||||||
})
|
})
|
||||||
if (r.alerts_generated > 0) {
|
if (r.alerts_generated > 0) {
|
||||||
deviationAlertMessage.value = `偏差检查完成:生成了 ${r.alerts_generated} 条预警`
|
deviationAlertMessage.value = `偏差检查完成:生成了 ${r.alerts_generated} 条预警`
|
||||||
|
|||||||
@@ -390,9 +390,13 @@ const overviewData = ref<any>({})
|
|||||||
const productOptions = ref<string[]>([])
|
const productOptions = ref<string[]>([])
|
||||||
const maxTrend = ref(0)
|
const maxTrend = ref(0)
|
||||||
|
|
||||||
|
function getEntityId() {
|
||||||
|
return Number(localStorage.getItem('cma_entity_id') || 1)
|
||||||
|
}
|
||||||
|
|
||||||
async function loadOverview() {
|
async function loadOverview() {
|
||||||
try {
|
try {
|
||||||
const r: any = await costApi.dashboard({ period: overviewPeriod.value })
|
const r: any = await costApi.dashboard({ period: overviewPeriod.value, entity_id: getEntityId() })
|
||||||
overviewData.value = r.data || r
|
overviewData.value = r.data || r
|
||||||
// 提取产品列表
|
// 提取产品列表
|
||||||
const products = overviewData.value.products || []
|
const products = overviewData.value.products || []
|
||||||
@@ -423,7 +427,7 @@ const stdProductFilter = ref('')
|
|||||||
async function loadStandardCosts() {
|
async function loadStandardCosts() {
|
||||||
stdLoading.value = true
|
stdLoading.value = true
|
||||||
try {
|
try {
|
||||||
const params: any = {}
|
const params: any = { entity_id: getEntityId() }
|
||||||
if (stdProductFilter.value) params.product_code = stdProductFilter.value
|
if (stdProductFilter.value) params.product_code = stdProductFilter.value
|
||||||
const r: any = await costApi.listStandardCosts(params)
|
const r: any = await costApi.listStandardCosts(params)
|
||||||
standardCosts.value = r.data || []
|
standardCosts.value = r.data || []
|
||||||
@@ -474,7 +478,7 @@ const actualSaving = ref(false)
|
|||||||
async function loadActualCosts() {
|
async function loadActualCosts() {
|
||||||
actualLoading.value = true
|
actualLoading.value = true
|
||||||
try {
|
try {
|
||||||
const params: any = { period: entryPeriod.value }
|
const params: any = { period: entryPeriod.value, entity_id: getEntityId() }
|
||||||
const r: any = await costApi.listActualCosts(params)
|
const r: any = await costApi.listActualCosts(params)
|
||||||
actualCosts.value = r.data || []
|
actualCosts.value = r.data || []
|
||||||
} catch (e) { ElMessage.error('加载实际成本失败') }
|
} catch (e) { ElMessage.error('加载实际成本失败') }
|
||||||
@@ -555,7 +559,7 @@ const allocSaving = ref(false)
|
|||||||
async function loadAllocations() {
|
async function loadAllocations() {
|
||||||
allocLoading.value = true
|
allocLoading.value = true
|
||||||
try {
|
try {
|
||||||
const r: any = await costApi.listAbcAllocations({ period: allocPeriod.value })
|
const r: any = await costApi.listAbcAllocations({ period: allocPeriod.value, entity_id: getEntityId() })
|
||||||
abcAllocations.value = r.data || []
|
abcAllocations.value = r.data || []
|
||||||
} catch (e) { /* ignore */ }
|
} catch (e) { /* ignore */ }
|
||||||
allocLoading.value = false
|
allocLoading.value = false
|
||||||
@@ -652,7 +656,7 @@ const compInsights = computed(() => compData.value.insights || [])
|
|||||||
async function loadComparison() {
|
async function loadComparison() {
|
||||||
compLoading.value = true
|
compLoading.value = true
|
||||||
try {
|
try {
|
||||||
const r: any = await costApi.comparison({ entity: compEntity.value })
|
const r: any = await costApi.comparison({ entity: compEntity.value, entity_id: getEntityId() })
|
||||||
compData.value = r.data || r
|
compData.value = r.data || r
|
||||||
} catch (e) { ElMessage.error('加载对比数据失败') }
|
} catch (e) { ElMessage.error('加载对比数据失败') }
|
||||||
compLoading.value = false
|
compLoading.value = false
|
||||||
|
|||||||
@@ -69,8 +69,9 @@ async function loadTrend() {
|
|||||||
// 从 KPIListView 内部获取当前 kpis
|
// 从 KPIListView 内部获取当前 kpis
|
||||||
// 由于 KPIListView 内部数据不暴露,直接通过 API 请求客户维度的前5个KPI
|
// 由于 KPIListView 内部数据不暴露,直接通过 API 请求客户维度的前5个KPI
|
||||||
trendLoading.value = true
|
trendLoading.value = true
|
||||||
|
const eid = Number(localStorage.getItem('cma_entity_id') || 1)
|
||||||
try {
|
try {
|
||||||
const r: any = await api.get('/kpis', { params: { dimension: 'customer', page_size: 5 } })
|
const r: any = await api.get('/kpis', { params: { dimension: 'customer', page_size: 5, entity_id: eid } })
|
||||||
const kpis = (r.data || []).slice(0, 5)
|
const kpis = (r.data || []).slice(0, 5)
|
||||||
const kpiIds = kpis.map((k: any) => k.id).filter(Boolean)
|
const kpiIds = kpis.map((k: any) => k.id).filter(Boolean)
|
||||||
if (kpiIds.length === 0) { trendLoading.value = false; return }
|
if (kpiIds.length === 0) { trendLoading.value = false; return }
|
||||||
@@ -78,6 +79,7 @@ async function loadTrend() {
|
|||||||
kpi_ids: kpiIds,
|
kpi_ids: kpiIds,
|
||||||
dimension: 'customer',
|
dimension: 'customer',
|
||||||
period_type: trendType.value,
|
period_type: trendType.value,
|
||||||
|
entity_id: eid,
|
||||||
})
|
})
|
||||||
trendData.value = trendRes.data || []
|
trendData.value = trendRes.data || []
|
||||||
trendLoading.value = false
|
trendLoading.value = false
|
||||||
|
|||||||
@@ -408,13 +408,14 @@ function onCustomRangeChange(val: any) {
|
|||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
try {
|
try {
|
||||||
const params = getPeriodParams()
|
const entityId = Number(localStorage.getItem('cma_entity_id') || 1)
|
||||||
|
const params = { ...getPeriodParams(), entity_id: entityId }
|
||||||
if (userRole.value === 'ceo') {
|
if (userRole.value === 'ceo') {
|
||||||
const [kpiRes, alertRes, sumRes, predRes] = await Promise.all([
|
const [kpiRes, alertRes, sumRes, predRes] = await Promise.all([
|
||||||
dashboardApi.kpis({ role: 'ceo', ...params }),
|
dashboardApi.kpis({ role: 'ceo', ...params }),
|
||||||
alertApi.list({ limit: 10 }),
|
alertApi.list({ limit: 10, entity_id: entityId }),
|
||||||
dashboardApi.summary({ role: 'ceo', ...params }),
|
dashboardApi.summary({ role: 'ceo', ...params }),
|
||||||
dashboardApi.predict({}).catch(() => ({ data: [] })),
|
dashboardApi.predict({ entity_id: entityId }).catch(() => ({ data: [] })),
|
||||||
])
|
])
|
||||||
kpis.value = (kpiRes as any).data || []
|
kpis.value = (kpiRes as any).data || []
|
||||||
alerts.value = (alertRes as any).data?.filter((a: any) => a.status === 'pending') || []
|
alerts.value = (alertRes as any).data?.filter((a: any) => a.status === 'pending') || []
|
||||||
@@ -422,11 +423,11 @@ async function loadData() {
|
|||||||
predictions.value = (predRes as any)?.predictions || []
|
predictions.value = (predRes as any)?.predictions || []
|
||||||
dataRange.value = (kpiRes as any).range?.start + ' ~ ' + (kpiRes as any).range?.end
|
dataRange.value = (kpiRes as any).range?.start + ' ~ ' + (kpiRes as any).range?.end
|
||||||
} else if (userRole.value === 'business') {
|
} else if (userRole.value === 'business') {
|
||||||
const r: any = await dashboardApi.myKpis?.(params)
|
const r: any = await dashboardApi.myKpis?.({ ...params })
|
||||||
myKpis.value = (r as any)?.data || []
|
myKpis.value = (r as any)?.data || []
|
||||||
dataRange.value = (r as any)?.period || ''
|
dataRange.value = (r as any)?.period || ''
|
||||||
} else if (userRole.value === 'finance') {
|
} else if (userRole.value === 'finance') {
|
||||||
const r: any = await dashboardApi.financeAnalysis?.(params)
|
const r: any = await dashboardApi.financeAnalysis?.({ ...params })
|
||||||
finKpis.value = (r as any)?.kpis || []
|
finKpis.value = (r as any)?.kpis || []
|
||||||
finSummary.value = (r as any)?.summary || {}
|
finSummary.value = (r as any)?.summary || {}
|
||||||
dataRange.value = (r as any)?.period || ''
|
dataRange.value = (r as any)?.period || ''
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ function onRowClick(row: any) {
|
|||||||
async function loadReport() {
|
async function loadReport() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const params: any = { hierarchical: true }
|
const params: any = { hierarchical: true, entity_id: Number(localStorage.getItem('cma_entity_id') || 1) }
|
||||||
if (filterYear.value) params.year = filterYear.value
|
if (filterYear.value) params.year = filterYear.value
|
||||||
if (filterMonth.value) params.month = filterMonth.value
|
if (filterMonth.value) params.month = filterMonth.value
|
||||||
if (filterDimension.value) params.dimension = filterDimension.value
|
if (filterDimension.value) params.dimension = filterDimension.value
|
||||||
|
|||||||
@@ -374,8 +374,8 @@ const searchStatus = ref('active')
|
|||||||
|
|
||||||
// ── 企业选择 ──
|
// ── 企业选择 ──
|
||||||
const entities = ref<any[]>([])
|
const entities = ref<any[]>([])
|
||||||
const currentEntityId = ref(1)
|
const currentEntityId = ref(Number(localStorage.getItem('cma_entity_id') || 1))
|
||||||
const currentEntityName = ref('酣客')
|
const currentEntityName = ref(localStorage.getItem('cma_entity_name') || '酣客')
|
||||||
|
|
||||||
// ── 分类树 ──
|
// ── 分类树 ──
|
||||||
const categoryTree = ref<any[]>([])
|
const categoryTree = ref<any[]>([])
|
||||||
|
|||||||
@@ -374,6 +374,10 @@ const loading = ref(false)
|
|||||||
const activeTab = ref('profit')
|
const activeTab = ref('profit')
|
||||||
const reportPeriod = ref('2026-06')
|
const reportPeriod = ref('2026-06')
|
||||||
|
|
||||||
|
function getEntityId() {
|
||||||
|
return Number(localStorage.getItem('cma_entity_id') || 1)
|
||||||
|
}
|
||||||
|
|
||||||
// API 配置
|
// API 配置
|
||||||
const api = axios.create({ baseURL: '/api/cma', timeout: 30000 })
|
const api = axios.create({ baseURL: '/api/cma', timeout: 30000 })
|
||||||
api.interceptors.request.use((config: any) => {
|
api.interceptors.request.use((config: any) => {
|
||||||
@@ -411,7 +415,7 @@ async function loadNew30() {
|
|||||||
loadingNew30.value = true
|
loadingNew30.value = true
|
||||||
dualComparisonData.value = null
|
dualComparisonData.value = null
|
||||||
try {
|
try {
|
||||||
const params: any = { period: reportPeriod.value }
|
const params: any = { period: reportPeriod.value, entity_id: getEntityId() }
|
||||||
if (new30Format.value === 'dual') {
|
if (new30Format.value === 'dual') {
|
||||||
params.format = 'dual'
|
params.format = 'dual'
|
||||||
} else {
|
} else {
|
||||||
@@ -497,7 +501,7 @@ const restatementNetProfit = ref<any>(null)
|
|||||||
async function loadRestatement() {
|
async function loadRestatement() {
|
||||||
loadingRestatement.value = true
|
loadingRestatement.value = true
|
||||||
try {
|
try {
|
||||||
const r = await api.get('/reports/restatement', { params: { period: reportPeriod.value } })
|
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).data || {}
|
||||||
restatementItems.value = d.items || []
|
restatementItems.value = d.items || []
|
||||||
restatementSummary.value = d.summary || null
|
restatementSummary.value = d.summary || null
|
||||||
@@ -549,14 +553,14 @@ function onPeriodChange() {
|
|||||||
// ── 加载 ──
|
// ── 加载 ──
|
||||||
async function loadProfit() {
|
async function loadProfit() {
|
||||||
try {
|
try {
|
||||||
const r = await api.get('/reports/profit-summary', { params: { period: reportPeriod.value } })
|
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).data?.items || []
|
||||||
} catch { profitItems.value = [] }
|
} catch { profitItems.value = [] }
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadBudget() {
|
async function loadBudget() {
|
||||||
try {
|
try {
|
||||||
const params: any = { period: reportPeriod.value }
|
const params: any = { period: reportPeriod.value, entity_id: getEntityId() }
|
||||||
if (budgetDim.value) params.dimension = budgetDim.value
|
if (budgetDim.value) params.dimension = budgetDim.value
|
||||||
if (budgetLevel.value) params.alert_level = budgetLevel.value
|
if (budgetLevel.value) params.alert_level = budgetLevel.value
|
||||||
const r = await api.get('/reports/budget-execution', { params })
|
const r = await api.get('/reports/budget-execution', { params })
|
||||||
@@ -568,7 +572,7 @@ async function loadBudget() {
|
|||||||
|
|
||||||
async function loadTrends() {
|
async function loadTrends() {
|
||||||
try {
|
try {
|
||||||
const params: any = { months: trendMonths.value }
|
const params: any = { months: trendMonths.value, entity_id: getEntityId() }
|
||||||
if (trendKpiId.value) params.kpi_id = trendKpiId.value
|
if (trendKpiId.value) params.kpi_id = trendKpiId.value
|
||||||
else if (trendDim.value) params.dimension = trendDim.value
|
else if (trendDim.value) params.dimension = trendDim.value
|
||||||
const r = await api.get('/reports/kpi-trends', { params })
|
const r = await api.get('/reports/kpi-trends', { params })
|
||||||
@@ -579,14 +583,14 @@ async function loadTrends() {
|
|||||||
|
|
||||||
async function loadBsc() {
|
async function loadBsc() {
|
||||||
try {
|
try {
|
||||||
const r = await api.get('/reports/bsc-scorecard', { params: { period: reportPeriod.value } })
|
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).data || {}
|
||||||
} catch { bscData.value = {} }
|
} catch { bscData.value = {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadKpiOptions() {
|
async function loadKpiOptions() {
|
||||||
try {
|
try {
|
||||||
const r = await api.get('/kpis', { params: { page_size: 100 } })
|
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?.data || []
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user