
襄行摩友是一个专注于服务襄阳地区摩托车友的云端一体化项目。它并非一个庞大的商业平台,而是一个以"小而美"为理念,旨在通过技术解决摩友日常痛点、营造良好骑行社区氛围的便利工具。项目采用uni-app、vue3、uni-admin与uni-cloud等前沿技术栈,实现了从前端到后端、从管理到运营的全栈开发,高效且成本可控。
明辰
技术为骨,社区为魂——一个个人开发者的骑行情怀实践
在襄阳这座有着深厚历史文化底蕴的城市,摩托车不仅是交通工具,更是一种生活方式。作为一名骑行爱好者和全栈开发者,我决定用技术为本地摩友社区做些有意义的事情。这就是"襄行摩友"小程序的起源——一个完全免费、社区共建的摩友专属工具。
在一年多的骑行经历中,我观察到本地摩友群体面临几个核心痛点:
信息碎片化问题
社区建设困境
基于这些观察,我确立了项目的核心目标:
作为个人项目,技术选型需要平衡开发效率、维护成本和功能需求:
// 技术栈组成
{
"前端框架": "uni-app + Vue3",
"后端服务": "uni-cloud 云开发",
"管理后台": "uni-admin",
"数据库": "uniCloud 数据库",
"存储服务": "uniCloud 存储",
"部署方式": "一站式云端部署"
}
解决什么问题
摩友发现优质骑行路线的需求,避免每次都去相同的地方。
功能特色
<template>
<view class="location-card">
<map :latitude="item.latitude" :longitude="item.longitude"></map>
<view class="card-content">
<text class="title">{{ item.title }}</text>
<text class="desc">{{ item.description }}</text>
<view class="tags">
<text v-for="tag in item.tags" :key="tag">{{ tag }}</text>
</view>
<view class="actions">
<button @click="navigateTo(item)">一键导航</button>
<button @click="collectItem(item)">收藏</button>
</view>
</view>
</view>
</template>
技术实现
真实场景还原
还记得那个经典的场景吗?摩友A的车坏了,在群里问哪里有修车的,消息很快被聊天刷屏,良久后摩友B回复"老周会修",但发来的定位距离太远,今天赶不过去...
我们的解决方案
// 商户服务云函数
export async function searchNearbyShops(userLocation, shopType) {
const db = uniCloud.database()
const { data } = await db.collection('shops')
.where({
type: shopType,
status: 'active'
})
.get()
// 计算距离并排序
const shopsWithDistance = data.map(shop => ({
...shop,
distance: calculateDistance(userLocation, shop.location)
})).sort((a, b) => a.distance - b.distance)
return shopsWithDistance
}
功能亮点
告别微信群接龙的烦恼
活动创建流程
<template>
<view class="activity-create">
<form @submit="createActivity">
<input v-model="form.title" placeholder="活动标题" />
<input v-model="form.date" type="datetime" placeholder="活动时间" />
<textarea v-model="form.description" placeholder="活动描述" />
<input v-model="form.location" placeholder="集合地点" />
<input v-model="form.maxParticipants" type="number" placeholder="人数限制" />
<button form-type="submit">发布活动</button>
</form>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { createActivity } from '@/cloudfunctions/activity'
const form = ref({
title: '',
date: '',
description: '',
location: '',
maxParticipants: 20
})
const createActivity = async () => {
try {
const result = await createActivity(form.value)
uni.showToast({ title: '活动发布成功' })
} catch (error) {
uni.showToast({ title: '发布失败', icon: 'error' })
}
}
</script>
活动特色设计
轻量级二手装备流转平台
// 商品发布流程
export async function publishProduct(productData) {
const db = uniCloud.database()
const result = await db.collection('products').add({
...productData,
status: 'pending', // 审核中
createTime: Date.now(),
updateTime: Date.now()
})
// 发送审核通知
await sendAuditNotification(result.id)
return result
}
数据库设计
考虑到小程序的特性,我设计了简洁高效的数据结构:
// 用户集合
const users = {
_id: '用户ID',
openid: '微信openid',
profile: {
nickname: '昵称',
avatar: '头像'
},
stats: {
activityCount: 0, // 参与活动次数
contributionCount: 0 // 内容贡献数
},
joinTime: '加入时间'
}
// 活动集合
const activities = {
_id: '活动ID',
title: '活动标题',
organizer: '组织者ID',
date: '活动时间',
location: '集合地点',
description: '活动描述',
participants: ['参与者ID数组'],
maxParticipants: 20,
status: 'active', // active, cancelled, finished
images: ['图片URL数组'],
createTime: '创建时间'
}
基于uni-cloud的云函数,实现了完整的后端逻辑:
// 云函数目录结构
cloudfunctions/
├── activity/ # 活动相关
│ ├── index.js # 主函数
│ └── package.json # 依赖配置
├── shop/ # 商户服务
├── location/ # 地点推荐
├── user/ # 用户管理
└── common/ # 公共函数
// 示例:活动报名云函数
export async function joinActivity(activityId, userId) {
const db = uniCloud.database()
const activity = await db.collection('activities').doc(activityId).get()
if (!activity.data) {
throw new Error('活动不存在')
}
if (activity.data.participants.length >= activity.data.maxParticipants) {
throw new Error('活动人数已满')
}
if (activity.data.participants.includes(userId)) {
throw new Error('已报名该活动')
}
// 更新参与者列表
const result = await db.collection('activities').doc(activityId).update({
participants: db.command.push(userId)
})
// 记录用户参与次数
await db.collection('users').doc(userId).update({
'stats.activityCount': db.command.inc(1)
})
return result
}
图片优化策略
// 图片上传预处理
export async function uploadImage(filePath) {
// 压缩图片
const compressedInfo = await uni.compressImage({
src: filePath,
quality: 80,
compressedWidth: 1000
})
// 上传到云存储
const uploadResult = await uniCloud.uploadFile({
filePath: compressedInfo.tempFilePath,
cloudPath: `images/${Date.now()}_${Math.random().toString(36).substr(2)}.jpg`
})
return uploadResult.fileID
}
数据库查询优化
// 使用索引优化查询
db.collection('locations')
.where({
status: 'active',
tags: db.command.in(['拍照', '休闲'])
})
.field({
title: true,
description: true,
location: true,
images: true,
tags: true
})
.orderBy('createTime', 'desc')
.limit(20)
.get()
uni-app生态的优势
遇到的挑战
"小而美"路线的验证
运营策略的调整
襄行摩友小程序的实践让我深刻体会到,技术的价值不在于其本身的复杂性,而在于它如何更好地服务于人。作为一个个人开发者项目,证明了:
这个项目不仅是一个技术作品,更是我对骑行热爱的一种表达。每次看到摩友们通过小程序找到心仪的骑行路线、解决车辆问题、结识新的骑友,都让我觉得所有的付出都是值得的。
未来,我将继续秉持"技术为骨,社区为魂"的理念,和襄阳的摩友们一起,把这个小而美的项目做得更好。也欢迎更多的技术爱好者和骑行爱好者加入我们,共同打造更好的骑行社区环境。