文件
yjyf/server/application/api/controller/Review.php
linda 376ce7b5c9 feat(api): 全链路后端 + 数据库设计 + E2E 测试(65 项断言全通过)
数据库:
- 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 未联系自动回流
2026-10-28 15:45:51 +08:00

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),
]);
}
}