From fbc6feee874a50583ad783be7587e32aaab3ff9f Mon Sep 17 00:00:00 2001 From: linda Date: Wed, 28 Oct 2026 19:27:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(merchant):=20=E4=BC=81=E4=B8=9A=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E8=81=9A=E5=90=88=E5=88=97=E8=A1=A8=E4=B8=8E=E5=85=B3?= =?UTF-8?q?=E8=81=94=E8=B4=A6=E5=8F=B7=E5=8F=AA=E8=AF=BB=E8=AF=A6=E6=83=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 /merchant/orders,按主账号+关联账号聚合订单并支持状态筛选 - 新增企业订单页,展示订单归属账号(主账号/关联账号) - 工作台企业订单入口改到聚合列表,近期订单可点击查看 - 订单详情允许同商家账号查看,非下单账号隐藏操作按钮 - 报价选择仅下单账号可操作,防止关联账号/主账号误操作 --- pages.json | 4 + pages/merchant/orders.vue | 106 ++++++++++++++++++ pages/merchant/workbench.vue | 5 +- pages/order/detail.vue | 10 +- .../application/api/controller/Merchant.php | 52 +++++++++ server/application/api/controller/Order.php | 42 ++++++- utils/api.js | 1 + 7 files changed, 213 insertions(+), 7 deletions(-) create mode 100644 pages/merchant/orders.vue diff --git a/pages.json b/pages.json index 243ba61..9f24204 100644 --- a/pages.json +++ b/pages.json @@ -98,6 +98,10 @@ "path": "pages/merchant/workbench", "style": { "navigationBarTitleText": "商家工作台" } }, + { + "path": "pages/merchant/orders", + "style": { "navigationBarTitleText": "企业订单" } + }, { "path": "pages/merchant/batch", "style": { "navigationBarTitleText": "批量下单" } diff --git a/pages/merchant/orders.vue b/pages/merchant/orders.vue new file mode 100644 index 0000000..74ce3ca --- /dev/null +++ b/pages/merchant/orders.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/pages/merchant/workbench.vue b/pages/merchant/workbench.vue index 10e7225..a4e760d 100644 --- a/pages/merchant/workbench.vue +++ b/pages/merchant/workbench.vue @@ -55,7 +55,7 @@ 近期订单全部 › - + {{ o.service_name }} {{ o.order_no }} · {{ o.time_text }} @@ -106,7 +106,7 @@ const entries = [ { key: 'batch', name: '批量下单', icon: '批', bg: '#FFF1E0', color: '#E07A2E', action: () => go('/pages/merchant/batch') }, - { key: 'orders', name: '企业订单', icon: '单', bg: '#EAF2FF', color: '#4A7CFF', action: () => go('/pages/order/list') }, + { key: 'orders', name: '企业订单', icon: '单', bg: '#EAF2FF', color: '#4A7CFF', action: () => go('/pages/merchant/orders') }, { key: 'invoice', name: '开具发票', icon: '票', bg: '#E8F7EE', color: '#2FA84F', action: () => go('/pages/merchant/invoice') }, { key: 'profile', name: '企业资料', icon: '档', bg: '#F0EBFF', color: '#7A5AF8', action: () => go('/pages/merchant/apply') }, { key: 'address', name: '服务地址', icon: '址', bg: '#FFF0F0', color: '#E8331B', action: () => go('/pages/address/list') }, @@ -114,6 +114,7 @@ ]; function go(url) { uni.navigateTo({ url: url }); } + function goOrder(id) { uni.navigateTo({ url: '/pages/order/detail?id=' + id }); } async function load() { if (!isLogin()) { toLogin(); return; } diff --git a/pages/order/detail.vue b/pages/order/detail.vue index 7a151d7..3a49aba 100644 --- a/pages/order/detail.vue +++ b/pages/order/detail.vue @@ -3,6 +3,7 @@ {{ order.status_text }} {{ statusTip }} + 商家账号查看 · 仅查看,操作请由下单账号完成 @@ -86,10 +87,10 @@ - 取消订单 - 去支付 - 确认验收 - 去评价 + 取消订单 + 去支付 + 确认验收 + 去评价 返回首页 @@ -115,6 +116,7 @@ const canChoose = computed(() => { return !!(order.value && order.value.price_type === 'quote' && Number(order.value.status) === 2 && Number(order.value.master_id) === 0 + && order.value.is_order_owner !== false && quotes.value.some(q => q.status === 'wait')); }); diff --git a/server/application/api/controller/Merchant.php b/server/application/api/controller/Merchant.php index 52384ba..7c8a244 100644 --- a/server/application/api/controller/Merchant.php +++ b/server/application/api/controller/Merchant.php @@ -171,6 +171,58 @@ class Merchant extends Base $this->success('', ['months' => $months, 'orders' => $orders]); } + /** + * 企业订单:主账号 + 关联账号的全部订单 + */ + public function orders() + { + $merchant = $this->requireMerchant(); + $uids = $this->merchantUserIds($merchant); + $status = $this->request->param('status', 'all'); + $page = max(1, (int)$this->request->param('page', 1)); + $limit = min(50, max(1, (int)$this->request->param('limit', 20))); + + $build = function () use ($uids, $status) { + $q = Db::name('order')->where('user_id', 'in', $uids); + if ($status === 'active') { + $q->where('status', 'in', \app\common\library\OrderStatus::activeValues()); + } elseif ($status === 'completed') { + $q->where('status', \app\common\library\OrderStatus::COMPLETED); + } elseif ($status === 'cancelled') { + $q->where('status', \app\common\library\OrderStatus::CANCELLED); + } elseif ($status !== 'all' && $status !== '') { + $q->where('status', (int)$status); + } + return $q; + }; + + $total = $build()->count(); + $rows = $build()->order('id desc')->page($page, $limit)->select(); + $userMap = Db::name('user')->where('id', 'in', $uids)->column('id,nickname,mobile', 'id'); + + foreach ($rows as &$row) { + $ownerUser = (int)$row['user_id'] === (int)$merchant['user_id']; + $u = isset($userMap[(int)$row['user_id']]) ? $userMap[(int)$row['user_id']] : null; + $mobile = $u ? (string)$u['mobile'] : ''; + $row['pay_amount'] = (float)$row['pay_amount']; + $row['urgent'] = (int)$row['urgent']; + $row['status_text'] = \app\common\library\OrderStatus::label((int)$row['status']); + $row['appoint_text'] = $row['appoint_time'] ? date('m-d H:i', (int)$row['appoint_time']) : '尽快上门'; + $row['create_text'] = date('Y-m-d H:i', (int)$row['createtime']); + $row['address_text'] = $row['province'] . $row['city'] . $row['district'] . $row['address']; + $row['account_name'] = $u && $u['nickname'] ? $u['nickname'] : ('用户' . substr($mobile, -4)); + $row['account_role'] = $ownerUser ? 'owner' : 'member'; + $row['account_role_text'] = $ownerUser ? '主账号' : '关联账号'; + } + unset($row); + + $this->success('', [ + 'list' => $rows, + 'total' => (int)$total, + 'page' => $page, + ]); + } + /** * 开票记录 */ diff --git a/server/application/api/controller/Order.php b/server/application/api/controller/Order.php index fa66ff5..14a0e98 100644 --- a/server/application/api/controller/Order.php +++ b/server/application/api/controller/Order.php @@ -216,7 +216,20 @@ class Order extends Base public function detail() { $orderId = (int)$this->request->param('id'); - $order = $this->ownOrder($orderId, 'user'); + if ($orderId <= 0) { + $this->error('订单参数错误'); + } + $order = Db::name('order')->where('id', $orderId)->find(); + if (!$order) { + $this->error('订单不存在'); + } + // 本人订单,或同一商家(主账号 + 关联账号)的订单 + if ((int)$order['user_id'] !== $this->uid()) { + $uids = $this->currentMerchantUserIds(); + if (!in_array((int)$order['user_id'], $uids, true)) { + $this->error('无权操作该订单', null, 403); + } + } $logs = Db::name('order_log')->where('order_id', $orderId)->order('id asc')->select(); foreach ($logs as &$log) { @@ -531,9 +544,36 @@ class Order extends Base 'create_text' => date('Y-m-d H:i', (int)$row['createtime']), 'urgent' => (int)$row['urgent'], 'price_type_text' => $this->priceTypeText($row['price_type']), + 'is_order_owner' => (int)$row['user_id'] === $this->uid(), ]); } + /** + * 当前用户所属商家的全部账号(主账号 + 关联账号) + */ + protected function currentMerchantUserIds() + { + $merchant = Db::name('merchant')->where('user_id', $this->uid())->find(); + if (!$merchant) { + $bind = Db::name('merchant_member')->where('user_id', $this->uid())->find(); + if ($bind) { + $merchant = Db::name('merchant')->where('id', (int)$bind['merchant_id'])->find(); + } + } + if (!$merchant) { + return []; + } + $ids = [(int)$merchant['user_id']]; + $rows = Db::name('merchant_member')->where('merchant_id', (int)$merchant['id'])->column('user_id'); + foreach ($rows as $id) { + $id = (int)$id; + if ($id > 0 && !in_array($id, $ids, true)) { + $ids[] = $id; + } + } + return $ids; + } + /** * 计价方式文案(前后端与后台统一口径) */ diff --git a/utils/api.js b/utils/api.js index 50628f2..5549198 100644 --- a/utils/api.js +++ b/utils/api.js @@ -74,6 +74,7 @@ export default { merchantInfo: () => get('/merchant/info'), merchantUpdate: (data) => post('/merchant/update', data), merchantBills: () => get('/merchant/bills'), + merchantOrders: (data) => get('/merchant/orders', data), merchantInvoices: () => get('/merchant/invoices'), merchantInvoice: (data) => post('/merchant/invoice', data), merchantMembers: () => get('/merchant/members'),