|
|
@@ -1,98 +1,106 @@
|
|
|
<script setup lang="ts">
|
|
|
import { computed, ref } from 'vue'
|
|
|
-import { onLoad, onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
|
|
|
+import { onShow, onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
|
|
|
import SegmentTabs from '@/components/SegmentTabs.vue'
|
|
|
import BusinessCard from '@/components/BusinessCard.vue'
|
|
|
-import { warnings, type ListItem } from '@/data/mock'
|
|
|
+import type { ListItem } from '@/data/mock'
|
|
|
import { getNoticeList, getNoticeTypeLabel, type SystemNotice } from '@/services/notices'
|
|
|
import { getMobilePendingWorkOrders, workOrderStatusText, workOrderTone, type WorkOrder } from '@/services/workorders'
|
|
|
+import { getMobilePendingWarnings, getWarningRevision, warningStatusText, warningStatusTone, type EarlyWarning } from '@/services/warnings'
|
|
|
import { navigateTo } from '@/utils/navigation'
|
|
|
|
|
|
const active = ref(0)
|
|
|
const notices = ref<SystemNotice[]>([])
|
|
|
const pendingOrders = ref<WorkOrder[]>([])
|
|
|
+const pendingWarnings = ref<EarlyWarning[]>([])
|
|
|
const pendingTotal = ref(0)
|
|
|
+const pendingWarningTotal = ref(0)
|
|
|
const pendingPageNum = ref(1)
|
|
|
+const warningPageNum = ref(1)
|
|
|
const pendingLoading = ref(false)
|
|
|
+const warningLoading = ref(false)
|
|
|
const pendingLoaded = ref(false)
|
|
|
+const warningLoaded = ref(false)
|
|
|
const pendingHasMore = computed(() => pendingOrders.value.length < pendingTotal.value)
|
|
|
-const list = computed<ListItem[]>(() => active.value === 0 ? pendingOrders.value.map(toCard) : warnings.slice(0, 4))
|
|
|
-const pendingCount = computed(() => pendingTotal.value + warnings.filter(item => item.status !== '已解除').length)
|
|
|
+const warningHasMore = computed(() => pendingWarnings.value.length < pendingWarningTotal.value)
|
|
|
+const list = computed<ListItem[]>(() => active.value === 0 ? pendingOrders.value.map(toCard) : pendingWarnings.value.map(toWarningCard))
|
|
|
+const pendingCount = computed(() => pendingTotal.value + pendingWarningTotal.value)
|
|
|
|
|
|
-async function refresh() {
|
|
|
- await Promise.all([loadPendingOrders(true), loadNotices()])
|
|
|
-}
|
|
|
-
|
|
|
-onLoad(refresh)
|
|
|
-onPullDownRefresh(async () => {
|
|
|
- await refresh()
|
|
|
- uni.stopPullDownRefresh()
|
|
|
-})
|
|
|
-onReachBottom(() => {
|
|
|
- if (active.value === 0) loadPendingOrders()
|
|
|
+async function refresh() { await Promise.all([loadPendingOrders(true), loadPendingWarnings(true), loadNotices()]) }
|
|
|
+let seenWarningRevision = -1
|
|
|
+onShow(() => {
|
|
|
+ const revision = getWarningRevision()
|
|
|
+ if (seenWarningRevision < 0) { seenWarningRevision = revision; refresh() }
|
|
|
+ else if (seenWarningRevision !== revision) { seenWarningRevision = revision; loadPendingWarnings(true) }
|
|
|
})
|
|
|
+onPullDownRefresh(async () => { await refresh(); uni.stopPullDownRefresh() })
|
|
|
+onReachBottom(() => active.value === 0 ? loadPendingOrders() : loadPendingWarnings())
|
|
|
|
|
|
function toCard(order: WorkOrder): ListItem {
|
|
|
const delayPending = Number(order.orderStatus) === 3 && Number(order.delayApplyStatus) === 1
|
|
|
return { id: order.orderNo, title: order.orderDesc || '故障工单', status: workOrderStatusText(order.orderStatus), tone: workOrderTone(order.orderStatus), secondaryStatus: delayPending ? '延期待审核' : undefined, secondaryTone: delayPending ? 'orange' : undefined, fields: [
|
|
|
...(delayPending ? [{ label: '延期申请', value: `待审核${order.delayedDeadline ? `(延期至 ${order.delayedDeadline})` : ''}` }] : []),
|
|
|
- { label: '工单描述', value: order.orderDesc || '—' },
|
|
|
- { label: '设备信息', value: order.deviceId ? `${order.deviceCode || '—'}${order.deviceName ? `(${order.deviceName})` : ''}` : '未关联设备' },
|
|
|
+ { label: '工单描述', value: order.orderDesc || '—' }, { label: '设备信息', value: order.deviceId ? `${order.deviceCode || '—'}${order.deviceName ? `(${order.deviceName})` : ''}` : '未关联设备' },
|
|
|
{ label: '安装位置', value: order.deviceLocation || '—' },
|
|
|
] }
|
|
|
}
|
|
|
|
|
|
+function toWarningCard(item: EarlyWarning): ListItem {
|
|
|
+ return { id: item.warningNo, title: item.warningContent || '预警', status: item.statusLabel || warningStatusText(item.status), tone: warningStatusTone(item.status), actionLabel: '详情', fields: [
|
|
|
+ { label: '预警内容', value: item.warningContent || '—' }, { label: '预警类型', value: item.warningTypeName || item.warningType || '—' },
|
|
|
+ { label: '关联设备', value: item.deviceCode ? `${item.deviceCode}${item.deviceName ? `(${item.deviceName})` : ''}` : '—' },
|
|
|
+ ] }
|
|
|
+}
|
|
|
+
|
|
|
+function updateBadge() {
|
|
|
+ const count = pendingCount.value
|
|
|
+ if (count > 0) uni.setTabBarBadge({ index: 0, text: String(Math.min(count, 99)) })
|
|
|
+ else uni.removeTabBarBadge({ index: 0 })
|
|
|
+}
|
|
|
+
|
|
|
async function loadPendingOrders(reset = false) {
|
|
|
if (pendingLoading.value || (!reset && !pendingHasMore.value)) return
|
|
|
- if (reset) {
|
|
|
- pendingPageNum.value = 1
|
|
|
- pendingOrders.value = []
|
|
|
- pendingTotal.value = 0
|
|
|
- }
|
|
|
+ if (reset) { pendingPageNum.value = 1; pendingOrders.value = []; pendingTotal.value = 0 }
|
|
|
pendingLoading.value = true
|
|
|
try {
|
|
|
const page = await getMobilePendingWorkOrders({ pageNum: pendingPageNum.value, pageSize: 10 })
|
|
|
pendingOrders.value = reset ? page.records : pendingOrders.value.concat(page.records)
|
|
|
pendingTotal.value = Number(page.total) || 0
|
|
|
if (pendingOrders.value.length < pendingTotal.value) pendingPageNum.value += 1
|
|
|
- const count = pendingCount.value
|
|
|
- if (count > 0) uni.setTabBarBadge({ index: 0, text: String(Math.min(count, 99)) })
|
|
|
- else uni.removeTabBarBadge({ index: 0 })
|
|
|
+ updateBadge()
|
|
|
} catch (error) {
|
|
|
- if (reset) {
|
|
|
- pendingOrders.value = []
|
|
|
- pendingTotal.value = 0
|
|
|
- }
|
|
|
+ if (reset) { pendingOrders.value = []; pendingTotal.value = 0 }
|
|
|
uni.showToast({ title: error instanceof Error ? error.message : '待办工单获取失败', icon: 'none' })
|
|
|
- } finally {
|
|
|
- pendingLoading.value = false
|
|
|
- pendingLoaded.value = true
|
|
|
- }
|
|
|
+ } finally { pendingLoading.value = false; pendingLoaded.value = true }
|
|
|
}
|
|
|
|
|
|
-async function loadNotices() {
|
|
|
+async function loadPendingWarnings(reset = false) {
|
|
|
+ if (warningLoading.value || (!reset && !warningHasMore.value)) return
|
|
|
+ if (reset) { warningPageNum.value = 1; pendingWarnings.value = []; pendingWarningTotal.value = 0 }
|
|
|
+ warningLoading.value = true
|
|
|
try {
|
|
|
- const result = await getNoticeList({ pageNum: 1, pageSize: 10 })
|
|
|
- notices.value = result.rows.filter(item => item.status !== '1')
|
|
|
+ const page = await getMobilePendingWarnings({ pageNum: warningPageNum.value, pageSize: 10 })
|
|
|
+ pendingWarnings.value = reset ? page.records : pendingWarnings.value.concat(page.records)
|
|
|
+ pendingWarningTotal.value = Number(page.total) || 0
|
|
|
+ if (pendingWarnings.value.length < pendingWarningTotal.value) warningPageNum.value += 1
|
|
|
+ updateBadge()
|
|
|
} catch (error) {
|
|
|
- notices.value = []
|
|
|
- uni.showToast({ title: error instanceof Error ? error.message : '通知公告获取失败', icon: 'none' })
|
|
|
- }
|
|
|
+ if (reset) { pendingWarnings.value = []; pendingWarningTotal.value = 0 }
|
|
|
+ uni.showToast({ title: error instanceof Error ? error.message : '待办预警获取失败', icon: 'none' })
|
|
|
+ } finally { warningLoading.value = false; warningLoaded.value = true }
|
|
|
}
|
|
|
|
|
|
-function openNotice(item?: SystemNotice) {
|
|
|
- if (item?.noticeId == null) return
|
|
|
- navigateTo(`/pages/message/notice-detail?id=${item.noticeId}`)
|
|
|
+async function loadNotices() {
|
|
|
+ try { const result = await getNoticeList({ pageNum: 1, pageSize: 10 }); notices.value = result.rows.filter(item => item.status !== '1') }
|
|
|
+ catch (error) { notices.value = []; uni.showToast({ title: error instanceof Error ? error.message : '通知公告获取失败', icon: 'none' }) }
|
|
|
}
|
|
|
|
|
|
-function openItem(index: number, status: string) {
|
|
|
+function openNotice(item?: SystemNotice) { if (item?.noticeId != null) navigateTo(`/pages/message/notice-detail?id=${item.noticeId}`) }
|
|
|
+function openItem(index: number) {
|
|
|
if (active.value === 0) navigateTo(`/pages/message/workorder-detail?id=${pendingOrders.value[index]?.orderId}`)
|
|
|
- else navigateTo(`/pages/message/warning-detail?status=${encodeURIComponent(status)}`)
|
|
|
-}
|
|
|
-
|
|
|
-function openAll() {
|
|
|
- navigateTo(active.value === 0 ? '/pages/profile/workorders' : '/pages/profile/warnings')
|
|
|
+ else navigateTo(`/pages/message/warning-detail?id=${pendingWarnings.value[index]?.warningId}`)
|
|
|
}
|
|
|
+function openAll() { navigateTo(active.value === 0 ? '/pages/profile/workorders' : '/pages/profile/warnings') }
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
@@ -112,10 +120,10 @@ function openAll() {
|
|
|
</view>
|
|
|
<SegmentTabs v-model="active" :items="['待办工单', '待办预警']" action-label="查看全部" @action="openAll" />
|
|
|
<view class="page-content with-tabs message-list">
|
|
|
- <BusinessCard v-for="(item,index) in list" :key="item.id" :item="item" :id-label="active === 0 ? '工单编号' : '预警编号'" @open="openItem(index, item.status)" />
|
|
|
- <view v-if="pendingLoaded && !list.length" class="empty-list">暂无待办数据</view>
|
|
|
- <view v-else-if="active === 0 && pendingLoading" class="load-tip">正在加载...</view>
|
|
|
- <view v-else-if="active === 0 && pendingOrders.length && !pendingHasMore" class="load-tip">已加载全部</view>
|
|
|
+ <BusinessCard v-for="(item,index) in list" :key="item.id" :item="item" :id-label="active === 0 ? '工单编号' : '预警编号'" detail-label="详情" @open="openItem(index)" />
|
|
|
+ <view v-if="(active === 0 ? pendingLoaded : warningLoaded) && !list.length" class="empty-list">暂无待办数据</view>
|
|
|
+ <view v-else-if="active === 0 ? pendingLoading : warningLoading" class="load-tip">正在加载...</view>
|
|
|
+ <view v-else-if="list.length && !(active === 0 ? pendingHasMore : warningHasMore)" class="load-tip">已加载全部</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
</template>
|
|
|
@@ -124,7 +132,7 @@ function openAll() {
|
|
|
.hero { padding: calc(36rpx + env(safe-area-inset-top)) 26rpx 28rpx; color: #fff; background: linear-gradient(135deg,#061b34,#174e76); }
|
|
|
.hero-top { display: flex; align-items: center; justify-content: space-between; padding: 4rpx 5rpx 30rpx; }
|
|
|
.hello,.sub { display: block; }.hello{font-size:36rpx;font-weight:650}.sub{margin-top:10rpx;color:rgba(255,255,255,.78);font-size:24rpx}
|
|
|
-.notice{display:flex;align-items:center;height:82rpx;padding:0 22rpx;border-radius:16rpx;background:rgba(255,255,255,.16);backdrop-filter:blur(8px)}.bell-icon{flex-shrink:0;width:34rpx;height:34rpx;margin-right:16rpx;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9'/%3E%3Cpath d='M13.7 21a2 2 0 0 1-3.4 0'/%3E%3C/svg%3E") center/contain no-repeat}.notice-swiper{flex:1;height:82rpx;min-width:0}.notice-swiper swiper-item{display:flex;align-items:center}.notice-main{display:flex;flex:1;align-items:center;min-width:0}.notice-label{flex-shrink:0;margin-right:16rpx;padding:4rpx 13rpx;color:#9be2f6;border-radius:99rpx;background:rgba(102,215,248,.14);font-size:22rpx;font-weight:600}.notice-text{overflow:hidden;color:rgba(255,255,255,.9);font-size:24rpx;text-overflow:ellipsis;white-space:nowrap}.empty-notice{color:rgba(255,255,255,.68)}.more{font-size:45rpx}
|
|
|
+.notice{display:flex;align-items:center;height:82rpx;padding:0 22rpx;border-radius:16rpx;background:rgba(255,255,255,.14)}.bell-icon{flex-shrink:0;width:34rpx;height:34rpx;margin-right:16rpx;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9'/%3E%3Cpath d='M13.7 21a2 2 0 0 1-3.4 0'/%3E%3C/svg%3E") center/contain no-repeat}.notice-swiper{flex:1;height:82rpx;min-width:0}.notice-swiper swiper-item{display:flex;align-items:center}.notice-main{display:flex;flex:1;align-items:center;min-width:0}.notice-label{flex-shrink:0;margin-right:16rpx;padding:4rpx 13rpx;color:#9be2f6;border-radius:99rpx;background:rgba(102,215,248,.14);font-size:22rpx;font-weight:600}.notice-text{overflow:hidden;color:#fff;font-size:26rpx;font-weight:500;text-overflow:ellipsis;white-space:nowrap}.empty-notice{color:rgba(255,255,255,.75)}.more{font-size:45rpx}
|
|
|
.message-list{padding-top:22rpx}
|
|
|
.empty-list{padding:100rpx 0;color:#94a0ae;text-align:center;font-size:24rpx}
|
|
|
.load-tip{padding:28rpx;color:#98a4b2;text-align:center;font-size:23rpx}
|