shuishen
19 hours ago 385be2eca72eb3833efa4be0a0088b34e764788a
apps/workbench-console/src/components/SpatialMeasurementPanel.vue
@@ -4,6 +4,7 @@
import { artifactUrl, createMeasurementRun, readFileAsPayload, type MeasurementCase } from "@/api/artifacts";
import ArtifactState from "@/components/ArtifactState.vue";
import RunDeletionControl from "@/components/RunDeletionControl.vue";
import { useArtifactStore } from "@/stores/artifacts";
interface GeoFeature { properties?: Record<string, unknown>; geometry?: { type: string; coordinates: unknown }; }
@@ -41,6 +42,7 @@
const vectorPaths = computed(() => allRings.value.map((ring) => ring.map((point, index) => `${index ? "L" : "M"}${point[0]},${point[1]}`).join(" ") + " Z"));
function syncSelection() { selectedName.value = currentCase.value?.run.images[0]?.file ?? ""; }
async function removeRun() { await store.loadMeasurement(true); caseId.value = Object.keys(store.measurementCases)[0] ?? ""; syncSelection(); }
function beforeUpload(file: File) { files.value = [...files.value, file]; return false; }
function removeFile(file: { name: string }) { files.value = files.value.filter((item) => item.name !== file.name); }
async function loadVector() {
@@ -80,7 +82,7 @@
  <template v-if="currentCase && selectedImage">
    <a-row :gutter="[18, 18]" class="measurement-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; syncSelection()">{{ 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; syncSelection()"><span class="run-item-label">{{ item.label }}</span><RunDeletionControl capability="04-spatial-measurement" :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"><a-select v-model:value="selectedName" :options="currentCase.run.images.map((item) => ({ value: item.file, label: item.file }))" /><span>{{ selectedImage.width }} x {{ selectedImage.height }} 栅格</span></div><div class="comparison-grid measurement-images"><figure><figcaption>栅格测量预览</figcaption><a-image :src="artifactUrl(`${currentCase.artifactRoot}/${selectedImage.preview_file}`)" /></figure><figure><figcaption>矢量对象范围</figcaption><svg class="vector-preview" :viewBox="vectorViewBox" preserveAspectRatio="xMidYMid meet"><path v-for="(path, index) in vectorPaths" :key="index" :d="path" /></svg></figure></div></section></a-col>
    </a-row>