董国庆
2026-05-25 a8efd69be79c5c49f7efadc1809f9a7a34e521be
feat(operationWorkbench): 新增点位状态过滤,优化搜索与页面样式

重构点位搜索逻辑,添加请求ID避免旧请求覆盖新结果
为点位列表新增状态筛选功能
调整策略单元格的HTML结构与CSS样式
修复选中项自动选择与样式作用域问题
2个文件已修改
157 ■■■■■ 已修改文件
src/views/businessOperations/operationWorkbench/list.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/businessOperations/operationWorkbench/map.vue 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/businessOperations/operationWorkbench/list.vue
@@ -1823,11 +1823,11 @@
            <div class="strategy-cell">
              {visibleRows.map((item: any) => (
                <div class="strategy-row">
                  <span class="strategy-label">
                  <div class="strategy-label">
                    {item.label}
                    :
                  </span>
                  <span class="strategy-time">{item.timeText}</span>
                  </div>
                  <div class="strategy-time">{item.timeText}</div>
                </div>
              ))}
              {strategyRows.length > 2
@@ -2583,7 +2583,7 @@
  font-weight: 400;
}
.link-text {
:deep(.link-text) {
  width: 100%;
  overflow: hidden;
  color: #0068ff;
@@ -2604,14 +2604,14 @@
}
:deep(.strategy-label) {
  flex: 1;
  flex-shrink: 0;
  max-width:50%;
  word-break: break-word;
  color: rgba(23, 31, 38, 0.6);
}
:deep(.strategy-time) {
  margin-left: 4px;
  flex: 1;
  // flex: 1;
  word-break: break-all;
  color: rgba(23, 31, 38, 1);
}
src/views/businessOperations/operationWorkbench/map.vue
@@ -175,6 +175,7 @@
const pointData = ref<ListItem[]>([]);
const pointSpatialData = ref<ListItem[]>([]);
const pointSearchList = ref<ListItem[]>([]);
const pointKeywordSearchActive = ref(false);
const fenceData = ref<ListItem[]>([]);
const fenceAreaData = ref<any[]>([]);
const stationData = ref<ListItem[]>([]);
@@ -535,7 +536,7 @@
}));
const pointDisplayList = computed(() => {
  return pointSearchList.value.length ? pointSearchList.value : pointData.value;
  return pointKeywordSearchActive.value ? pointSearchList.value : pointData.value;
});
const searchPlaceholder = computed(() => {
@@ -545,7 +546,15 @@
});
const currentList = computed(() => {
  if (activeTab.value === "point") return pointDisplayList.value;
  if (activeTab.value === "point")
    return pointDisplayList.value.filter((item) => {
      if (!selectedStatuses.value.length) return true;
      return selectedStatuses.value.some(
        (value) =>
          normalizeStatusFilterLabel("point", item.status)
          === getStatusLabelByValue("point", value)
      );
    });
  const normalizedKeyword = keyword.value.trim().toLowerCase();
  return tabDataMap.value[activeTab.value].filter((item) => {
    const searchTexts = [item.name, item.id];
@@ -614,10 +623,7 @@
    (item) => item.id === selectedId.value
  );
  if (matchedStation) return matchedStation;
  return (
    currentList.value[0] ||
    null
  );
  return null;
});
const currentTabLabel = computed(
@@ -3230,6 +3236,8 @@
watch(activeTab, async (value) => {
  keyword.value = "";
  selectedStatuses.value = [];
  pointKeywordSearchActive.value = false;
  pointSearchList.value = [];
  statusDropdownVisible.value = false;
  stationPanelClosed.value = false;
  if (value === "point") {
@@ -3245,27 +3253,19 @@
  }
  pointPanelClosed.value = false;
  await loadStationData();
  if (!stationCreateMode.value && pendingWorkbenchType.value !== "create") {
    const stationList = tabDataMap.value[value];
    const hasMatchedSelectedStation = stationList.some(
      (item) => String(item.id) === String(selectedId.value)
    );
    if (!hasMatchedSelectedStation)
      selectedId.value = stationList[0]?.id || "";
  }
});
watch(currentList, (list) => {
  if (activeTab.value === "point") {
    if (pointCreateMode.value) return;
    const apiList = pointData.value;
    if (!apiList.length) {
    const availableList = list.filter((item) => item.source !== "amap");
    if (!availableList.length) {
      selectedId.value = "";
      return;
    }
    if (
      selectedId.value &&
      !apiList.some((item) => item.id === selectedId.value)
      !availableList.some((item) => item.id === selectedId.value)
    )
      selectedId.value = "";
    return;
@@ -3308,8 +3308,8 @@
    selectedId.value = "";
    return;
  }
  if (!list.some((item) => item.id === selectedId.value))
    selectedId.value = list[0].id;
  if (selectedId.value && !list.some((item) => item.id === selectedId.value))
    selectedId.value = "";
});
async function handleEntrySelection(
@@ -3514,17 +3514,17 @@
);
let pointSearchTimer: ReturnType<typeof setTimeout> | null = null;
let pointKeywordSearchRequestId = 0;
watch(
  [keyword, selectedStatuses],
  keyword,
  () => {
    if (activeTab.value !== "point") return;
    if (pointSearchTimer) clearTimeout(pointSearchTimer);
    pointSearchTimer = setTimeout(() => {
      loadPointData();
      loadPointKeywordSearch();
    }, 250);
  },
  { deep: true }
  }
);
watch(
@@ -5762,11 +5762,51 @@
async function loadPointData() {
  try {
    const keywordText = keyword.value.trim();
    const keywordResult = await fetchPointList({
    const pointResult = await fetchPointList({
      cityCode: cityValue.value || undefined,
      queryParams: keywordText || undefined,
    } as any);
    const apiPoints =
      pointResult.code === 200 && Array.isArray(pointResult.data)
        ? pointResult.data
            .map((point: any) => mapPointApiItemToListItem(point))
            .filter(
              (item) => Number.isFinite(item.lng) && Number.isFinite(item.lat)
            )
        : [];
    pointData.value = apiPoints;
    pointSpatialData.value = apiPoints;
  } catch (error) {
    console.error("加载点位失败:", error);
    pointData.value = [];
    pointSpatialData.value = [];
  }
}
async function loadPointResources() {
  await loadPointData();
}
async function loadPointKeywordSearch() {
  const keywordText = keyword.value.trim();
  if (!keywordText) {
    pointKeywordSearchRequestId += 1;
    pointKeywordSearchActive.value = false;
    pointSearchList.value = [];
    return;
  }
  const requestId = ++pointKeywordSearchRequestId;
  pointKeywordSearchActive.value = true;
  try {
    const [keywordResult, amapResult] = await Promise.all([
      fetchPointList({
        cityCode: cityValue.value || undefined,
        queryParams: keywordText,
      } as any),
      searchAMap(keywordText),
    ]);
    if (requestId !== pointKeywordSearchRequestId) return;
    const apiPoints =
      keywordResult.code === 200 && Array.isArray(keywordResult.data)
@@ -5775,22 +5815,7 @@
            .filter(
              (item) => Number.isFinite(item.lng) && Number.isFinite(item.lat)
            )
            .filter((item) => {
              if (!selectedStatuses.value.length) return true;
              return selectedStatuses.value.some(
                (value) => item.status === getStatusLabelByValue("point", value)
              );
            })
        : [];
    pointData.value = apiPoints;
    if (!keywordText) {
      pointSearchList.value = [];
      return;
    }
    const amapResult = await searchAMap(keywordText);
    const amapPoints: ListItem[] = amapResult
      .map((tip: any, index: number) => ({
        id: `amap_${tip.id || index}_${Date.now()}`,
@@ -5809,33 +5834,10 @@
    pointSearchList.value = [...apiPoints, ...amapPoints];
  } catch (error) {
    console.error("加载点位失败:", error);
    pointData.value = [];
    if (requestId !== pointKeywordSearchRequestId) return;
    console.error("搜索点位失败:", error);
    pointSearchList.value = [];
  }
}
async function loadPointSpatialData() {
  try {
    const res = await fetchPointList({
      cityCode: cityValue.value || undefined,
    } as any);
    pointSpatialData.value =
      res.code === 200 && Array.isArray(res.data)
        ? res.data
            .map((point: any) => mapPointApiItemToListItem(point))
            .filter(
              (item) => Number.isFinite(item.lng) && Number.isFinite(item.lat)
            )
        : [];
  } catch (error) {
    console.error("加载围栏空间点位失败:", error);
    pointSpatialData.value = [];
  }
}
async function loadPointResources() {
  await Promise.all([loadPointData(), loadPointSpatialData()]);
}
async function loadFenceData() {
@@ -5910,15 +5912,6 @@
  workbenchDataReady.value = false;
  await Promise.all([loadPointResources(), loadFenceData(), loadStationData()]);
  workbenchDataReady.value = true;
  if (
    activeTab.value !== "point" &&
    activeTab.value !== "fence" &&
    !stationCreateMode.value &&
    !selectedId.value &&
    pendingWorkbenchType.value !== "create"
  ) {
    selectedId.value = tabDataMap.value[activeTab.value][0]?.id || "";
  }
  if (pendingWorkbenchType.value === "create") {
    pendingWorkbenchType.value = "";
    await handleWorkbenchCreateByTab(activeTab.value);