shuishen
12 hours ago 385be2eca72eb3833efa4be0a0088b34e764788a
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>