refactor(store): 合并改价到确认收款弹窗

- 去除独立的“改价”按钮与修改金额弹窗相关状态和逻辑
- 在确认收款弹窗内新增“实付金额”输入框,预填当前值支持修改
- 取消改价时单独输入原因,仅保留收款备注说明
- 提交确认收款时,先调用接口更新改价信息,再调用确认收款接口
- 调整订单操作类型及按钮展示,移除改价相关项
- 更新界面样式及交互,支持合并改价与收款流程
- 更新业务状态说明,调整发货及付款状态文案逻辑
This commit is contained in:
2026-07-17 16:39:34 +08:00
parent 69862bfc0c
commit 7ff921d973
2 changed files with 56 additions and 146 deletions

View File

@@ -135,5 +135,10 @@
| 线下付款+未付款+已发货(有送达照片) | ❌ | ❌ | ✅ |
| 已付款+已发货(无送达照片) | ✅ | ✅ | ❌ |
| 已付款+已发货(有送达照片) | ❌ | ✅ | ❌ |
- **deliveryStatus 含义**10=待发货, 20=已发货, 30=已送达/已收货
- **状态文案**deliveryStatus=30 + 未付款 → "已送达待收款"deliveryStatus=30 + 已付款 → "待确认完成"
- **deliveryStatus 含义**10=待发货, 20=已发货, 30=部分发货(未使用)
- **状态文案**deliveryStatus=20+未付款+线下付款 → "已发货待收款"deliveryStatus=20+已付款 → "待收货"(蓝)
### 门店端:改价功能合并到确认收款弹窗
- 去掉独立的"改价"按钮和修改金额弹窗(`editPrice` OpType、`showEditPriceModal``editReason` 等)
- 在确认收款弹窗中增加"实付金额"输入框(预填当前值,可修改),改价不再需要单独输入原因(收款备注即可说明)
- 提交时:如果金额有变化,先调 `updateShopOrder` 更新 `payPrice`+`merchantRemarks`,再调 `confirmOfflinePayment` 确认收款

View File

@@ -28,13 +28,12 @@ const TABS: { key: TabKey; label: string; params: Partial<ShopOrderParam>[] }[]
]
// ─── 操作类型 ─────────────────────────────────────────────────────
type OpType = 'confirmPay' | 'deliver' | 'complete' | 'editPrice' | 'ship'
type OpType = 'confirmPay' | 'deliver' | 'complete' | 'ship'
const OP_LABEL: Record<OpType, string> = {
confirmPay: '收款',
deliver: '送达',
complete: '已完成',
editPrice: '金额',
ship: '发货',
}
@@ -42,7 +41,6 @@ const OP_DESC: Record<OpType, string> = {
confirmPay: '确认已收到线下付款',
deliver: '上传送达凭证照片,标记为已收货(不改变付款和订单完成状态)',
complete: '确认订单已完成,收款后点击此按钮标记订单完成',
editPrice: '修改订单实付金额',
ship: '选择发货人员并生成发货单,订单将进入已发货状态',
}
@@ -134,10 +132,6 @@ function isOrderActionable(order: ShopOrder): boolean {
function getOrderActions(order: ShopOrder): { label: string; type: OpType }[] {
if (!isOrderActionable(order)) return []
const actions: { label: string; type: OpType }[] = []
// 修改金额:仅在确认收款前显示(未付款时才可改价)
if (!order.payStatus) {
actions.push({label: '改价', type: 'editPrice'})
}
// 线下付款·待确认收款:显示"确认收款"按钮
if (!order.payStatus && order.payType === 9 && order.orderStatus === 0) {
actions.push({label: '确认收款', type: 'confirmPay'})
@@ -182,10 +176,8 @@ export default function StoreOrdersPage() {
const [payRemarks, setPayRemarks] = useState('')
const [submitting, setSubmitting] = useState(false)
// 修改金额弹窗状态
const [showEditPriceModal, setShowEditPriceModal] = useState(false)
// 确认收款弹窗:修改金额(选填)
const [editPayPrice, setEditPayPrice] = useState('')
const [editReason, setEditReason] = useState('')
// 发货弹窗状态
const [showShipModal, setShowShipModal] = useState(false)
@@ -321,6 +313,7 @@ export default function StoreOrdersPage() {
setOpType(type)
setProofImages([])
setPayRemarks('')
setEditPayPrice(String(order.payPrice || order.totalPrice || ''))
setShowModal(true)
}
@@ -330,57 +323,7 @@ export default function StoreOrdersPage() {
setCurrentOrder(null)
setProofImages([])
setPayRemarks('')
}
/** 打开修改金额弹窗 */
const openEditPriceModal = (order: ShopOrder) => {
setCurrentOrder(order)
setEditPayPrice(String(order.payPrice || order.totalPrice || ''))
setEditReason('')
setShowEditPriceModal(true)
}
/** 关闭修改金额弹窗 */
const closeEditPriceModal = () => {
setShowEditPriceModal(false)
setCurrentOrder(null)
setEditPayPrice('')
setEditReason('')
}
/** 提交修改金额 */
const submitEditPrice = async () => {
if (!currentOrder) return
const newPrice = parseFloat(editPayPrice)
if (isNaN(newPrice) || newPrice < 0) {
Taro.showToast({title: '请输入有效的金额', icon: 'none'})
return
}
if (!editReason.trim()) {
Taro.showToast({title: '请输入修改原因', icon: 'none'})
return
}
setSubmitting(true)
try {
const oldPrice = currentOrder.payPrice || currentOrder.totalPrice || '0'
const changeRecord = `【门店修改金额】原实付¥${oldPrice} → 新实付¥${newPrice.toFixed(2)},原因:${editReason.trim()}`
await updateShopOrder({
orderId: currentOrder.orderId,
payPrice: newPrice.toFixed(2),
merchantRemarks: (currentOrder.merchantRemarks || '') + `\n${changeRecord}`,
} as ShopOrder)
Taro.showToast({title: '修改成功', icon: 'success'})
closeEditPriceModal()
loadOrders(activeTab, 1)
} catch (e: any) {
Taro.showToast({title: e.message || '修改失败', icon: 'none'})
} finally {
setSubmitting(false)
}
}
/** 选择并上传凭证图片 */
@@ -440,7 +383,23 @@ export default function StoreOrdersPage() {
setSubmitting(true)
try {
if (opType === 'confirmPay') {
// 确认线下收款:调用专用接口
// 确认线下收款:检查是否需要改价,合并改价+确认收款
const newPrice = parseFloat(editPayPrice)
const oldPriceStr = String(currentOrder.payPrice || currentOrder.totalPrice || '')
const oldPrice = parseFloat(oldPriceStr)
const priceChanged = !isNaN(newPrice) && newPrice >= 0 && Math.abs(newPrice - oldPrice) > 0.01
if (priceChanged) {
// 先更新金额
const changeRecord = `【门店修改金额】原实付¥${oldPriceStr} → 新实付¥${newPrice.toFixed(2)}`
await updateShopOrder({
orderId: currentOrder.orderId,
payPrice: newPrice.toFixed(2),
merchantRemarks: (currentOrder.merchantRemarks || '') + `\n${changeRecord}`,
} as ShopOrder)
}
// 确认收款
await confirmOfflinePayment(
currentOrder.orderId!,
payRemarks.trim() || undefined,
@@ -695,20 +654,16 @@ export default function StoreOrdersPage() {
? 'bg-green-500'
: act.type === 'confirmPay'
? 'bg-blue-500'
: act.type === 'editPrice'
? 'bg-orange-500'
: act.type === 'ship'
? 'bg-purple-500'
: 'border border-blue-500'
}`}
onClick={() => act.type === 'editPrice'
? openEditPriceModal(order)
: act.type === 'ship'
? openShipModal(order)
: openModal(order, act.type)}
onClick={() => act.type === 'ship'
? openShipModal(order)
: openModal(order, act.type)}
>
<Text className={`text-sm ${
act.type === 'complete' || act.type === 'editPrice' || act.type === 'confirmPay' || act.type === 'ship' ? 'text-white' : 'text-blue-500'
act.type === 'complete' || act.type === 'confirmPay' || act.type === 'ship' ? 'text-white' : 'text-blue-500'
}`}>{act.label}</Text>
</View>
))}
@@ -873,17 +828,31 @@ export default function StoreOrdersPage() {
{/* 备注(仅确认收款时显示) */}
{opType === 'confirmPay' && (
<View className='mb-6'>
<Text className='text-sm text-gray-600 mb-2 block'></Text>
<Textarea
className='w-full px-4 py-3 rounded-xl border border-gray-200 text-sm text-gray-800'
style={{minHeight: '60px'}}
value={payRemarks}
onInput={(e) => setPayRemarks(e.detail.value)}
placeholder='可填写备注(如:微信转账已收到)'
maxlength={200}
/>
</View>
<>
<View className='mb-6'>
<Text className='text-sm text-gray-600 mb-2 block'></Text>
<Textarea
className='w-full px-4 py-3 rounded-xl border border-gray-200 text-sm text-gray-800'
style={{minHeight: '60px'}}
value={payRemarks}
onInput={(e) => setPayRemarks(e.detail.value)}
placeholder='可填写备注(如:微信转账已收到)'
maxlength={200}
/>
</View>
{/* 修改金额(选填,合并到确认收款) */}
<View className='mb-6'>
<Text className='text-sm text-gray-600 mb-2 block'></Text>
<Input
type='digit'
className='w-full px-4 py-3 rounded-xl border border-gray-200 text-lg text-gray-800'
value={editPayPrice}
onInput={(e) => setEditPayPrice(e.detail.value)}
placeholder='如需改价请直接修改,不改则保持原值'
/>
</View>
</>
)}
{/* 确认完成不需要备注时补充间距 */}
@@ -911,70 +880,6 @@ export default function StoreOrdersPage() {
</View>
)}
{/* 修改金额弹窗 */}
{showEditPriceModal && currentOrder && (
<View className='fixed inset-0 z-50 flex items-end justify-center'>
{/* 遮罩 */}
<View className='absolute inset-0 bg-black/50' onClick={closeEditPriceModal}/>
{/* 弹窗内容 */}
<View className='relative bg-white rounded-t-2xl w-full px-5 pt-6 pb-10'>
<Text className='text-lg font-medium text-gray-800 text-center mb-5 block'>
</Text>
{/* 订单信息 */}
<View className='bg-gray-50 rounded-xl p-4 mb-5'>
<Text className='text-sm text-gray-700 block'>{currentOrder.orderNo}</Text>
<Text className='text-sm text-gray-700 mt-1 block'>
<Text className='text-red-500 font-medium'>¥{currentOrder.payPrice || currentOrder.totalPrice}</Text>
</Text>
</View>
{/* 新金额输入 */}
<View className='mb-5'>
<Text className='text-sm text-gray-600 mb-2 block'></Text>
<Input
type='digit'
className='w-full px-4 py-3 rounded-xl border border-gray-200 text-lg text-gray-800'
value={editPayPrice}
onInput={(e) => setEditPayPrice(e.detail.value)}
placeholder='请输入新的实付金额'
/>
</View>
{/* 修改原因 */}
<View className='mb-6'>
<Text className='text-sm text-gray-600 mb-2 block'></Text>
<Textarea
className='w-full px-4 py-3 rounded-xl border border-gray-200 text-sm text-gray-800'
style={{minHeight: '60px'}}
value={editReason}
onInput={(e) => setEditReason(e.detail.value)}
placeholder='请输入修改原因,如:商品缺货调整、协商降价等'
maxlength={100}
/>
</View>
{/* 操作按钮 */}
<View className='flex gap-3'>
<View className='flex-1 py-3 rounded-xl bg-gray-100 text-center' onClick={closeEditPriceModal}>
<Text className='text-sm text-gray-600'></Text>
</View>
<View
className='flex-1 py-3 rounded-xl bg-orange-500 text-center flex items-center justify-center'
onClick={submitting ? undefined : submitEditPrice}
>
{submitting ? (
<Text className='text-sm text-white'>...</Text>
) : (
<Text className='text-sm text-white'></Text>
)}
</View>
</View>
</View>
</View>
)}
{/* 发货弹窗:选择发货人员 */}
{showShipModal && currentOrder && (
<View className='fixed inset-0 z-50 flex items-end justify-center'>