diff --git a/backend/internal/model/mohong.go b/backend/internal/model/mohong.go
index 5ecc3f0..5d2f6fd 100644
--- a/backend/internal/model/mohong.go
+++ b/backend/internal/model/mohong.go
@@ -6,7 +6,7 @@ import (
"gorm.io/datatypes"
)
-// MohongCategory 摸大红商品分类。
+// MohongCategory 撞车商品分类。
type MohongCategory struct {
ID uint64 `gorm:"primaryKey" json:"id"`
Name string `gorm:"size:64;not null;uniqueIndex" json:"name"`
@@ -31,7 +31,7 @@ func (MohongProductCategory) TableName() string {
return "mohong_product_categories"
}
-// MohongProduct 摸大红商品。
+// MohongProduct 撞车商品。
type MohongProduct struct {
ID uint64 `gorm:"primaryKey" json:"id"`
CategoryID *uint64 `gorm:"column:category_id;index" json:"category_id"` // 主分类(展示用)
@@ -55,7 +55,7 @@ func (MohongProduct) TableName() string {
return "mohong_products"
}
-// MohongOrder 摸大红订单。
+// MohongOrder 撞车订单。
type MohongOrder struct {
ID uint64 `gorm:"primaryKey" json:"id"`
OrderNo string `gorm:"size:64;not null;uniqueIndex" json:"order_no"`
diff --git a/backend/internal/modules/chat/conversation.go b/backend/internal/modules/chat/conversation.go
index 98453d2..9568cd9 100644
--- a/backend/internal/modules/chat/conversation.go
+++ b/backend/internal/modules/chat/conversation.go
@@ -169,6 +169,22 @@ func (r *Repository) EnsureSupportConversation(ctx context.Context, userID uint6
_ = tx.Model(&existing).Update("support_scene", SupportSceneGeneral).Error
}
}
+ // 兼容旧摸大红场景码 mohong → crash
+ if existing.ID == 0 && scene == SupportSceneCrash {
+ err = tx.Table("chat_conversations AS c").
+ Select("c.*").
+ Joins("JOIN chat_participants AS cp ON cp.conversation_id = c.id").
+ Where(
+ "c.type = ? AND c.support_scene = ? AND cp.participant_type = ? AND cp.participant_id = ?",
+ ConversationTypeGeneralSupport, SupportSceneMohong, "user", userID,
+ ).
+ Order("c.id ASC").
+ Limit(1).
+ Find(&existing).Error
+ if err != nil {
+ return err
+ }
+ }
if existing.ID > 0 {
conversationID = existing.ID
return nil
diff --git a/backend/internal/modules/chat/dto.go b/backend/internal/modules/chat/dto.go
index a1c0690..b5aa8d8 100644
--- a/backend/internal/modules/chat/dto.go
+++ b/backend/internal/modules/chat/dto.go
@@ -35,7 +35,7 @@ type ConversationDTO struct {
// EnsureSupportRequest 创建/复用客服会话。
type EnsureSupportRequest struct {
- // Scene 业务场景:general(默认)/ mohong(摸大红)
+ // Scene 业务场景:general(默认)/ crash(撞车,兼容旧值 mohong)
Scene string `json:"scene"`
}
diff --git a/backend/internal/modules/chat/support_scene.go b/backend/internal/modules/chat/support_scene.go
index 2f05773..c8287e7 100644
--- a/backend/internal/modules/chat/support_scene.go
+++ b/backend/internal/modules/chat/support_scene.go
@@ -11,18 +11,20 @@ import (
// 客服入口业务场景(与前端 POST /chats/support 的 scene 对齐)。
const (
SupportSceneGeneral = "general"
- SupportSceneMohong = "mohong"
+ SupportSceneCrash = "crash"
+ // SupportSceneMohong 兼容旧 scene 值,与 crash 同一客服分组。
+ SupportSceneMohong = "mohong"
)
// resolveSupportScene 规范化场景并返回标题、客服分组 code、欢迎语。
// groupCode 为空时表示不走分组,使用默认客服选取逻辑。
func resolveSupportScene(raw string) (scene, title, groupCode, welcome string) {
switch strings.ToLower(strings.TrimSpace(raw)) {
- case SupportSceneMohong:
- return SupportSceneMohong,
- "摸大红客服",
- supportgroup.GroupCodeMohong,
- "您好,这里是摸大红客服。请直接描述问题,可将订单信息复制后发送。"
+ case SupportSceneCrash, SupportSceneMohong:
+ return SupportSceneCrash,
+ "撞车客服",
+ supportgroup.GroupCodeMohong, // 分组 code 仍为 mohong,后台可改显示名
+ "您好,这里是撞车客服。请直接描述问题,可将订单信息复制后发送。"
default:
// 未知场景回落平台客服,避免随意 scene 绕开分配策略
return SupportSceneGeneral,
diff --git a/backend/internal/modules/file/handler.go b/backend/internal/modules/file/handler.go
index 831b27c..b258f66 100644
--- a/backend/internal/modules/file/handler.go
+++ b/backend/internal/modules/file/handler.go
@@ -70,7 +70,7 @@ func (h *Handler) writeObject(c *gin.Context, publicOnly bool) {
!strings.HasPrefix(key, "avatar/") &&
!strings.HasPrefix(key, "payment-cert/") &&
!strings.HasPrefix(key, "announcement/") &&
- !strings.HasPrefix(key, "mohong/") {
+ !strings.HasPrefix(key, "mohong/") && !strings.HasPrefix(key, "crash/") {
response.Error(c, http.StatusNotFound, "not_found", "文件不存在或暂不可访问")
return
}
diff --git a/backend/internal/modules/file/service.go b/backend/internal/modules/file/service.go
index 1a35798..4426ba2 100644
--- a/backend/internal/modules/file/service.go
+++ b/backend/internal/modules/file/service.go
@@ -106,7 +106,7 @@ func normalizeContentType(contentType string, data []byte) string {
func fileURLForScene(scene string, key string) string {
fileURL := "/api/files/object?key=" + url.QueryEscape(key)
- if scene == "home-banner" || scene == "avatar" || scene == "payment-cert" || scene == "announcement" || scene == "mohong" {
+ if scene == "home-banner" || scene == "avatar" || scene == "payment-cert" || scene == "announcement" || scene == "mohong" || scene == "crash" {
fileURL = "/api/public/files/object?key=" + url.QueryEscape(key)
}
return fileURL
@@ -115,7 +115,7 @@ func fileURLForScene(scene string, key string) string {
func normalizeScene(scene string) string {
scene = strings.TrimSpace(strings.ToLower(scene))
switch scene {
- case "listing", "handoff", "dispute", "realname", "avatar", "home-banner", "chat", "payment-cert", "announcement", "qrcode", "mohong":
+ case "listing", "handoff", "dispute", "realname", "avatar", "home-banner", "chat", "payment-cert", "announcement", "qrcode", "mohong", "crash":
return scene
default:
return "misc"
diff --git a/backend/internal/modules/mohong/config.go b/backend/internal/modules/mohong/config.go
index e484fc6..d88f12f 100644
--- a/backend/internal/modules/mohong/config.go
+++ b/backend/internal/modules/mohong/config.go
@@ -14,7 +14,7 @@ const (
configKeyDefaultQrcodeURL = "mohong.default_qrcode_url"
configKeyOrderCopyTemplate = "mohong.order_copy_template"
- defaultOrderCopyTemplate = "【摸大红订单】\n订单号:{{order_no}}\n下单时间:{{created_at}}\n商品明细:\n{{items}}\n数量合计:{{quantity}}\n金额:{{amount}}\n下单人:{{buyer_name}}({{buyer_phone}})"
+ defaultOrderCopyTemplate = "【撞车订单】\n订单号:{{order_no}}\n下单时间:{{created_at}}\n商品明细:\n{{items}}\n数量合计:{{quantity}}\n金额:{{amount}}\n下单人:{{buyer_name}}({{buyer_phone}})"
)
func (r *Repository) GetConfig(ctx context.Context) (*ConfigDTO, error) {
@@ -42,12 +42,12 @@ func (r *Repository) UpdateConfig(ctx context.Context, req UpdateConfigRequest)
}
err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
if req.DefaultQrcodeURL != nil {
- if err := upsertConfig(tx, configKeyDefaultQrcodeURL, strings.TrimSpace(*req.DefaultQrcodeURL), "摸大红全局默认固定二维码图片URL"); err != nil {
+ if err := upsertConfig(tx, configKeyDefaultQrcodeURL, strings.TrimSpace(*req.DefaultQrcodeURL), "撞车全局默认固定二维码图片URL"); err != nil {
return err
}
}
if req.OrderCopyTemplate != nil {
- if err := upsertConfig(tx, configKeyOrderCopyTemplate, strings.TrimSpace(*req.OrderCopyTemplate), "摸大红订单一键复制文案模板"); err != nil {
+ if err := upsertConfig(tx, configKeyOrderCopyTemplate, strings.TrimSpace(*req.OrderCopyTemplate), "撞车订单一键复制文案模板"); err != nil {
return err
}
}
diff --git a/backend/internal/modules/mohong/order_repo.go b/backend/internal/modules/mohong/order_repo.go
index 5f71524..8dcc1ce 100644
--- a/backend/internal/modules/mohong/order_repo.go
+++ b/backend/internal/modules/mohong/order_repo.go
@@ -111,7 +111,7 @@ func (r *Repository) CreateOrder(ctx context.Context, userID uint64, req CreateO
if err := notification.Append(tx, notification.Entry{
UserID: userID,
Type: "order",
- Title: "摸大红订单已创建",
+ Title: "撞车订单已创建",
Content: "订单已创建,请在有效时间内完成支付。",
BizType: "mohong_order",
BizID: &orderID,
@@ -311,8 +311,8 @@ func (r *Repository) AdminCompleteOrder(ctx context.Context, orderID uint64, rem
return r.AdminFindOrder(ctx, orderID)
}
-// ConfirmPaidFromChannelTx 支付成功后推进摸大红订单:固化二维码快照与可复制文案。
-// 返回值固定为 0,兼容支付模块会话通知签名(摸大红无订单群)。
+// ConfirmPaidFromChannelTx 支付成功后推进撞车订单:固化二维码快照与可复制文案。
+// 返回值固定为 0,兼容支付模块会话通知签名(撞车无订单群)。
func (r *Repository) ConfirmPaidFromChannelTx(tx *gorm.DB, orderID uint64) (uint64, error) {
var order model.MohongOrder
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&order, orderID).Error; err != nil {
@@ -348,7 +348,7 @@ func (r *Repository) ConfirmPaidFromChannelTx(tx *gorm.DB, orderID uint64) (uint
if err := notification.Append(tx, notification.Entry{
UserID: order.UserID,
Type: "order",
- Title: "摸大红订单支付成功",
+ Title: "撞车订单支付成功",
Content: "支付已完成,请在订单详情扫码联系客服,并复制订单信息发送。",
BizType: "mohong_order",
BizID: &orderIDCopy,
@@ -358,7 +358,7 @@ func (r *Repository) ConfirmPaidFromChannelTx(tx *gorm.DB, orderID uint64) (uint
return 0, nil
}
-// NotifyNewConversation 兼容支付模块接口;摸大红不创建会话,空实现。
+// NotifyNewConversation 兼容支付模块接口;撞车不创建会话,空实现。
func (r *Repository) NotifyNewConversation(conversationID uint64) {}
func (r *Repository) cancelPendingOrderTx(tx *gorm.DB, order *model.MohongOrder, reason string) error {
diff --git a/backend/internal/modules/mohong/repository.go b/backend/internal/modules/mohong/repository.go
index d2b495a..1163cab 100644
--- a/backend/internal/modules/mohong/repository.go
+++ b/backend/internal/modules/mohong/repository.go
@@ -2,7 +2,7 @@ package mohong
import "gorm.io/gorm"
-// Repository 摸大红数据访问。
+// Repository 撞车数据访问。
type Repository struct {
db *gorm.DB
}
diff --git a/backend/internal/modules/payment/mohong_payment.go b/backend/internal/modules/payment/mohong_payment.go
index 1d7a666..a8609fe 100644
--- a/backend/internal/modules/payment/mohong_payment.go
+++ b/backend/internal/modules/payment/mohong_payment.go
@@ -13,7 +13,7 @@ import (
const bizTypeMohongPay = "mohong_pay"
-// StartMohong 发起摸大红订单支付。
+// StartMohong 发起撞车订单支付。
func (r *Repository) StartMohong(ctx context.Context, userID uint64, orderID uint64, req StartPaymentRequest, clientIP string) (*PaymentDTO, error) {
req.PayWay = normalizePayWay(req.PayWay)
defaultConfig, err := r.defaultRuntimeConfig(ctx, req.PayWay)
@@ -73,7 +73,7 @@ func (r *Repository) StartMohong(ctx context.Context, userID uint64, orderID uin
NotifyURL: runtimeConfig.NotifyURL,
JumpURL: runtimeConfig.JumpURL,
ClientIP: clientIP,
- Body: "摸大红订单 " + orderRow.OrderNo,
+ Body: "撞车订单 " + orderRow.OrderNo,
Attach: orderRow.OrderNo,
})
if err != nil {
@@ -202,7 +202,7 @@ func newMohongPayment(row model.MohongOrder, req StartPaymentRequest, runtimeCon
return payment, nil
}
-// QueryMohong 查询摸大红订单支付状态。
+// QueryMohong 查询撞车订单支付状态。
func (r *Repository) QueryMohong(ctx context.Context, userID uint64, orderID uint64) (*PaymentDTO, error) {
var payment model.PaymentOrder
if err := r.db.WithContext(ctx).
diff --git a/backend/internal/modules/payment/repository.go b/backend/internal/modules/payment/repository.go
index 7b21744..3a9da8f 100644
--- a/backend/internal/modules/payment/repository.go
+++ b/backend/internal/modules/payment/repository.go
@@ -13,7 +13,7 @@ import (
"gorm.io/gorm"
)
-// MohongOrderConfirmer 摸大红订单支付确认接口,避免 payment 与 mohong 循环依赖。
+// MohongOrderConfirmer 撞车订单支付确认接口,避免 payment 与 mohong 循环依赖。
type MohongOrderConfirmer interface {
ConfirmPaidFromChannelTx(tx *gorm.DB, orderID uint64) (uint64, error)
NotifyNewConversation(conversationID uint64)
@@ -89,7 +89,7 @@ func WithLogger(logger *zap.Logger) RepositoryOption {
}
}
-// WithMohongRepo 注入摸大红订单确认器。
+// WithMohongRepo 注入撞车订单确认器。
func WithMohongRepo(repo MohongOrderConfirmer) RepositoryOption {
return func(r *Repository) {
r.mohongRepo = repo
diff --git a/backend/internal/router/router.go b/backend/internal/router/router.go
index 6f8f722..d25aeb9 100644
--- a/backend/internal/router/router.go
+++ b/backend/internal/router/router.go
@@ -428,23 +428,26 @@ func New(cfg config.Config, deps Dependencies, logger *zap.Logger) *gin.Engine {
sellerPickupRoutes.GET("", pickupHandler.ListForSeller)
}
- // 摸大红:商品公开,下单需登录+实名
+ // 撞车(对外路径 /crash;兼容旧路径 /mohong):商品公开,下单需登录+实名
if mohongHandler != nil {
- mohongPublic := api.Group("/mohong")
- {
- mohongPublic.GET("/categories", mohongHandler.ListCategories)
- mohongPublic.GET("/products", mohongHandler.ListProducts)
- mohongPublic.GET("/products/:id", mohongHandler.GetProduct)
+ registerCrashPublic := func(g *gin.RouterGroup) {
+ g.GET("/categories", mohongHandler.ListCategories)
+ g.GET("/products", mohongHandler.ListProducts)
+ g.GET("/products/:id", mohongHandler.GetProduct)
}
- mohongAuth := api.Group("/mohong", requireAuth)
- {
- mohongAuth.POST("/orders", requireRealname, mohongHandler.CreateOrder)
- mohongAuth.GET("/orders", mohongHandler.ListMyOrders)
- mohongAuth.GET("/orders/:id", mohongHandler.GetMyOrder)
- mohongAuth.POST("/orders/:id/cancel", mohongHandler.CancelMyOrder)
- mohongAuth.POST("/orders/:id/start-payment", requireRealname, paymentHandler.StartMohong)
- mohongAuth.GET("/orders/:id/query-payment", paymentHandler.QueryMohong)
+ registerCrashAuth := func(g *gin.RouterGroup) {
+ g.POST("/orders", requireRealname, mohongHandler.CreateOrder)
+ g.GET("/orders", mohongHandler.ListMyOrders)
+ g.GET("/orders/:id", mohongHandler.GetMyOrder)
+ g.POST("/orders/:id/cancel", mohongHandler.CancelMyOrder)
+ g.POST("/orders/:id/start-payment", requireRealname, paymentHandler.StartMohong)
+ g.GET("/orders/:id/query-payment", paymentHandler.QueryMohong)
}
+ registerCrashPublic(api.Group("/crash"))
+ registerCrashAuth(api.Group("/crash", requireAuth))
+ // 兼容旧 API 前缀
+ registerCrashPublic(api.Group("/mohong"))
+ registerCrashAuth(api.Group("/mohong", requireAuth))
}
orderRoutes := api.Group("/orders", requireAuth)
@@ -599,24 +602,28 @@ func New(cfg config.Config, deps Dependencies, logger *zap.Logger) *gin.Engine {
adminRoutes.POST("/listings/:id/offline", requirePerm("listing:offline"), listingHandler.AdminOffline)
adminRoutes.POST("/listings/:id/mark-abnormal", requirePerm("listing:offline"), listingHandler.AdminMarkAbnormal)
- // 摸大红
+ // 撞车后台(/admin/crash;兼容 /admin/mohong)
if mohongHandler != nil {
// 商品编辑需要拉分类列表,故 GET 用 product_view
- adminRoutes.GET("/mohong/categories", requirePerm("mohong:product_view"), mohongHandler.AdminListCategories)
- adminRoutes.POST("/mohong/categories", requirePerm("mohong:category"), mohongHandler.AdminCreateCategory)
- adminRoutes.PUT("/mohong/categories/:id", requirePerm("mohong:category"), mohongHandler.AdminUpdateCategory)
- adminRoutes.DELETE("/mohong/categories/:id", requirePerm("mohong:category"), mohongHandler.AdminDeleteCategory)
- adminRoutes.GET("/mohong/products", requirePerm("mohong:product_view"), mohongHandler.AdminListProducts)
- adminRoutes.GET("/mohong/products/:id", requirePerm("mohong:product_view"), mohongHandler.AdminGetProduct)
- adminRoutes.POST("/mohong/products", requirePerm("mohong:product_manage"), mohongHandler.AdminCreateProduct)
- adminRoutes.PUT("/mohong/products/:id", requirePerm("mohong:product_manage"), mohongHandler.AdminUpdateProduct)
- adminRoutes.DELETE("/mohong/products/:id", requirePerm("mohong:product_manage"), mohongHandler.AdminDeleteProduct)
- adminRoutes.GET("/mohong/orders", requirePerm("mohong:order_view"), mohongHandler.AdminListOrders)
- adminRoutes.GET("/mohong/orders/:id", requirePerm("mohong:order_view"), mohongHandler.AdminGetOrder)
- adminRoutes.POST("/mohong/orders/:id/complete", requirePerm("mohong:order_manage"), mohongHandler.AdminCompleteOrder)
- adminRoutes.POST("/mohong/orders/:id/cancel", requirePerm("mohong:order_manage"), mohongHandler.AdminCancelOrder)
- adminRoutes.GET("/mohong/config", requirePerm("mohong:config"), mohongHandler.AdminGetConfig)
- adminRoutes.PUT("/mohong/config", requirePerm("mohong:config"), mohongHandler.AdminUpdateConfig)
+ registerCrashAdmin := func(prefix string) {
+ adminRoutes.GET(prefix+"/categories", requirePerm("mohong:product_view"), mohongHandler.AdminListCategories)
+ adminRoutes.POST(prefix+"/categories", requirePerm("mohong:category"), mohongHandler.AdminCreateCategory)
+ adminRoutes.PUT(prefix+"/categories/:id", requirePerm("mohong:category"), mohongHandler.AdminUpdateCategory)
+ adminRoutes.DELETE(prefix+"/categories/:id", requirePerm("mohong:category"), mohongHandler.AdminDeleteCategory)
+ adminRoutes.GET(prefix+"/products", requirePerm("mohong:product_view"), mohongHandler.AdminListProducts)
+ adminRoutes.GET(prefix+"/products/:id", requirePerm("mohong:product_view"), mohongHandler.AdminGetProduct)
+ adminRoutes.POST(prefix+"/products", requirePerm("mohong:product_manage"), mohongHandler.AdminCreateProduct)
+ adminRoutes.PUT(prefix+"/products/:id", requirePerm("mohong:product_manage"), mohongHandler.AdminUpdateProduct)
+ adminRoutes.DELETE(prefix+"/products/:id", requirePerm("mohong:product_manage"), mohongHandler.AdminDeleteProduct)
+ adminRoutes.GET(prefix+"/orders", requirePerm("mohong:order_view"), mohongHandler.AdminListOrders)
+ adminRoutes.GET(prefix+"/orders/:id", requirePerm("mohong:order_view"), mohongHandler.AdminGetOrder)
+ adminRoutes.POST(prefix+"/orders/:id/complete", requirePerm("mohong:order_manage"), mohongHandler.AdminCompleteOrder)
+ adminRoutes.POST(prefix+"/orders/:id/cancel", requirePerm("mohong:order_manage"), mohongHandler.AdminCancelOrder)
+ adminRoutes.GET(prefix+"/config", requirePerm("mohong:config"), mohongHandler.AdminGetConfig)
+ adminRoutes.PUT(prefix+"/config", requirePerm("mohong:config"), mohongHandler.AdminUpdateConfig)
+ }
+ registerCrashAdmin("/crash")
+ registerCrashAdmin("/mohong")
}
adminRoutes.GET("/disputes", requirePerm("dispute:view"), disputeHandler.AdminList)
diff --git a/backend/migrations/000032_crash_branding.sql b/backend/migrations/000032_crash_branding.sql
new file mode 100644
index 0000000..64bb2e8
--- /dev/null
+++ b/backend/migrations/000032_crash_branding.sql
@@ -0,0 +1,31 @@
+-- +goose Up
+
+UPDATE chat_support_groups
+SET name = '撞车-客服',
+ description = '用户从撞车入口联系客服时,按本组成员在线与负载分配'
+WHERE code = 'mohong';
+
+UPDATE system_configs
+SET description = REPLACE(description, '摸大红', '撞车'),
+ `value` = REPLACE(`value`, '摸大红', '撞车')
+WHERE `key` LIKE 'mohong.%';
+
+UPDATE permissions
+SET name = REPLACE(name, '摸大红', '撞车')
+WHERE code LIKE 'mohong:%';
+
+-- +goose Down
+
+UPDATE chat_support_groups
+SET name = '摸大红-客服',
+ description = '用户从摸大红入口联系客服时,按本组成员在线与负载分配'
+WHERE code = 'mohong';
+
+UPDATE system_configs
+SET description = REPLACE(description, '撞车', '摸大红'),
+ `value` = REPLACE(`value`, '撞车', '摸大红')
+WHERE `key` LIKE 'mohong.%';
+
+UPDATE permissions
+SET name = REPLACE(name, '撞车', '摸大红')
+WHERE code LIKE 'mohong:%';
diff --git a/frontend/src/features/admin/views/AdminMohongCategoriesView.vue b/frontend/src/features/admin/views/AdminMohongCategoriesView.vue
index 486800f..6374f52 100644
--- a/frontend/src/features/admin/views/AdminMohongCategoriesView.vue
+++ b/frontend/src/features/admin/views/AdminMohongCategoriesView.vue
@@ -96,7 +96,7 @@ async function handleDelete(item: MohongCategory) {
-
摸大红分类
+
撞车分类
大红 / 四格大红 / 炫彩等分类,前台左侧筛选使用
diff --git a/frontend/src/features/admin/views/AdminMohongConfigView.vue b/frontend/src/features/admin/views/AdminMohongConfigView.vue
index 9add081..bb62558 100644
--- a/frontend/src/features/admin/views/AdminMohongConfigView.vue
+++ b/frontend/src/features/admin/views/AdminMohongConfigView.vue
@@ -49,7 +49,7 @@ async function handleSave() {
async function uploadQrcode(file: File) {
try {
- const uploaded = await uploadAdminFile(file, 'mohong')
+ const uploaded = await uploadAdminFile(file, 'crash')
form.default_qrcode_url = uploaded.url
ElMessage.success('上传成功')
} catch (error) {
@@ -63,7 +63,7 @@ async function uploadQrcode(file: File) {
-
摸大红配置
+
撞车配置
全局默认固定二维码与订单复制模板。商品可覆盖默认二维码;支付后用户在订单详情扫码并复制信息联系客服。
保存配置
diff --git a/frontend/src/features/admin/views/AdminMohongOrdersView.vue b/frontend/src/features/admin/views/AdminMohongOrdersView.vue
index 5d4c5cc..80c0371 100644
--- a/frontend/src/features/admin/views/AdminMohongOrdersView.vue
+++ b/frontend/src/features/admin/views/AdminMohongOrdersView.vue
@@ -85,7 +85,7 @@ async function copyText(text: string) {
-
摸大红订单
+
撞车订单
查看订单、完成履约、复制用户订单信息
刷新
diff --git a/frontend/src/features/admin/views/AdminMohongProductsView.vue b/frontend/src/features/admin/views/AdminMohongProductsView.vue
index 3abe240..d912471 100644
--- a/frontend/src/features/admin/views/AdminMohongProductsView.vue
+++ b/frontend/src/features/admin/views/AdminMohongProductsView.vue
@@ -177,7 +177,7 @@ async function handleDelete(item: MohongProduct) {
async function uploadImage(file: File, target: 'cover' | 'gallery' | 'qrcode') {
try {
- const uploaded = await uploadAdminFile(file, 'mohong')
+ const uploaded = await uploadAdminFile(file, 'crash')
if (target === 'cover') form.cover_url = uploaded.url
else if (target === 'qrcode') form.qrcode_image_url = uploaded.url
else form.image_urls.push(uploaded.url)
@@ -197,7 +197,7 @@ function removeGallery(url: string) {
-
摸大红商品
+
撞车商品
管理商品图片、价格、库存与专属二维码
diff --git a/frontend/src/features/chats/api/chats.ts b/frontend/src/features/chats/api/chats.ts
index c9cec47..c6df45e 100644
--- a/frontend/src/features/chats/api/chats.ts
+++ b/frontend/src/features/chats/api/chats.ts
@@ -14,7 +14,7 @@ export interface ChatParticipant {
joined_at: string
}
-export type SupportScene = 'general' | 'mohong'
+export type SupportScene = 'general' | 'crash'
export interface ChatConversation {
id: number
@@ -42,15 +42,19 @@ export interface ChatConversation {
updated_at: string
}
-/** 根据当前路由推断客服场景:摸大红页 → mohong,其它 → general */
+/** 根据当前路由推断客服场景:撞车页 → crash,其它 → general */
export function resolveSupportScene(path: string): SupportScene {
if (
+ path === '/crash' ||
+ path.startsWith('/crash/') ||
+ path === '/m/crash' ||
+ path.startsWith('/m/crash/') ||
path === '/mohong' ||
path.startsWith('/mohong/') ||
path === '/m/mohong' ||
path.startsWith('/m/mohong/')
) {
- return 'mohong'
+ return 'crash'
}
return 'general'
}
diff --git a/frontend/src/features/listings/views/HomeView.vue b/frontend/src/features/listings/views/HomeView.vue
index abfb41b..2b6ae5e 100644
--- a/frontend/src/features/listings/views/HomeView.vue
+++ b/frontend/src/features/listings/views/HomeView.vue
@@ -260,8 +260,8 @@ loadHome()
租号大厅
高哈夫币 · 安全交接 · 随租随玩
-
- 摸大红 NEW
+
+ 撞车 NEW
选购商品 · 支付后进群联系客服
@@ -372,7 +372,7 @@ loadHome()
font-size: 13px;
}
-.biz-entry.mohong strong em {
+.biz-entry.crash strong em {
margin-left: 6px;
padding: 1px 6px;
border-radius: 999px;
diff --git a/frontend/src/features/listings/views/MobileHomeView.css b/frontend/src/features/listings/views/MobileHomeView.css
index 48fa8f5..3ac0006 100644
--- a/frontend/src/features/listings/views/MobileHomeView.css
+++ b/frontend/src/features/listings/views/MobileHomeView.css
@@ -364,28 +364,6 @@
box-shadow: 0 4px 14px rgba(23, 35, 61, 0.04);
}
-.biz-entry-icon {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- width: 30px;
- height: 30px;
- border-radius: 9px;
- font-size: 13px;
- font-weight: 800;
- margin-bottom: 2px;
-}
-
-.biz-entry-icon.rental {
- background: #fff1e6;
- color: #ff6a00;
-}
-
-.biz-entry-icon.mohong {
- background: #fee2e2;
- color: #dc2626;
-}
-
.biz-entry strong {
color: #17233d;
font-size: 15px;
diff --git a/frontend/src/features/listings/views/MobileHomeView.vue b/frontend/src/features/listings/views/MobileHomeView.vue
index 8ffcfe1..936ab85 100644
--- a/frontend/src/features/listings/views/MobileHomeView.vue
+++ b/frontend/src/features/listings/views/MobileHomeView.vue
@@ -818,13 +818,11 @@ syncMobileHomeQuery()
- 租
租号大厅
高哈夫币 · 随租随玩
-
- 红
- 摸大红
+
+ 撞车
选购商品 · 一键找客服
NEW
diff --git a/frontend/src/features/mohong/api/mohong.ts b/frontend/src/features/mohong/api/mohong.ts
index 2a23530..8d799fe 100644
--- a/frontend/src/features/mohong/api/mohong.ts
+++ b/frontend/src/features/mohong/api/mohong.ts
@@ -92,7 +92,7 @@ export interface Paginated {
}
export async function fetchMohongCategories() {
- const { data } = await apiClient.get>('/mohong/categories')
+ const { data } = await apiClient.get>('/crash/categories')
return data.data || []
}
@@ -102,14 +102,14 @@ export async function fetchMohongProducts(params?: {
page?: number
page_size?: number
}) {
- const { data } = await apiClient.get>>('/mohong/products', {
+ const { data } = await apiClient.get>>('/crash/products', {
params,
})
return data.data
}
export async function fetchMohongProduct(id: number | string) {
- const { data } = await apiClient.get>(`/mohong/products/${id}`)
+ const { data } = await apiClient.get>(`/crash/products/${id}`)
return data.data
}
@@ -121,7 +121,7 @@ export async function createMohongOrder(
const payload = Array.isArray(productIdOrItems)
? { items: productIdOrItems }
: { product_id: productIdOrItems, quantity }
- const { data } = await apiClient.post>('/mohong/orders', payload)
+ const { data } = await apiClient.post>('/crash/orders', payload)
return data.data
}
@@ -130,19 +130,19 @@ export async function fetchMyMohongOrders(params?: {
page?: number
page_size?: number
}) {
- const { data } = await apiClient.get>>('/mohong/orders', {
+ const { data } = await apiClient.get>>('/crash/orders', {
params,
})
return data.data
}
export async function fetchMyMohongOrder(id: number | string) {
- const { data } = await apiClient.get>(`/mohong/orders/${id}`)
+ const { data } = await apiClient.get>(`/crash/orders/${id}`)
return data.data
}
export async function cancelMyMohongOrder(id: number | string, reason?: string) {
- const { data } = await apiClient.post>(`/mohong/orders/${id}/cancel`, {
+ const { data } = await apiClient.post>(`/crash/orders/${id}/cancel`, {
reason: reason || '',
})
return data.data
@@ -154,7 +154,7 @@ export async function startMohongPayment(
jsPayFlag?: string
) {
const { data } = await apiClient.post>(
- `/mohong/orders/${orderId}/start-payment`,
+ `/crash/orders/${orderId}/start-payment`,
{
pay_way: payWay || 'ZFBZF',
jspay_flag: jsPayFlag || '',
@@ -165,14 +165,14 @@ export async function startMohongPayment(
export async function queryMohongPayment(orderId: number) {
const { data } = await apiClient.get>(
- `/mohong/orders/${orderId}/query-payment`
+ `/crash/orders/${orderId}/query-payment`
)
return data.data
}
// Admin APIs
export async function fetchAdminMohongCategories() {
- const { data } = await apiClient.get>('/admin/mohong/categories')
+ const { data } = await apiClient.get>('/admin/crash/categories')
return data.data || []
}
@@ -183,7 +183,7 @@ export async function createAdminMohongCategory(payload: {
status?: string
}) {
const { data } = await apiClient.post>(
- '/admin/mohong/categories',
+ '/admin/crash/categories',
payload
)
return data.data
@@ -194,7 +194,7 @@ export async function updateAdminMohongCategory(
payload: Partial<{ name: string; code: string; sort_order: number; status: string }>
) {
const { data } = await apiClient.put>(
- `/admin/mohong/categories/${id}`,
+ `/admin/crash/categories/${id}`,
payload
)
return data.data
@@ -202,7 +202,7 @@ export async function updateAdminMohongCategory(
export async function deleteAdminMohongCategory(id: number) {
const { data } = await apiClient.delete>(
- `/admin/mohong/categories/${id}`
+ `/admin/crash/categories/${id}`
)
return data.data
}
@@ -215,25 +215,25 @@ export async function fetchAdminMohongProducts(params?: {
page_size?: number
}) {
const { data } = await apiClient.get>>(
- '/admin/mohong/products',
+ '/admin/crash/products',
{ params }
)
return data.data
}
export async function fetchAdminMohongProduct(id: number | string) {
- const { data } = await apiClient.get>(`/admin/mohong/products/${id}`)
+ const { data } = await apiClient.get>(`/admin/crash/products/${id}`)
return data.data
}
export async function createAdminMohongProduct(payload: Partial & { title: string; price_cent: number }) {
- const { data } = await apiClient.post>('/admin/mohong/products', payload)
+ const { data } = await apiClient.post>('/admin/crash/products', payload)
return data.data
}
export async function updateAdminMohongProduct(id: number, payload: Record) {
const { data } = await apiClient.put>(
- `/admin/mohong/products/${id}`,
+ `/admin/crash/products/${id}`,
payload
)
return data.data
@@ -241,7 +241,7 @@ export async function updateAdminMohongProduct(id: number, payload: Record>(
- `/admin/mohong/products/${id}`
+ `/admin/crash/products/${id}`
)
return data.data
}
@@ -252,20 +252,20 @@ export async function fetchAdminMohongOrders(params?: {
page?: number
page_size?: number
}) {
- const { data } = await apiClient.get>>('/admin/mohong/orders', {
+ const { data } = await apiClient.get>>('/admin/crash/orders', {
params,
})
return data.data
}
export async function fetchAdminMohongOrder(id: number | string) {
- const { data } = await apiClient.get>(`/admin/mohong/orders/${id}`)
+ const { data } = await apiClient.get>(`/admin/crash/orders/${id}`)
return data.data
}
export async function completeAdminMohongOrder(id: number, remark?: string) {
const { data } = await apiClient.post>(
- `/admin/mohong/orders/${id}/complete`,
+ `/admin/crash/orders/${id}/complete`,
{ remark: remark || '' }
)
return data.data
@@ -273,19 +273,19 @@ export async function completeAdminMohongOrder(id: number, remark?: string) {
export async function cancelAdminMohongOrder(id: number, reason?: string) {
const { data } = await apiClient.post>(
- `/admin/mohong/orders/${id}/cancel`,
+ `/admin/crash/orders/${id}/cancel`,
{ reason: reason || '' }
)
return data.data
}
export async function fetchAdminMohongConfig() {
- const { data } = await apiClient.get>('/admin/mohong/config')
+ const { data } = await apiClient.get>('/admin/crash/config')
return data.data
}
export async function updateAdminMohongConfig(payload: Partial) {
- const { data } = await apiClient.put>('/admin/mohong/config', payload)
+ const { data } = await apiClient.put>('/admin/crash/config', payload)
return data.data
}
diff --git a/frontend/src/features/mohong/components/MohongCartPanel.vue b/frontend/src/features/mohong/components/MohongCartPanel.vue
index 1ad6dd5..2bd733f 100644
--- a/frontend/src/features/mohong/components/MohongCartPanel.vue
+++ b/frontend/src/features/mohong/components/MohongCartPanel.vue
@@ -69,7 +69,7 @@ async function handleCheckout() {
clearCart()
closeCart()
const payment = await startMohongPayment(order.id, payWay)
- const orderPath = props.mobile ? `/m/mohong/orders/${order.id}` : `/mohong/orders/${order.id}`
+ const orderPath = props.mobile ? `/m/crash/orders/${order.id}` : `/crash/orders/${order.id}`
if (payment.paid || payment.status === 'paid') {
ElMessage.success('支付成功')
await router.push(orderPath)
diff --git a/frontend/src/features/mohong/components/MohongProductCard.vue b/frontend/src/features/mohong/components/MohongProductCard.vue
index 93f1c0d..514cdb8 100644
--- a/frontend/src/features/mohong/components/MohongProductCard.vue
+++ b/frontend/src/features/mohong/components/MohongProductCard.vue
@@ -18,7 +18,7 @@ const stockLabel = computed(() => {
-
+
![]()
{
- await router.push(`/m/mohong/orders/${order.id}`)
+ await router.push(`/m/crash/orders/${order.id}`)
})
} catch (error) {
showToast({ message: readError(error, '下单失败'), icon: 'cross' })
diff --git a/frontend/src/features/mohong/views/MobileMohongListView.vue b/frontend/src/features/mohong/views/MobileMohongListView.vue
index 8abae7e..88b7a68 100644
--- a/frontend/src/features/mohong/views/MobileMohongListView.vue
+++ b/frontend/src/features/mohong/views/MobileMohongListView.vue
@@ -165,11 +165,11 @@ function syncQuery() {
const query: Record
= {}
if (keyword.value.trim()) query.keyword = keyword.value.trim()
if (activeCategoryId.value) query.category_id = String(activeCategoryId.value)
- router.replace({ path: '/mohong', query })
+ router.replace({ path: '/crash', query })
}
function goDetail(id: number) {
- router.push(`/mohong/${id}`)
+ router.push(`/crash/${id}`)
}
function markCoverFailed(id: number) {
@@ -188,7 +188,7 @@ async function handleSupportClick() {
if (supportLoading.value) return
supportLoading.value = true
try {
- const chat = await ensureSupportChat('mohong')
+ const chat = await ensureSupportChat('crash')
router.push(`/m/chats/${chat.id}`)
} catch {
showToast({ message: '联系客服失败,请稍后重试', icon: 'cross' })
@@ -224,7 +224,7 @@ async function handleSupportClick() {
>
{{ supportLoading ? '...' : '客服' }}
-
+
diff --git a/frontend/src/features/mohong/views/MobileMohongOrdersView.vue b/frontend/src/features/mohong/views/MobileMohongOrdersView.vue
index 9014994..5d81e84 100644
--- a/frontend/src/features/mohong/views/MobileMohongOrdersView.vue
+++ b/frontend/src/features/mohong/views/MobileMohongOrdersView.vue
@@ -35,7 +35,7 @@ async function loadOrders() {
-
摸大红订单
+
撞车订单
加载中...
@@ -46,7 +46,7 @@ async function loadOrders() {
:key="item.id"
type="button"
class="card"
- @click="router.push(`/mohong/orders/${item.id}`)"
+ @click="router.push(`/crash/orders/${item.id}`)"
>
{{ item.order_no }}
diff --git a/frontend/src/features/mohong/views/MohongDetailView.vue b/frontend/src/features/mohong/views/MohongDetailView.vue
index ef54504..c7d6e73 100644
--- a/frontend/src/features/mohong/views/MohongDetailView.vue
+++ b/frontend/src/features/mohong/views/MohongDetailView.vue
@@ -146,11 +146,11 @@ async function handleBuy() {
const payment = await startMohongPayment(order.id, payWay)
if (payment.paid || payment.status === 'paid') {
ElMessage.success('支付成功')
- await router.push(`/mohong/orders/${order.id}`)
+ await router.push(`/crash/orders/${order.id}`)
return
}
await cashier.openPaymentCashier(payment, async () => {
- await router.push(`/mohong/orders/${order.id}`)
+ await router.push(`/crash/orders/${order.id}`)
})
} catch (error) {
ElMessage.error(readError(error, '下单失败'))
@@ -184,7 +184,7 @@ async function handleBuy() {
-
摸大红商品
+
撞车商品
{{ product.title }}
{{ product.description || '暂无说明' }}
@@ -238,7 +238,7 @@ async function handleBuy() {
购物车{{ cartCount > 0 ? `(${cartCount})` : '' }}
-
+
返回列表
diff --git a/frontend/src/features/mohong/views/MohongListView.vue b/frontend/src/features/mohong/views/MohongListView.vue
index de9a521..75804d3 100644
--- a/frontend/src/features/mohong/views/MohongListView.vue
+++ b/frontend/src/features/mohong/views/MohongListView.vue
@@ -180,7 +180,7 @@ function syncQuery() {
const query: Record
= {}
if (keyword.value.trim()) query.keyword = keyword.value.trim()
if (activeCategoryId.value) query.category_id = String(activeCategoryId.value)
- router.replace({ path: '/mohong', query })
+ router.replace({ path: '/crash', query })
}
const activeCategoryName = () => {
@@ -196,7 +196,7 @@ async function handleSupportClick() {
if (supportLoading.value) return
supportLoading.value = true
try {
- const chat = await ensureSupportChat('mohong')
+ const chat = await ensureSupportChat('crash')
router.push(`/messages/${chat.id}`)
} catch {
ElMessage.error('联系客服失败,请稍后重试')
@@ -210,7 +210,7 @@ async function handleSupportClick() {
-