From 385be2eca72eb3833efa4be0a0088b34e764788a Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Mon, 31 Aug 2026 09:04:45 +0800
Subject: [PATCH] feat(pointcloud): complete annotation and result lifecycle workflows

---
 apps/workbench-console/src/components/RiskRulePanel.vue |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/apps/workbench-console/src/components/RiskRulePanel.vue b/apps/workbench-console/src/components/RiskRulePanel.vue
index b3ba044..857b926 100644
--- a/apps/workbench-console/src/components/RiskRulePanel.vue
+++ b/apps/workbench-console/src/components/RiskRulePanel.vue
@@ -4,6 +4,7 @@
 
 import { artifactUrl, createRiskRuleRun, readFileAsPayload, type RiskRuleCase, type RiskScoreFeature } from "@/api/artifacts";
 import ArtifactState from "@/components/ArtifactState.vue";
+import RunDeletionControl from "@/components/RunDeletionControl.vue";
 import { useArtifactStore } from "@/stores/artifacts";
 
 const store = useArtifactStore();
@@ -18,6 +19,7 @@
 const currentCase = computed<RiskRuleCase | undefined>(() => store.riskRuleCases[caseId.value] ?? Object.values(store.riskRuleCases)[0]);
 const caseOptions = computed(() => Object.values(store.riskRuleCases).map((item) => ({ value: item.id, label: item.label })));
 const filteredCaseOptions = computed(() => caseOptions.value.filter((item) => item.label.toLowerCase().includes(searchText.value.trim().toLowerCase())));
+async function removeRun() { await store.loadRiskRule(true); caseId.value = Object.keys(store.riskRuleCases)[0] ?? ""; }
 const levelColor = (level: string) => ({ low: "green", medium: "gold", high: "orange", critical: "red" }[level] ?? "default");
 const vectorViewBox = computed(() => {
   const bounds = currentCase.value?.run.raster.bounds ?? [0, 0, 1, 1];
@@ -85,7 +87,7 @@
 
   <template v-if="currentCase">
     <a-row :gutter="[18, 18]" class="risk-workspace">
-      <a-col :xs="24" :xl="5"><section class="surface-section run-library"><h2>案例库</h2><a-input-search v-model:value="searchText" placeholder="搜索运行" allow-clear /><a-list size="small" :data-source="filteredCaseOptions"><template #renderItem="{ item }"><a-list-item class="run-item" :class="{ active: item.value === currentCase.id }" @click="caseId = item.value">{{ item.label }}</a-list-item></template></a-list></section></a-col>
+      <a-col :xs="24" :xl="5"><section class="surface-section run-library"><h2>案例库</h2><a-input-search v-model:value="searchText" placeholder="搜索运行" allow-clear /><a-list size="small" :data-source="filteredCaseOptions"><template #renderItem="{ item }"><a-list-item class="run-item" :class="{ active: item.value === currentCase.id }" @click="caseId = item.value"><span class="run-item-label">{{ item.label }}</span><RunDeletionControl capability="07-risk-rule-engine" :run-id="item.value" :label="item.label" @removed="removeRun" /></a-list-item></template></a-list></section></a-col>
       <a-col :xs="24" :xl="19"><section class="surface-section"><div class="section-toolbar"><div><h2>栅格与矢量结果</h2><span class="toolbar-note">{{ currentCase.run.crs }} · {{ currentCase.run.raster.width }} x {{ currentCase.run.raster.height }} · {{ currentCase.run.parameters.raster_resolution }} m 像元</span></div></div><div class="comparison-grid risk-images"><figure><figcaption>风险评分栅格</figcaption><a-image :src="artifactUrl(`${currentCase.artifactRoot}/${currentCase.run.artifacts.risk_preview}`)" /></figure><figure><figcaption>对象评分矢量</figcaption><svg class="risk-vector" :viewBox="vectorViewBox" preserveAspectRatio="xMidYMid meet"><g transform="scale(1,-1)"><circle v-for="feature in points" :key="feature.properties.object_id" :cx="feature.geometry.coordinates[0]" :cy="feature.geometry.coordinates[1]" :r="Math.max(currentCase.run.parameters.raster_resolution * 1.25, 6)" :class="`risk-${feature.properties.risk_level}`"><title>{{ feature.properties.object_id }}: {{ feature.properties.risk_score }}</title></circle></g></svg></figure></div></section></a-col>
     </a-row>
 

--
Gitblit v1.9.3