agri-app/pages/index.vue

302 lines
7.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="page-container">
<scroll-view
scroll-y
class="list-scroll"
@scrolltolower="loadMore"
:style="{ height: scrollHeight + 'px' }"
lower-threshold="50"
scroll-with-animation
>
<view
v-for="(item, index) in listData"
:key="index"
class="list-item"
@tap="onItemTap(item)"
>
<view class="item-title">
<view class="title-text">{{ item.title }}</view>
<text :class="['tag','tag-status',{'tag-manual':item.status==='手动模式'}]" v-if="item.status">{{ item.status }}</text>
<text :class="['tag','tag-online',{'tag-offline':item.online==='离线'}]" v-if="item.online">{{ item.online }}</text>
</view>
<view class="item-subtitle">
{{ item.subtitle }}
</view>
<view class="item-tags">
<text class="tag tag-temp1">温度1: {{ item.temp1 }}℃</text>
<text class="tag tag-temp2">温度2: {{ item.temp2 }}℃</text>
<text class="tag tag-temp3">温度3: {{ item.temp3 }}℃</text>
<text class="tag tag-temp4">温度4: {{ item.temp4 }}℃</text>
</view>
</view>
<view v-if="isLoading" class="loading-more">
<uni-icons type="spinner-cycle" size="20" color="#999"></uni-icons>
<text>加载中...</text>
</view>
<view v-else-if="noMore" class="no-more"></view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
listData: [],
page: 1,
pageSize: 6,
isLoading: false,
noMore: false,
total: 20, // 模拟总条数
scrollHeight: 0
}
},
onLoad() {
this.getListData()
// 计算滚动区域高度适配不同设备兼容rpx/px转换
const systemInfo = uni.getSystemInfoSync()
// 80rpx转px适配不同屏幕密度避免高度计算偏差
const topHeight = 80 * (systemInfo.windowWidth / 750)
this.scrollHeight = systemInfo.windowHeight - topHeight
},
onReady() {
// 页面渲染完成后再确认高度,避免小程序端高度计算不准
const systemInfo = uni.getSystemInfoSync()
const topHeight = 80 * (systemInfo.windowWidth / 750)
this.scrollHeight = systemInfo.windowHeight - topHeight
},
methods: {
// 模拟获取列表数据
getListData(isRefresh = false) {
if (isRefresh) {
this.page = 1
this.noMore = false
this.listData = []
}
if (this.isLoading || this.noMore) return
this.isLoading = true
// 模拟接口请求
setTimeout(() => {
const start = (this.page - 1) * this.pageSize
const end = this.page * this.pageSize
const newData = []
for (let i = start; i < end && i < this.total; i++) {
// 新增给每条数据加唯一id优化v-for的key
newData.push({
id: `item-${i}`,
title: `设备名称${i + 1}`,
subtitle: `设备编号SN-${10000 + i}`,
status: i % 2 === 0 ? "自动模式" : "手动模式",
online: i % 3 === 0 ? "在线" : "离线",
temp1: Math.floor(Math.random() * 51), // 0-50随机温度
temp2: Math.floor(Math.random() * 51),
temp3: Math.floor(Math.random() * 51),
temp4: Math.floor(Math.random() * 51)
})
}
this.listData = isRefresh ? newData : [...this.listData, ...newData]
this.page++
this.isLoading = false
if (this.listData.length >= this.total) {
this.noMore = true
}
}, 0)
},
// 加载更多(防抖:避免快速上拉重复触发)
loadMore() {
if (!this.isLoading && !this.noMore) {
// 延迟触发,避免滚动到底部瞬间多次调用
setTimeout(() => {
this.getListData()
}, 100)
}
},
// 点击列表项
onItemTap(item) {
uni.showToast({
title: `点击了:${item.title}`,
icon: 'none'
})
},
// 下拉刷新(可选)
onPullDownRefresh() {
this.getListData(true)
setTimeout(() => {
uni.stopPullDownRefresh()
}, 1000)
}
}
}
</script>
<style scoped>
/* 适配小程序/H5的盒模型避免padding导致宽度溢出 */
page {
box-sizing: border-box;
}
.page-container {
padding: 20rpx;
box-sizing: border-box;
background: radial-gradient(circle at top left, #E8F4F8 40%, #F8FCFE 100%);
}
.list-scroll {
/* 把背景色改为透明,才能透出背景渐变 */
background-color: transparent;
border-radius: 8rpx;
overflow: hidden;
margin-top: 10rpx;
/* 新增H5端避免滚动条样式不一致 */
scrollbar-width: thin;
}
/* H5端滚动条样式优化可选 */
.list-scroll::-webkit-scrollbar {
width: 4rpx;
}
.list-scroll::-webkit-scrollbar-thumb {
background-color: #e0e0e0;
border-radius: 2rpx;
}
.list-item {
padding: 14rpx 30rpx;
/* 移除border-bottom改为margin-top并且把列表项背景设为半透明白色 */
margin-bottom: 20rpx;
background-color: rgba(255, 255, 255, 0.85);
border-radius: 12rpx;
/* 新增:点击态样式,双端统一 */
transition: all 0.2s ease;
box-shadow: 8rpx 5rpx 10rpx #999;
}
.list-item:active {
background-color: rgba(255, 255, 255, 0.95);
transform: scale(0.98);
}
.item-title {
font-size: 28rpx;
line-height: 52rpx;
font-weight: bolder;
color: #333;
/* 核心flex布局让文字和标签在同一行 */
display: flex;
align-items: center;
width: 100%;
box-sizing: border-box;
}
.title-text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* 在线标签样式 */
.tag-online {
font-size: 20rpx;
border-radius: 4rpx;
background-color: #f0f9eb;
color: #67c23a;
white-space: nowrap;
line-height: 30rpx;
/* 兜底如果flex失效用margin-left:auto强制居右 */
margin-left: auto;
display: inline-block; /* 确保样式生效 */
}
.tag-status.tag-manual {
background-color: #dde3f6;
color: #7491ef;
}
/* 离线:深灰色系 */
.tag-offline {
background-color: #f2f2f2;
color: #c5c3c3;
}
.item-subtitle {
font-size: 26rpx;
color: #666;
line-height: 52rpx;
display: block;
}
.item-tags {
display: flex;
gap: 16rpx;
flex-wrap: wrap; /* 新增:标签过多时换行,避免溢出 */
margin: 14rpx 0;
}
.tag {
font-size: 22rpx;
padding: 4rpx 12rpx;
border-radius: 4rpx;
display: inline-block; /* 修复H5端padding不生效问题 */
}
.tag-status {
background-color: #f8f1f1;
color: #e66060;
margin-left: 20rpx;
font-weight: lighter;
line-height: 30rpx;
padding: 4rpx 6rpx;
font-size: 20rpx;
}
.tag-temp1 {
background-color: #e8f4ff;
color: #409eff;
}
.tag-temp2 {
background-color: #fdf4e4;
color: #f5961d;
}
.tag-temp3 {
background-color: #f4f4f5;
color: #909399;
}
.tag-temp4 {
background-color: #e7faf4;
color: #1bd1a7;
}
.loading-more {
display: flex;
align-items: center;
justify-content: center;
padding: 30rpx;
color: #999;
font-size: 26rpx;
gap: 10rpx;
margin-top: 20rpx;
background-color: rgba(255, 255, 255, 0.85);
border-radius: 12rpx;
}
.no-more {
/* 核心flex布局实现居中 */
display: flex;
align-items: center;
justify-content: center;
/* 占满滚动容器剩余高度,保证垂直居中 */
min-height: 200rpx; /* 最小高度,避免内容太少时不居中 */
/* 文字样式保留 */
color: #999;
font-size: 26rpx;
/* 可选:增加上下内边距,视觉更舒适 */
padding: 30rpx 0;
margin-top: 20rpx;
background-color: rgba(255, 255, 255, 0.85);
border-radius: 12rpx;
}
</style>