feat(scene): 新增场景选择页(列表加载/错误重试/点选返回)

This commit is contained in:
ozh 2026-08-18 17:30:23 +08:00
parent 3ffdce0ec5
commit 8af15703f0
1 changed files with 119 additions and 0 deletions

119
pages/scene/select.vue Normal file
View File

@ -0,0 +1,119 @@
<!-- 场景选择页加载场景列表点选后保存并返回首页 -->
<template>
<view class="page page-base">
<up-navbar title="选择场所" :fixed="false" :safe-area-inset-top="true" :border="false" />
<view v-if="loading" class="state-wrap">
<up-loading-icon mode="circle" size="48" text="加载中..." />
</view>
<view v-else-if="loadError" class="state-wrap">
<up-empty mode="error" text="加载失败,请检查网络" />
<up-button type="success" shape="circle" text="重试" class="retry-btn" @click="loadScenes" />
</view>
<view v-else-if="sceneList.length === 0" class="state-wrap">
<up-empty mode="list" text="暂无场景" />
</view>
<view v-else class="scene-list">
<view
v-for="scene in sceneList"
:key="scene.id"
class="scene-item"
:class="{ 'scene-item--active': scene.id === currentSceneId }"
@click="selectScene(scene)"
>
<text class="scene-name">{{ scene.name }}</text>
<up-icon
:name="scene.id === currentSceneId ? 'checkmark' : 'arrow-right'"
:size="scene.id === currentSceneId ? '16' : '14'"
:color="scene.id === currentSceneId ? '#26c996' : '#c0c4cc'"
/>
</view>
</view>
</view>
</template>
<script>
import { getSceneList } from '@/api/scene'
import { getCurrentScene, setCurrentScene } from '@/store/scene'
import { navigateBack } from '@/utils/navigation'
export default {
data() {
return {
loading: true,
loadError: false,
sceneList: [],
currentSceneId: getCurrentScene()?.id ?? null
}
},
onLoad() {
this.loadScenes()
},
methods: {
// toast
async loadScenes() {
this.loading = true
this.loadError = false
try {
this.sceneList = (await getSceneList()) || []
} catch (error) {
this.loadError = true
} finally {
this.loading = false
}
},
// onShow
selectScene(scene) {
setCurrentScene(scene)
navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
@import '@/styles/common.css';
.state-wrap {
margin-top: 120rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.retry-btn {
margin-top: 40rpx;
width: 240rpx;
}
.scene-list {
margin-top: 20rpx;
}
.scene-item {
height: 104rpx;
padding: 0 32rpx;
margin-bottom: 2rpx;
background: #ffffff;
display: flex;
align-items: center;
justify-content: space-between;
}
.scene-item--active {
background: #e9fff3;
}
.scene-name {
font-size: 32rpx;
color: #222;
font-weight: 600;
}
.scene-item--active .scene-name {
color: #26c996;
}
</style>