数据库: - db/schema_phase1.sql 16 张业务表(类目/服务/地址/师傅/订单/流水/取证/报价/评价/券/钱包/提现/结算/消息) - db/seed_phase1.sql 15 类目 + 32 服务项目 + 新人券(幂等) 后端 API (application/api/controller): - Base/Auth/Home/Address/Order/Master/Review - app/common/library/OrderStatus 11 状态机 + 流转矩阵 - application/api/common.php PHP 8.5 兼容垫片(E_DEPRECATED 不再升级为异常) 测试: - tests/e2e_flow.js 用户下单→支付→师傅抢单→履约→验收→结算→评价 全链路 65 项断言 - 含异常用例:越权/重复操作/非法状态流转/2h 未联系自动回流
115 行
3.9 KiB
PHP
115 行
3.9 KiB
PHP
<?php
|
|
|
|
namespace app\api\controller;
|
|
|
|
use app\common\library\OrderStatus;
|
|
use think\Db;
|
|
|
|
/**
|
|
* 评价:用户提交 / 师傅收到的评价
|
|
*/
|
|
class Review extends Base
|
|
{
|
|
protected $noNeedLogin = ['masterList'];
|
|
|
|
/**
|
|
* 提交评价
|
|
* @ApiMethod (POST)
|
|
*/
|
|
public function create()
|
|
{
|
|
$orderId = (int)$this->request->post('order_id');
|
|
$score = (int)$this->request->post('score', 5);
|
|
$content = trim((string)$this->request->post('content'));
|
|
$tags = $this->request->post('tags', '');
|
|
$images = $this->request->post('images', '');
|
|
$anonymous = (int)$this->request->post('is_anonymous', 0);
|
|
|
|
$order = $this->ownOrder($orderId, 'user');
|
|
if ((int)$order['status'] !== OrderStatus::COMPLETED) {
|
|
$this->error('订单未完成,暂不能评价');
|
|
}
|
|
if ((int)$order['is_review'] === 1) {
|
|
$this->error('该订单已评价');
|
|
}
|
|
if ($score < 1 || $score > 5) {
|
|
$this->error('请选择 1-5 星');
|
|
}
|
|
|
|
Db::startTrans();
|
|
try {
|
|
Db::name('review')->insert([
|
|
'order_id' => $orderId,
|
|
'user_id' => $this->uid(),
|
|
'master_id' => (int)$order['master_id'],
|
|
'score' => $score,
|
|
'tags' => is_array($tags) ? json_encode($tags, JSON_UNESCAPED_UNICODE) : (string)$tags,
|
|
'content' => mb_substr($content, 0, 500),
|
|
'images' => is_array($images) ? json_encode($images, JSON_UNESCAPED_UNICODE) : (string)$images,
|
|
'is_anonymous' => $anonymous ? 1 : 0,
|
|
'status' => 'normal',
|
|
'createtime' => time(),
|
|
]);
|
|
Db::name('order')->where('id', $orderId)->update(['is_review' => 1, 'updatetime' => time()]);
|
|
|
|
// 刷新师傅综合评分
|
|
$masterId = (int)$order['master_id'];
|
|
if ($masterId > 0) {
|
|
$avg = Db::name('review')->where('master_id', $masterId)->where('status', 'normal')->avg('score');
|
|
Db::name('master')->where('id', $masterId)->update([
|
|
'score' => round((float)$avg, 2),
|
|
'updatetime' => time(),
|
|
]);
|
|
}
|
|
Db::commit();
|
|
} catch (\Exception $e) {
|
|
Db::rollback();
|
|
$this->error('评价失败:' . $e->getMessage());
|
|
}
|
|
|
|
$this->success('评价成功');
|
|
}
|
|
|
|
/**
|
|
* 师傅收到的评价
|
|
*/
|
|
public function masterList()
|
|
{
|
|
$masterId = (int)$this->request->param('master_id');
|
|
if ($masterId <= 0) {
|
|
$master = $this->masterInfo();
|
|
if (!$master) {
|
|
$this->error('师傅不存在');
|
|
}
|
|
$masterId = (int)$master['id'];
|
|
}
|
|
$list = Db::name('review')
|
|
->alias('r')
|
|
->join('user u', 'u.id = r.user_id', 'LEFT')
|
|
->field('r.id,r.score,r.tags,r.content,r.images,r.is_anonymous,r.reply,r.createtime,u.nickname,u.avatar')
|
|
->where('r.master_id', $masterId)
|
|
->where('r.status', 'normal')
|
|
->order('r.id desc')
|
|
->limit(50)
|
|
->select();
|
|
|
|
foreach ($list as &$row) {
|
|
if ((int)$row['is_anonymous'] === 1) {
|
|
$row['nickname'] = '匿名用户';
|
|
$row['avatar'] = '';
|
|
}
|
|
$row['time_text'] = date('Y-m-d H:i', (int)$row['createtime']);
|
|
}
|
|
unset($row);
|
|
|
|
$stat = Db::name('review')->where('master_id', $masterId)->where('status', 'normal')
|
|
->field('count(*) as total, avg(score) as avg_score')->find();
|
|
|
|
$this->success('', [
|
|
'list' => $list,
|
|
'total' => (int)$stat['total'],
|
|
'avg_score' => round((float)$stat['avg_score'], 2),
|
|
]);
|
|
}
|
|
}
|