校园二手物品交易一直是个高频刚需场景。每到毕业季,大量教材、电子产品、生活用品被低价抛售;而新生入学时,又急需采购各类二手物资。传统线下交易方式存在信息不对称、交易效率低、缺乏信任机制等问题。我在帮母校计算机系开发这套系统时,发现几个关键痛点:
这套系统创新性地将捐赠功能与交易平台结合,不仅解决闲置流转问题,还通过积分激励促进环保行为。实测数据显示,上线首月就促成交易427笔,捐赠物品193件,减少垃圾处理量约1.2吨。
采用PHP+MySQL经典组合,主要基于以下考量:
mermaid复制graph TD
A[微信小程序] --> B[API接口层]
B --> C[业务逻辑层]
C --> D[数据访问层]
D --> E[MySQL数据库]
C --> F[七牛云存储]
sql复制CREATE TABLE `items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`title` varchar(100) NOT NULL,
`category` enum('教材','电子','日用','其他') NOT NULL,
`price` decimal(10,2) DEFAULT NULL,
`is_donation` tinyint(1) DEFAULT 0,
`status` enum('待交易','已预约','已完成') DEFAULT '待交易',
`view_count` int(11) DEFAULT 0,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
特别注意:捐赠物品的price字段为NULL,通过is_donation标志区分交易类型
使用微信官方JS-SDK实现一键登录:
javascript复制uni.login({
provider: 'weixin',
success: function(res) {
uni.request({
url: 'https://api.xxx.com/login',
data: { code: res.code },
success: (res) => {
uni.setStorageSync('token', res.data.token)
}
});
}
});
基于用户行为数据实现个性化推荐:
php复制public function recommendItems($user_id)
{
// 获取用户最近浏览的3个商品类别
$history = Db::name('browse_log')
->where('user_id', $user_id)
->order('create_time DESC')
->limit(3)
->column('category');
// 混合推荐:80%相似商品 + 20%热门商品
return Db::name('items')
->where('category', 'in', $history)
->where('status', '待交易')
->orderRaw("RAND()")
->limit(8)
->union(
Db::name('items')
->where('status', '待交易')
->order('view_count DESC')
->limit(2)
)
->select();
}
设计规则:
php复制public function handleDonation($item_id)
{
Db::startTrans();
try {
// 更新物品状态
Db::name('items')
->where('id', $item_id)
->update([
'status' => '已完成',
'complete_time' => date('Y-m-d H:i:s')
]);
// 增加用户积分
Db::name('users')
->where('id', $user_id)
->inc('credit', 10)
->update();
Db::commit();
} catch (\Exception $e) {
Db::rollback();
throw $e;
}
}
采用双向匿名评价机制:
sql复制CREATE TABLE `ratings` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` int(11) NOT NULL,
`rater_id` int(11) NOT NULL COMMENT '评价人',
`target_id` int(11) NOT NULL COMMENT '被评人',
`score` tinyint(1) NOT NULL COMMENT '1-5分',
`content` varchar(255) DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `order_unique` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
小程序端实现方案:
html复制<image
lazy-load
:src="item.thumbnail || '/static/default.png'"
mode="aspectFill"
></image>
PHP端生成缩略图:
php复制public function uploadImage()
{
$file = request()->file('image');
$info = $file->validate(['size'=>2048000,'ext'=>'jpg,png'])->move('../uploads');
// 生成缩略图
$image = \think\Image::open('../uploads/'.$info->getSaveName());
$image->thumb(300, 300)->save('../uploads/thumb_'.$info->getFilename());
return [
'original' => '/uploads/'.$info->getSaveName(),
'thumbnail' => '/uploads/thumb_'.$info->getFilename()
];
}
使用Redis缓存热门数据:
php复制public function getHotItems()
{
$cacheKey = 'hot_items_'.date('Ymd');
if ($data = Redis::get($cacheKey)) {
return json_decode($data, true);
}
$data = Db::name('items')
->where('status', '待交易')
->order('view_count DESC')
->limit(10)
->select();
Redis::setex($cacheKey, 3600, json_encode($data));
return $data;
}
使用ThinkPHP的预处理机制:
php复制Db::name('items')
->where('title', 'like', '%'.input('keyword').'%')
->where('price', '<=', floatval(input('max_price')))
->select();
接入微信内容安全API:
php复制public function checkTextSafety($content)
{
$wxapi = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=".$this->getAccessToken();
$response = Http::post($wxapi, [
'content' => $content
]);
return json_decode($response, true)['errcode'] == 0;
}
最低配置要求:
推荐使用Docker部署:
dockerfile复制FROM php:7.4-fpm
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
&& docker-php-ext-install -j$(nproc) pdo_mysql
使用Crontab处理过期商品:
bash复制0 3 * * * /usr/bin/php /var/www/html/artisan auto_archive_items
对应PHP代码:
php复制public function handle()
{
Db::name('items')
->where('status', '待交易')
->where('create_time', '<', date('Y-m-d', strtotime('-30 days')))
->update([
'status' => '已下架'
]);
}
sql复制SELECT
COUNT(*) AS total_items,
SUM(is_donation) AS donation_count,
COUNT(DISTINCT user_id) AS active_users,
AVG(TIMESTAMPDIFF(HOUR, create_time, complete_time)) AS avg_deal_hours
FROM items
WHERE create_time BETWEEN ? AND ?
使用埋点方案:
javascript复制// 小程序端埋点示例
function trackEvent(event, params) {
uni.request({
url: 'https://api.xxx.com/track',
method: 'POST',
data: {
event: event,
params: JSON.stringify(params),
path: getCurrentPages().pop().route
}
});
}
集成WebSocket实现实时通知:
php复制// 使用Workerman实现
$worker = new Worker('websocket://0.0.0.0:2346');
$worker->onMessage = function($connection, $data) {
$message = json_decode($data, true);
if ($message['type'] == 'bind') {
// 绑定用户ID与连接
} else {
// 转发消息
}
};
接入快递鸟API示例:
php复制public function queryExpress($code, $no)
{
$requestData = json_encode([
'OrderCode' => '',
'ShipperCode' => $code,
'LogisticCode' => $no
]);
$datas = [
'EBusinessID' => config('express.appid'),
'RequestType' => '1002',
'RequestData' => urlencode($requestData),
'DataType' => '2',
];
$datas['DataSign'] = $this->encrypt($requestData);
return Http::post('http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx', $datas);
}
经过三个月的开发和两个月的试运行,系统展现出三个显著价值:
在后续迭代中,我计划加入AI图像识别自动分类、LBS就近推荐等功能。对于想复现该项目的开发者,建议重点关注以下三点:
这个项目给我的最大启示是:技术解决方案必须深度结合具体场景特点。校园场景下的信任建立、用户粘性培养都与商业平台有本质区别,这也是我们系统能获得95%用户满意度的关键所在。