Appearance
概述
EBAOZU V4 相对 V3 的核心功能改动包括:公域产品同步方式调整、租赁运费模板、押金手工设置、支付宝白底图同步、设备管理模块、顺丰电子面单集成、订单/账期列表信息展示优化。本文档按代码实现逐项说明,功能清单原始说明见 runtime/docs/lj改动.md。
公域产品同步
V4 将产品规格由公私域各自维护,调整为统一以私域产品规格为准同步到公域;公域商品的所有操作入口集中在私域商品列表。
后台路由(route/admin.php)
| 路由 | 控制器方法 | 说明 |
|---|---|---|
GET product/sync_product_sku/:id(:2532) | StoreProduct::syncProductSkuToPublicSku | 私域规格同步公域 |
POST product/modi_aliapy_product/:id(:2616) | StoreProduct::modiAlipayProduct | 同步修改公域商品 |
POST product/modi_aliapy_price/:id | StoreProduct::modiAlipayPrice | 同步修改公域价格 |
POST product/on_alipay_product/:id | StoreProduct::onAlipayProduct | 公域上架 |
POST product/off_alipay_product/:id | StoreProduct::offAlipayProduct | 公域下架 |
POST product/rm_alipay_product/:id | StoreProduct::rmAlipayProduct | 移除公域商品 |
product/quick_public_modi、quick_public_update 及批量版本 | 同控制器 | 快捷下单/免审快捷下单 |
product/generate_public_product(:2403) | PublicProduct 控制器 | 私域产品生成公域产品 |
公域产品/SKU/套餐的完整管理路由见 route/admin.php:2370-2450(v1.product.PublicProduct / PublicProductSku / PublicPackage)。
核心实现
app/controller/admin/v1/product/StoreProduct.php:1901syncProductSkuToPublicSku():- 调
PublicProductServices::checkProductSkuSame()(app/services/product/product/PublicProductServices.php:935)比对公私域规格,一致则拒绝同步; - 不一致则
insertRelatedProduct()(:71)按私域商品重新生成公域父产品,读取rent_freight/rent_postage/rent_temp_id等私域字段; copySyncProductSkuToPublicProduct()(:738)在事务内复制公域 SKU、SKU 明细,并按租赁套餐生成新子产品。
- 调
- 公域商品修改/上下架走
app/services/alipay/QuickOrderServices.php:modiPublicItemQuickOrderInfo()(:4314)、modiPublicDirectQuickOrderInfo()(:4436)、offShelfAlipayProduct()、deletePublicItemInfo();成功后回写eb_store_product.is_syncCompleted(0 未同步 / 1 已上架 / 2 已下线)。
涉及数据表
eb_store_product:public_product_id、public_sub_product_id、item_id、is_public、is_syncCompletedeb_public_product、eb_public_product_sku、eb_public_product_sku_detail、eb_public_package(_detail)- 视图
eb_store_public_product
前端
- 私域商品列表:
view/admin/src/pages/product/productList/index.vue(:989/:1001 引入modi_aliapy_product、on_alipay_product、rm_alipay_product,:1426-1428 操作映射) - API 封装:
view/admin/src/api/product.js:1038、view/admin/src/api/productZfb.js:272(sync_public_sku)
注意:sync_public_sku(对应 sync_product_sku 路由)在前端 src 内暂无调用页面,仅 API 函数已定义,该入口当前只有后端路由可用。
租赁运费模板
商品层新增【租赁模板】,可设置运费及送达天数。操作路径:编辑商品 → 物流设置 → 租赁运费,可选包邮 / 固定邮费 / 运费模板 / 到付。
数据表(建表语句见 ebaozu_v3/ebaozu_v4.sql)
| 表 | 说明 | 关键字段 |
|---|---|---|
eb_store_product | 商品 | rent_freight(1包邮/2固定邮费/3指定模板/4到付)、rent_postage、rent_temp_id |
eb_rent_shipping_templates | 租赁运费模板主表 | — |
eb_rent_shipping_templates_free | 指定包邮区域 | delivery_day、append_price |
eb_rent_shipping_templates_no_delivery | 指定不送达区域 | — |
eb_rent_shipping_templates_region | 区域运费规则 | first_rule(default顺丰动态/fixed固定/free包邮)、delivery_rule(default/today/tomorrow/custom)、delivery_day、append_price |
后端
- 控制器:
app/controller/admin/v1/product/RentShippingTemplates.php(temp_list:35、edit:50、save:59、delete:92、city_list:113);路由route/admin.php:2907-2915(rent_shipping_templates/*) - 服务:
app/services/product/rentshipping/RentShippingTemplatesServices.php(getShippingList:54、save:163、detete:212 删除模板时联动清除商品rent_temp_id);RegionServices:109按delivery_rule解析送达天数 - 商品编辑取模板:
route/admin.php:2702template/get_rent_template→StoreProduct.php:1234 get_rent_template() - 下单侧:
app/controller/api/v1/order/StoreOrder.php:7175-7228按rent_temp_id结合顺丰接口送达天数计算运费与建议发货时间;app/services/order/StoreOrderComputedServices.php:180处理rent_freight==1包邮判断
前端
- 商品编辑页:
view/admin/src/pages/product/productAdd/index.vue:2907-2947(物流设置 → 租赁运费 Radio:包邮/固定邮费/运费模板),:7170 查看/新增模板弹窗 - 模板管理页:
view/admin/src/pages/setting/shippingTemplatesLease/index.vue(路由注册于view/admin/src/router/modules/setting.js:566-574) - 模板编辑组件:
view/admin/src/components/freightTemplateLease/index.vue
押金设置
V4 支持在商品规格上手工设置/调整押金金额,押金作为 SKU 字段直接录入存储,代码中不存在"押金 = 买断金额 − 总租金"的自动计算公式。
数据表字段
eb_store_product_attr_value.deposit(租赁商品押金)、buyout_money(买断价)- 公域侧:
eb_public_product_sku_detail.deposit - 订单侧:
eb_store_order_lease.deposit
后端
- 商品保存:
app/services/product/product/StoreProductServices.php:951/1008/1090,deposit作为 SKU 字段原样透传存储(默认 0) - 订单级押金调整:
route/admin.php:2331sync_deposit/:id("修改押金并同步")→app/common/controller/Lease.php:1182 syncDeposit()→app/services/order/StoreOrderServices.php:6888 syncDeposit():更新eb_store_order_lease.deposit并同步StoreOrderDepositServices押金记录(money/less_money);押金支付/退款/列表路由见route/admin.php:2332-2337 - 同步支付宝免押额度:
app/services/alipay/QuickOrderServices.php:9014-9124取规格deposit作免押额度(为空时回退买断价)
前端
- 商品编辑页
view/admin/src/pages/product/productAdd/index.vue:- :1096-1099 单规格押金 InputNumber
- :1366-1384 多规格押金列 +
batchSetting('deposit')批量设置 - :5931-5933 保存校验押金必须大于 0
- :8711-8732 押金 ≤ 最大总租金时弹出"押金风险提示"
- 订单侧:
view/admin/src/api/leaseOrder.js:535(order/sync_deposit)、view/admin/src/pages/order/leaseOrderList/components/detailModal.vue:317、tableExpand.vue:250/405(补充押金)
支付宝白底图同步
商品新增封面白底图字段,用于同步到支付宝商品管理后台(白底图有机会在支付宝首页曝光)。
实现
- 数据表:
eb_store_product.cover_image(注释"商品封面白底图(有机会在支付宝首页曝光)") - 保存校验:
app/services/product/product/StoreProductServices.php:1878-1880(未上传白底图抛"请上传商品封面白底图");:2352data['image'] = data['cover_image'] - 同步支付宝:
app/services/alipay/QuickOrderServices.php:7977-7993—— 取cover_image,调uploadProductImage()(:5947,场景ITEM_IMAGE_LIST)上传支付宝素材库获得image_id,既作head_img又组装white_ground_image属性(:5772-5773、:8563-8564) - 前端:
view/admin/src/pages/product/productAdd/index.vue:210("商品白底图"上传项cover_image)、:4734 必填校验、:8584-8586 提交前拦截提示
设备管理
V4 新增独立的设备管理模块(代码内部命名 Kit,历史注释称"配件包",后台界面与路由 real_name 均为"设备"),统一管理数码设备,支持商品规格与设备预绑定。绑定操作只能选择已添加的设备,即"先添加设备信息,再预绑定"。
注意与两个同名模块区分:mdm(移动设备管控,route/admin.php:439-452,与本模块无关);DeviceModel(app/controller/api/v1/other/DeviceModel.php,仅是型号字典上传)。
后台路由(route/admin.php:2354-2368,前缀 /adminapi/product/kit/)
| 路由 | 方法 | 说明 |
|---|---|---|
POST kit/add_kit_info | addKitInfo | 添加设备信息 |
POST kit/bind_kit_code/:id | bindKitCodeInfo | 绑定设备编码信息 |
POST kit/update_kit_info/:id | updateKitInfo | 更新设备信息 |
GET kit/get_kit_info/:id | getKitInfo | 获取指定设备信息 |
POST kit/get_new_kitcode/:id | getNewKitCode | 生成新设备编码 |
GET kit/get_kit_list | getKitList | 设备列表 |
GET kit/get_kit_code_list/:id | getKitCodeList | 设备编码列表 |
POST kit/update_kit_code/:id | updateKitCodeInfo | 更新设备绑定编码 |
GET kit/get_kit_ids | getKitIdList | 获取规格已绑定设备ID集合 |
POST kit/bind_sku_kit | bindKitIdByProductSku | 商品规格绑定设备(预绑定入口) |
GET kit/get_sku_sn_code/:order_id/:product_id/:sku_id | getKitSnByProductSku | 发货时取可选设备编码 |
GET kit/get_kit_accessories/:product_id/:sku_id | getKitAccessoriesList | 按商品规格取设备列表 |
门店端、移动端同模块路由见 route/store.php:506-514、route/api.php:183-191。
后端分层
- 控制器:
app/controller/admin/v1/kit/Kit.php(另有 store/supplier/api 端复刻) - Services:
app/services/kit/KitServices.php、KitCodeServices.php、KitAccessoriesServices.php - DAO:
app/dao/kit/KitDao.php、KitCodeDao.php、KitAccessoriesDao.php - Model:
app/model/kit/Kit.php(eb_kit,软删除,hasManycodes())、KitCode.php、KitAccessories.php - 编码生成:
app/services/other/DeviceCodeService.php:52 generateBatch()(前缀 +-+ 7位序号,如OP3V-0000001,行锁防重);序号表eb_device_code_seq
数据表
| 表 | 说明 | 关键字段 |
|---|---|---|
eb_kit | 设备主表 | kit_brand_id(品牌JSON)、prefix、kit_name、code_num、has_sn、stock_in_num/stock_out_num/kit_num、owner_id |
eb_kit_code | 设备编码/实例表 | kit_id、kit_code(唯一索引)、kit_sn、owner_id(plat-/store-/sup- 前缀归属)、product_id/sku_id(预绑定目标)、order_id、status(0未绑定/1已绑定未发货/2已发货)、price |
eb_kit_accessories | 商品规格 ↔ 设备预绑定关系表 | product_id/sku_id/kit_id |
eb_device_code_seq | 编码序号表 | — |
冗余字段:eb_store_order.kit_info/kit_id/kit_code/product_sn、eb_store_product_attr_value.kit_info/kit_id/kit_code_id。
注意:仓库内 SQL 快照落后于代码,eb_kit_code.kit_sn/owner_id/care_*、eb_kit_accessories.product_id/sku_id 等列在 sql 文件中无对应建表/变更语句,实际表结构以数据库为准。
业务流程
- 添加设备(
Kit::addKitInfo,Kit.php:97):校验名称/前缀唯一 →DeviceCodeService::syncMaxFromDevice()对齐序号 →generateBatch()批量生成编码 → 存eb_kit - 录入编码/序列号(
KitCodeServices.php:113/175):逐条写入eb_kit_code(含kit_sn、owner_id、价格、保障信息),事务内回写eb_kit库存统计 - 商品规格预绑定(
Kit::bindKitIdByProductSku→KitAccessoriesDao::updateKitAccessory,KitAccessoriesDao.php:67):事务内删除该 SKU 旧关联、解绑旧编码(product_id/sku_id清零),批量插入eb_kit_accessories,并把所选设备下status=0的编码置为status=1写入product_id/sku_id;设备清单 JSON 冗余写入eb_store_product_attr_value.kit_info - 下单:
StoreOrderCreateServices.php:294-304从购物车attrInfo.kit_id取设备ID写入eb_store_order.kit_id - 发货(
StoreOrderDeliveryServices.php:164-183):接收前端发货弹窗提交的product_id/sku_id/kit_id[]/sn_id[],事务内KitServices::updateKitStock()(eb_kit在库-1/出库+1,eb_kit_code.status=2并写order_id),设备信息 JSON 写入eb_store_order.kit_info;可选编码列表由getKitSnByProductSku(KitAccessoriesServices.php:74)按订单归属(plat/store/sup)过滤 - 归还回滚:
KitServices::syncKitInfo($kitId, $orderId, $sn, 'back')(KitServices.php:132)把编码状态退回 1 并清空订单号
前端
- 设备管理列表页:
view/admin/src/pages/product/kitBag/index.vue,弹窗kitAddModal.vue、kitViewDetailModal.vue;路由view/admin/src/router/modules/product.js:276-282 - 商品预绑定弹窗:
view/admin/src/pages/product/components/deviceBindModal.vue(商品列表productList/index.vue:931,1005引入) - 发货绑定弹窗:
view/admin/src/pages/order/leaseOrderList/components/bindDeviceModal.vue(发货页orderSend.vue:290,748-749引入) - 订单详情查看设备:
order/leaseOrderList/components/kitDetailByOrder.vue;入库绑定:pages/stockManage/components/bindKit.vue - API 封装集中在
view/admin/src/api/leaseOrder.js:1044-1156
顺丰电子面单
发货界面集成顺丰接口,商家可在后台在线下单并打印顺丰电子面单。项目中存在两套独立顺丰集成,注意区分:
| 集成 | 用途 | 核心类 | 对接方式 |
|---|---|---|---|
| 顺丰快递电子面单(本节) | 发货在线下单 + 云打印面单;租赁归还预约上门取件 | extend/libs/SFExpress.php | 直连顺丰开放平台 bspgw.sf-express.com/std/service |
| 顺丰同城配送 | 同城即时配送(与达达、UU跑腿并列) | extend/libs/SFDelivery.php、crmeb/services/delivery/storage/Sf.php | 走自研一号通中转 |
API 封装类 extend/libs/SFExpress.php
- 顾客编码/校验码硬编码为构造默认值(
SFExpress.php:352),未走 sys_config createSFOrder():767 — 下单(EXP_RECE_CREATE_ORDER),返回顺丰单号getCloudPrintHtml():483 /getCloudPrintHtmlSource():570 — 云打印面单(模板fm_76130_standard_YYRJKS3P5HBU),返回并抓取面单 HTMLpreCreateOrderInfo():1336 预下单;queryOrderStatus():974 结果查询;orderConfirmStatus():1075 确认/取消getSFEexpressTime():604 时效及运费查询;queryShippingFee():1181 清单运费查询;checkPickupTime():1482 揽件时间校验;parseAddress():1776 地址解析
后台发货面单流程
- 路由:
route/admin.php:1987GET adminapi/order/get_sfwaybill_html/:id→app/controller/admin/v1/order/StoreOrder.php::getCloudPrintHtml():853 - 流程:
- 已有
express_dump且订单待发货则直接返回缓存的面单 HTML - 否则
createSfWaybillOrder($id, $pickupTime)(:968):寄件人取sys_config('refund_address/refund_name/refund_phone'),月结卡号取sys_config('monthly_card')(:1065),调createSFOrder()取顺丰单号 - 取面单 HTML 回写订单:
delivery_name='顺丰快运'、delivery_id=运单号、delivery_code='shunfengkuaiyun'、express_dump=HTML、pickup_time(:925-935) - 异常时自动调
orderConfirmStatus()取消顺丰单
- 已有
- 发货提交仍是常规路由
PUT adminapi/order/delivery/:id(route/admin.php:2216),前端先把顺丰单号填进表单再提交 - 取消归还预约联动取消顺丰单:
StoreOrder.php:648-665 - 归还预约顺丰下单:
app/services/order/StoreDeliveryOrderServices.php:891-996(月结卡号硬编码'22222222',:981);重新预约入口StoreDeliveryOrder.php::reCreateSfPreOrder()/reCreateSfWaybillOrder():403/:437 - 顺丰回调(清单运费/路由推送):
route/admin.php:39-40→app/controller/admin/PublicController.php::notifyExpressFee():314
配置项
- 月结卡号:
sys_config('monthly_card'),仅发货链路读取;归还链路硬编码'22222222',两处不一致;后台无对应设置界面,值直接存于system_config表 - 寄件地址/联系人:复用退货地址配置
refund_address/refund_name/refund_phone - 顺丰同城配置(另一套):
sf_delivery_status、sf_dev_key、sf_dev_id,设置表单见app/services/system/config/SystemConfigServices.php:1894-1915
前端与移动端
- 发货弹窗:
view/admin/src/pages/order/leaseOrderList/handle/orderSend.vue(:48-51 「顺丰一键下单/面单打印」入口;:322-347 顺丰下单弹窗选上门取件时间 →confirmSfOrder():565) - 打印组件:
view/admin/src/pages/order/leaseOrderList/components/sfPrint.vue(print-jsraw-html直接打印面单 HTML) - API:
view/admin/src/api/leaseOrder.js:1354getSfHtml() - 移动端归还场景:
view/uniapp/api/leaseOrder.js:191-202(order/get_sfexpress_time_price、order/create_sf_order、取消顺丰订单)→app/controller/api/v1/order/StoreOrder.php::getSFExpressTimePrice():4618、createSFOrder():4695;页面view/uniapp/pages/goods/lease_order_return/index.vue
涉及数据表
eb_store_order:express_dump(面单 HTML)、pickup_time、delivery_id/delivery_name/delivery_codeeb_store_delivery_order:归还/配送单,delivery_no存顺丰运单号、sf_order_id存同城配送单号
注意:route/admin.php:23-35 注册的 7 个顺丰接口调试路由指向 app/controller/admin/Site.php,该控制器当前只剩 test() 方法,这些调试路由实际不可用。
订单列表信息展示优化
列表链路:route/admin.php:2030 GET /adminapi/order/lease_list → app/common/controller/Order.php:1858 leaseList(),列表组装在同文件 :1919-2219。前端页面:view/admin/src/pages/order/leaseOrderList/(index.vue、components/tableList.vue、components/tableExpand.vue、js/orderMix.js),API 封装 view/admin/src/api/leaseOrder.js。
新老用户标识与历史订单
- 后端:
Order.php:1948-1950预载lease_user关联取is_new_user, order_total, order_history(用户表冗余字段) - 数据回填:
app/services/order/StoreOrderServices.php:11467 updateUserOrderInfo()写入is_new_user='n'、order_total、order_history(JSON),缓存 tagupdate_user_order_history(1 小时);由定时任务statistics_users_order_history驱动(app/listener/system/timer/SystemTimer.php:359) - 前端:
tableList.vue:1106-1107——is_new_user == 'y'显示绿色「新用户」标签,否则显示蓝色可点击「老用户:N单」;点击openOrderHistory()(:2101-2105)弹出下单历史弹窗,数据直接取lease_user.order_history,不调新接口
订单类型标签
- 前端按行内字段渲染(
tableList.vue:90-122):自定义(custom_lease=='y')、0元随心租(is_super==1)、续租(order_lease.relet_times>0且在租)、预约单(is_appointment=='y'且未发货)、代客下单(clerk_id) - 后端筛选参数
plat_type(0 平台/1 门店/2 供应商/4 短租/5 归还,Order.php:1868-1869);后端不单独返回order_type字段
租金明细展示
- 后端:
Order.php:1959批量调StoreOrderServices::getPureRentPriceBatch($orderIds)(StoreOrderServices.php:7768)避免循环查库;Order.php:2137-2185组装order_rent_price集合(约 20 个字段:pure_total_price/before_pure_total_price/pure_first_price/promotions_price/extra_price(运费+增值服务+卡项)/first_pay_price/sign_total_price/buyout_tail_price/total_price/actual_total_price/已付未付应付实付等) - 前端:
tableList.vue:579-631金额区域展示订单总额/已付/未付(实付+优惠前划线价);行展开组件tableExpand.vue展示总租金、首期、额外费用、优惠金额明细 - 字段字典:
view/admin/src/pages/order/leaseOrderList/components/tableList.md
建议发货时间
- 后端计算:
Order.php:2065-2117,仅待发货(status=1)时:若expected_shipping_date为空,调getExpectDeliveryDateTime()(StoreOrderServices.php:11848,顺丰时效接口)得送达天数,建议发货时间 = 起租日 - 送达天数 - 1天 + 送达时点(12:00/18:00),并回写订单表;同时输出latest_shipping_date - 排序:请求参数
sort_type=5→expected_shipping_date ASC(Order.php:1910-1912,注释写"降序"与实际升序不一致);前端orderMix.js:457,1101传sort_type - 前端提醒:
tableList.vue:678-687待发货状态显示「建议发货时间」,颜色由getLatestShipColor()(orderMix.js:916-927)控制:当天绿色、逾期红色、未到不染色;另有「查询顺丰送达时间」Poptip(tableList.vue:689-706,接口/order/get_order_shipping_time/:id) - 待发货统计:
Order.php:1914-1917,2217附shipping_statistics(昨天/今天/明天/后天/3天后待发货单数),逻辑在StoreOrderServices.php:9696 getStatisticsDeliveryOrder()(按起租日-3天18:00 推算) - 次日达检测:
Order.php:2187-2191next_day_arrived(checkNextDayArrived(),Order.php:2599)
芝麻信用分与折扣优惠
- 芝麻分:前端
tableList.vue:1322-1328显示「芝麻分row.custom_form[0]」标签。后端Order.php:2196-2213解析custom_form(差异化定价表单);商品参与芝麻差异化定价但无优惠金额时兜底custom_form = ["650及以下"](:2211-2212) - 折扣:
Order.php:2193-2209计算discount(1 - promotion_price/before_pure_total_price,如 "8折");前端tableList.vue:1329-1334显示紫色「租金X折」标签 - 优惠汇总:
Order.php:1968-2009遍历order_installment累加promotions(商家:芝麻差异化定价merchant_sesame_promo_amount、商家券merchant_voucher_promo_amount;平台:立减platform_discount_promo_amount、平台券platform_voucher_promo_amount)
账期列表(租金账单)明细
- 路由:
route/admin.php:2084GET /adminapi/order/get_installment_list/:id→app/common/controller/Lease.php:569 getInstallmentList()→app/services/order/StoreOrderServices.php:5862 getInstallmentList() - 前端:
view/admin/src/pages/order/leaseOrderList/components/rentDetailModal.vue,列定义rentColumns(:497-510):期数/租金到期日/账单租金/额外费用/应付金额/优惠金额/实付金额等 - 公域优惠分摊到每期:每期行带
merchant_sesame_promo_amount/merchant_voucher_promo_amount/platform_discount_promo_amount/platform_voucher_promo_amount字段,前端rentDetailModal.vue:35-68在「优惠金额」列以问号 Tooltip 悬浮展示公域优惠(芝麻高分专享/商家券/平台立减/平台券)或私域优惠券金额 - 额外费用明细:
rentDetailModal.vue:81-90首期(num==1)且extra_price>0时以问号 Tooltip 展示运费/增值服务/卡项权益明细;实付金额列也有 Tooltip(首期费用+减免金额) - 另一套相似组装:
StoreOrderServices.php:9277 getOrderCapitalData()(:9344-9377 每期before_amount、首期合并额外费用extra_price=运费+added_service_amount+card_amount进pay_price) - 交互说明文档:
view/admin/src/pages/order/leaseOrderList/components/rentDetailModal.md
注意:原始说明中的"公摊优惠折叠/展开"在代码中的对应实现是「公域优惠分摊到每期 + 问号 Tooltip 悬浮」,并非表格行折叠展开(rentDetailModal.vue:914 有一行被注释掉的 _expanded = true,expand 方案未启用);订单行级折叠/展开由 tableExpand.vue(iView expand-row)实现,属于订单列表而非账期列表。
已知问题与注意事项
sync_public_sku后端路由可用但前端无调用页面- 顺丰月结卡号:发货链路读
sys_config('monthly_card'),归还链路硬编码'22222222',两处不一致且无后台设置界面 - 顺丰调试路由(
route/admin.php:23-35)指向的控制器方法不存在,实际不可用 - 设备模块 SQL 快照落后于代码,部分字段以线上库实际结构为准
- 建议发货时间排序注释("降序")与实际代码(
ASC)不一致