index.vue
6.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
<template>
<view class="page-container">
<!-- 顶部固定区域:Tabs + 搜索框 -->
<view class="top-fixed">
<!-- uView Tabs 标签 -->
<u-tabs
v-model="activeTab"
:list="tabList"
:is-scroll="false"
:activeStyle="{
color: '#3c9cff',
fontWeight: 'bold',
transform: 'scale(1.05)'
}"
:inactiveStyle="{
color: '#606266',
transform: 'scale(1)'
}"
font-size="28rpx"
@change="handleTabChange"
></u-tabs>
<!-- 道路名称搜索框 -->
<u-search
v-model="searchValue"
placeholder="请输入道路名称"
bg-color="#f5f5f5"
border-radius="8rpx"
:clearabled="true"
@search="handleSearch"
@clear="handleSearchClear"
maxlength="50"
style="margin: 10rpx 20rpx 0"
></u-search>
</view>
<!-- z-paging 分页列表 -->
<z-paging
v-model="planList"
:page-size="pageSize"
:total="total"
@query="loadData"
:scroll-top-reset-type="1"
:top="160"
bg-color="#f8f8f8"
>
<!-- 计划卡片列表 -->
<view class="card-list">
<view class="plan-card" v-for="(item, index) in planList" :key="index">
<view class="card-content">
<!-- 道路名称 -->
<view class="row-item">
<text class="label">道路名称:</text>
<text class="value">{{ item.roadName }}</text>
</view>
<!-- 所属街道 -->
<view class="row-item">
<text class="label">所属街道:</text>
<text class="value">{{ item.street }}</text>
</view>
<!-- 养护级别 + 计划明细按钮 -->
<view class="row-item flex-between">
<view>
<text class="label">养护级别:</text>
<text class="value">{{ item.maintainLevel }}</text>
</view>
<text class="detail-btn" @click="gotoDetail(item)">计划明细</text>
</view>
<!-- 计划类型 -->
<view class="row-item">
<text class="label">计划类型:</text>
<text class="value">{{ item.planType }}</text>
</view>
<!-- 计划时间 -->
<view class="row-item">
<text class="label">计划时间:</text>
<text class="value">{{ item.planTime }}</text>
</view>
</view>
</view>
</view>
<!-- 空数据占位 -->
<template #empty>
<view class="empty-wrap">
<text class="empty-text">暂无相关计划数据</text>
</view>
</template>
</z-paging>
</view>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
// Tabs 配置
const tabList = ref([
{name: '待完成', id: 'pending'},
{name: '已失效', id: 'invalid'},
{name: '已完成', id: 'completed'}
]);
const activeTab = ref('pending'); // 当前激活的Tab
// 搜索相关
const searchValue = ref(''); // 搜索框值
// 分页相关
const pageNo = ref(1); // 当前页码
const pageSize = ref(10); // 每页条数
const total = ref(100); // 总记录数(模拟大量数据)
const planList = ref([]); // 计划列表数据
// Tab切换事件(清空搜索条件)
const handleTabChange = () => {
// 清空搜索框
searchValue.value = '';
// 重置分页
pageNo.value = 1;
// 重新加载数据
loadData(true);
};
// 搜索事件
const handleSearch = () => {
pageNo.value = 1;
loadData(true);
};
// 清空搜索框
const handleSearchClear = () => {
pageNo.value = 1;
loadData(true);
};
// 生成模拟数据
const generateMockData = (page) => {
const mockList = [];
const tabMap = {
pending: '待完成',
invalid: '已失效',
completed: '已完成'
};
const maintainLevels = ['一级养护', '二级养护', '三级养护'];
const planTypes = ['日常养护', '专项养护', '应急养护'];
const streets = ['西长安街街道', '东城区东华门街道', '朝阳区望京街道', '海淀区中关村街道', '丰台区马家堡街道'];
const roadNames = [
'长安街', '王府井大街', '中关村南大街', '朝阳北路', '建国路',
'复兴路', '西直门外大街', '广渠路', '阜成门外大街', '安定门东大街'
];
// 生成当前页数据
for (let i = 0; i < 35; i++) {
const idx = (page - 1) * pageSize.value + i;
mockList.push({
id: idx + 1,
roadName: `${roadNames[idx % roadNames.length]}${idx + 1}段`,
street: streets[Math.floor(Math.random() * streets.length)],
maintainLevel: maintainLevels[Math.floor(Math.random() * maintainLevels.length)],
planType: planTypes[Math.floor(Math.random() * planTypes.length)],
planTime: `2025-${Math.floor(Math.random() * 12) + 1}-${Math.floor(Math.random() * 28) + 1} 至 2025-${Math.floor(Math.random() * 12) + 1}-${Math.floor(Math.random() * 28) + 1}`,
status: tabMap[activeTab.value]
});
}
return mockList;
};
// 加载数据(z-paging 核心方法)
const loadData = (isRefresh = false) => {
// 模拟接口请求延迟
setTimeout(() => {
const newData = generateMockData(pageNo.value);
if (isRefresh) {
planList.value = newData; // 刷新:替换数据
} else {
planList.value = [...planList.value, ...newData]; // 加载更多:追加数据
}
}, 500);
};
// 跳转到计划明细页面
const gotoDetail = (item) => {
uni.navigateTo({
url: `/pages/plan-detail/index?id=${item.id}&status=${activeTab.value}`
});
};
// 页面加载初始化
onLoad(() => {
loadData(true);
});
</script>
<style scoped lang="scss">
.page-container {
min-height: 100vh;
background-color: #f8f8f8;
}
/* 顶部固定区域 */
.top-fixed {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
background-color: #fff;
padding-bottom: 10rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
/* 计划卡片样式 */
.card-list {
padding: 170rpx 20rpx 20rpx;
}
.plan-card {
background-color: #fff;
border-radius: 12rpx;
padding: 20rpx;
margin-bottom: 15rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
}
.card-content {
display: flex;
flex-direction: column;
gap: 12rpx;
}
.row-item {
display: flex;
align-items: center;
font-size: 28rpx;
line-height: 1.5;
}
.flex-between {
display: flex;
justify-content: space-between;
align-items: center;
}
.label {
color: #999;
width: 140rpx;
flex-shrink: 0;
}
.value {
color: #333;
flex: 1;
}
.detail-btn {
color: #1989fa;
font-size: 26rpx;
padding: 0 10rpx;
}
/* 空数据样式 */
.empty-wrap {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
}
.empty-text {
font-size: 28rpx;
color: #999;
}
</style>