| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- /**
- * 设施点位与管线图层状态(票 24)。
- *
- * 与监测点摘要(`mapStore`)**分开持有**:两者是不同业务对象、不同读取路径、不同统计口径
- * (管线不进地图摘要总数,监测点也不当管线渲染)。合并成一个 store 会让两种口径互相污染。
- *
- * 失败纪律沿用全舱:几何取不到只让**设施/管线图层**降级,不牵连监测点、设备与面板,
- * 也绝不回退 mock(票 04 的 real 纪律)。
- */
- import { computed, ref } from 'vue'
- import { defineStore } from 'pinia'
- import { SECTION_STATE, section } from '../domain/sectionState.js'
- import { REQUEST_REASON } from '../domain/requestReason.js'
- import { filterPipeNetwork } from '../domain/pipeNetwork.js'
- import { fetchPipeNetwork } from '../services/pipeLayerService.js'
- /** 未取数时的分区(与其它 store 同形,`loaded:false` 表示"还没请求过")。 */
- function pending() {
- return { state: SECTION_STATE.EMPTY, reason: '', mode: '', data: null, missing: [], freshness: '', retained: false, loaded: false }
- }
- const EMPTY_LAYER = { pipes: [], components: [], blocked: [], coverage: {}, counts: {}, districtApplied: false, districtUnresolvedCount: 0 }
- export const usePipeNetworkStore = defineStore('pipeNetworkStore', () => {
- const layer = ref(pending())
- const industry = ref('all')
- /**
- * 当前生效的片区筛选(前端键;票 67 更正)。
- *
- * 与行业同层、同一套纪律:几何是**全量取回、本地裁剪**,所以切片区只改本地筛选条件、
- * 不重新发请求(切换必须即时)。片区的来源是**设施编码前缀**(片区+行业+时间编码),
- * 见 `domain/pipeNetwork.js` 的 `pipeDistrictOf`。
- */
- const scope = ref('all')
- let requestOptions = {}
- /** 请求注入(config / fetchImpl):取一次让后续取数共用。 */
- function configure(options = {}) {
- requestOptions = { ...requestOptions, ...options }
- }
- /** 只读写入分区(走查与单测注入用)。 */
- function setLayer(value) {
- layer.value = { ...value, loaded: true }
- }
- /** 当前行业 + 片区筛选下的图层(图层过滤只此一处,引擎与组件都不做第二次过滤)。 */
- const filtered = computed(() =>
- filterPipeNetwork(layer.value.data || EMPTY_LAYER, { industry: industry.value, scope: scope.value }),
- )
- /** 取数成功(含真实为空)才交数组;**失败或还没取过一律交 `null`**。 */
- function layerOrNull(list) {
- const current = layer.value
- const settled = current.loaded === true
- && [SECTION_STATE.SUCCESS, SECTION_STATE.EMPTY, SECTION_STATE.STALE].includes(current.state)
- return settled ? list : null
- }
- /** 给 `modeLayerPlan` 的两段(与计划里的 `facilities`/`pipelines` 同形)。 */
- const facilities = computed(() => layerOrNull(filtered.value.components))
- const pipelines = computed(() => layerOrNull(filtered.value.pipes))
- /** 被拦下的对象(「无地图位置」清单的来源,带中文原因)。 */
- const blocked = computed(() => filtered.value.blocked)
- /** 行业覆盖:哪个行业有几何、哪个没有,由后端 `coverage` 表达,前端只转述。 */
- const coverage = computed(() => filtered.value.coverage)
- const loaded = computed(() => layer.value.loaded === true)
- const state = computed(() => layer.value.state)
- const reason = computed(() => layer.value.reason)
- /** 只改行业筛选(几何已全量取回,切行业不重新发请求)。 */
- function setIndustry(next) {
- industry.value = typeof next === 'string' && next ? next : 'all'
- return industry.value
- }
- /** 只改片区筛选(同上:本地裁剪,不重新发请求)。 */
- function setScope(next) {
- scope.value = typeof next === 'string' && next ? next : 'all'
- return scope.value
- }
- async function load(options = {}) {
- if (options.industry !== undefined) industry.value = options.industry
- if (options.scope !== undefined) scope.value = options.scope
- if (Object.keys(options).some((key) => !['industry', 'scope'].includes(key))) configure(options)
- let result = null
- try {
- result = await fetchPipeNetwork(requestOptions)
- } catch {
- // 适配层不抛;真抛了也要收成失败分区,不能让一次几何失败掀掉整个外壳。
- result = section(SECTION_STATE.FAILED, { reason: REQUEST_REASON.UNREACHABLE, data: null })
- }
- layer.value = { ...result, loaded: true }
- return layer.value
- }
- return { layer, loaded, state, reason, industry, scope, filtered, facilities, pipelines, blocked, coverage, load, setIndustry, setScope, configure, setLayer }
- })
|