feat: 战略地图收尾 — 自动保存+导出+表迁移+因果链推荐

This commit is contained in:
Hermes CI Fix
2026-07-14 17:32:22 +08:00
parent 5594a572e9
commit 9afcea8f8d
18 changed files with 207 additions and 59 deletions
+74 -1
View File
@@ -24,7 +24,9 @@
<input type="radio" v-model="viewDirection" value="causal" /> 🔗 因果
</label>
</span>
<el-button type="primary" @click="saveCanvas">保存</el-button>
<el-button @click="exportImage">📷 导出图片</el-button>
<el-button @click="showCausalityRecommendations">🔗 因果链推荐</el-button>
<el-button type="primary" @click="saveCanvas(false)">保存</el-button>
<el-button type="success" @click="publishMap" v-if="currentMap?.status === 'draft'">发布</el-button>
<el-button @click="showVersions = true; loadVersions()">版本历史</el-button>
<el-button @click="goAlignment" type="info" plain>
@@ -167,6 +169,35 @@
</div>
</div>
<!-- KPI因果链推荐弹窗 -->
<div v-show="showCausalityDialog" class="mc-dialog-overlay" @click.self="showCausalityDialog=false">
<div class="mc-dialog-box" style="width:680px;">
<div class="mc-dialog-header">
<span>🔗 KPI因果链推荐</span>
<button class="mc-dialog-close" @click="showCausalityDialog=false">×</button>
</div>
<div class="mc-dialog-body" style="max-height:400px;overflow-y:auto;">
<div v-if="causalityLoading" style="text-align:center;padding:20px;color:#999;">加载中...</div>
<div v-else-if="causalityRecommendations.length === 0" style="text-align:center;padding:20px;color:#999;">暂无因果链推荐</div>
<div v-else>
<div v-for="(rec,idx) in causalityRecommendations" :key="idx" style="padding:10px 0;border-bottom:1px solid #f0f0f0;display:flex;justify-content:space-between;align-items:center;">
<div>
<strong>{{ rec.source_kpi_code || rec.source_code }}</strong>
<span style="color:#999;margin:0 8px;">→</span>
<strong>{{ rec.target_kpi_code || rec.target_code }}</strong>
<span style="margin-left:8px;font-size:12px;color:#666;">强度: {{ rec.strength || '-' }}</span>
</div>
<button class="mc-btn" @click="applyCausality(rec)">应用</button>
</div>
</div>
</div>
<div class="mc-dialog-footer" v-if="causalityRecommendations.length > 0">
<button class="mc-btn" @click="showCausalityDialog=false">取消</button>
<button class="mc-btn mc-btn-primary" @click="applyAllCausality">一键全部应用</button>
</div>
</div>
</div>
<!-- 版本历史弹窗 -->
<div v-show="showVersions" class="mc-dialog-overlay" @click.self="showVersions=false">
<div class="mc-dialog-box" style="width:620px;">
@@ -935,6 +966,48 @@ async function exportImage() {
ElMessage.error('导出失败')
}
}
// ── KPI因果链推荐 ──
const showCausalityDialog = ref(false)
const causalityRecommendations = ref<any[]>([])
const causalityLoading = ref(false)
async function showCausalityRecommendations() {
if (!currentMap.value) { ElMessage.warning('请先选择或创建战略地图'); return }
causalityLoading.value = true
showCausalityDialog.value = true
try {
const r: any = await api.get('/kpi-causality')
const items = r.data || r.items || r || []
causalityRecommendations.value = Array.isArray(items) ? items : []
} catch (e) {
ElMessage.error('加载因果链失败')
causalityRecommendations.value = []
}
causalityLoading.value = false
}
async function applyCausality(rec: any) {
try {
await api.post(\\`/maps/\\${currentMap.value?.id}/connections\\`, { from: rec.source_kpi_code, to: rec.target_kpi_code })
ElMessage.success('连线已添加')
showCausalityDialog.value = false
loadMap()
} catch { ElMessage.error('添加失败') }
}
async function applyAllCausality() {
let added = 0
for (const rec of causalityRecommendations.value) {
try {
await api.post(\\`/maps/\\${currentMap.value?.id}/connections\\`, { from: rec.source_kpi_code, to: rec.target_kpi_code })
added++
} catch {}
}
ElMessage.success(\\`已添加 \\${added}/\\${causalityRecommendations.value.length} 条因果链\\`)
showCausalityDialog.value = false
loadMap()
}
onMounted(async () => {
const r: any = await mapApi.list()