Files
xingque/pages/merchant-dispatch/merchant-dispatch.js
XingQue c03d22776f backup: 紫色UI换肤前完整备份(当前橙色逍遥梦主题)
保留改造前全部页面样式与功能代码,便于回滚。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 01:59:42 +08:00

442 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// pages/merchant-dispatch/merchant-dispatch.js
import { createPage, request } from '../../utils/base-page.js'
import PopupService from '../../services/popupService.js' // 引入弹窗服务
import { STAFF_API, isStaffMode, refreshStaffContext, getStaffContext, restoreStaffContextAfterAuth, isMerchantPortalUser } from '../../utils/staff-api.js'
Page(createPage({
data: {
// 可用余额 / 客服额度
sjyue: '0.00',
isStaffMode: false,
balanceLabel: '可用余额',
balanceTip: '派单将从此余额扣除',
// 商品类型列表
shangpinList: [],
// 当前选中的商品类型信息
selectedTypeId: null,
selectedHuiyuanId: null,
selectedYaoqiuleixing: null,
// 当前商品类型下的称号列表(用于标签选择器)
currentTypeChenghaoList: [],
// 表单字段
dingdanJieshao: '', // 订单介绍
dingdanBeizhu: '', // 订单备注
laobanName: '', // 老板游戏昵称/UID
zhidingUid: '', // 指定打手UID
jiage: '', // 订单价格
// 新增字段:抢单标签(称号)
selectedLabelId: '', // 选中的标签ID
selectedLabelName: '', // 选中的标签名称
// 新增字段:佣金要求(压金)
commissionEnabled: false, // 是否开启佣金要求
commissionValue: '', // 佣金金额(元)
// 页面状态
isLoading: false, // 加载商品类型中
isSubmitting: false, // 提交派单中
// 教程按钮状态
tutorialBtnHidden: false, // false=完全显示true=缩进隐藏(只露边)
// 背景图URL动态拼接
bgImageUrl: ''
},
async onLoad() {
if (wx.getStorageSync('token')) {
await restoreStaffContextAfterAuth()
}
if (!isMerchantPortalUser()) {
wx.showToast({ title: '请先成为商家或绑定客服', icon: 'none' })
setTimeout(() => wx.navigateBack(), 1500)
return
}
this.loadBgImage() // 拼接背景图
this.loadShangjiaYue() // 从全局变量获取商家余额
this.loadShangpinTypes() // 加载商品类型
this.startTutorialBtnTimer() // 启动按钮缩进定时器
},
onShow() {
this.loadShangjiaYue()
this.loadBgImage()
this.registerNotificationComponent()
this.startTutorialBtnTimer()
},
onHide() {
// 页面隐藏时重置弹窗服务状态,避免影响其他页面
PopupService.reset()
},
onUnload() {
// 清除缩进定时器,避免内存泄漏
if (this.tutorialTimer) {
clearTimeout(this.tutorialTimer)
}
// 页面卸载时重置弹窗服务
PopupService.reset()
},
// ==================== 背景图动态拼接 ====================
loadBgImage() {
const app = getApp()
const ossBase = app.globalData.ossImageUrl || 'https://your-oss-bucket.oss-cn-region.aliyuncs.com'
// 拼接完整路径beijing/shangjiapaidan/bg.jpg
const bgUrl = ossBase.replace(/\/$/, '') + '/beijing/shangjiapaidan/bg.jpg'
this.setData({ bgImageUrl: bgUrl })
},
// ==================== 基础数据加载 ====================
loadShangjiaYue() {
const staff = isStaffMode()
this.setData({
isStaffMode: staff,
balanceLabel: staff ? '可用额度' : '可用余额',
balanceTip: staff ? '派单将从您的客服额度扣除(需老板先划额度)' : '派单将从此余额扣除',
})
if (staff) {
const ctx = getStaffContext() || {}
const wallet = ctx.wallet || {}
this.setData({ sjyue: wallet.quota_available || '0.00' })
refreshStaffContext(request).then((fresh) => {
const w = (fresh && fresh.wallet) || wallet
this.setData({ sjyue: w.quota_available || '0.00' })
}).catch(() => {})
return
}
const app = getApp()
const shangjiaData = app.globalData.shangjia || {}
this.setData({
sjyue: shangjiaData.sjyue || '0.00'
})
},
// 加载商品类型(与极速派单完全一致)
async loadShangpinTypes() {
this.setData({ isLoading: true })
const staff = isStaffMode()
try {
const res = await request({
url: staff ? STAFF_API.productTypes : '/dingdan/sjspleixing',
method: 'POST'
})
const code = res && res.data && res.data.code
if (code === 200 || code === 0) {
let list = (res.data.data || [])
if (!Array.isArray(list) && list.list) list = list.list
// 强制倒序排列(与极速派单保持一致)
list.reverse()
this.setData({
shangpinList: list,
isLoading: false
})
// 默认选中第一个
if (list.length > 0) {
this.setSelectedType(list[0])
}
} else {
throw new Error((res.data && res.data.msg) || '加载失败')
}
} catch (error) {
console.error('加载商品类型失败:', error)
this.setData({ isLoading: false })
wx.showToast({
title: error.message || '加载类型失败',
icon: 'none',
duration: 2000
})
}
},
// 设置选中的商品类型,并提取该类型下的称号列表
setSelectedType(item) {
this.setData({
selectedTypeId: item.id,
selectedHuiyuanId: item.huiyuan_id,
selectedYaoqiuleixing: item.yaoqiuleixing,
currentTypeChenghaoList: item.chenghaoList || [],
// 切换商品类型时,清空之前选择的标签和佣金
selectedLabelId: '',
selectedLabelName: '',
commissionEnabled: false,
commissionValue: ''
})
},
// ==================== 教程按钮控制 ====================
// 启动定时器5秒后让按钮缩进
startTutorialBtnTimer() {
// 清除旧的定时器
if (this.tutorialTimer) {
clearTimeout(this.tutorialTimer)
}
// 5秒后将按钮缩进隐藏
this.tutorialTimer = setTimeout(() => {
this.setData({ tutorialBtnHidden: true })
}, 5000)
},
// 重置按钮状态完全显示并重新开始5秒倒计时
resetTutorialBtn() {
// 如果按钮当前是缩进状态,先恢复完全显示
if (this.data.tutorialBtnHidden) {
this.setData({ tutorialBtnHidden: false })
}
// 重新开始计时清除旧定时器新定时器5秒后缩进
if (this.tutorialTimer) {
clearTimeout(this.tutorialTimer)
}
this.tutorialTimer = setTimeout(() => {
this.setData({ tutorialBtnHidden: true })
}, 5000)
},
// 点击教程按钮:重置按钮状态,并调用 PopupService 弹出教程
async onTutorialBtnTap() {
// 首先重置按钮状态(完全显示并重新计时)
this.resetTutorialBtn()
// 调用弹窗服务,页面标识为 'sjpd1'
PopupService.checkAndShow(this, 'sjpd1')
},
// ==================== 表单输入事件 ====================
onDingdanJieshaoInput(e) {
this.setData({ dingdanJieshao: e.detail.value })
},
onDingdanBeizhuInput(e) {
this.setData({ dingdanBeizhu: e.detail.value })
},
onLaobanNameInput(e) {
this.setData({ laobanName: e.detail.value })
},
onZhidingUidInput(e) {
this.setData({ zhidingUid: e.detail.value })
},
onJiageInput(e) {
let value = e.detail.value
// 前端验证:确保是数字且最多两位小数
if (value === '' || /^\d+(\.\d{0,2})?$/.test(value)) {
this.setData({ jiage: value })
}
},
// 标签选择器picker事件
onLabelChange(e) {
const idx = e.detail.value
const label = this.data.currentTypeChenghaoList[idx]
if (label) {
this.setData({
selectedLabelId: label.id,
selectedLabelName: label.mingcheng
})
} else {
this.setData({
selectedLabelId: '',
selectedLabelName: ''
})
}
},
// 佣金开关
onCommissionToggle() {
this.setData({ commissionEnabled: !this.data.commissionEnabled })
},
onCommissionValueInput(e) {
let value = e.detail.value
if (value === '' || /^\d+(\.\d{0,2})?$/.test(value)) {
this.setData({ commissionValue: value })
}
},
// ==================== 表单验证与提交 ====================
validateForm() {
const {
selectedTypeId,
dingdanJieshao,
laobanName,
jiage,
sjyue,
commissionEnabled,
commissionValue
} = this.data
// 1. 验证必填项
if (!selectedTypeId) {
wx.showToast({ title: '请选择订单类型', icon: 'none' })
return false
}
if (!dingdanJieshao.trim()) {
wx.showToast({ title: '请输入订单介绍', icon: 'none' })
return false
}
if (!laobanName.trim()) {
wx.showToast({ title: '请输入老板游戏昵称', icon: 'none' })
return false
}
if (!jiage) {
wx.showToast({ title: '请输入订单价格', icon: 'none' })
return false
}
// 2. 验证价格格式和范围
const price = parseFloat(jiage)
if (isNaN(price) || price < 0.1 || price > 10000) {
wx.showToast({ title: '价格需在0.1-10000元之间', icon: 'none' })
return false
}
if (jiage.includes('.') && jiage.split('.')[1].length > 2) {
wx.showToast({ title: '最多支持两位小数', icon: 'none' })
return false
}
// 3. 验证佣金要求(若开启)
if (commissionEnabled) {
const commission = parseFloat(commissionValue)
if (isNaN(commission) || commission <= 0) {
wx.showToast({ title: '请输入有效的佣金金额', icon: 'none' })
return false
}
if (commission > 50000) {
wx.showToast({ title: '佣金建议不超过50000元', icon: 'none' })
return false
}
}
// 4. 验证余额/额度是否足够
const balance = parseFloat(sjyue)
if (price > balance) {
if (this.data.isStaffMode) {
wx.showModal({
title: '额度不足',
content: `当前可用额度${sjyue}元,需要${jiage}元。请联系商家老板划额度。`,
showCancel: false,
})
} else {
wx.showModal({
title: '余额不足',
content: `当前余额${sjyue}元,需要${jiage}元。请先充值。`,
confirmText: '去充值',
success: (res) => {
if (res.confirm) {
wx.navigateTo({
url: '/pages/merchant-recharge/merchant-recharge'
})
}
}
})
}
return false
}
return true
},
// 重置表单(保留商品类型选中状态)
resetForm() {
this.setData({
dingdanJieshao: '',
dingdanBeizhu: '',
laobanName: '',
zhidingUid: '',
jiage: '',
selectedLabelId: '',
selectedLabelName: '',
commissionEnabled: false,
commissionValue: ''
})
// 重置选中第一个商品类型(可选)
if (this.data.shangpinList.length > 0) {
this.setSelectedType(this.data.shangpinList[0])
}
},
// 提交派单
async onSubmit() {
if (this.data.isSubmitting) return
if (!this.validateForm()) return
this.setData({ isSubmitting: true })
// 准备提交数据(原有字段 + 新增字段)
const postData = {
// 原有必传字段
shangpinTypeId: this.data.selectedTypeId,
huiyuanId: this.data.selectedHuiyuanId,
yaoqiuleixing: this.data.selectedYaoqiuleixing,
dingdanJieshao: this.data.dingdanJieshao.trim(),
dingdanBeizhu: this.data.dingdanBeizhu.trim() || '',
laobanName: this.data.laobanName.trim(),
zhidingUid: this.data.zhidingUid.trim() || '',
jiage: this.data.jiage,
// 新增字段
labelId: this.data.selectedLabelId || '',
labelName: this.data.selectedLabelName || '',
commissionEnabled: this.data.commissionEnabled,
commissionValue: this.data.commissionEnabled ? this.data.commissionValue : ''
}
try {
const res = await request({
url: isStaffMode() ? STAFF_API.orderDispatch : '/dingdan/sjpaifa',
method: 'POST',
data: postData
})
if (res && res.data.code === 200) {
wx.showToast({
title: '派单成功',
icon: 'success',
duration: 2000
})
const orderAmount = parseFloat(this.data.jiage)
if (this.data.isStaffMode) {
this.loadShangjiaYue()
} else {
const app = getApp()
if (app.globalData.shangjia) {
const newBalance = parseFloat(app.globalData.shangjia.sjyue || '0') - orderAmount
app.globalData.shangjia.sjyue = newBalance.toFixed(2)
app.globalData.shangjia.fadanzong = (parseInt(app.globalData.shangjia.fadanzong || '0') + 1).toString()
app.globalData.shangjia.riliushui = (parseFloat(app.globalData.shangjia.riliushui || '0') + orderAmount).toFixed(2)
app.globalData.shangjia.yueliushui = (parseFloat(app.globalData.shangjia.yueliushui || '0') + orderAmount).toFixed(2)
this.setData({ sjyue: app.globalData.shangjia.sjyue })
}
}
// 延迟重置表单,避免用户连续提交
setTimeout(() => {
this.resetForm()
this.setData({ isSubmitting: false })
}, 1500)
} else {
wx.showModal({
title: '派单失败',
content: res.data.msg || '请稍后重试',
showCancel: false
})
this.setData({ isSubmitting: false })
}
} catch (error) {
console.error('派单请求失败:', error)
wx.showModal({
title: '请求失败',
content: error.message || '网络错误,请检查连接',
showCancel: false
})
this.setData({ isSubmitting: false })
}
},
// ==================== 商品类型选择 ====================
onSelectType(e) {
const { id, item } = e.currentTarget.dataset
this.setSelectedType(item)
}
}))