This commit is contained in:
Zy
2026-08-20 09:31:38 +08:00
8 changed files with 261 additions and 140 deletions

View File

@@ -2,8 +2,8 @@
"name" : "花开管家", "name" : "花开管家",
"appid" : "__UNI__5F224F3", "appid" : "__UNI__5F224F3",
"description" : "智慧社区管家端,专为小区物业管理人员打造,支持多小区灵活切换管理。集成账号密码、手机号密码双重登录模式,内置忘记密码找回功能,保障账号安全。涵盖消息通知、日常巡检、故障报修、一键开门、工单流转、投诉处理等核心办公功能,物业人员可在线完成巡检打卡、问题上报、工单派发跟进、投诉对接处理等日常工作,同时支持查看个人上报记录、巡检历史,便捷修改账号信息与登录密码。高效简化社区物业办公流程,提升小区服务与管理效率,打造便捷智能的社区管理服务平台。", "description" : "智慧社区管家端,专为小区物业管理人员打造,支持多小区灵活切换管理。集成账号密码、手机号密码双重登录模式,内置忘记密码找回功能,保障账号安全。涵盖消息通知、日常巡检、故障报修、一键开门、工单流转、投诉处理等核心办公功能,物业人员可在线完成巡检打卡、问题上报、工单派发跟进、投诉对接处理等日常工作,同时支持查看个人上报记录、巡检历史,便捷修改账号信息与登录密码。高效简化社区物业办公流程,提升小区服务与管理效率,打造便捷智能的社区管理服务平台。",
"versionName" : "1.0.7", "versionName" : "1.1.0",
"versionCode" : 107, "versionCode" : 110,
"transformPx" : false, "transformPx" : false,
"app-plus" : { "app-plus" : {
"usingComponents" : true, "usingComponents" : true,

View File

@@ -2,7 +2,9 @@
<view class="form-container"> <view class="form-container">
<!-- 维修项目展示 --> <!-- 维修项目展示 -->
<view class="form-item"> <view class="form-item">
<text class="label">维修项目</text> <view class="label">
<text class="required">*</text>维修项目
</view>
<view class="value" @click="goBackSelect"> <view class="value" @click="goBackSelect">
<view> <view>
<text v-if="!repairProject">请选择项目</text> <text v-if="!repairProject">请选择项目</text>
@@ -14,34 +16,43 @@
<!-- 标题输入 --> <!-- 标题输入 -->
<view class="form-item"> <view class="form-item">
<text class="label">标题</text> <text class="label">标题</text>
<!-- <input type="text" placeholder="请输入问题标题" v-model="form.title" /> -->
<uni-easyinput <uni-easyinput
v-model="form.title" v-model="form.title"
placeholder="请输入内容" placeholder="请输入标题(最多30字符)"
:inputBorder="false" :inputBorder="false"
maxlength="30"
></uni-easyinput> ></uni-easyinput>
</view> </view>
<!-- 问题描述 --> <!-- 问题描述 -->
<view class="form-item-wenti"> <view class="form-item-wenti">
<text class="label">问题描述</text> <!-- <text class="label">问题描述</text> -->
<!-- <textarea placeholder="请输入问题内容" v-model="form.desc" rows="5" ></textarea> --> <view class="label">
<uni-easyinput <text class="required">*</text>问题描述
</view>
<view class="textarea-wrap">
<textarea v-model="form.desc" placeholder="请描述你的问题(最多200字)" maxlength="200" class="desc-textarea" />
<text class="char-count">{{ form.desc.length }}/200</text>
</view>
<!-- <uni-easyinput
v-model="form.desc" v-model="form.desc"
placeholder="请描述你的问题" placeholder="请描述你的问题"
type="textarea" type="textarea"
></uni-easyinput> ></uni-easyinput> -->
</view> </view>
<!-- 手机号 --> <!-- 手机号 -->
<view class="form-item"> <view class="form-item">
<text class="label">手机号</text> <view class="label">
<text class="required">*</text>手机号
</view>
<uni-easyinput <uni-easyinput
type="number" type="number"
v-model="form.phone" v-model="form.phone"
placeholder="请输入手机号" placeholder="请输入手机号"
:inputBorder="false" :inputBorder="false"
maxlength="11"
></uni-easyinput> ></uni-easyinput>
</view> </view>
@@ -60,7 +71,7 @@
<!-- <uni-icons type="close" size="16" @click="deleteImage(index)"></uni-icons> --> <!-- <uni-icons type="close" size="16" @click="deleteImage(index)"></uni-icons> -->
</view> </view>
<!-- 上传按钮 --> <!-- 上传按钮 -->
<view class="upload-btn" @click="chooseImage" v-if="form.images.length < 3"> <view class="upload-btn" @click="chooseImage" v-if="form.images.length < 9">
<uni-icons type="plusempty" size="24"></uni-icons> <uni-icons type="plusempty" size="24"></uni-icons>
<!-- <text>上传照片</text> --> <!-- <text>上传照片</text> -->
</view> </view>
@@ -69,6 +80,9 @@
<!-- 提交按钮 --> <!-- 提交按钮 -->
<button class="submit-btn" @click="submitForm">提交</button> <button class="submit-btn" @click="submitForm">提交</button>
<!-- 提交时遮罩,禁止页面点击 -->
<view class="submit-mask" v-if="submitting"></view>
</view> </view>
</template> </template>
@@ -90,6 +104,9 @@ const form = ref({
images: [] // 图片列表 images: [] // 图片列表
}) })
// 防止重复点击
const submitting = ref(false)
// ==========方法======== // ==========方法========
// 页面加载 // 页面加载
@@ -122,10 +139,10 @@ const goBackSelect = () => {
// 选择图片 // 选择图片
const chooseImage = () => { const chooseImage = () => {
// 计算还能选几张 // 计算还能选几张
const remainCount = 3 - form.value.images.length const remainCount = 9 - form.value.images.length
if (remainCount <= 0) { if (remainCount <= 0) {
uni.showToast({ uni.showToast({
title: '最多只能上传3张图片', title: '最多只能上传9张图片',
icon: 'none' icon: 'none'
}) })
return return
@@ -171,15 +188,13 @@ const deleteImage = index => {
// 表单提交 // 表单提交
const submitForm = async () => { const submitForm = async () => {
// 防止重复提交
if (submitting.value) return
// 表单校验 // 表单校验
if (!repairProject.value) { if (!repairProject.value) {
uni.showToast({ title: '请选择维修项目', icon: 'none' }) uni.showToast({ title: '请选择维修项目', icon: 'none' })
return return
} }
if (!form.value.title) {
uni.showToast({ title: '请输入问题标题', icon: 'none' })
return
}
if (!form.value.desc) { if (!form.value.desc) {
uni.showToast({ title: '请输入问题描述', icon: 'none' }) uni.showToast({ title: '请输入问题描述', icon: 'none' })
return return
@@ -189,6 +204,7 @@ const submitForm = async () => {
return return
} }
// 提交数据 // 提交数据
submitting.value = true
uni.showLoading({ title: '提交中...' ,mask:true}) uni.showLoading({ title: '提交中...' ,mask:true})
try { try {
// 先上传图片 // 先上传图片
@@ -219,6 +235,7 @@ const submitForm = async () => {
} catch (e) { } catch (e) {
uni.showToast({ title: e.msg || '网络异常', icon: 'none' }) uni.showToast({ title: e.msg || '网络异常', icon: 'none' })
} finally { } finally {
submitting.value = false
uni.hideLoading() uni.hideLoading()
} }
@@ -244,11 +261,15 @@ const submitForm = async () => {
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
} }
.label { .label {
width: 140rpx; width: 180rpx;
font-size: 28rpx; font-size: 28rpx;
color: #333; color: #333;
line-height: 80rpx; line-height: 80rpx;
} }
.required {
color: red;
margin-right: 4rpx;
}
.value { .value {
flex: 1; flex: 1;
@@ -259,6 +280,27 @@ const submitForm = async () => {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.textarea-wrap {
flex: 1;
position: relative;
}
.desc-textarea {
width: 100%;
height: 160rpx;
font-size: 28rpx;
padding: 10rpx 0;
box-sizing: border-box;
border: 1px solid #eee;
border-radius: 4px;
padding: 5px;
}
.char-count {
position: absolute;
right: 10rpx;
bottom: 10rpx;
font-size: 24rpx;
color: #999;
}
.input, .input,
.textarea { .textarea {
font-size: 14px; font-size: 14px;
@@ -318,4 +360,12 @@ const submitForm = async () => {
line-height: 44px; line-height: 44px;
font-size: 16px; font-size: 16px;
} }
.submit-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
}
</style> </style>

View File

@@ -1,11 +1,5 @@
<template> <template>
<view class="page_padding"> <view class="page_padding">
<!-- 状态栏 -->
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
<!-- 导航栏 -->
<uni-nav-bar title="实收统计" backgroundColor="transparent" :border="false" left-icon="left" @click-left="goBack" />
<!-- 筛选条件 --> <!-- 筛选条件 -->
<view class="filter-section"> <view class="filter-section">
<view class="filter-row"> <view class="filter-row">
@@ -53,7 +47,14 @@
</view> </view>
<!-- 统计表格列表 --> <!-- 统计表格列表 -->
<scroll-view class="table-scroll" scroll-y show-scrollbar="false"> <scroll-view
class="table-scroll"
scroll-y
show-scrollbar="false"
refresher-enabled
:refresher-triggered="refresherTriggered"
@refresherrefresh="onPullRefresh"
>
<!-- 循环渲染每个表格 --> <!-- 循环渲染每个表格 -->
<view v-for="(table, index) in tableConfigs" :key="index" class="table-wrapper"> <view v-for="(table, index) in tableConfigs" :key="index" class="table-wrapper">
<!-- 标题独立于卡片外 --> <!-- 标题独立于卡片外 -->
@@ -102,9 +103,6 @@
import { onShow } from '@dcloudio/uni-app' import { onShow } from '@dcloudio/uni-app'
import { getVillageList,getFeeTypes,getTableList} from '../../api/api.js' import { getVillageList,getFeeTypes,getTableList} from '../../api/api.js'
// ============ 系统信息 ============
const statusBarHeight = ref(uni.getSystemInfoSync().statusBarHeight || 0)
// ============ 筛选数据 ============ // ============ 筛选数据 ============
// 项目选项(从接口获取) // 项目选项(从接口获取)
const projectOptions = ref([]) const projectOptions = ref([])
@@ -119,6 +117,9 @@
// 日期范围 // 日期范围
const datetimerange = ref([]) const datetimerange = ref([])
// 下拉刷新触发状态
const refresherTriggered = ref(false)
// ============ 表格数据 ============ // ============ 表格数据 ============
const tableConfigs = reactive([ const tableConfigs = reactive([
{ {
@@ -143,7 +144,7 @@
// ============ 获取小区列表 ============ // ============ 获取小区列表 ============
const fetchVillageList = () => { const fetchVillageList = () => {
getVillageList() return getVillageList()
.then((res) => { .then((res) => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
const list = res.data.map((item) => ({ const list = res.data.map((item) => ({
@@ -164,7 +165,7 @@
// ============ 获取收费类型列表 ============ // ============ 获取收费类型列表 ============
const fetchFeeTypes = () => { const fetchFeeTypes = () => {
getFeeTypes() return getFeeTypes()
.then((res) => { .then((res) => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
const list = res.data.map((item) => ({ const list = res.data.map((item) => ({
@@ -198,7 +199,7 @@
params.startDate = datetimerange.value[0] params.startDate = datetimerange.value[0]
params.endDate = datetimerange.value[1] params.endDate = datetimerange.value[1]
} }
getTableList(params) return getTableList(params)
.then((res) => { .then((res) => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
// 项目总览 // 项目总览
@@ -250,11 +251,19 @@
fetchTableList() fetchTableList()
}) })
// ============ 事件处理 ============ // 下拉刷新
const goBack = () => { const onPullRefresh = () => {
uni.navigateBack() refresherTriggered.value = true
Promise.allSettled([
fetchVillageList(),
fetchFeeTypes(),
fetchTableList()
]).finally(() => {
refresherTriggered.value = false
})
} }
// ============ 事件处理 ============
const onProjectChange = (e) => { const onProjectChange = (e) => {
const index = e.detail.value const index = e.detail.value
const option = projectOptions.value[index] const option = projectOptions.value[index]
@@ -295,11 +304,6 @@
flex-direction: column; flex-direction: column;
height: 100vh; height: 100vh;
.status-bar {
width: 100%;
flex-shrink: 0;
}
// ===== 筛选区域(取消背景) ===== // ===== 筛选区域(取消背景) =====
.filter-section { .filter-section {
padding: 24rpx 0 16rpx; padding: 24rpx 0 16rpx;

View File

@@ -2,18 +2,17 @@
<view class="news-detail-page"> <view class="news-detail-page">
<!-- 循环渲染通知列表 --> <!-- 循环渲染通知列表 -->
<view class="news-card" v-for="item in noticeList" :key="item.id"> <view class="news-card" v-for="item in noticeList" :key="item.id">
<view class="news-meta">
<text class="author">{{item.notice}}</text>
<!-- <text class="author">{{ item.residentName || '管理员' }}</text> -->
<!-- <text class="publish-time">{{ item.createTime }}</text> -->
</view>
<view class="news-header"> <view class="news-header">
<text class="news-title">{{ item.item || '暂无标题' }}</text> <text class="news-title">{{ item.item || '暂无标题' }}</text>
<view class="unread-dot" v-if="item.isCheckStr === '未读'"></view> <view class="unread-dot" v-if="item.isCheckStr === '未读'"></view>
</view> </view>
<view class="news-meta">
<text class="author">{{ item.residentName || '管理员' }}</text>
<text class="publish-time">{{ item.createTime }}</text>
</view>
<view class="news-content"> <view class="news-content">
<text class="content-text">{{ item.notice || item.problem }}</text> <text class="content-text">{{ item.problem}}</text>
</view> </view>
<view class="detail-btn" @click="goToDetail(item)"> <view class="detail-btn" @click="goToDetail(item)">

View File

@@ -1,14 +1,14 @@
<template> <template>
<view class="report-record-page"> <view class="report-record-page">
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view> <!-- <view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view> -->
<!-- 顶部导航栏 --> <!-- 顶部导航栏 -->
<uni-nav-bar <!-- <uni-nav-bar
left-icon="back" left-icon="back"
title="上报记录" title="上报记录"
backgroundColor="transparent" backgroundColor="transparent"
:border="false" :border="false"
@clickLeft="navBack" @clickLeft="navBack"
/> /> -->
<!-- 状态筛选标签 --> <!-- 状态筛选标签 -->
<view class="status-tabs"> <view class="status-tabs">
@@ -40,7 +40,9 @@
<scroll-view <scroll-view
class="record-list" class="record-list"
scroll-y scroll-y
:style="{ height: `calc(100vh - ${navHeight + statusTabHeight + typeTabHeight}px)` }" refresher-enabled
:refresher-triggered="refresherTriggered"
@refresherrefresh="onPullRefresh"
> >
<!-- 记录卡片 --> <!-- 记录卡片 -->
<view v-for="record in reportRecords" :key="record.id" class="record-card"> <view v-for="record in reportRecords" :key="record.id" class="record-card">
@@ -86,20 +88,15 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { onReady, onReachBottom, onPullDownRefresh, onShow } from '@dcloudio/uni-app' import { onShow } from '@dcloudio/uni-app'
import { getMyOrderList } from '../../api/api.js' import { getMyOrderList } from '../../api/api.js'
// 导航栏/标签高度(适配不同设备)
const navHeight = ref(44)
const statusTabHeight = ref(88)
const typeTabHeight = ref(88)
const statusBarHeight = ref(uni.getSystemInfoSync().statusBarHeight || 0)
// 分页 // 分页
const pageNum = ref(1) // 当前页 const pageNum = ref(1) // 当前页
const pageSize = ref(5) // 每页条数 const pageSize = ref(10) // 每页条数
const total = ref(0) // 总条数 const total = ref(0) // 总条数
const loading = ref(false) // 加载状态 const loading = ref(false) // 加载状态
const noMore = ref(false) // 是否没有更多 const noMore = ref(false) // 是否没有更多
const refresherTriggered = ref(false) // 下拉刷新触发状态
// 筛选状态 // 筛选状态
const activeStatus = ref('all') // 全部/待分配/待解决/已完成 const activeStatus = ref('all') // 全部/待分配/待解决/已完成
const activeType = ref('all') // 全部/公共报修/个人报修 const activeType = ref('all') // 全部/公共报修/个人报修
@@ -107,7 +104,7 @@ const activeType = ref('all') // 全部/公共报修/个人报修
// 状态筛选选项 // 状态筛选选项
const statusTabs = ref([ const statusTabs = ref([
{ label: '全部', value: 'all' }, { label: '全部', value: 'all' },
// { label: '待分配', value: 'pending' }, { label: '待分配', value: '0' },
{ label: '待解决', value: '1' }, { label: '待解决', value: '1' },
{ label: '已完成', value: '2' } { label: '已完成', value: '2' }
]) ])
@@ -161,23 +158,17 @@ const getReportList = (isRefresh = false) => {
.finally(() => { .finally(() => {
loading.value = false loading.value = false
if (isRefresh) { if (isRefresh) {
uni.stopPullDownRefresh() refresherTriggered.value = false
} }
}) })
} }
// 上拉加载更多
onReachBottom(() => {
if (noMore.value || loading.value) return
pageNum.value++
getReportList()
})
// 下拉刷新 // 下拉刷新
onPullDownRefresh(() => { const onPullRefresh = () => {
refresherTriggered.value = true
pageNum.value = 1 pageNum.value = 1
noMore.value = false noMore.value = false
getReportList(true) getReportList(true)
}) }
// 筛选/分页重置后重新拉数据 // 筛选/分页重置后重新拉数据
const reloadList = () => { const reloadList = () => {
@@ -211,7 +202,7 @@ const navBack = () => {
// 获取状态文本 // 获取状态文本
const getStatusText = status => { const getStatusText = status => {
const statusMap = { const statusMap = {
// "pending": '已分配', 0: '待分配',
1: '待解决', 1: '待解决',
2: '已完成' 2: '已完成'
} }
@@ -220,6 +211,7 @@ const getStatusText = status => {
// 获取状态标签样式类名 // 获取状态标签样式类名
const getStatusClass = status => { const getStatusClass = status => {
const classMap = { const classMap = {
0:'pending',
1: 'processing', 1: 'processing',
2: 'completed' 2: 'completed'
} }
@@ -230,26 +222,15 @@ onShow(() => {
noMore.value = false noMore.value = false
getReportList() getReportList()
}) })
// 页面渲染完成后适配高度
onReady(() => {
// 可根据实际设备调整高度
uni.getSystemInfo({
success: res => {
if (res.platform === 'ios') {
navHeight.value = 44
} else {
navHeight.value = 48
}
}
})
})
</script> </script>
<style scoped> <style scoped>
.report-record-page { .report-record-page {
width: 100%; width: 100%;
height: 100vh; height: 100vh;
display: flex;
flex-direction: column;
box-sizing: border-box;
background: linear-gradient(to left bottom, #e2efff 0%, #f9f9f9 50%); background: linear-gradient(to left bottom, #e2efff 0%, #f9f9f9 50%);
} }
.status-bar { .status-bar {
@@ -265,6 +246,7 @@ onReady(() => {
padding: 0 40rpx; padding: 0 40rpx;
height: 88rpx; height: 88rpx;
align-items: center; align-items: center;
flex-shrink: 0;
} }
.status-tab-item { .status-tab-item {
@@ -304,6 +286,7 @@ onReady(() => {
padding: 20rpx 40rpx; padding: 20rpx 40rpx;
margin-top: 10rpx; margin-top: 10rpx;
justify-content: flex-start; justify-content: flex-start;
flex-shrink: 0;
/* gap: 20rpx; */ /* gap: 20rpx; */
} }
@@ -325,6 +308,8 @@ onReady(() => {
/* 记录列表 */ /* 记录列表 */
.record-list { .record-list {
flex: 1;
min-height: 0;
padding: 20rpx 40rpx; padding: 20rpx 40rpx;
box-sizing: border-box; box-sizing: border-box;
} }
@@ -346,14 +331,18 @@ onReady(() => {
} }
.card-title { .card-title {
flex: 1;
font-size: 32rpx; font-size: 32rpx;
font-weight: 500; font-weight: 500;
color: #333; color: #333;
margin-right: 20rpx; margin-right: 20rpx;
word-break: break-all;
} }
/* 状态标签 */ /* 状态标签 */
.status-tag { .status-tag {
flex-shrink: 0;
white-space: nowrap;
padding: 6rpx 16rpx; padding: 6rpx 16rpx;
font-size: 20rpx; font-size: 20rpx;
border-radius: 12rpx; border-radius: 12rpx;

View File

@@ -71,7 +71,7 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { onShow } from '@dcloudio/uni-app' import { onShow, onPullDownRefresh } from '@dcloudio/uni-app'
import { getVillageList, getFeeTypes } from '@/api/api.js' import { getVillageList, getFeeTypes } from '@/api/api.js'
import FeeOverviewCard from './components/FeeOverviewCard.vue' import FeeOverviewCard from './components/FeeOverviewCard.vue'
import ParkingFeeCard from './components/ParkingFeeCard.vue' import ParkingFeeCard from './components/ParkingFeeCard.vue'
@@ -158,7 +158,7 @@ const fetchVillageList = () => {
} }
const fetchManagedArea = (villageId) => { const fetchManagedArea = (villageId) => {
getManagedArea({ villageId: villageId || '' }).then(res => { return getManagedArea({ villageId: villageId || '' }).then(res => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
manageArea.value = res.data.manageArea manageArea.value = res.data.manageArea
serviceHouseholds.value = res.data.serviceHouseCount serviceHouseholds.value = res.data.serviceHouseCount
@@ -167,7 +167,7 @@ const fetchManagedArea = (villageId) => {
} }
const fetchRate = (villageId) => { const fetchRate = (villageId) => {
getRate({ villageId: villageId || '' }).then(res => { return getRate({ villageId: villageId || '' }).then(res => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
occupancyRate.value = res.data.occupancyRate occupancyRate.value = res.data.occupancyRate
rentalRate.value = res.data.rentalRate rentalRate.value = res.data.rentalRate
@@ -176,7 +176,7 @@ const fetchRate = (villageId) => {
} }
// 车位收费总览 // 车位收费总览
const fetchParkingFee = (villageId) => { const fetchParkingFee = (villageId) => {
getParkingFee({ villageId: villageId || '' }).then(res => { return getParkingFee({ villageId: villageId || '' }).then(res => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
const d = res.data const d = res.data
parkingCount.value = Number(d.parkingCount) || 0 parkingCount.value = Number(d.parkingCount) || 0
@@ -189,7 +189,7 @@ const fetchParkingFee = (villageId) => {
// 收费总览 // 收费总览
const fetchFeeSummary = () => { const fetchFeeSummary = () => {
getFeeSummary({ return getFeeSummary({
villageId: selectedProject.value || '', villageId: selectedProject.value || '',
chargeTypeId: selectedFeeType.value || '', chargeTypeId: selectedFeeType.value || '',
timeScope: activeTab.value timeScope: activeTab.value
@@ -226,7 +226,7 @@ const fetchFeeTypes = () => {
} }
// 押金余额统计 // 押金余额统计
const fetchDepositBalance = (villageId) => { const fetchDepositBalance = (villageId) => {
getDepositBalance({ villageId: villageId}).then(res => { return getDepositBalance({ villageId: villageId}).then(res => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
const d = res.data const d = res.data
depositBalance.value = d.totalBalance depositBalance.value = d.totalBalance
@@ -236,7 +236,7 @@ const fetchDepositBalance = (villageId) => {
} }
// 巡检总览 // 巡检总览
const fetchInspection = (villageId) => { const fetchInspection = (villageId) => {
getInspection({ villageId: villageId || '' }).then(res => { return getInspection({ villageId: villageId || '' }).then(res => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
const d = res.data const d = res.data
inspectionList.value = [ inspectionList.value = [
@@ -249,15 +249,30 @@ const fetchInspection = (villageId) => {
}).catch(() => {}) }).catch(() => {})
} }
onShow(() => { // 加载全部数据(首屏 / 下拉刷新共用)
Promise.all([fetchVillageList(), fetchFeeTypes()]).then(() => { const loadAll = () => {
fetchManagedArea(selectedProject.value) return Promise.all([fetchVillageList(), fetchFeeTypes()]).then(() => {
fetchRate(selectedProject.value) return Promise.allSettled([
fetchFeeSummary() fetchManagedArea(selectedProject.value),
fetchParkingFee(selectedProject.value) fetchRate(selectedProject.value),
fetchDepositBalance(selectedProject.value) fetchFeeSummary(),
fetchInspection(selectedProject.value) fetchParkingFee(selectedProject.value),
fetchDepositBalance(selectedProject.value),
fetchInspection(selectedProject.value)
])
}) })
}
onShow(() => {
loadAll()
})
onPullDownRefresh(async () => {
try {
await loadAll()
} finally {
uni.stopPullDownRefresh()
}
}) })
</script> </script>

View File

@@ -1,9 +1,12 @@
{ {
"pages": [{ "pages": [
{
"path": "pages/index/index", "path": "pages/index/index",
"style": { "style": {
"navigationBarTitleText": "工作台", "navigationBarTitleText": "工作台",
"navigationStyle": "custom" "navigationStyle": "custom",
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark"
} }
}, },
{ {
@@ -21,9 +24,11 @@
} }
} }
], ],
"subPackages": [{ "subPackages": [
{
"root": "pageSubPack/loginSub", "root": "pageSubPack/loginSub",
"pages": [{ "pages": [
{
"path": "pwd-login", "path": "pwd-login",
"style": { "style": {
"navigationBarTitleText": "账号登录", "navigationBarTitleText": "账号登录",
@@ -67,7 +72,8 @@
}, },
{ {
"root": "pageSubPack/notice-list", "root": "pageSubPack/notice-list",
"pages": [{ "pages": [
{
"path": "select-community", "path": "select-community",
"style": { "style": {
"navigationBarTitleText": "选择小区" "navigationBarTitleText": "选择小区"
@@ -85,7 +91,8 @@
}, },
{ {
"root": "pageSubPack/inspection", "root": "pageSubPack/inspection",
"pages": [{ "pages": [
{
"path": "toDays_inscpection", "path": "toDays_inscpection",
"style": { "style": {
"navigationBarTitleText": "今日巡检", "navigationBarTitleText": "今日巡检",
@@ -116,7 +123,8 @@
}, },
{ {
"root": "pageSubPack/instrument", "root": "pageSubPack/instrument",
"pages": [{ "pages": [
{
"path": "replacement_record", "path": "replacement_record",
"style": { "style": {
"navigationBarTitleText": "仪表换新记录", "navigationBarTitleText": "仪表换新记录",
@@ -138,24 +146,28 @@
{ {
"path": "revenue_statistics", "path": "revenue_statistics",
"style": { "style": {
"navigationBarTitleText": "实收统计", "navigationBarTitleText": "实收统计"
"navigationStyle": "custom"
} }
} }
] ]
}, },
{ {
"root": "pageSubPack/statistics", "root": "pageSubPack/statistics",
"pages": [{ "pages": [
"path": "statistics", {
"style": { "path": "statistics",
"navigationBarTitleText": "收费总览" "style": {
"navigationBarTitleText": "收费总览",
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark"
}
} }
}] ]
}, },
{ {
"root": "pageSubPack/complaint", "root": "pageSubPack/complaint",
"pages": [{ "pages": [
{
"path": "Details", "path": "Details",
"style": { "style": {
"navigationBarTitleText": "投诉详情", "navigationBarTitleText": "投诉详情",
@@ -187,7 +199,8 @@
}, },
{ {
"root": "pageSubPack/ticket", "root": "pageSubPack/ticket",
"pages": [{ "pages": [
{
"path": "hall", "path": "hall",
"style": { "style": {
"navigationBarTitleText": "工单大厅", "navigationBarTitleText": "工单大厅",
@@ -221,22 +234,35 @@
"navigationBarTitleText": "维修完成", "navigationBarTitleText": "维修完成",
"navigationBarBackgroundColor": "#fff" "navigationBarBackgroundColor": "#fff"
} }
},
{
"path": "reportingRecord",
"style": {
"navigationBarTitleText": "上报记录",
// "navigationStyle": "custom",
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark"
// "onReachBottomDistance": 100
}
} }
] ]
}, },
{ {
"root": "pageSubPack/oneClickOpen", "root": "pageSubPack/oneClickOpen",
"pages": [{ "pages": [
"path": "oneClickOpen", {
"style": { "path": "oneClickOpen",
"navigationBarTitleText": "一键开门", "style": {
"navigationStyle": "custom" "navigationBarTitleText": "一键开门",
"navigationStyle": "custom"
}
} }
}] ]
}, },
{ {
"root": "pageSubPack/fault-reporting", "root": "pageSubPack/fault-reporting",
"pages": [{ "pages": [
{
"path": "fault-reporting", "path": "fault-reporting",
"style": { "style": {
"navigationBarTitleText": "填写维修信息" "navigationBarTitleText": "填写维修信息"
@@ -252,17 +278,19 @@
}, },
{ {
"root": "pageSubPack/report-record", "root": "pageSubPack/report-record",
"pages": [{ "pages": [
"path": "report-record", {
"style": { "path": "report-record",
"navigationBarTitleText": "上报记录", "style": {
"navigationStyle": "custom" "navigationBarTitleText": "上报记录"
}
} }
}] ]
}, },
{ {
"root": "pageSubPack/setting", "root": "pageSubPack/setting",
"pages": [{ "pages": [
{
"path": "setting", "path": "setting",
"style": { "style": {
"navigationBarTitleText": "设置" "navigationBarTitleText": "设置"
@@ -303,7 +331,8 @@
"backgroundColor": "#F5F6F6", "backgroundColor": "#F5F6F6",
"borderStyle": "white", "borderStyle": "white",
"selectedColor": "#666666", "selectedColor": "#666666",
"list": [{ "list": [
{
"pagePath": "pages/index/index", "pagePath": "pages/index/index",
"iconPath": "/static/imgs/index.png", "iconPath": "/static/imgs/index.png",
"selectedIconPath": "/static/imgs/index-lan.png", "selectedIconPath": "/static/imgs/index-lan.png",

View File

@@ -53,6 +53,12 @@
</template> </template>
</up-swiper> </up-swiper>
</view> </view>
<!-- banner 占位 -->
<view class="bannarClass" v-else>
<view class="banner-placeholder">
<text>暂无轮播图</text>
</view>
</view>
<!-- 巡检 --> <!-- 巡检 -->
<view class="inspectionClass"> <view class="inspectionClass">
@@ -125,7 +131,7 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { onLoad, onUnload, onShow, onReady } from '@dcloudio/uni-app' import { onLoad, onUnload, onShow, onReady, onPullDownRefresh } from '@dcloudio/uni-app'
import { import {
getCurrentVillage, getCurrentVillage,
getTodayInspection, getTodayInspection,
@@ -308,7 +314,7 @@ const handleFunctionClick = item => {
// 获取当前小区 // 获取当前小区
const currentVillageData = () => { const currentVillageData = () => {
currentCommunity.value = '请先绑定房屋' currentCommunity.value = '请先绑定房屋'
getCurrentVillage() return getCurrentVillage()
.then(res => { .then(res => {
const data = res.data const data = res.data
if (data) { if (data) {
@@ -323,7 +329,7 @@ const currentVillageData = () => {
} }
// 获取今日巡检数据 // 获取今日巡检数据
const getInspectionData = () => { const getInspectionData = () => {
getTodayInspection() return getTodayInspection()
.then(res => { .then(res => {
if (res.code === 200) { if (res.code === 200) {
if (res.data) { if (res.data) {
@@ -346,7 +352,7 @@ const getInspectionData = () => {
// 获取消息通知 // 获取消息通知
const getNoticeData = () => { const getNoticeData = () => {
getNewNoticeData().then(res => { getNewNoticeData().then(res => {
const notice = res.code === 200 && res.data ? (res.data.notice || '') : '暂无公告' const notice = res.code === 200 && res.data ? `${res.data.notice || ''} : ${res.data.item || ''}` : '暂无公告'
// 仅在内容真正变化时才更新 // 仅在内容真正变化时才更新
if (noticeText.value !== notice) { if (noticeText.value !== notice) {
noticeText.value = notice noticeText.value = notice
@@ -369,7 +375,7 @@ function getbannarData(forceRefresh = false) {
} }
} catch (e) {} } catch (e) {}
} }
getBannarList() return getBannarList()
.then(res => { .then(res => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
const newData = res.data const newData = res.data
@@ -397,7 +403,7 @@ function getbannarData(forceRefresh = false) {
const MyOrderNum = ref(0) const MyOrderNum = ref(0)
// 查询我的工单-待办数量 // 查询我的工单-待办数量
function getMyOrderNum() { function getMyOrderNum() {
myOrderCount() return myOrderCount()
.then(res => { .then(res => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
MyOrderNum.value = res.data MyOrderNum.value = res.data
@@ -421,10 +427,9 @@ const slelctHomeData = data => {
onShow(() => { onShow(() => {
if (!isLoggedIn.value) return if (!isLoggedIn.value) return
if (!hasInit.value) { if (!hasInit.value) {
// 首次加载:onLoad 已触发过核心数据请求,这里只补 onLoad 没调的和需要每次都刷新的
hasInit.value = true hasInit.value = true
getbannarData() // onLoad 没调 banner getbannarData()
getMyOrderNum() // onLoad 没调工单数 getMyOrderNum()
permStore.initPerm() // 刷新权限缓存 permStore.initPerm() // 刷新权限缓存
// currentVillageData 和 getInspectionData 已在 onLoad 中调用,不再重复 // currentVillageData 和 getInspectionData 已在 onLoad 中调用,不再重复
return return
@@ -432,6 +437,7 @@ onShow(() => {
// 从其他页面返回 / 从后台恢复:只刷新可能变化的数据 // 从其他页面返回 / 从后台恢复:只刷新可能变化的数据
getbannarData() getbannarData()
getMyOrderNum() getMyOrderNum()
getNoticeData()
// 换账号登录后 currentVillage 缓存已被清除,需要重新获取小区 // 换账号登录后 currentVillage 缓存已被清除,需要重新获取小区
if (!uni.getStorageSync('currentVillage')) { if (!uni.getStorageSync('currentVillage')) {
currentVillageData() currentVillageData()
@@ -470,6 +476,24 @@ onReady(() => {
onUnload(() => { onUnload(() => {
uni.$off('confirm', slelctHomeData) uni.$off('confirm', slelctHomeData)
}) })
// 下拉刷新
onPullDownRefresh(async () => {
if (!isLoggedIn.value) {
uni.stopPullDownRefresh()
return
}
try {
await Promise.allSettled([
currentVillageData(),
getInspectionData(),
getbannarData(true),
getMyOrderNum()
])
} finally {
uni.stopPullDownRefresh()
}
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -609,6 +633,17 @@ onUnload(() => {
border-radius: 15rpx; border-radius: 15rpx;
} }
.banner-placeholder {
height: 180px;
background: #e8f1fb;
border-radius: 15rpx;
display: flex;
align-items: center;
justify-content: center;
color: #999;
font-size: 26rpx;
}
.inspectionClass { .inspectionClass {
background: linear-gradient(to right, #7b87fa, #4d5dfa); background: linear-gradient(to right, #7b87fa, #4d5dfa);
border-radius: 16rpx; border-radius: 16rpx;