From ea689dd91eaa72425dc01759042c3b4eb2186512 Mon Sep 17 00:00:00 2001
From: doum <doum>
Date: 星期三, 17 六月 2026 10:14:44 +0800
Subject: [PATCH] 新增智能电表、空调管理

---
 h5/pages/customer/bill/list.vue |  270 +++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 249 insertions(+), 21 deletions(-)

diff --git a/h5/pages/customer/bill/list.vue b/h5/pages/customer/bill/list.vue
index 3f19a89..ea842a2 100644
--- a/h5/pages/customer/bill/list.vue
+++ b/h5/pages/customer/bill/list.vue
@@ -4,27 +4,77 @@
 
     <view class="cu-bill-page__header">
 
-      <view class="cu-tabs cu-bill-tabs">
+      <view class="cu-bill-page__toolbar">
 
-        <view
+        <view class="cu-tabs cu-bill-tabs cu-bill-tabs--toolbar">
 
-          v-for="(t, i) in tabs"
+          <view
 
-          :key="i"
+            v-for="(t, i) in tabs"
 
-          :class="['cu-tab', tabIdx === i ? 'cu-tab--active' : '']"
+            :key="i"
 
-          @click="tabIdx = i; load()"
+            :class="['cu-tab', tabIdx === i ? 'cu-tab--active' : '']"
 
-        >{{ t }}</view>
+            @click="switchPayTab(i)"
+
+          >{{ t }}</view>
+
+        </view>
+
+
+
+        <picker :range="costTypeFilters" range-key="label" @change="onCostTypeChange">
+
+          <view :class="['cu-bill-cost-picker', costTypeIdx > 0 ? 'cu-bill-cost-picker--active' : '', costTypePickerClass]">
+
+            <text class="cu-bill-cost-picker__label">{{ costTypeLabel }}</text>
+
+            <text class="cu-bill-cost-picker__arrow">鈻�</text>
+
+          </view>
+
+        </picker>
 
       </view>
 
+
+
       <view class="cu-bill-summary">
 
-        <text class="cu-bill-summary__count">{{ list.length }}</text>
+        <view class="cu-bill-summary__main">
 
-        <text class="cu-bill-summary__label">绗旇处鍗�</text>
+          <text class="cu-bill-summary__count">{{ list.length }}</text>
+
+          <text class="cu-bill-summary__label">绗旇处鍗�</text>
+
+        </view>
+
+
+
+        <view v-if="overdueCount > 0" class="cu-bill-summary__overdue-group">
+
+          <text class="cu-bill-summary__chip cu-bill-summary__chip--stat">{{ overdueCount }}绗旈�炬湡</text>
+
+          <view
+
+            :class="['cu-bill-summary__chip', 'cu-bill-summary__chip--filter', onlyOverdue ? 'cu-bill-summary__chip--filter-on' : '']"
+
+            @click="toggleOnlyOverdue"
+
+          >
+
+            <view :class="['cu-bill-summary__check', onlyOverdue ? 'cu-bill-summary__check--on' : '']">
+
+              <text v-if="onlyOverdue" class="cu-bill-summary__check-icon">鉁�</text>
+
+            </view>
+
+            <text class="cu-bill-summary__chip-text">浠呯湅閫炬湡</text>
+
+          </view>
+
+        </view>
 
       </view>
 
@@ -36,7 +86,7 @@
 
       <view
 
-        v-for="item in list"
+        v-for="item in displayList"
 
         :key="item.id"
 
@@ -52,19 +102,21 @@
 
         <view class="cu-bill-card__body">
 
-          <view class="cu-bill-card__head">
+          <view class="cu-bill-card__type-row">
 
-            <view class="cu-bill-card__head-main">
+            <view :class="['cu-bill-type-tag', costTypeBadgeClass(item.costType)]">
 
-              <text class="cu-bill-card__type">{{ costTypeText(item.costType) }}</text>
-
-              <text class="cu-bill-card__code">{{ item.code }}</text>
+              <text class="cu-bill-type-tag__text">{{ costTypeText(item.costType) }}</text>
 
             </view>
 
             <text :class="['cu-status', payStatusClass(item.payStatus)]">{{ payText(item.payStatus) }}</text>
 
           </view>
+
+
+
+          <view class="cu-bill-card__code">{{ item.code }}</view>
 
 
 
@@ -117,10 +169,15 @@
 
 
           <view class="cu-bill-card__meta">
+
             <view class="cu-bill-card__meta-item cu-bill-card__meta-item--full">
+
               <text class="cu-bill-card__meta-label">璁¤垂鍛ㄦ湡</text>
+
               <text class="cu-bill-card__meta-value">{{ item.startDate }} ~ {{ item.endDate }}</text>
+
             </view>
+
           </view>
 
 
@@ -137,7 +194,7 @@
 
       </view>
 
-      <u-empty v-if="!list.length" text="鏆傛棤璐﹀崟" margin-top="80" />
+      <u-empty v-if="!displayList.length" :text="onlyOverdue ? '鏆傛棤閫炬湡璐﹀崟' : '鏆傛棤璐﹀崟'" margin-top="80" />
 
     </view>
 
@@ -175,9 +232,105 @@
 
 
 
+const COST_TYPE_FILTERS = [
+
+  { label: '璐圭敤绫诲瀷', value: null },
+
+  { label: '绉熻祦璐�', value: 0 },
+
+  { label: '鐗╀笟璐�', value: 1 },
+
+  { label: '绉熻祦鎶奸噾', value: 2 },
+
+  { label: '鐗╀笟鎶奸噾', value: 3 },
+
+  { label: '姘寸數璐�', value: 4 },
+
+  { label: '鏉傞」璐�', value: 5 },
+
+  { label: '鍏朵粬', value: 6 },
+
+  { label: '淇濊瘉閲�', value: 7 }
+
+]
+
+
+
 export default {
 
-  data () { return { list: [], tabIdx: 0, tabs: ['鍏ㄩ儴', '寰呮敮浠�', '宸叉敮浠�'] } },
+  data () {
+
+    return {
+
+      list: [],
+
+      tabIdx: 0,
+
+      costTypeIdx: 0,
+
+      tabs: ['鍏ㄩ儴', '寰呮敮浠�', '宸叉敮浠�'],
+
+      costTypeFilters: COST_TYPE_FILTERS,
+
+      onlyOverdue: false
+
+    }
+
+  },
+
+  computed: {
+
+    costTypeLabel () {
+
+      return this.costTypeFilters[this.costTypeIdx].label
+
+    },
+
+    costTypePickerClass () {
+
+      const value = this.costTypeFilters[this.costTypeIdx].value
+
+      if (value == null) return ''
+
+      const map = {
+
+        0: 'cu-bill-cost-picker--rent',
+
+        1: 'cu-bill-cost-picker--property',
+
+        2: 'cu-bill-cost-picker--deposit',
+
+        3: 'cu-bill-cost-picker--deposit',
+
+        4: 'cu-bill-cost-picker--utility',
+
+        5: 'cu-bill-cost-picker--misc',
+
+        6: 'cu-bill-cost-picker--misc',
+
+        7: 'cu-bill-cost-picker--deposit'
+
+      }
+
+      return map[value] || ''
+
+    },
+
+    overdueCount () {
+
+      return this.list.filter(item => this.isOverdue(item)).length
+
+    },
+
+    displayList () {
+
+      if (!this.onlyOverdue) return this.list
+
+      return this.list.filter(item => this.isOverdue(item))
+
+    }
+
+  },
 
   onShow () { this.load() },
 
@@ -187,13 +340,79 @@
 
       const payTab = this.tabIdx === 0 ? null : (this.tabIdx === 1 ? 0 : 1)
 
-      customerBillPage({ page: 1, capacity: 50, model: { payTab } })
+      const costType = this.costTypeFilters[this.costTypeIdx].value
 
-        .then(res => { this.list = (res.data && res.data.records) || [] })
+      const model = { payTab }
+
+      if (costType != null) model.costType = costType
+
+      customerBillPage({ page: 1, capacity: 50, model })
+
+        .then(res => {
+
+          this.list = (res.data && res.data.records) || []
+
+          if (!this.list.some(item => this.isOverdue(item))) this.onlyOverdue = false
+
+        })
+
+    },
+
+    toggleOnlyOverdue () {
+
+      this.onlyOverdue = !this.onlyOverdue
+
+    },
+
+    switchPayTab (i) {
+
+      if (this.tabIdx === i) return
+
+      this.tabIdx = i
+
+      this.load()
+
+    },
+
+    onCostTypeChange (e) {
+
+      const idx = Number(e.detail.value)
+
+      if (this.costTypeIdx === idx) return
+
+      this.costTypeIdx = idx
+
+      this.load()
 
     },
 
     costTypeText (type) { return COST_TYPE_MAP[type] || '璐﹀崟' },
+
+    costTypeBadgeClass (type) {
+
+      const map = {
+
+        0: 'cu-bill-type-tag--rent',
+
+        1: 'cu-bill-type-tag--property',
+
+        2: 'cu-bill-type-tag--deposit',
+
+        3: 'cu-bill-type-tag--deposit',
+
+        4: 'cu-bill-type-tag--utility',
+
+        5: 'cu-bill-type-tag--misc',
+
+        6: 'cu-bill-type-tag--misc',
+
+        7: 'cu-bill-type-tag--deposit'
+
+      }
+
+      return map[type] || 'cu-bill-type-tag--default'
+
+    },
 
     formatMoney (val) {
 
@@ -242,16 +461,27 @@
     },
 
     contractPeriod (item) {
+
       if (!item) return '-'
+
       const start = this.formatDate(item.contractStartDate)
+
       const end = this.formatDate(item.contractEndDate)
+
       if (!start && !end) return '-'
+
       return `${start || '-'} ~ ${end || '-'}`
+
     },
+
     formatDate (val) {
+
       if (!val) return ''
+
       return String(val).replace('T', ' ').substring(0, 10)
+
     },
+
     goDetail (id) { uni.navigateTo({ url: `/pages/customer/bill/detail?id=${id}` }) }
 
   }
@@ -259,5 +489,3 @@
 }
 
 </script>
-
-

--
Gitblit v1.9.3