Parcourir la source

feat(eventList): 优化事件列表页面布局和功能

- 替换时间类型选择器为按钮组,提高用户体验
- 调整事件卡片样式,增加视觉可读性
- 优化首页状态概览布局,突出待处理告警信息
- 移除不必要的代码和样式,提高代码可维护性
nahida il y a 1 an
Parent
commit
c40031a140
2 fichiers modifiés avec 426 ajouts et 409 suppressions
  1. 416 397
      pages/eventList/index.vue
  2. 10 12
      pages/index/index.vue

+ 416 - 397
pages/eventList/index.vue

@@ -1,59 +1,60 @@
 <template>
-	<view class="page">
-		<view class="header" style="height: 70rpx;">
-			<picker mode="selector" :range="timeTypes" :value="selectedTimeType" @change="onTimeTypeChange">
-				<view class="time-type-picker" :class="processTimeTypes(timeTypes[selectedTimeType])">
-					<text>{{ selectedTimeType === -1? '全部' : timeTypes[selectedTimeType] }}</text>
-					<uni-icons type="arrowdown" size="20" color="#333" />
-				</view>
-			</picker>
-		</view>
-
-		<scroll-view scroll-y class="event-list" @refresherrefresh="onRefresh" :refresher-triggered="isRefreshing"
-			refresher-enabled>
-			<view v-if="filteredEventList.length > 0">
-				<view v-for="(item, index) in filteredEventList" :key="index" class="event-card">
-					<view class="event-header">
-						<view :class="['status-tag', item.status]">{{ item.statusText }}</view>
-						<text class="time">{{ item.time }}</text>
-					</view>
-
-					<view class="event-info">
-						<view class="location">
-							<uni-icons type="location" size="16" color="#666" />
-							<text class="location-text">{{ item.location }}</text>
-						</view>
-						<view class="type-level">
-							<text :class="['level-tag', item.levelClass]">{{ item.level }}</text>
-							<text class="type">{{ item.type }}</text>
-						</view>
-						<view class="description">{{ item.description }}</view>
-						<view :class="['message-box', item.status]" v-if="item.status !== 'pending'">{{ item.message }}</view>
-					</view>
-
-					<view class="action-buttons">
-						<uni-button size="mini" type="warn" @click="handleEmergency(item)">
-							<view class="button-content">
-								<uni-icons type="phone-filled" size="16" color="#fff" />
-								<text>一键报警</text>
-							</view>
-						</uni-button>
-						<uni-button size="mini" type="default" @click="viewDetail(item)">
-							<view class="button-content">
-								<uni-icons type="more-filled" size="16" color="#666" />
-								<text>查看详情</text>
-							</view>
-						</uni-button>
-					</view>
-				</view>
-				<view class="pagination-container">
-					<uni-pagination :show-icon="true" :total="total" v-model="currentPage" :pageSize="pageSize" title="标题文字"
-						@change="getEventList" />
-				</view>
-			</view>
-			<view v-else class="no-data">无数据</view>
-		</scroll-view>
-	</view>
+    <view class="page">
+        <view class="header" style="height: 70rpx;">
+            <!-- 四个按钮 -->
+            <view class="button-group">
+                <button :class="{ 'active': selectedTimeType === -1 }" @click="selectTimeType(-1)">全部</button>
+                <button :class="{ 'active': selectedTimeType === 0 }" @click="selectTimeType(0)">严重</button>
+                <button :class="{ 'active': selectedTimeType === 1 }" @click="selectTimeType(1)">一般</button>
+                <button :class="{ 'active': selectedTimeType === 2 }" @click="selectTimeType(2)">轻微</button>
+            </view>
+        </view>
+
+        <scroll-view scroll-y class="event-list" @refresherrefresh="onRefresh" :refresher-triggered="isRefreshing"
+                     refresher-enabled>
+            <view v-if="filteredEventList.length > 0">
+                <view v-for="(item, index) in filteredEventList" :key="index" class="event-card">
+                    <view class="event-header">
+                        <view :class="['status-tag', item.status]">{{ item.statusText }}</view>
+                        <text class="time">{{ item.time }}</text>
+                    </view>
+
+                    <view class="event-info">
+                        <view class="location">
+                            <uni-icons type="location" size="16" color="#666" />
+                            <text class="location-text">{{ item.location }}</text>
+                        </view>
+                        <view class="type-level">
+                            <text :class="['level-tag', item.levelClass]">{{ item.level }}</text>
+                            <text class="type">{{ item.type }}</text>
+                        </view>
+                        <view class="description">{{ item.description }}</view>
+                        <view :class="['message-box', item.status]" v-if="item.status !== 'pending'">{{ item.message }}</view>
+                    </view>
+
+                    <view class="action-buttons">
+                        <uni-button size="mini" type="warn" @click="handleEmergency(item)">
+                            <view class="button-content">
+                                <uni-icons type="phone-filled" size="16" color="#fff" />
+                                <text>一键报警</text>
+                            </view>
+                        </uni-button>
+                        <uni-button size="mini" type="default" @click="viewDetail(item)">
+                            <view class="button-content">
+                                <uni-icons type="more-filled" size="16" color="#666" />
+                                <text>查看详情</text>
+                            </view>
+                        </uni-button>
+                    </view>
+                </view>
+                <view class="pagination-container">
+                    <uni-pagination :show-icon="true" :total="total" v-model="currentPage" :pageSize="pageSize" title="标题文字"
+                                    @change="getEventList" />
+                </view>
+            </view>
+            <view v-else class="no-data">无数据</view>
+        </scroll-view>
+    </view>
 </template>
 
 <script lang="ts" setup>
@@ -63,347 +64,365 @@ import {alarmGradeClassMap, alarmGradeMap, alarmTypeMap} from './eventMap';
 import {onShow} from '@dcloudio/uni-app';
 
 interface EventItem {
-		id : number;
-		status : "ignore" | "mistake" | "completed" | "processing" | "pending";
-		statusText : string;
-		time : string;
-		location : string;
-		level : string;
-		levelClass : string;
-		type : string;
-		description : string;
-		person : string;
-		message : string;
-	}
-
-	const eventList = ref<EventItem[]>([]);
-
-	const timeTypes = ['严重', '一般', '轻微'] as const;
-	const selectedTimeType = ref(-1);
-
-	const processTimeTypes = (type : typeof timeTypes[number]) => {
-		if (type === '严重') {
-			return "urgent"
-		} else if (type === '轻微') {
-			return "normal"
-		} else if (type === '一般') {
-			return "important"
-		} else {
-			return "";
-		}
-	}
-
-	const filteredEventList = computed(() => {
-		if (selectedTimeType.value === -1) {
-			return eventList.value;
-		}
-		const selectedType = timeTypes[selectedTimeType.value];
-		return eventList.value.filter(item => item.level === selectedType);
-	});
-
-	const handleEmergency = (item : EventItem) => {
-		uni.showActionSheet({
-			itemList: ['拨打110', '拨打119', '拨打120'],
-			success: function (res) {
-				const phoneNumbers = ['110', '119', '120'];
-				uni.makePhoneCall({
-					phoneNumber: phoneNumbers[res.tapIndex]
-				});
-			}
-		});
-	};
-
-	const notifySecurity = (item : EventItem) => {
-		uni.showToast({
-			title: '已通知保安',
-			icon: 'success'
-		});
-	};
-
-	const notifyVisitor = (item : EventItem) => {
-		uni.showToast({
-			title: '已发送通知',
-			icon: 'success'
-		});
-	};
-
-	const viewDetail = (item : EventItem) => {
-		uni.setStorageSync("eventDetail", item);
-		uni.navigateTo({
-			url: "/pages/eventDetail/index"
-		})
-	};
-
-	const isRefreshing = ref(false);
-
-	const onRefresh = async () => {
-		isRefreshing.value = true;
-		await getEventList();
-		isRefreshing.value = false;
-		uni.showToast({
-			title: '刷新成功',
-			icon: 'success'
-		});
-	};
-
-	const onTimeTypeChange = (e : any) => {
-		selectedTimeType.value = e.detail.value;
-	};
-
-	const currentPage = ref(1);
-	const pageSize = ref(10);
-	const total = ref(0);
-
-	const getEventList = async () => {
-		const res = await clientPostWithQueryParams("/visualization/fireFighting/queryEventStatisticsPage", {
-			pageNum: currentPage.value,
-			pageSize: pageSize.value,
-			sortType: 'DESC'
-		})
-		if (res.code !== 200) {
-			uni.showToast({
-				title: "请求数据失败",
-				duration: 2000
-			})
-		}
-		const res2 = await clientPostWithQueryParams('/visualization/fireFighting/queryEventStatistics')
-		if (res2.code !== 200) {
-			uni.showToast({
-				title: "请求数据失败",
-				duration: 2000
-			})
-		}
-		total.value = res2.data.value;
-		console.log(res);
-		const processEventList : EventItem[] = res.data.pageData.map(q => {
-			const statusArr : EventItem['status'][] = ["pending", "processing", "completed", "mistake", "ignore"]
-			const statusArrText : string[] = ["未处理", "处理中", "处理完成", "误报", "忽略"]
-			const r : EventItem = {
-				id: q.alarmCode,
-				location: q.alarmPosition,
-				status: statusArr[q.handleStat],
-				statusText: statusArrText[q.handleStat],
-				time: q.alarmDate,
-				level: alarmGradeMap.get(q.alarmGrade),
-				levelClass: alarmGradeClassMap.get(q.alarmGrade),
-				type: q.orgName,
-				description: alarmTypeMap.get(q.alarmType),
-				person: 'string',
-				message:q.handleMessage
-			}
-			return r;
-		})
-		eventList.value = processEventList
-		console.log(processEventList);
-	}
-	
-	onShow(() => {
-		getEventList();
-	})
-	
+    id: number;
+    status: "ignore" | "mistake" | "completed" | "processing" | "pending";
+    statusText: string;
+    time: string;
+    location: string;
+    level: string;
+    levelClass: string;
+    type: string;
+    description: string;
+    person: string;
+    message: string;
+}
+
+const eventList = ref<EventItem[]>([]);
+
+const timeTypes = ['严重', '一般', '轻微'] as const;
+const selectedTimeType = ref(-1);
+
+const processTimeTypes = (type: typeof timeTypes[number]) => {
+    if (type === '严重') {
+        return "urgent"
+    } else if (type === '轻微') {
+        return "normal"
+    } else if (type === '一般') {
+        return "important"
+    } else {
+        return "";
+    }
+}
+
+const filteredEventList = computed(() => {
+    if (selectedTimeType.value === -1) {
+        return eventList.value;
+    }
+    const selectedType = timeTypes[selectedTimeType.value];
+    return eventList.value.filter(item => item.level === selectedType);
+});
+
+const handleEmergency = (item: EventItem) => {
+    uni.showActionSheet({
+        itemList: ['拨打110', '拨打119', '拨打120'],
+        success: function (res) {
+            const phoneNumbers = ['110', '119', '120'];
+            uni.makePhoneCall({
+                phoneNumber: phoneNumbers[res.tapIndex]
+            });
+        }
+    });
+};
+
+const notifySecurity = (item: EventItem) => {
+    uni.showToast({
+        title: '已通知保安',
+        icon: 'success'
+    });
+};
+
+const notifyVisitor = (item: EventItem) => {
+    uni.showToast({
+        title: '已发送通知',
+        icon: 'success'
+    });
+};
+
+const viewDetail = (item: EventItem) => {
+    uni.setStorageSync("eventDetail", item);
+    uni.navigateTo({
+        url: "/pages/eventDetail/index"
+    })
+};
+
+const isRefreshing = ref(false);
+
+const onRefresh = async () => {
+    isRefreshing.value = true;
+    await getEventList();
+    isRefreshing.value = false;
+    uni.showToast({
+        title: '刷新成功',
+        icon: 'success'
+    });
+};
+
+const selectTimeType = (index: number) => {
+    selectedTimeType.value = index;
+};
+
+const currentPage = ref(1);
+const pageSize = ref(10);
+const total = ref(0);
+
+const getEventList = async () => {
+    const res = await clientPostWithQueryParams("/visualization/fireFighting/queryEventStatisticsPage", {
+        pageNum: currentPage.value,
+        pageSize: pageSize.value,
+        sortType: 'DESC'
+    })
+    if (res.code !== 200) {
+        uni.showToast({
+            title: "请求数据失败",
+            duration: 2000
+        })
+    }
+    const res2 = await clientPostWithQueryParams('/visualization/fireFighting/queryEventStatistics')
+    if (res2.code !== 200) {
+        uni.showToast({
+            title: "请求数据失败",
+            duration: 2000
+        })
+    }
+    total.value = res2.data.value;
+    const processEventList: EventItem[] = res.data.pageData.map(q => {
+        const statusArr: EventItem['status'][] = ["pending", "processing", "completed", "mistake", "ignore"]
+        const statusArrText: string[] = ["未处理", "处理中", "处理完成", "误报", "忽略"]
+        const r: EventItem = {
+            id: q.alarmCode,
+            location: q.alarmPosition,
+            status: statusArr[q.handleStat],
+            statusText: statusArrText[q.handleStat],
+            time: q.alarmDate,
+            level: alarmGradeMap.get(q.alarmGrade),
+            levelClass: alarmGradeClassMap.get(q.alarmGrade),
+            type: q.orgName,
+            description: alarmTypeMap.get(q.alarmType),
+            person: 'string',
+            message: q.handleMessage
+        }
+        return r;
+    })
+    eventList.value = processEventList
+};
+
+onShow(() => {
+    getEventList();
+})
 </script>
 
-<style>
-	page {
-		height: 100%;
-	}
-
-	.page {
-		display: flex;
-		flex-direction: column;
-		height: 100%;
-		background-color: #f5f5f5;
-	}
-
-	.header {
-		display: flex;
-		justify-content: center;
-		align-items: center;
-		padding: 20rpx 30rpx;
-		background-color: #fff;
-		border-bottom: 1px solid #eee;
-	}
-
-	.time-type-picker {
-		display: flex;
-		align-items: center;
-		gap: 10rpx;
-		background-color: #F8F9FB;
-		padding: 10rpx 20rpx;
-		border-radius: 10rpx;
-		font-size: 28rpx;
-		color: #666;
-	}
-
-	.event-list {
-		flex: 1;
-		overflow: auto;
-		padding: 20rpx;
-	}
-
-	.event-card {
-		width: 650rpx;
-		background-color: #fff;
-		border-radius: 12px;
-		padding: 30rpx;
-		margin-bottom: 20rpx;
-		box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
-	}
-
-	.event-header {
-		display: flex;
-		justify-content: space-between;
-		align-items: center;
-		margin-bottom: 20rpx;
-	}
-
-	.status-tag {
-		padding: 4rpx 16rpx;
-		border-radius: 4px;
-		font-size: 12px;
-	}
-
-	.pending {
-		background-color: #ff4d4f;
-		color: #fff;
-	}
-
-	.processing {
-		background-color: #faad14;
-		color: #fff;
-	}
-
-	.completed {
-		background-color: #52c41a;
-		color: #fff;
-	}
-
-	.mistake {
-		background-color: #55aa7f;
-		color: #fff;
-	}
-
-	.ignore {
-		background-color: #55ffff;
-		color: #fff;
-	}
-
-	.time {
-		font-size: 14px;
-		color: #999;
-	}
-
-	.event-info {
-		margin-bottom: 30rpx;
-	}
-
-	.location {
-		display: flex;
-		align-items: center;
-		margin-bottom: 16rpx;
-	}
-
-	.location-text {
-		margin-left: 8rpx;
-		font-size: 14px;
-		color: #666;
-	}
-
-	.type-level {
-		display: flex;
-		align-items: center;
-		margin-bottom: 16rpx;
-	}
-
-	.level-tag {
-		padding: 4rpx 16rpx;
-		border-radius: 4px;
-		font-size: 12px;
-		margin-right: 16rpx;
-	}
-
-	.urgent {
-		background-color: #ff4d4f;
-		color: #fff;
-	}
-
-	.important {
-		background-color: #faad14;
-		color: #fff;
-	}
-
-	.normal {
-		background-color: #1890ff;
-		color: #fff;
-	}
-
-	.type {
-		font-size: 14px;
-		color: #666;
-	}
-
-	.description {
-		font-size: 14px;
-		color: #333;
-		margin-bottom: 16rpx;
-		line-height: 1.5;
-	}
-
-	.person-info {
-		font-size: 14px;
-		color: #666;
-	}
-
-	.label {
-		color: #999;
-	}
-
-	.action-buttons {
-		display: flex;
-		justify-content: space-between;
-	}
-
-	.button-content text {
-		margin-left: 8rpx;
-		font-size: 12px;
-	}
-
-	.uni-button {
-		margin: 0;
-		flex: 1;
-		margin-right: 16rpx;
-	}
-
-	.uni-button:last-child {
-		margin-right: 0;
-	}
-
-	.pagination-container {
-		width: 80vw;
-		margin: auto;
-	}
-
-	.no-data {
-		text-align: center;
-		color: #999;
-		font-size: 14px;
-		padding: 20rpx;
-	}
-	
-	.message-box {
-	  padding: 16rpx 24rpx;
-	  background-color: #f8f9fb;
-	  border-radius: 8rpx;
-	  font-size: 24rpx;
-	  color: #666;
-	  line-height: 1.6;
-	  margin-top: 20rpx;
-	  border: 1px solid #eee;
-	}
-	
-	/* 扩展不同状态的消息样式(可选) */
-.message-box.processing { background-color: #fff3d6; border-color: #ffe5b4; }
-.message-box.completed { background-color: #e8f9eb; border-color: #c8e6c9; }
-.message-box.mistake { background-color: #e0f2f1; border-color: #b2dfdb; }
-.message-box.ignore { background-color: #fff3b0; border-color: #fff9c4; }
-</style>
+<style scoped>
+.page {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+    background-color: #f5f5f5;
+}
+
+.header {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    padding: 20rpx 30rpx;
+    background-color: #fff;
+    border-bottom: 1px solid #eee;
+}
+
+.button-group {
+    display: flex;
+    justify-content: space-around;
+    width: 100%;
+}
+
+.button-group button {
+    padding: 10rpx 20rpx;
+    border: none;
+    border-radius: 10rpx;
+    background-color: #F8F9FB;
+    color: #666;
+    font-size: 28rpx;
+}
+
+.button-group button.active {
+    background-color: #1890ff;
+    color: white;
+}
+
+.event-list {
+    flex: 1;
+    overflow: auto;
+    padding: 20rpx;
+}
+
+.event-card {
+    width: 650rpx;
+    background-color: #fff;
+    border-radius: 12px;
+    padding: 30rpx;
+    margin-bottom: 20rpx;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+}
+
+.event-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 20rpx;
+}
+
+.status-tag {
+    padding: 4rpx 16rpx;
+    border-radius: 4px;
+    font-size: 12px;
+}
+
+.pending {
+    background-color: #ff4d4f;
+    color: #fff;
+}
+
+.processing {
+    background-color: #faad14;
+    color: #fff;
+}
+
+.completed {
+    background-color: #52c41a;
+    color: #fff;
+}
+
+.mistake {
+    background-color: #55aa7f;
+    color: #fff;
+}
+
+.ignore {
+    background-color: #55ffff;
+    color: #fff;
+}
+
+.time {
+    font-size: 14px;
+    color: #999;
+}
+
+.event-info {
+    margin-bottom: 30rpx;
+}
+
+.location {
+    display: flex;
+    align-items: center;
+    margin-bottom: 16rpx;
+}
+
+.location-text {
+    margin-left: 8rpx;
+    font-size: 14px;
+    color: #666;
+}
+
+.type-level {
+    display: flex;
+    align-items: center;
+    margin-bottom: 16rpx;
+}
+
+.level-tag {
+    padding: 4rpx 16rpx;
+    border-radius: 4px;
+    font-size: 12px;
+    margin-right: 16rpx;
+}
+
+.urgent {
+    background-color: #ff4d4f;
+    color: #fff;
+}
+
+.important {
+    background-color: #faad14;
+    color: #fff;
+}
+
+.normal {
+    background-color: #1890ff;
+    color: #fff;
+}
+
+.type {
+    font-size: 14px;
+    color: #666;
+}
+
+.description {
+    font-size: 14px;
+    color: #333;
+    margin-bottom: 16rpx;
+    line-height: 1.5;
+}
+
+.person-info {
+    font-size: 14px;
+    color: #666;
+}
+
+.label {
+    color: #999;
+}
+
+.action-buttons {
+    display: flex;
+    justify-content: space-between;
+}
+
+.button-content text {
+    margin-left: 8rpx;
+    font-size: 12px;
+}
+
+.uni-button {
+    margin: 0;
+    flex: 1;
+    margin-right: 16rpx;
+}
+
+.uni-button:last-child {
+    margin-right: 0;
+}
+
+.pagination-container {
+    width: 80vw;
+    margin: auto;
+}
+
+.no-data {
+    text-align: center;
+    color: #999;
+    font-size: 14px;
+    padding: 20rpx;
+}
+
+.message-box {
+    padding: 16rpx 24rpx;
+    background-color: #f8f9fb;
+    border-radius: 8rpx;
+    font-size: 24rpx;
+    color: #666;
+    line-height: 1.6;
+    margin-top: 20rpx;
+    border: 1px solid #eee;
+}
+
+/* 扩展不同状态的消息样式(可选) */
+.message-box.processing {
+    background-color: #fff3d6;
+    border-color: #ffe5b4;
+}
+
+.message-box.completed {
+    background-color: #e8f9eb;
+    border-color: #c8e6c9;
+}
+
+.message-box.mistake {
+    background-color: #e0f2f1;
+    border-color: #b2dfdb;
+}
+
+.message-box.ignore {
+    background-color: #fff3b0;
+    border-color: #fff9c4;
+}
+</style>
+    

+ 10 - 12
pages/index/index.vue

@@ -55,17 +55,13 @@
 
       <!-- 状态概览 -->
       <view class="status-overview">
-        <view class="status-item">
+        <!-- <view class="status-item">
           <text class="status-value">358</text>
           <text class="status-label">在线设备</text>
-        </view>
+        </view> -->
         <view class="status-item">
-          <text class="status-value">3</text>
           <text class="status-label">待处理告警</text>
-        </view>
-        <view class="status-item">
-          <text class="status-value">98%</text>
-          <text class="status-label">设备在线率</text>
+					<text class="status-value">3</text>
         </view>
       </view>
     </scroll-view>
@@ -222,7 +218,7 @@ page {
 
 .status-overview {
   display: grid;
-  grid-template-columns: repeat(3, 1fr);
+  grid-template-columns: repeat(1, 1fr);
   gap: 24rpx;
   background-color: #FFFFFF;
   padding: 32rpx;
@@ -232,19 +228,21 @@ page {
 
 .status-item {
   display: flex;
-  flex-direction: column;
-  align-items: center;
+  /* flex-direction: column; */
+  /* align-items: center; */
+	justify-content: space-between;
   gap: 8rpx;
 }
 
 .status-value {
-  font-size: 24px;
+  font-size: 20px;
   font-weight: 600;
   color: #333333;
 }
 
 .status-label {
-  font-size: 14px;
+  font-size: 18px;
+	font-weight: 700;
   color: #666666;
 }