diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index a768f681..dbb586d0 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -1,10 +1,14 @@ import axios from 'axios' +import { ElMessage } from 'element-plus' const api = axios.create({ baseURL: '/api/cma', timeout: 15000, }) +// 网络层错误提示节流标记(3 秒内只弹一次) +let lastNetErrToast = 0 + api.interceptors.request.use((config) => { const token = localStorage.getItem('cma_token') if (token) config.headers.Authorization = `Bearer ${token}` @@ -19,6 +23,13 @@ api.interceptors.response.use( localStorage.removeItem('cma_token') localStorage.removeItem('cma_user') window.location.href = '/login' + } else if (error.code === 'ECONNABORTED' || !error.response) { + // BUG-001 兜底(2026-09-03):网络层失败(超时/断连)节流提示,避免并行请求重复弹窗 + const now = Date.now() + if (now - lastNetErrToast > 3000) { + lastNetErrToast = now + ElMessage.warning(error.code === 'ECONNABORTED' ? '请求超时,请稍后重试' : '网络异常,请检查连接后重试') + } } return Promise.reject(error) } diff --git a/frontend/src/views/BudgetManagement.vue.bak b/frontend/src/views/BudgetManagement.vue.bak deleted file mode 100644 index bb21bd4e..00000000 --- a/frontend/src/views/BudgetManagement.vue.bak +++ /dev/null @@ -1,475 +0,0 @@ - - - 预算管理 - - 暂无已发布的战略地图 - 预算编制需要基于已发布的战略地图,请先在【战略地图】中创建并发布 - 去创建战略地图 - - - - - - 选择战略地图 - - - - 已选择 - 共 {{ total }} 条KPI - - - - - - 查询 - + 新增预算 - 年度分解 - - KPI列表维度汇总 - - 批量保存 ({{ changedRows.length }}) - 取消 - - - - - - - {{ dimLabel(row.dimension) }} - - - {{ formatNumber(row.budget_value, row.unit) }} - - - - - - — - - {{ row._actionCount != null ? `${row._actionCount}项` : '关联' }} - - - - - - 编辑 - 保存取消 - {{ row.dimension === 'finance' ? '财务指标' : '删除' }} - - - - - - - - - {{ card.icon }} {{ card.name }}{{ formatNumber(card.totalBudget) }}{{ card.kpiCount }}个KPI · 占比{{ card.ratio }}% - - - - - {{ dimLabel(row.dimension) }} - - {{ formatNumber(row.totalBudget) }} - - {{ formatNumber(row.avgPerKpi) }} - - - - - - - 年度预算 → 月度自动分解执行分解 - - - 均分(1/12)按历史权重 - - - - - {{ formatNumber(row.annual_budget) }} - - - - - - - 请先在预算录入中选择战略地图 - - - {{ selectedMap.title }}已发布 - - - 刷新 - 已选 {{ strategySelectedKpis.length }} 个KPI - 统一设值 - - 批量保存 - - - - {{ dim.icon }}{{ dim.name }} - ({{ dim.kpiCount }}个KPI · 预算合计:{{ formatNumber(dim.totalBudget) }}) - 全选 - - - {{ obj.name }} - onStrategyKpiSelect(sel, dim.key)"> - - - - - - {{ row.unit }} - 保存 - - - - - - - - - - - - - 刷新 - - - {{ row.version }} - - 已批准待审批已驳回草稿 - - - {{ formatNumber(row.total_budget) }} - - - - 提交审批 - 批准驳回 - 重新提交 - - - - - 对比 {{ selectedVersions[0].version }} vs {{ selectedVersions[1].version }} - - - - - - - - 刷新 - - - {{ card.label }}{{ card.value }} - - - - {{ dimLabel(row.dimension) }} - {{ formatNumber(row.budget_value, row.unit) }} - {{ formatNumber(row.actual_value, row.unit) }} - {{ row.deviation_value > 0 ? '+' : '' }}{{ formatNumber(row.deviation_value, row.unit) }} - - 严重关注正常 - - - - - - - - - - - - 取消创建 - - - - - 对比 {{ diffData.summary.version_a }} → {{ diffData.summary.version_b }} - - - {{ formatNumber(row.old_value) }} - {{ formatNumber(row.new_value) }} - {{ row.diff_value > 0 ? '+' : '' }}{{ formatNumber(row.diff_value) }} - 持平{{ row.diff_rate > 0 ? '+' : '' }}{{ row.diff_rate }}% - - - 关闭 - - - - - - 已关联 {{ actionPlansForKpi.length }} 项行动方案 - - - - {{ plan.title }} - {{ plan.description }} - - 已完成 - 进行中 - {{ plan.status }} - - - 负责人: {{ plan.assignee || '未指定' }} - 截止: {{ plan.due_date?.slice(0,10) }} - 优先级: {{ plan.priority }} - - - - - 暂无关联行动方案 - 非财务维度KPI需要配套行动方案才能将战略意图转化为实际行动 - - - + 新建行动方案 - 去行动方案库查看 - - 关闭 - - - - - - - diff --git a/frontend/src/views/CMAKnowledge.vue.bak b/frontend/src/views/CMAKnowledge.vue.bak deleted file mode 100644 index 8f489373..00000000 --- a/frontend/src/views/CMAKnowledge.vue.bak +++ /dev/null @@ -1,731 +0,0 @@ - - - - - - - - CMA知识库 - - - - - - 搜索结果({{ searchResults.length }}条) - - {{ catLabel(item.category) }} - {{ item.title }} - {{ item.summary }} - - 未找到相关内容 - - - - - - - {{ cat.icon }} - {{ cat.name }} - {{ cat.items.length }}篇 - - - - {{ item.title }} - {{ item.summary }} - - - - - - - - - - 关闭 - - - - - - - - - ⚖️ CMA职业道德自测 - 本测试包含 10道 IMA职业道德情景题,涵盖: - - 诚信 Integrity — 诚实、公正地处理事务 - 客观 Objectivity — 保持独立性和职业判断 - 保密 Confidentiality — 保护公司机密信息 - 胜任 Competence — 持续提升专业能力 - - - 开始自测 - - - - - - - - - 第 {{ currentQuestion + 1 }} / {{ questions.length }} 题 - - - - - - - - Q{{ currentQuestion + 1 }} - {{ questions[currentQuestion].scenario }} - - - - - {{ opt.id.toUpperCase() }} - {{ opt.text }} - - - - - - {{ selectedOption?.correct ? '✅' : '❌' }} - - {{ selectedOption?.correct ? '正确!' : '选择有误' }} - {{ feedbackMessage }} - - - - - - - 下一题 → - - - 查看成绩 🏆 - - - - - - - - {{ scoreEmoji }} - {{ scoreTitle }} - {{ correctCount }} / {{ questions.length }} - - - ✅ 正确:{{ correctCount }} 题 - ❌ 错误:{{ questions.length - correctCount }} 题 - - - 重新测试 - 返回首页 - - - - - - 逐题回顾 - - - {{ userAnswers[idx]?.correct ? '✅' : '❌' }} - Q{{ idx + 1 }}. {{ q.scenario }} - - - 你的选择:{{ userAnswers[idx]?.text || '未作答' }} - - - 正确答案:{{ q.options.find(o => o.correct)?.text }} - - - 💡 {{ userAnswers[idx]?.feedback || q.options.find(o => o.correct)?.feedback }} - - - - - - - - - - - - - diff --git a/frontend/src/views/DeviationDashboard.vue.bak b/frontend/src/views/DeviationDashboard.vue.bak deleted file mode 100644 index 0208a46c..00000000 --- a/frontend/src/views/DeviationDashboard.vue.bak +++ /dev/null @@ -1,410 +0,0 @@ - - - 差异分析看板 - - - - - - - - - - - - - - - - - - - - - - 刷新 - 导出CSV - - - - - - - - 已录预算KPI - {{ stats.total_kpis || 0 }} - - - - - - - {{ dim.icon }} {{ dim.name }} - - {{ dim.summary.deviation_rate != null ? dim.summary.deviation_rate.toFixed(1) + '%' : '-' }} - - - {{ dim.summary.has_budget }}/{{ dim.summary.count }} KPI有预算 - - - - - - - - - - - 差异趋势(各月实际 vs 预算) - - - - - - - - - - - - {{ item.period }} - - {{ item.deviation > 0 ? '+' : '' }}{{ item.deviation.toFixed(1) }}% - - - - - {{ trendLoading ? '加载中...' : '选择一个KPI查看趋势' }} - - - - - - - - - - {{ row.icon }} - {{ row._type === 'dimension' ? row.name + ' 维度' : row.name }} - - {{ row.summary.deviation_rate != null ? row.summary.deviation_rate.toFixed(1) + '%' : '--' }} - - - {{ row.summary.deviation_rate != null ? row.summary.deviation_rate.toFixed(1) + '%' : '--' }} - - - {{ row.summary.has_budget }}/{{ row.summary.count }} KPI - - - {{ row.summary.has_budget }}/{{ row.summary.count }} KPI - - - - - - - {{ row.kpi_code }} - - - - - - {{ row.budget_value != null ? fmtVal(row.budget_value) : '--' }} - - - - - - - {{ row.actual_value != null ? fmtVal(row.actual_value) : '--' }} - - - - - - - {{ row.deviation_amount !== undefined ? fmtVal(row.deviation_amount) : '--' }} - - - - - - - {{ row.deviation_rate > 0 ? '+' : '' }}{{ row.deviation_rate.toFixed(2) }}% - - - - - - - {{ row.yoy.diff_rate > 0 ? '+' : '' }}{{ row.yoy.diff_rate.toFixed(1) }}% - - - - - - - {{ row.mom.diff_rate > 0 ? '+' : '' }}{{ row.mom.diff_rate.toFixed(1) }}% - - - - - - - {{ row.deviation_rate > 20 ? '红色' : row.deviation_rate > 10 ? '黄色' : '正常' }} - - - - - - - - - - - - - - diff --git a/frontend/src/views/KPIList.vue.bak b/frontend/src/views/KPIList.vue.bak deleted file mode 100644 index 9f1e9e66..00000000 --- a/frontend/src/views/KPIList.vue.bak +++ /dev/null @@ -1,738 +0,0 @@ - - - - - KPI字典 - - 📋 从模板创建 - + 新建KPI - - - - - - - BSC分类导航 - - - - {{ data.label }} - {{ data.count }} - - - - - - - - - - - - - - - - - - - - 查询 - 重置 - - - - - 已选 {{ selectedIds.length }} 条 - 批量删除 - 导出CSV - 取消选择 - - - - $router.push('/kpis/' + row.id)" - border - stripe - size="small" - > - - - - {{ row.kpi_code }} - - - - - - {{ dimLabel(row.dimension) }} - - - - {{ catLabel(row.category) }} - - - {{ formatTarget(row.target_value, row.unit) }} - - - {{ freqLabel(row.frequency) }} - - - {{ sourceLabel(row.data_source_type) }} - - - - - {{ row.actual_value }}{{ row.unit }} - - - - - - - - 系统 - 自定义 - - - - - - {{ row.alert_level === 'red' ? '红灯' : row.alert_level === 'yellow' ? '黄灯' : '绿灯' }} - - - - - - - - 编辑 - 删除 - - - - - - - 共 {{ total }} 条 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 超过此值视为正常 - - - - - - 超过此值预警 - - - - - - 触发此值紧急 - - - - - - - - - - - 取消 - {{ editMode ? '保存' : '创建' }} - - - - - - - - - - - - - - - - 查询 - - - - - - {{ row.kpi_code }} - - - - {{ dimLabel(row.dimension) }} - - - {{ catLabel(row.category) }} - - - - {{ row.target_value ?? '-' }} - - - - - 系统 - 自定义 - - - - 请选择一个模板,然后填写实例化信息 - - - 从「{{ selectedTemplate.kpi_name }}」创建KPI实例 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * 编码和名称不填则使用模板默认值,后续可在KPI字典中修改 - - - - 取消 - 从模板创建 - - - - - - - - diff --git a/frontend/src/views/MapCanvas.vue.bak b/frontend/src/views/MapCanvas.vue.bak deleted file mode 100644 index 6db49f12..00000000 --- a/frontend/src/views/MapCanvas.vue.bak +++ /dev/null @@ -1,979 +0,0 @@ - - - - - 战略地图画布 — 四层泳道 - - - - - - - − - {{ Math.round(zoomLevel * 100) }}% - + - 100% - - 保存 - 发布 - 版本历史 - - - - - 查看执行看板 - - - - - - - 🔗 从「{{ linkingFrom.obj.name }}」连线 — 点击另一个目标完成连线 - 取消 - - - - - - - - - - - - - - - - - - - - - - openAddDialog(k)" - @edit-objective="(p: any) => openEditDialog(p.dimKey, p.idx, p.obj)" - @delete-objective="(p: any) => deleteNode(p.dimKey, p.idx)" - @start-link="(p: any) => { const ps = p.key.split('-'); startLink(ps[0], parseInt(ps[ps.length-1]), p.obj) }" - @link-drag-start="(e: MouseEvent, dk: string, oi: number, obj: any) => onLinkDragStart(e, dk, oi, obj)" - @kpi-click="(code: string) => goKPI(code)" - @show-plan-list="(p: any) => showPlanList(p.dimKey, p.idx, p.obj)" - @node-click="(dk: string, oi: number, obj: any) => onNodeClick(dk, oi, obj)" - @reorder="(dk: string) => onLayerReorder(dk)" - /> - - - - - - - - - - - - - - - - - - - - - - - 版本历史 - × - - - - 说明创建时间操作 - - - {{ v.comment || '-' }} - {{ v.created_at }} - 回滚 - - - - 暂无版本记录 - - - - - - - - - 📊 {{ kpiDetailObjName }} — KPI详情 - × - - - - 该目标暂未关联KPI - - - - {{ badgeIcon(getKpiLevel(item)) }} - {{ item.code }} - {{ item.name }} - - - - 实际值 - {{ item.actual != null ? fmtKpiVal(item.actual) : '—' }} - - - 目标值 - {{ item.target != null ? fmtKpiVal(item.target) : '—' }} - - - 达成率 - - {{ (item.actual / item.target * 100).toFixed(1) }}% - - - - 单位 - {{ item.unit }} - - - - - - - - - - - - - 📋 {{ planPopupObjName }} — 关联行动方案 - × - - - - 暂无关联的行动方案 - - - - {{ planStatusLabel(p.status) }} - {{ p.title }} - - - 👤 {{ p.assignee }} - 📅 {{ p.due_date.slice(0, 10) }} - 进度 {{ p.progress }}% - - - - - - - - - - - - - - - - diff --git a/frontend/src/views/MapReview.vue.bak b/frontend/src/views/MapReview.vue.bak deleted file mode 100644 index e91e5c30..00000000 --- a/frontend/src/views/MapReview.vue.bak +++ /dev/null @@ -1,351 +0,0 @@ - - - - - - ← 返回战略地图 - 🗺️ 打开画布 - {{ mapTitle }} · 战略回顾 - - - - - - - 本月 - 本季 - 本年 - - - - - - - - - - - - - - - {{ summary.health_score }}% - 整体健康度 - - - 🟢 {{ summary.green }}个达成 - 🟡 {{ summary.yellow }}个预警 - 🔴 {{ summary.red }}个异常 - - - - - - - - - {{ dim.icon }} - {{ dim.name }} - - - - {{ badgeIcon(obj.level) }} - - {{ obj.name }} - - - {{ fmtValue(k.actual_value, k.kpi_code) }}/{{ k.target_value ?? '-' }} - - - - - - - - - - - 🔴 需重点关注 - - - {{ item.level === 'red' ? '紧急' : '预警' }} - {{ item.name }} - - - - {{ k.kpi_name }} - - {{ fmtValue(k.actual_value, k.kpi_code) }} / {{ k.target_value ?? '-' }} - - - - - - - {{ planIcon(p) }} - {{ p.title }} - {{ p.assignee }} - {{ dueText(p) }} - - - - - - - - 📋 改善行动进度 - - {{ pendingCount }} 待处理 - {{ inProgressCount }} 进行中 - {{ doneCount }} 已完成 - {{ overdueCount }} 逾期 - - $router.push('/action-plans?kpi='+r.kpi_id)"> - - - - - {{ planLabel(row) }} - - - - - - - - - - {{ row.due_date ? row.due_date.slice(0,10) : '-' }} - - - - - - - - - - - {{ badgeIcon(k.level) }} - {{ k.kpi_name }} ({{ k.kpi_code }}) - - - - 实际值 - {{ fmtValue(k.actual_value, k.kpi_code) }} - - - 目标值 - {{ k.target_value ?? '-' }} {{ k.unit }} - - - 达成率 - - {{ (k.actual_value / k.target_value * 100).toFixed(1) }}% - - - 查看KPI详情 → - - - - - - - - -
暂无已发布的战略地图
预算编制需要基于已发布的战略地图,请先在【战略地图】中创建并发布
请先在预算录入中选择战略地图
暂无关联行动方案
非财务维度KPI需要配套行动方案才能将战略意图转化为实际行动
本测试包含 10道 IMA职业道德情景题,涵盖:
{{ questions[currentQuestion].scenario }}
{{ feedbackMessage }}