From 5de005e011de15cc9a03bc43f94aa9e0f259f586 Mon Sep 17 00:00:00 2001 From: lyf <2514544224@qq.com> Date: Mon, 31 Aug 2026 17:00:42 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BC=96=E5=8F=B7=E8=AE=B2?= =?UTF-8?q?=E8=A7=A3=E5=B8=83=E5=B1=80=E4=B8=8E=E8=BF=94=E5=9B=9E=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将讲解编号置于标题上方并增强辨识度 - 编号详情返回后保留输入界面并清空原编号 - 增加页面栈丢失时恢复编号输入页的兜底逻辑 - 补充编号布局和返回流程回归测试 Made-with: Proma --- .../explain/ExplainGuideStopCatalog.vue | 4 +-- src/components/explain/ExplainHallSelect.vue | 5 +-- src/pages/exhibit/detail.vue | 31 +++++++++++++++-- src/pages/explain/list.vue | 9 +++-- src/pages/index/index.vue | 1 + tests/unit/ExhibitDetailAudioFirst.spec.ts | 34 +++++++++++++++++++ tests/unit/ExplainGuideStopCatalog.spec.ts | 3 ++ tests/unit/ExplainHallSelect.spec.ts | 5 +++ 8 files changed, 83 insertions(+), 9 deletions(-) diff --git a/src/components/explain/ExplainGuideStopCatalog.vue b/src/components/explain/ExplainGuideStopCatalog.vue index e18d50a..3668974 100644 --- a/src/components/explain/ExplainGuideStopCatalog.vue +++ b/src/components/explain/ExplainGuideStopCatalog.vue @@ -30,8 +30,8 @@ {{ stop.name.slice(0, 1) }} - {{ stop.name }} 编号:{{ stop.externalCode }} + {{ stop.name }} {{ availabilityLabel(stop) }} @@ -155,6 +155,6 @@ const handleScroll = (event: Event) => { const target = event.target as HTMLElem .header-back { position: absolute; left: 12px; top: 10px; width: 44px; height: 44px; display: flex; align-items: center; }.header-back-icon { width: 20px; height: 20px; position: relative; } .header-back-icon::before { content: ''; position: absolute; left: 3px; top: 4px; width: 10px; height: 10px; border-left: 1.5px solid #262421; border-bottom: 1.5px solid #262421; transform: rotate(45deg); } .header-back-text { display: none; }.header-title { max-width: calc(100% - 152px); padding: 0 8px; font-size: 18px; line-height: 26px; font-weight: 700; color: #262421; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .explain-scroll { height: 100%; padding: 80px 16px calc(16px + env(safe-area-inset-bottom)); box-sizing: border-box; background: #f7f9f2; }.host-navigation .explain-scroll { padding-top: 16px; } -.stop-list { display: flex; width: 100%; min-width: 0; flex-direction: column; gap: 4px; }.stop-card { width: 100%; min-width: 0; min-height: 80px; padding: 8px 0; display: flex; align-items: center; gap: 12px; box-sizing: border-box; overflow: hidden; border: 0; border-bottom: 1px solid #dbded4; border-radius: 0; background: transparent; }.stop-card:active { background: rgba(227, 235, 201, 0.4); }.stop-cover { flex: 0 0 64px; width: 64px; height: 64px; overflow: hidden; border-radius: 6px; background: #f5f5ed; }.stop-cover-fallback { font-size: 22px; line-height: 28px; color: #a9b29b; }.stop-copy { min-width: 0; display: flex; flex: 1; flex-direction: column; justify-content: center; gap: 3px; overflow: hidden; }.stop-code { display: block; overflow: hidden; font-size: 11px; line-height: 16px; font-weight: 600; color: #68725d; text-overflow: ellipsis; white-space: nowrap; }.stop-name { display: -webkit-box; max-height: 40px; font-size: 14px; line-height: 20px; font-weight: 700; color: #262421; overflow: hidden; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }.stop-name + .stop-code { margin-top: 1px; }.stop-status { flex: 0 0 44px; width: 44px; height: 24px; display: flex; align-items: center; justify-content: center; border-radius: 12px; background: #e3ebc9; }.stop-status-text { font-size: 11px; line-height: 16px; color: #262421; white-space: nowrap; } +.stop-list { display: flex; width: 100%; min-width: 0; flex-direction: column; gap: 4px; }.stop-card { width: 100%; min-width: 0; min-height: 80px; padding: 8px 0; display: flex; align-items: center; gap: 12px; box-sizing: border-box; overflow: hidden; border: 0; border-bottom: 1px solid #dbded4; border-radius: 0; background: transparent; }.stop-card:active { background: rgba(227, 235, 201, 0.4); }.stop-cover { flex: 0 0 64px; width: 64px; height: 64px; overflow: hidden; border-radius: 6px; background: #f5f5ed; }.stop-cover-fallback { font-size: 22px; line-height: 28px; color: #a9b29b; }.stop-copy { min-width: 0; display: flex; flex: 1; flex-direction: column; justify-content: center; gap: 3px; overflow: hidden; }.stop-code { display: block; overflow: hidden; font-size: 13px; line-height: 18px; font-weight: 700; color: #68725d; text-overflow: ellipsis; white-space: nowrap; }.stop-name { display: -webkit-box; max-height: 40px; font-size: 14px; line-height: 20px; font-weight: 700; color: #262421; overflow: hidden; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }.stop-code + .stop-name { margin-top: 1px; }.stop-status { flex: 0 0 44px; width: 44px; height: 24px; display: flex; align-items: center; justify-content: center; border-radius: 12px; background: #e3ebc9; }.stop-status-text { font-size: 11px; line-height: 16px; color: #262421; white-space: nowrap; } .state-block { margin: 34px 0; padding: 22px 16px; box-sizing: border-box; text-align: center; border: 1px solid #e4e6df; border-radius: 8px; background: #fff; }.state-block.error { border-color: #e5c2c2; background: #fff7f7; }.state-title,.state-desc { display: block; }.state-title { font-size: 15px; line-height: 21px; font-weight: 700; color: #141412; }.state-desc { margin-top: 6px; font-size: 12px; line-height: 18px; color: #68725d; }.state-retry { margin-top: 12px; padding: 0 14px; font-size: 13px; line-height: 32px; color: #141412; background: #e0df00; border: 0; border-radius: 6px; }.load-more-state { min-height: 52px; padding: 12px 16px calc(12px + env(safe-area-inset-bottom)); text-align: center; } diff --git a/src/components/explain/ExplainHallSelect.vue b/src/components/explain/ExplainHallSelect.vue index 6b892d2..6196ea5 100644 --- a/src/components/explain/ExplainHallSelect.vue +++ b/src/components/explain/ExplainHallSelect.vue @@ -453,10 +453,11 @@ const showCodeEntryError = (message: string) => { } const completeCodeEntry = () => { - closeCodeEntry() + codeEntryValue.value = '' + codeEntryError.value = '' } -defineExpose({ showCodeEntryError, completeCodeEntry }) +defineExpose({ openCodeEntry, showCodeEntryError, completeCodeEntry }) const handleBusinessUnitClick = (unitId: string) => { emit('businessUnitClick', unitId) diff --git a/src/pages/exhibit/detail.vue b/src/pages/exhibit/detail.vue index 4668b55..2b4693e 100644 --- a/src/pages/exhibit/detail.vue +++ b/src/pages/exhibit/detail.vue @@ -247,6 +247,7 @@ const detailTextLoadedByLanguage = ref>({ }) const shouldUseHostNavigation = computed(() => isEmbeddedInWechatMiniProgram()) const shouldAutoplayOnEntry = ref(false) +const enteredByGuideCode = ref(false) const isAudioLanguage = (value: unknown): value is AudioLanguage => ( value === 'zh-CN' || value === 'yue-HK' || value === 'en-US' @@ -533,7 +534,9 @@ onLoad(async (options: any = {}) => { } const rawLang = Array.isArray(options.lang) ? options.lang[0] : options.lang const rawAutoplay = Array.isArray(options.autoplay) ? options.autoplay[0] : options.autoplay + const rawEntry = Array.isArray(options.entry) ? options.entry[0] : options.entry shouldAutoplayOnEntry.value = rawAutoplay === '1' || rawAutoplay === 'true' + enteredByGuideCode.value = rawEntry === 'code' const lang = typeof rawLang === 'string' ? normalizeGuideAudioLanguage(rawLang) : 'zh-CN' @@ -935,6 +938,16 @@ const decodeRouteParam = (value: string) => { return decoded } +const fallbackToCodeEntry = () => { + const url = '/pages/explain/list?codeEntry=1' + uni.redirectTo({ + url, + fail: () => { + uni.reLaunch({ url }) + } + }) +} + const fallbackToExplainObjectList = () => { const hallId = detailEntryRequest.value?.hallId || exhibit.value.hallId const hallName = decodeRouteParam(detailEntryRequest.value?.hallName || exhibit.value.hallName || '讲解') @@ -957,15 +970,27 @@ type ExplainDetailPageStackEntry = { const returnToExplainObjectList = () => { closeDetailAudioOnExit() + const pages = getCurrentPages() + const previousPage = pages[pages.length - 2] as ExplainDetailPageStackEntry | undefined + + if (enteredByGuideCode.value) { + if (previousPage?.route === 'pages/explain/list' || previousPage?.route === 'pages/index/index') { + uni.navigateBack({ + delta: 1, + fail: fallbackToCodeEntry + }) + return + } + fallbackToCodeEntry() + return + } + // H5 history can omit intermediate uni-app pages after a refresh or deep link. if (typeof window !== 'undefined' && window.location.hash.startsWith('#/')) { fallbackToExplainObjectList() return } - const pages = getCurrentPages() - const previousPage = pages[pages.length - 2] as ExplainDetailPageStackEntry | undefined - if (previousPage?.route === 'pages/explain/guide-stop-list') { uni.navigateBack({ delta: 1, diff --git a/src/pages/explain/list.vue b/src/pages/explain/list.vue index a051328..41feba2 100644 --- a/src/pages/explain/list.vue +++ b/src/pages/explain/list.vue @@ -24,7 +24,7 @@