feat: watch UI empty shell (3-page swiper, mascot, sessions, settings, detail, input)

This commit is contained in:
2026-09-01 18:45:58 +08:00
parent 25798241db
commit a8ee608e6f
10 changed files with 615 additions and 46 deletions
+254 -22
View File
@@ -1,48 +1,280 @@
<template>
<div class="demo-page">
<text class="title">{{ $t("a.b") }},欢迎打开{{ title }}</text>
<!-- 点击跳转详情页 -->
<input class="btn" type="button" value="跳转到详情页" onclick="routeDetail" />
<div class="page">
<swiper class="swiper" ref="swiper" index="{{currentIndex}}" indicator="false" loop="false"
previousmargin="14px" nextmargin="14px" onchange="onSwipeChange">
<!-- 左页:会话 -->
<div class="page-item left-page">
<text class="page-title">会话</text>
<div class="session-list">
<div class="session-row" for="{{sessions}}" tid="{{$item.sessionId}}" onclick="selectSession({{$index}})">
<text class="session-title">{{$item.title}}</text>
<text class="session-dot" if="{{$item.running}}">●</text>
</div>
</div>
<text class="page-hint" if="{{!sessions.length}}">暂无会话</text>
</div>
<!-- 中页:主页 / 吉祥物 -->
<div class="page-item center-page">
<image class="mascot" src="/common/dsniang.png" onclick="openDetail" />
<text class="status-text">{{statusText}}</text>
<text class="session-hint">{{activeTitle}}</text>
<div class="center-actions">
<input class="btn" type="button" value="输入" onclick="openInput" />
<input class="btn btn-ghost" type="button" value="详情" onclick="openDetail" />
</div>
</div>
<!-- 右页:设置 -->
<div class="page-item right-page">
<text class="page-title">设置</text>
<text class="setting-label">服务器</text>
<input class="setting-input" type="text" value="{{settings.serverUrl}}" onchange="onServerChange" />
<text class="setting-label">用户ID</text>
<input class="setting-input" type="text" value="{{settings.userId}}" onchange="onUserChange" />
<text class="setting-label">Token</text>
<input class="setting-input" type="password" value="{{settings.token}}" onchange="onTokenChange" />
<text class="conn-text">{{connText}}</text>
<input class="btn" type="button" value="连接状态" onclick="refreshConn" />
<input class="btn btn-ghost" type="button" value="更多设置" onclick="openSettings" />
</div>
</swiper>
<div class="dots">
<div class="dot {{currentIndex == 0 ? 'dot-active' : ''}}"></div>
<div class="dot {{currentIndex == 1 ? 'dot-active' : ''}}"></div>
<div class="dot {{currentIndex == 2 ? 'dot-active' : ''}}"></div>
</div>
</div>
</template>
<script>
import router from "@system.router"
import router from '@system.router'
export default {
// 页面级组件的数据模型,影响传入数据的覆盖机制:private内定义的属性不允许被覆盖
private: {
title: "示例页面"
currentIndex: 1,
sessions: [
{ sessionId: 'demo-1', title: '原型演示会话', running: false },
{ sessionId: 'demo-2', title: 'UI 对齐中', running: true },
{ sessionId: 'demo-3', title: '待接入 Harness', running: false }
],
statusText: '未连接',
activeTitle: '会话 demo-1',
settings: {
serverUrl: 'ws://127.0.0.1:8787',
userId: '',
token: ''
},
connText: '手机/手表未连接'
},
routeDetail() {
// 跳转到应用内的某个页面,router用法详见:文档->接口->页面路由
router.push({
uri: "/pages/detail"
})
onInit() {
// 空壳:暂无逻辑
},
onReady() {
// 空壳:后续在此初始化 interconnect
this.refreshConn()
},
onSwipeChange(e) {
if (e && typeof e.index === 'number') {
this.currentIndex = e.index
}
},
goTo(index) {
this.currentIndex = index
if (this.$refs && this.$refs.swiper && this.$refs.swiper.swipeTo) {
this.$refs.swiper.swipeTo({ index })
}
},
selectSession(index) {
const item = this.sessions[index]
if (item) {
this.activeTitle = '会话 ' + item.title
this.goTo(1)
}
},
openDetail() {
router.push({ uri: '/pages/detail' })
},
openInput() {
router.push({ uri: '/pages/input' })
},
openSettings() {
router.push({ uri: '/pages/settings' })
},
onServerChange(e) { this.settings.serverUrl = e && e.value || '' },
onUserChange(e) { this.settings.userId = e && e.value || '' },
onTokenChange(e) { this.settings.token = e && e.value || '' },
refreshConn() {
// 空壳:后续通过 interconnect getReadyState 获取真实连接状态
this.connText = '手机/手表未连接'
}
}
</script>
<style>
.demo-page {
.page {
width: 100%;
height: 100%;
flex-direction: column;
background-color: #0b1220;
}
.swiper {
flex: 1;
width: 100%;
indicator-size: 0px;
}
.page-item {
width: 100%;
height: 100%;
padding: 12px;
box-sizing: border-box;
}
.left-page,
.right-page {
flex-direction: column;
align-items: flex-start;
}
.center-page {
flex-direction: column;
justify-content: center;
align-items: center;
}
.title {
font-size: 20px;
text-align: center;
.page-title {
color: #e6f0ff;
font-size: 24px;
font-weight: bold;
margin-bottom: 12px;
}
.page-hint {
color: #6b7a99;
font-size: 16px;
margin-top: 20px;
}
.session-list {
width: 100%;
flex-direction: column;
}
.session-row {
width: 100%;
height: 44px;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
padding: 0 10px;
border-radius: 10px;
background-color: #152238;
}
.session-title {
color: #dbe8ff;
font-size: 17px;
}
.session-dot {
color: #33b4ff;
font-size: 16px;
}
.mascot {
width: 180px;
height: 180px;
}
.status-text {
color: #e6f0ff;
font-size: 18px;
margin-top: 14px;
}
.session-hint {
color: #7d8fb0;
font-size: 14px;
margin-top: 4px;
}
.center-actions {
flex-direction: row;
margin-top: 18px;
gap: 12px;
}
.btn {
width: 200px;
width: 100px;
height: 40px;
margin-top: 20px;
border-radius: 5px;
background-color: #09ba07;
font-size: 20px;
color: #ffffff;
border-radius: 20px;
background-color: #33b4ff;
color: #08131f;
font-size: 16px;
text-align: center;
}
.btn-ghost {
background-color: #1c2c47;
color: #dbe8ff;
}
.setting-label {
color: #8fa4c9;
font-size: 14px;
margin-top: 8px;
}
.setting-input {
width: 100%;
height: 38px;
border-radius: 8px;
background-color: #152238;
color: #e6f0ff;
font-size: 15px;
padding: 0 8px;
margin-bottom: 4px;
}
.conn-text {
color: #6b7a99;
font-size: 14px;
margin-top: 8px;
}
.dots {
flex-direction: row;
justify-content: center;
align-items: center;
height: 14px;
margin-top: 4px;
gap: 8px;
}
.dot {
width: 7px;
height: 7px;
border-radius: 4px;
background-color: rgba(255, 255, 255, 0.28);
}
.dot-active {
width: 22px;
border-radius: 4px;
background-color: #33b4ff;
}
</style>