发布日期:2024年4月15日
一、系统架构设计
本教程将开发一个完整的社区物业管理系统,包含以下核心模块:
- 业主门户:业主认证与信息管理
- 工单系统:报修投诉全流程跟踪
- 物业缴费:在线支付与账单管理
- 智能门禁:蓝牙/NFC开门集成
- 社区服务:便民服务预约系统
技术栈:UniApp + Vue3 + Pinia + uView UI + 微信云开发
二、项目初始化与工程配置
1. 创建项目并安装依赖
# 使用Vue3/Vite模板创建项目
npx degit dcloudio/uni-preset-vue#vite property-management
# 安装核心依赖
cd property-management
npm install
npm install pinia uview-ui @uni-helper/uni-ui
# 微信云开发扩展
npm install wx-cloud -D
2. 项目目录结构规划
src/
├── api/ # 接口服务
├── components/ # 公共组件
│ ├── property/ # 物业专用组件
│ └── common/ # 通用组件
├── composables/ # 组合式函数
├── pages/ # 页面组件
│ ├── owner/ # 业主端页面
│ └── property/ # 物业端页面
├── static/ # 静态资源
├── store/ # Pinia状态管理
├── styles/ # 全局样式
├── utils/ # 工具函数
├── App.vue # 应用入口
└── main.js # 主配置文件
三、核心功能实现
1. 业主身份认证模块
// composables/useOwnerAuth.js
import { ref } from 'vue'
import { useStore } from '@/store/owner'
export function useOwnerAuth() {
const store = useStore()
const authStatus = ref('unverified')
// 提交认证信息
const submitVerification = async (formData) => {
try {
const res = await uniCloud.callFunction({
name: 'owner-verify',
data: formData
})
if (res.result.code === 200) {
authStatus.value = 'pending'
store.setOwnerInfo(res.result.data)
}
} catch (e) {
uni.showToast({ title: '认证失败', icon: 'error' })
}
}
// 检查认证状态
const checkAuthStatus = async () => {
const res = await uniCloud.callFunction({
name: 'check-owner-status'
})
authStatus.value = res.result.status
}
return { authStatus, submitVerification, checkAuthStatus }
}
2. 工单系统实现
// pages/owner/work-order/index.vue
<template>
<view class="work-order-container">
<u-tabs :list="tabList" @click="changeTab"></u-tabs>
<scroll-view scroll-y class="order-list">
<work-order-card
v-for="order in filteredOrders"
:key="order.id"
:order="order"
@click="viewDetail(order.id)"
/>
</scroll-view>
<u-button
type="primary"
icon="plus"
@click="createOrder"
class="float-button"
>新建工单</u-button>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { useWorkOrderStore } from '@/store/workOrder'
const store = useWorkOrderStore()
const tabList = [
{ name: 'all', label: '全部' },
{ name: 'pending', label: '处理中' },
{ name: 'completed', label: '已完成' }
]
const activeTab = ref('all')
const filteredOrders = computed(() => {
return store.orders.filter(order =>
activeTab.value === 'all' ||
order.status === activeTab.value
)
})
onLoad(async () => {
await store.fetchOrders()
})
function viewDetail(id) {
uni.navigateTo({
url: `/pages/owner/work-order/detail?id=${id}`
})
}
</script>
四、智能门禁集成
1. 蓝牙门禁控制
// utils/door-control.js
export class DoorController {
static async init() {
// #ifdef MP-WEIXIN
await this.initWXBLE()
// #endif
// #ifdef APP-PLUS
await this.initNativeBLE()
// #endif
}
static async openDoor(deviceId) {
try {
// 发送开门指令
const command = this.generateCommand('open')
await uni.writeBLECharacteristicValue({
deviceId,
serviceId: '0000FFE0-0000-1000-8000-00805F9B34FB',
characteristicId: '0000FFE1-0000-1000-8000-00805F9B34FB',
value: command
})
uni.showToast({ title: '开门指令已发送' })
} catch (e) {
uni.showToast({ title: '开门失败', icon: 'error' })
}
}
static generateCommand(action) {
const encoder = new TextEncoder()
return encoder.encode(
`DOOR:${action}:${Date.now()}`
)
}
}
2. 访客二维码生成
// composables/useVisitorQR.js
import { ref } from 'vue'
import QRCode from 'qrcode'
export function useVisitorQR() {
const qrCode = ref('')
const generating = ref(false)
const generateQR = async (visitorInfo) => {
generating.value = true
try {
// 生成临时访问令牌
const res = await uniCloud.callFunction({
name: 'generate-visitor-token',
data: visitorInfo
})
// 生成二维码
qrCode.value = await QRCode.toDataURL(
JSON.stringify({
token: res.result.token,
expire: res.result.expire
}),
{ width: 200 }
)
} finally {
generating.value = false
}
}
return { qrCode, generating, generateQR }
}
五、物业缴费系统
1. 账单列表与支付
// pages/owner/payment/index.vue
<template>
<view class="payment-container">
<u-sticky bgColor="#fff">
<u-tabs :list="years" @click="changeYear"></u-tabs>
</u-sticky>
<view class="bill-list">
<bill-card
v-for="bill in filteredBills"
:key="bill.id"
:bill="bill"
@pay="handlePay(bill)"
/>
</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { usePaymentStore } from '@/store/payment'
const store = usePaymentStore()
const years = ref(['2024', '2023', '2022'])
const activeYear = ref('2024')
const filteredBills = computed(() => {
return store.bills.filter(bill =>
bill.year === activeYear.value
)
})
onLoad(async () => {
await store.fetchBills()
})
async function handlePay(bill) {
try {
const res = await uni.requestPayment({
provider: 'wxpay',
orderInfo: await store.generateOrder(bill)
})
if (res[0].errMsg === 'requestPayment:ok') {
await store.updateBillStatus(bill.id)
uni.showToast({ title: '支付成功' })
}
} catch (e) {
uni.showToast({ title: '支付取消', icon: 'none' })
}
}
</script>
2. 支付状态同步
// store/payment.js
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const usePaymentStore = defineStore('payment', () => {
const bills = ref([])
async function fetchBills() {
const res = await uniCloud.callFunction({
name: 'get-owner-bills'
})
bills.value = res.result.data
}
async function updateBillStatus(billId) {
await uniCloud.callFunction({
name: 'update-bill-status',
data: { billId }
})
await fetchBills()
}
return { bills, fetchBills, updateBillStatus }
})
六、多端适配方案
1. 平台特定组件封装
// components/common/ImageUploader.vue
<template>
<view class="uploader">
<!-- 微信小程序专用上传 -->
<!-- #ifdef MP-WEIXIN -->
<button
class="upload-btn"
open-type="chooseMedia"
@choose="handleWxChoose"
>上传图片</button>
<!-- #endif -->
<!-- App端上传 -->
<!-- #ifdef APP-PLUS -->
<button
class="upload-btn"
@click="handleNativeUpload"
>上传图片</button>
<!-- #endif -->
<!-- H5端上传 -->
<!-- #ifdef H5 -->
<input
type="file"
accept="image/*"
@change="handleH5Upload"
>
<!-- #endif -->
</view>
</template>
<script setup>
function handleWxChoose(e) {
// 微信小程序上传逻辑
}
function handleNativeUpload() {
// App端上传逻辑
}
function handleH5Upload(e) {
// H5上传逻辑
}
</script>
2. 响应式布局设计
// composables/useResponsive.js
import { ref, onMounted, onUnmounted } from 'vue'
export function useResponsive() {
const screenWidth = ref(uni.getSystemInfoSync().screenWidth)
const isMobile = computed(() => screenWidth.value screenWidth.value >= 768 && screenWidth.value screenWidth.value >= 992)
const updateSize = () => {
screenWidth.value = uni.getSystemInfoSync().screenWidth
}
onMounted(() => {
uni.onWindowResize(updateSize)
})
onUnmounted(() => {
uni.offWindowResize(updateSize)
})
return { isMobile, isTablet, isDesktop }
}
七、性能优化实践
1. 图片懒加载与缓存
// 图片懒加载配置
<image
lazy-load
:src="imageUrl"
mode="aspectFill"
@load="handleImageLoad"
@error="handleImageError"
></image>
// 数据缓存策略
async function getCachedData(key, fetchFunc) {
try {
const cached = uni.getStorageSync(key)
if (cached) {
return JSON.parse(cached)
}
const freshData = await fetchFunc()
uni.setStorageSync(key, JSON.stringify(freshData))
return freshData
} catch (e) {
return fetchFunc()
}
}
2. 组件按需加载
// 动态导入重型组件
const HeavyComponent = defineAsyncComponent(() =>
import('./HeavyComponent.vue')
)
// 路由懒加载
const routes = [
{
path: '/complex-page',
component: () => import('@/pages/complex-page.vue')
}
]
八、总结与扩展
通过本教程,您已经掌握了:
- UniApp企业级应用架构设计
- 复杂业务模块的实现方法
- 硬件设备集成方案
- 多端适配与性能优化
扩展学习方向:
- 物业数据可视化分析
- AI工单自动分类
- WebSocket实时通知
- 微前端架构改造