success\(\'\', \[\'list\' => \$list, \'total\' => \(int\)\$total, \'page\' => \$page\]\);\s*\}/s'; $newIndex = <<<'PHP' public function index() { $status = $this->request->param('status', 'all'); $keyword = trim((string)$this->request->param('keyword', '')); $page = max(1, (int)$this->request->param('page', 1)); $limit = min(50, max(1, (int)$this->request->param('limit', 10))); $build = function () use ($status, $keyword) { $q = Db::name('order')->where('user_id', $this->uid())->where('user_deleted', 0); if ($keyword !== '') { $q->where(function ($sub) use ($keyword) { $sub->where('contact', 'like', "%{$keyword}%") ->whereOr('mobile', 'like', "%{$keyword}%") ->whereOr('order_no', 'like', "%{$keyword}%") ->whereOr('service_name', 'like', "%{$keyword}%") ->whereOr('address', 'like', "%{$keyword}%") ->whereOr('remark', 'like', "%{$keyword}%"); }); } if ($status === 'active') { $q->where('status', 'in', OrderStatus::activeValues()); } elseif ($status === 'completed' || $status === '8') { $q->where('status', OrderStatus::COMPLETED); } elseif ($status === 'cancelled' || $status === '9') { $q->where('status', OrderStatus::CANCELLED); } elseif ($status === 'pending_pay' || $status === '0') { $q->where('status', OrderStatus::PENDING_PAY); } elseif ($status === 'pending_accept' || $status === '1') { $q->where('status', OrderStatus::PENDING_ACCEPT); } elseif ($status === 'quoting' || $status === '2') { $q->where('status', OrderStatus::QUOTING); } elseif ($status === 'scheduled' || $status === '3') { $q->where('status', OrderStatus::ACCEPTED); } elseif ($status === 'serving' || $status === '4_6') { $q->where('status', 'in', [OrderStatus::SCHEDULED, OrderStatus::ARRIVED, OrderStatus::WORKING]); } elseif ($status === 'pending_verify' || $status === '7') { $q->where('status', OrderStatus::PENDING_VERIFY); } elseif ($status !== 'all' && $status !== '') { $q->where('status', (int)$status); } return $q; }; $total = $build()->count(); $list = $build()->order('id desc')->page($page, $limit)->select(); $orderIds = array_column($list, 'id'); $allGoods = []; if (!empty($orderIds)) { $goodsRows = Db::name('order_goods')->where('order_id', 'in', $orderIds)->select(); foreach ($goodsRows as $gr) { $allGoods[$gr['order_id']][] = $gr; } } foreach ($list as &$row) { $row = $this->formatOrder($row); if (!empty($allGoods[$row['id']])) { $row['goods_list'] = $allGoods[$row['id']]; $firstG = $allGoods[$row['id']][0]; $row['goods_title'] = $firstG['goods_name'] . (!empty($firstG['goods_model']) ? ' (' . $firstG['goods_model'] . ')' : '') . ' x ' . $firstG['goods_num'] . '套'; if (!empty($firstG['addon_services'])) { $row['service_items_text'] = '服务项目: ' . $firstG['addon_services']; } if (!empty($firstG['goods_image'])) { $row['goods_image_url'] = $firstG['goods_image']; } } } unset($row); $this->success('', ['list' => $list, 'total' => (int)$total, 'page' => $page]); } /** * 删除订单(用户端软删除,隐藏订单) * @ApiMethod (POST) */ public function delete() { $orderId = (int)$this->request->post('order_id'); $order = $this->ownOrder($orderId, 'user'); if (!in_array((int)$order['status'], [OrderStatus::CANCELLED, OrderStatus::COMPLETED], true)) { $this->error('仅已关闭或已完成的订单支持删除'); } Db::name('order')->where('id', $orderId)->update(['user_deleted' => 1, 'updatetime' => time()]); $this->success('订单已删除'); } PHP; $code = preg_replace($oldIndexPattern, $newIndex, $code); // 2. 增强 detail() 中的返回值:补齐 goods_list 与 order_contact $oldDetailReturnPattern = '/\$this->success\(\'\', \[\s*\'order\'\s*=> \$this->formatOrder\(\$order\),\s*\'goods_list\'\s*=> Db::name\(\'order_goods\'\)->where\(\'order_id\', \$orderId\)->select\(\),/s'; $newDetailReturn = <<<'PHP' $creatorUser = Db::name('user')->where('id', (int)$order['user_id'])->find(); $orderContact = $creatorUser ? (($creatorUser['username'] ?: '用户') . ', ' . ($creatorUser['mobile'] ?: $order['mobile'])) : $order['mobile']; $formattedOrder = $this->formatOrder($order); $formattedOrder['order_contact'] = $orderContact; $formattedOrder['remark_display'] = !empty($order['remark']) ? $order['remark'] : '无备注'; $goodsList = Db::name('order_goods')->where('order_id', $orderId)->select(); if (empty($goodsList)) { $goodsList = [ [ 'goods_name' => $formattedOrder['goods_name'] ?: $formattedOrder['service_name'], 'goods_model' => $formattedOrder['goods_model'] ?: '', 'goods_num' => max(1, (int)$formattedOrder['goods_num']), 'goods_image' => $formattedOrder['goods_image_url'], 'addon_services' => '安装x' . max(1, (int)$formattedOrder['goods_num']) . ';', 'base_price' => (float)$formattedOrder['pay_amount'], ] ]; } $this->success('', [ 'order' => $formattedOrder, 'goods_list' => $goodsList, PHP; $code = preg_replace($oldDetailReturnPattern, $newDetailReturn, $code); // 3. 替换 formatOrder 方法 $oldFormatPattern = '/protected function formatOrder\(\$row\)\s*\{.*?return array_merge\(\$row, \[.*?\]\);\s*\}/s'; $newFormat = <<<'PHP' protected function formatOrder($row) { $status = (int)$row['status']; $appoint = (int)$row['appoint_time']; $mobile = (string)$row['mobile']; $mobileMask = strlen($mobile) === 11 ? substr_replace($mobile, '****', 3, 4) : $mobile; $prov = isset($row['province']) ? $row['province'] : ''; $city = isset($row['city']) ? $row['city'] : ''; $dist = isset($row['district']) ? $row['district'] : ''; $addr = isset($row['address']) ? $row['address'] : ''; $fullAddress = trim($prov . $city . $dist . $addr); if (empty($fullAddress)) { $fullAddress = $addr; } // 状态轨迹提示文案与时间 $statusTimelineText = OrderStatus::tip($status); $statusTime = !empty($row['updatetime']) ? (int)$row['updatetime'] : (int)$row['createtime']; if ($status === OrderStatus::CANCELLED) { $statusTimelineText = ((int)$row['pay_status'] === 0) ? '订单未支付,您已取消订单' : '订单已取消,退款处理中'; } elseif ($status === OrderStatus::PENDING_PAY) { $statusTimelineText = '订单待支付,请尽快完成支付'; } elseif ($status === OrderStatus::PENDING_ACCEPT) { $statusTimelineText = '订单已进入接单大厅,正在匹配师傅'; } elseif ($status === OrderStatus::QUOTING) { $statusTimelineText = '已有师傅进行报价,请比对选择'; } elseif ($status === OrderStatus::ACCEPTED) { $statusTimelineText = '师傅已接单,请等待师傅联系并上门'; if (!empty($row['accept_time'])) $statusTime = (int)$row['accept_time']; } elseif ($status === OrderStatus::SCHEDULED) { $statusTimelineText = '已预约上门服务时间:' . ($appoint ? date('Y-m-d H:i', $appoint) : '尽快上门'); } elseif ($status === OrderStatus::ARRIVED) { $statusTimelineText = '师傅已到达现场,准备开工'; if (!empty($row['arrive_time'])) $statusTime = (int)$row['arrive_time']; } elseif ($status === OrderStatus::WORKING) { $statusTimelineText = '师傅施工中,请稍候'; if (!empty($row['start_time'])) $statusTime = (int)$row['start_time']; } elseif ($status === OrderStatus::PENDING_VERIFY) { $statusTimelineText = '师傅已完工,请核验施工质量后验收'; if (!empty($row['finish_time'])) $statusTime = (int)$row['finish_time']; } elseif ($status === OrderStatus::COMPLETED) { $statusTimelineText = '服务已完成,期待您的评价'; if (!empty($row['verify_time'])) $statusTime = (int)$row['verify_time']; } // 期望上门文本 $appointDateText = '尽快上门'; if ($appoint > 0) { $hour = (int)date('H', $appoint); $period = $hour < 12 ? '上午' : ($hour < 18 ? '下午' : '晚上'); $appointDateText = date('Y-n-j', $appoint) . ' ' . $period; } // 商品与服务概览 $goodsNum = max(1, (int)$row['goods_num']); $goodsTitle = ($row['service_name'] ?: '专业师傅上门服务') . ' x ' . $goodsNum . '套'; $serviceItemsText = '服务项目: 安装x' . $goodsNum . ';'; if (!empty($row['goods_model'])) { $serviceItemsText = '规格型号: ' . $row['goods_model'] . '; 安装x' . $goodsNum . ';'; } // 默认商品图/服务图 $goodsImageUrl = !empty($row['service_image']) ? $row['service_image'] : '/static/icons/appliance.png'; return array_merge($row, [ 'id' => (int)$row['id'], 'status' => $status, 'status_text' => OrderStatus::label($status), 'status_tip' => OrderStatus::tip($status), 'status_timeline_text'=> $statusTimelineText, 'status_time_text' => date('Y-m-d H:i:s', $statusTime), 'status_time_short' => date('Y/m/d H:i:s', $statusTime), 'can_cancel' => OrderStatus::canCancelByUser($status), 'can_delete' => in_array($status, [OrderStatus::CANCELLED, OrderStatus::COMPLETED], true), 'can_verify' => $status === OrderStatus::PENDING_VERIFY, 'can_review' => $status === OrderStatus::COMPLETED && (int)$row['is_review'] === 0, 'can_pay' => $status === OrderStatus::PENDING_PAY, 'pay_amount' => (float)$row['pay_amount'], 'total_amount' => (float)$row['total_amount'], 'appoint_text' => $appoint ? date('m-d H:i', $appoint) : '尽快上门', 'appoint_date_text' => $appointDateText, 'create_text' => date('Y-m-d H:i', (int)$row['createtime']), 'create_full_text' => date('Y/m/d H:i:s', (int)$row['createtime']), 'urgent' => (int)$row['urgent'], 'price_type_text' => $this->priceTypeText($row['price_type']), 'price_type_tag' => $row['price_type'] === 'quote' ? '报价' : ($row['price_type'] === 'custom' ? '自定价' : '一口价'), 'is_order_owner' => (int)$row['user_id'] === $this->uid(), 'mobile_mask' => $mobileMask, 'full_address' => $fullAddress, 'goods_title' => $goodsTitle, 'service_items_text' => $serviceItemsText, 'goods_image_url' => $goodsImageUrl, 'diff_amount' => isset($row['diff_amount']) ? (float)$row['diff_amount'] : 0.00, 'diff_status' => isset($row['diff_status']) ? (int)$row['diff_status'] : 0, 'diff_remark' => isset($row['diff_remark']) ? (string)$row['diff_remark'] : '', 'diff_image' => isset($row['diff_image']) ? (string)$row['diff_image'] : '', 'empty_run_fee' => isset($row['empty_run_fee']) ? (float)$row['empty_run_fee'] : 0.00, 'auto_quote_timeout' => isset($row['auto_quote_timeout']) ? (int)$row['auto_quote_timeout'] : 0, ]); } PHP; $code = preg_replace($oldFormatPattern, $newFormat, $code); file_put_contents($orderFile, $code); echo "Order.php enhanced successfully.\n";