feat(order): 下单支持一口价/师傅报价竞价/用户自主定价三种方式
- 下单页新增计价方式选择;自主定价填写总价,师傅报价单进入报价大厅 - 用户订单详情展示师傅报价列表并可选定师傅;选定后同步师傅、金额与订单状态 - 师傅大厅新增用户定价筛选与按价接单;报价单禁止直接抢单 - 后端订单新增 custom 价态、金额口径统一由 calcAmount 输出 - 报价中状态纳入用户可取消范围;超时回流重新开放报价 - 新增 fa_order.price_type custom 枚举迁移脚本(schema_phase6)
这个提交包含在:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户