Files
chengkong-huakaiwuye/huakai-app/pages/index/index.vue
2026-08-15 17:57:18 +08:00

213 lines
6.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="home">
<!-- 顶部品牌区 -->
<view class="header">
<view class="app-name">花开物业</view>
<view class="app-slogan">物业缴费服务</view>
</view>
<!-- 未登录:登录引导 -->
<view v-if="!logged" class="guest">
<view class="guest-card">
<view class="guest-title">欢迎使用花开物业</view>
<view class="guest-tip">登录后可查询缴费记录、在线缴纳</view>
<button class="primary-btn" @click="goLogin">登录 / 注册</button>
</view>
</view>
<!-- 已登录:缴费记录 -->
<view v-else class="member">
<view class="section-head">
<text class="section-title">缴费记录</text>
<text class="section-sub" v-if="records.length">共 {{ records.length }} 条</text>
</view>
<view v-if="loading" class="empty">加载中...</view>
<view v-else-if="records.length === 0" class="empty">暂无缴费记录</view>
<view v-else class="record-list">
<view v-for="(r, i) in records" :key="i" class="record-item">
<view class="record-left">
<text class="record-type">{{ r.type }}</text>
<text class="record-time">{{ r.time }}</text>
</view>
<view class="record-right">
<text class="record-amount">{{ r.amount }}</text>
<text class="record-status">{{ r.status }}</text>
</view>
</view>
</view>
<button class="logout-btn" @click="logout">退出登录</button>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { getTopupRecordWithStat } from '/pageSubPack/api/apiSub.js'
import { isLoggedIn, clearLoginState } from '/pageSubPack/api/auth.js'
import { getAppPaymentData } from '/pageSubPack/api/appLaunch.js'
const logged = ref(false)
const loading = ref(false)
const records = ref([])
onShow(() => {
// 从花开物业 App 跳转进入(带支付参数)→ 直接进入缴费页
if (getAppPaymentData()) {
uni.redirectTo({ url: '/pages/arrearsPayment/arrearsPayment' })
return
}
logged.value = isLoggedIn()
if (logged.value) {
loadRecords()
}
})
const goLogin = () => {
uni.navigateTo({ url: '/pageSubPack/loginSub/pwd-login' })
}
const loadRecords = async () => {
const residentUserId = uni.getStorageSync('userId') || uni.getStorageSync('residentUserId')
if (!residentUserId) {
records.value = []
return
}
loading.value = true
try {
const res = await getTopupRecordWithStat({ residentUserId, pageNum: 1, pageSize: 20 })
if (res.code === 200 && res.data) {
const list = res.data.list || res.data.records || res.data.rows || []
// 打印首条原始数据,便于核对后端返回字段
if (list.length) console.log('缴费记录示例:', JSON.stringify(list[0]))
records.value = list.map(normalizeRecord)
} else {
records.value = []
}
} catch (err) {
console.error('加载缴费记录失败:', err)
records.value = []
} finally {
loading.value = false
}
}
// 后端返回字段未明确,这里做防御性映射,字段名以实际接口为准
const normalizeRecord = (r) => ({
type: r.payType || r.type || r.goodName || r.feeName || '缴费',
time: r.createTime || r.payTime || r.updateTime || '',
amount: formatAmount(r.payAmount ?? r.amount ?? r.rechargeAmount ?? r.money),
status: formatStatus(r.status ?? r.payStatus)
})
const formatAmount = (v) => {
if (v === undefined || v === null || v === '') return ''
const n = Number(v)
return isNaN(n) ? String(v) : '¥' + n.toFixed(2)
}
const formatStatus = (s) => {
if (s === undefined || s === null || s === '') return ''
const map = { 0: '待支付', 1: '支付成功', 2: '支付失败' }
if (map[s] !== undefined) return map[s]
const str = String(s)
if (str === 'SUCCESS') return '支付成功'
if (str === 'FAIL') return '支付失败'
return str
}
const logout = () => {
uni.showModal({
title: '提示',
content: '确定退出登录吗?',
success: (res) => {
if (res.confirm) {
clearLoginState()
logged.value = false
records.value = []
}
}
})
}
</script>
<style scoped>
page { background-color: #f6f7fb; }
.home { min-height: 100vh; }
.header {
background: linear-gradient(180deg, #1677ff, #4c9aff);
padding: 120rpx 40rpx 60rpx;
color: #fff;
}
.app-name { font-size: 44rpx; font-weight: 700; }
.app-slogan { font-size: 26rpx; opacity: 0.85; margin-top: 12rpx; }
.guest { padding: 40rpx; }
.guest-card {
background: #fff;
border-radius: 20rpx;
padding: 60rpx 40rpx;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
}
.guest-title { font-size: 34rpx; font-weight: 600; color: #222; }
.guest-tip { font-size: 26rpx; color: #888; margin: 20rpx 0 50rpx; text-align: center; }
.primary-btn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
background: #1677ff;
color: #fff;
border-radius: 44rpx;
font-size: 30rpx;
}
.primary-btn::after { border: none; }
.member { padding: 32rpx 40rpx; }
.section-head {
display: flex;
align-items: baseline;
justify-content: space-between;
margin-bottom: 24rpx;
}
.section-title { font-size: 34rpx; font-weight: 600; color: #222; }
.section-sub { font-size: 24rpx; color: #999; }
.empty { text-align: center; color: #999; font-size: 28rpx; padding: 120rpx 0; }
.record-list { display: flex; flex-direction: column; gap: 20rpx; }
.record-item {
display: flex;
align-items: center;
justify-content: space-between;
background: #fff;
border-radius: 16rpx;
padding: 28rpx 30rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
}
.record-left { display: flex; flex-direction: column; }
.record-type { font-size: 30rpx; color: #222; font-weight: 500; }
.record-time { font-size: 24rpx; color: #999; margin-top: 8rpx; }
.record-right { display: flex; flex-direction: column; align-items: flex-end; }
.record-amount { font-size: 32rpx; color: #1677ff; font-weight: 600; }
.record-status { font-size: 24rpx; color: #999; margin-top: 8rpx; }
.logout-btn {
margin-top: 60rpx;
width: 100%;
height: 88rpx;
line-height: 88rpx;
background: #fff;
color: #666;
border-radius: 44rpx;
font-size: 30rpx;
}
.logout-btn::after { border: none; }
</style>