feat(order): 下单支持一口价/师傅报价竞价/用户自主定价三种方式

- 下单页新增计价方式选择;自主定价填写总价,师傅报价单进入报价大厅
- 用户订单详情展示师傅报价列表并可选定师傅;选定后同步师傅、金额与订单状态
- 师傅大厅新增用户定价筛选与按价接单;报价单禁止直接抢单
- 后端订单新增 custom 价态、金额口径统一由 calcAmount 输出
- 报价中状态纳入用户可取消范围;超时回流重新开放报价
- 新增 fa_order.price_type custom 枚举迁移脚本(schema_phase6)
这个提交包含在:
linda
2026-10-28 17:48:23 +08:00
父节点 3bba2d6e94
当前提交 e1bf139c5a
共有 11 个文件被更改,包括 500 次插入 和 50 次删除

查看文件

@@ -144,7 +144,7 @@ class Master extends Base
}
/**
* 订单大厅:支持排序与单类型筛选(一口价 / 报价 / 悬赏)
* 订单大厅:支持排序与单类型筛选(一口价 / 师傅报价 / 用户自主定价)
*/
public function hall()
{
@@ -155,17 +155,20 @@ class Master extends Base
$page = max(1, (int)$this->request->param('page', 1));
$limit = min(30, max(1, (int)$this->request->param('limit', 10)));
$sort = $this->request->param('sort', 'new'); // new 最新 / amount 报酬 / urgent 急单 / time 时效
$type = $this->request->param('type', 'all'); // all / fixed 一口价 / quote 报价
$type = $this->request->param('type', 'all'); // all / fixed 一口价 / quote 师傅报价 / custom 用户自主定价
$build = function () use ($catIds, $type) {
$q = Db::name('order')->where('status', OrderStatus::PENDING_ACCEPT)->where('master_id', 0);
$q = Db::name('order')->where('master_id', 0)
->where('status', 'in', [OrderStatus::PENDING_ACCEPT, OrderStatus::QUOTING]);
if (!empty($catIds)) {
$q->where('cat_id', 'in', $catIds);
}
if ($type === 'fixed') {
$q->where('price_type', 'fixed');
$q->where('status', OrderStatus::PENDING_ACCEPT)->where('price_type', 'fixed');
} elseif ($type === 'quote') {
$q->where('price_type', 'quote');
$q->where('status', 'in', [OrderStatus::PENDING_ACCEPT, OrderStatus::QUOTING])->where('price_type', 'quote');
} elseif ($type === 'custom') {
$q->where('status', OrderStatus::PENDING_ACCEPT)->where('price_type', 'custom');
}
return $q;
};
@@ -193,6 +196,10 @@ class Master extends Base
$row['status_text'] = OrderStatus::label($row['status']);
$row['left_seconds'] = max(0, (int)$row['createtime'] + 3600 - $now);
$row['quote_count'] = (int)Db::name('order_quote')->where('order_id', $row['id'])->count();
$row['price_type_text'] = $row['price_type'] === 'fixed' ? '一口价'
: ($row['price_type'] === 'quote' ? '师傅报价'
: ($row['price_type'] === 'custom' ? '用户自主定价' : '按面积计价'));
$row['user_price'] = $row['price_type'] === 'custom' ? (float)$row['base_amount'] : 0;
}
unset($row);
@@ -217,6 +224,9 @@ class Master extends Base
if (!$order) {
$this->error('订单不存在');
}
if ($order['price_type'] === 'quote') {
$this->error('该订单为师傅报价订单,请提交报价');
}
if ((int)$order['status'] !== OrderStatus::PENDING_ACCEPT || (int)$order['master_id'] !== 0) {
$this->error('手慢了,该订单已被接走');
}
@@ -433,9 +443,15 @@ class Master extends Base
if (!$order) {
$this->error('订单不存在');
}
if ((int)$order['status'] !== OrderStatus::PENDING_ACCEPT) {
if ($order['price_type'] !== 'quote') {
$this->error('该订单不是报价竞价订单');
}
if (!in_array((int)$order['status'], [OrderStatus::PENDING_ACCEPT, OrderStatus::QUOTING], true)) {
$this->error('该订单已不在报价阶段');
}
if ((int)$order['master_id'] > 0) {
$this->error('该订单已选定师傅');
}
if ($amount <= 0) {
$this->error('请填写报价金额');
}
@@ -453,6 +469,13 @@ class Master extends Base
'status' => 'wait',
'createtime' => time(),
]);
// 兼容旧流程:已支付但仍在待接单的报价单,收到首个报价时进入「报价中」
if ((int)$order['status'] === OrderStatus::PENDING_ACCEPT) {
$this->transit($order, OrderStatus::QUOTING, '收到师傅报价,订单进入报价中', [], 'master', (int)$master['id']);
}
$this->notify('user', (int)$order['user_id'], '收到新报价', '师傅 ' . $master['realname'] . ' 对订单 ' . $order['order_no'] . ' 报价 ¥' . round($amount, 2) . ',请前往订单详情选择', 'order', $orderId);
$this->success('报价已提交');
}
@@ -518,13 +541,17 @@ class Master extends Base
->limit(50)
->select();
foreach ($rows as $row) {
$toStatus = $row['price_type'] === 'quote' ? OrderStatus::QUOTING : OrderStatus::PENDING_ACCEPT;
Db::name('order')->where('id', $row['id'])->update([
'master_id' => 0,
'status' => OrderStatus::PENDING_ACCEPT,
'status' => $toStatus,
'accept_time' => null,
'updatetime' => time(),
]);
$this->addLog($row['id'], OrderStatus::PENDING_ACCEPT, '超 2 小时未联系客户,订单自动回流大厅', 'system', 0);
if ($row['price_type'] === 'quote') {
Db::name('order_quote')->where('order_id', $row['id'])->where('status', 'accept')->update(['status' => 'wait']);
}
$this->addLog($row['id'], $toStatus, $row['price_type'] === 'quote' ? '师傅超 2 小时未联系客户,订单重新开放报价' : '超 2 小时未联系客户,订单自动回流大厅', 'system', 0);
}
}