feat: 重构首页与全局UI,新增服务选择抽屉与统一导航组件
新增统一导航栏组件YjyfNavBar,替换各页面原生导航 新增服务选择抽屉组件GoodsPickerDrawer,实现分类选品流程 新增tabbar图标矢量资源,优化底部导航样式 新增后端运力统计接口与多商品下单逻辑 修复页面跳转逻辑,统一使用switchTab/redirectTo 优化订单创建与评价页的UI组件化,提升一致性
这个提交包含在:
@@ -34,15 +34,31 @@ class Order extends Base
|
||||
$remark = trim((string)$this->request->post('remark'));
|
||||
$goodsImages = $this->request->post('goods_images', '');
|
||||
|
||||
$service = Db::name('service')->where('id', $serviceId)->where('status', 'normal')->find();
|
||||
if (!$service) {
|
||||
// 支持多商品组合 (goods_list)
|
||||
$goodsListRaw = $this->request->post('goods_list');
|
||||
$goodsList = [];
|
||||
if (!empty($goodsListRaw)) {
|
||||
$goodsList = is_array($goodsListRaw) ? $goodsListRaw : json_decode((string)$goodsListRaw, true);
|
||||
}
|
||||
|
||||
$service = null;
|
||||
if (!empty($goodsList) && is_array($goodsList)) {
|
||||
$first = reset($goodsList);
|
||||
$serviceId = isset($first['service_id']) ? (int)$first['service_id'] : $serviceId;
|
||||
}
|
||||
|
||||
if ($serviceId > 0) {
|
||||
$service = Db::name('service')->where('id', $serviceId)->where('status', 'normal')->find();
|
||||
}
|
||||
if (!$service && empty($goodsList)) {
|
||||
$this->error('服务不存在或已下架');
|
||||
}
|
||||
|
||||
// 下单页可选择:一口价 / 师傅报价 / 用户自主定价(未传则沿用服务默认)
|
||||
$priceType = trim((string)$this->request->post('price_type', $service['price_type']));
|
||||
$defaultPriceType = $service ? $service['price_type'] : 'fixed';
|
||||
$priceType = trim((string)$this->request->post('price_type', $defaultPriceType));
|
||||
if (!in_array($priceType, ['fixed', 'quote', 'custom', 'range'], true)) {
|
||||
$priceType = $service['price_type'];
|
||||
$priceType = $defaultPriceType;
|
||||
}
|
||||
$userPrice = round((float)$this->request->post('user_price', 0), 2);
|
||||
if ($priceType === 'custom') {
|
||||
@@ -53,35 +69,105 @@ class Order extends Base
|
||||
$userPrice = 0;
|
||||
}
|
||||
|
||||
$address = Db::name('address')->where('id', $addressId)->where('user_id', $this->uid())->find();
|
||||
// 支持直接传 address_id 或传入新地址对象并自动保存
|
||||
$address = null;
|
||||
if ($addressId > 0) {
|
||||
$address = Db::name('address')->where('id', $addressId)->where('user_id', $this->uid())->find();
|
||||
}
|
||||
if (!$address) {
|
||||
$this->error('请选择服务地址');
|
||||
$contact = trim((string)$this->request->post('contact'));
|
||||
$mobile = trim((string)$this->request->post('mobile'));
|
||||
$province = trim((string)$this->request->post('province', '贵州省'));
|
||||
$city = trim((string)$this->request->post('city', '贵阳市'));
|
||||
$district = trim((string)$this->request->post('district', ''));
|
||||
$detailAddr = trim((string)$this->request->post('address'));
|
||||
$floor = max(1, (int)$this->request->post('floor', 1));
|
||||
$hasElevator = (int)$this->request->post('has_elevator', 1);
|
||||
|
||||
if ($contact && $mobile && $detailAddr) {
|
||||
$addressId = Db::name('address')->insertGetId([
|
||||
'user_id' => $this->uid(),
|
||||
'contact' => $contact,
|
||||
'mobile' => $mobile,
|
||||
'province' => $province,
|
||||
'city' => $city,
|
||||
'district' => $district,
|
||||
'address' => $detailAddr,
|
||||
'floor' => $floor,
|
||||
'has_elevator' => $hasElevator,
|
||||
'createtime' => time(),
|
||||
'updatetime' => time(),
|
||||
]);
|
||||
$address = Db::name('address')->where('id', $addressId)->find();
|
||||
}
|
||||
}
|
||||
|
||||
if (!$address) {
|
||||
$this->error('请选择或填写完整服务地址');
|
||||
}
|
||||
if ($appointTime > 0 && $appointTime < time()) {
|
||||
$this->error('预约时间不能早于当前时间');
|
||||
}
|
||||
|
||||
// 多商品组合名称、总件数与图片汇总
|
||||
$serviceName = $service ? $service['name'] : '同城综合上门服务';
|
||||
$catId = $service ? (int)$service['cat_id'] : 1;
|
||||
$serviceImage = $service ? $service['image'] : '';
|
||||
if (!empty($goodsList) && is_array($goodsList)) {
|
||||
$names = [];
|
||||
$totalCount = 0;
|
||||
$allImages = [];
|
||||
foreach ($goodsList as $idx => $g) {
|
||||
$gName = isset($g['item_name']) ? $g['item_name'] : (isset($g['name']) ? $g['name'] : '服务项');
|
||||
$gNum = isset($g['num']) ? (int)$g['num'] : 1;
|
||||
$names[] = $gName . 'x' . $gNum;
|
||||
$totalCount += $gNum;
|
||||
if (!empty($g['images']) && is_array($g['images'])) {
|
||||
$allImages = array_merge($allImages, $g['images']);
|
||||
}
|
||||
}
|
||||
if (!empty($names)) {
|
||||
$serviceName = implode(' + ', array_slice($names, 0, 3)) . (count($names) > 3 ? ' 等' : '');
|
||||
}
|
||||
if ($totalCount > 0) {
|
||||
$goodsNum = $totalCount;
|
||||
}
|
||||
if (!empty($allImages)) {
|
||||
$goodsImages = $allImages;
|
||||
}
|
||||
}
|
||||
|
||||
// 金额统一由 Home::calcAmount 计算,保证与试算口径一致
|
||||
$amount = Home::calcAmount($service, [
|
||||
'floor' => (int)$address['floor'],
|
||||
'has_elevator' => (int)$address['has_elevator'],
|
||||
'urgent' => $urgent,
|
||||
], $couponId, $this->uid(), $priceType, $userPrice);
|
||||
], $couponId, $this->uid(), $priceType, $userPrice, $goodsList);
|
||||
$amount['price_type'] = $priceType;
|
||||
|
||||
$orderNo = $this->makeOrderNo();
|
||||
$verifyCode = (string)mt_rand(1000, 9999);
|
||||
|
||||
// 如果有多商品明细,结构化存入 goods_images 或在 remark 补充
|
||||
$goodsImagesPayload = is_array($goodsImages) ? json_encode($goodsImages, JSON_UNESCAPED_UNICODE) : (string)$goodsImages;
|
||||
if (!empty($goodsList)) {
|
||||
$extraPayload = [
|
||||
'goods_list' => $goodsList,
|
||||
'images' => is_array($goodsImages) ? $goodsImages : [],
|
||||
];
|
||||
$goodsImagesPayload = json_encode($extraPayload, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
$id = Db::name('order')->insertGetId([
|
||||
'order_no' => $orderNo,
|
||||
'user_id' => $this->uid(),
|
||||
'master_id' => 0,
|
||||
'cat_id' => (int)$service['cat_id'],
|
||||
'service_id' => (int)$service['id'],
|
||||
'service_name' => $service['name'],
|
||||
'service_image' => $service['image'],
|
||||
'cat_id' => $catId,
|
||||
'service_id' => $service ? (int)$service['id'] : 0,
|
||||
'service_name' => $serviceName,
|
||||
'service_image' => $serviceImage,
|
||||
'price_type' => $priceType,
|
||||
'goods_images' => is_array($goodsImages) ? json_encode($goodsImages, JSON_UNESCAPED_UNICODE) : (string)$goodsImages,
|
||||
'goods_images' => $goodsImagesPayload,
|
||||
'goods_model' => mb_substr($goodsModel, 0, 100),
|
||||
'goods_num' => $goodsNum,
|
||||
'floor' => (int)$address['floor'],
|
||||
|
||||
在新工单中引用
屏蔽一个用户